/// <summary> /// Create DDS Texture From Image. /// </summary> /// <param name="image">Main Image.</param> /// <param name="mipMaps">Number of MipMaps.</param> /// <param name="format">Destination Format.</param> /// <param name="bw">Binary Writer To Save Output DDS Texture.</param> public static void CreateFromBitmap(Bitmap image, uint mipMaps, DDSImageDestination format, BinaryWriter bw) { if (mipMaps < 1) mipMaps = 1; bool asRgb32 = false; switch (format) { case DDSImageDestination.BC1: case DDSImageDestination.BC2: case DDSImageDestination.BC3: case DDSImageDestination.BC4: case DDSImageDestination.BC5: case DDSImageDestination.Dxt1: case DDSImageDestination.Dxt3: case DDSImageDestination.Dxt5: asRgb32 = true; break; } DDSHeader cheader = null; byte[] buffer = new byte[0]; if (asRgb32) { int step = Bitmap.GetPixelFormatSize(image.PixelFormat); bool alpha = (step == 32); char[] chrs = new char[4]; SquishFlags flag = SquishFlags.Dxt1; switch (format) { case DDSImageDestination.BC1: case DDSImageDestination.Dxt1: chrs = new char[] { 'D', 'X', 'T', '1' }; flag = SquishFlags.Dxt1; break; case DDSImageDestination.BC2: case DDSImageDestination.Dxt3: chrs = new char[] { 'D', 'X', 'T', '3' }; flag = SquishFlags.Dxt3; break; case DDSImageDestination.Dxt5: case DDSImageDestination.BC3: chrs = new char[] { 'D', 'X', 'T', '5' }; flag = SquishFlags.Dxt5; break; case DDSImageDestination.BC4: chrs = new char[] { 'A', 'T', 'I', '1' }; flag = SquishFlags.BC4; break; case DDSImageDestination.BC5: chrs = new char[] { 'A', 'T', 'I', '2' }; flag = SquishFlags.BC5; break; } SquishFlags fit = CompressionFlags & (SquishFlags.ColourIterativeClusterFit | SquishFlags.ColourClusterFit | SquishFlags.ColourRangeFit); SquishFlags metric = CompressionFlags & (SquishFlags.ColourMetricPerceptual | SquishFlags.ColourMetricUniform); SquishFlags extra = CompressionFlags & SquishFlags.WeightColourByAlpha; if (fit != SquishFlags.ColourRangeFit) fit = SquishFlags.ColourClusterFit; if (metric != SquishFlags.ColourMetricUniform) metric = SquishFlags.ColourMetricPerceptual; flag |= fit | metric | extra; cheader = new DDSHeader() { Size = 124, Flags = DDSFlagsTexture, Height = (uint)image.Height, Width = (uint)image.Width, PitchOrLinearSize = 0, Depth = 32, MipMapCount = mipMaps, Reserved1 = new uint[11], Caps = DDSCaps.DDSCAPS_TEXTURE | DDSCaps.DDSCAPS_MIPMAP, Caps2 = (DDSCaps2)0, Caps3 = 0, Caps4 = 0, Reserved2 = 0 }; cheader.PixelFormat = new DDSPixelFormat() { Size = 32, Flags = DDSPixelFormatFlags.DDPF_FOURCC, FourCC = new string(chrs), RGBBitCount = 32, RBitMask = 0, GBitMask = 0, BBitMask = 0, ABitMask = 0 }; List<byte> _cbuff = new List<byte>(); Bitmap cimage = (Bitmap)image.Clone(); for (int i = 0; i < mipMaps; i++) { byte[] cbuf1 = FlipImageData(GetImageData(cimage, true)); cbuf1 = SharpSquish.CompressImage(cbuf1, cimage.Width, cimage.Height, flag); _cbuff.AddRange(cbuf1); int width = Math.Max(cimage.Width / 2, 1); int height = Math.Max(cimage.Height / 2, 1); cimage = ResizeImage(cimage, width, height); } cimage.Dispose(); buffer = _cbuff.ToArray(); } else { int step = Bitmap.GetPixelFormatSize(image.PixelFormat); bool alpha = (step == 32); cheader = new DDSHeader() { Size = 124, Flags = DDSFlags.DDSD_CAPS | DDSFlags.DDSD_HEIGHT | DDSFlags.DDSD_MIPMAPCOUNT | DDSFlags.DDSD_PIXELFORMAT| DDSFlags.DDSD_WIDTH, Height = (uint)image.Height, Width = (uint)image.Width, PitchOrLinearSize = 0, Depth = 1, MipMapCount = mipMaps, Reserved1 = new uint[11], Caps = DDSCaps.DDSCAPS_TEXTURE | DDSCaps.DDSCAPS_MIPMAP, Caps2 = (DDSCaps2)0, Caps3 = 0, Caps4 = 0, Reserved2 = 0 }; uint dwRBitMask = 0, dwGBitMask = 0, dwBBitMask = 0, dwABitMask = 0; switch (step) { case 32: dwRBitMask = 0xff; dwGBitMask = 0xff00; dwBBitMask = 0xff0000; dwABitMask = 0xff000000; break; case 24: dwRBitMask = 0xff0000; dwGBitMask = 0xff00; dwBBitMask = 0xff; break; case 16: dwRBitMask = 0x7c00; dwGBitMask = 0x3e0; dwBBitMask = 0x1f; break; } cheader.PixelFormat = new DDSPixelFormat() { Size = 32, Flags = DDSPixelFormatFlags.DDPF_RGB | ((alpha) ? DDSPixelFormatFlags.DDPF_ALPHAPIXELS : (DDSPixelFormatFlags)0), FourCC = new string(new char[] { '\0', '\0', '\0', '\0' }), RGBBitCount = (uint)step, ABitMask = dwABitMask, RBitMask = dwRBitMask, BBitMask = dwBBitMask, GBitMask = dwGBitMask }; List<byte> _cbuff = new List<byte>(); Bitmap cimage = (Bitmap)image.Clone(); for (int i = 0; i < mipMaps; i++) { byte[] cbuf1 = GetImageData(cimage, false); _cbuff.AddRange(cbuf1); int width = Math.Max(cimage.Width / 2, 1); int height = Math.Max(cimage.Height / 2, 1); if (cimage != null) cimage.Dispose(); cimage = ResizeImage(cimage, width, height); } cimage.Dispose(); buffer = _cbuff.ToArray(); } bw.Write((uint)0x20534444); cheader.WriteTo(bw); bw.Write(buffer); }
/// <summary> /// Create DDS Texture From Image. /// </summary> /// <param name="image">Main Image.</param> /// <param name="mipMaps">Number of MipMaps.</param> /// <param name="format">Destination Format.</param> /// <param name="file">FilePath To Save DDS Texture.</param> public static void CreateFromBitmap(Bitmap image, uint mipMaps, DDSImageDestination format, string file) { using (FileStream fs = File.Open(file, FileMode.OpenOrCreate, FileAccess.Write)) { CreateFromBitmap(image, mipMaps, format, fs); } }
/// <summary> /// Create DDS Texture From Image. /// </summary> /// <param name="image">Main Image.</param> /// <param name="mipMaps">Number of MipMaps.</param> /// <param name="format">Destination Format.</param> /// <param name="stream">Stream To Write Output DDS Texture.</param> public static void CreateFromBitmap(Bitmap image, uint mipMaps, DDSImageDestination format, Stream stream) { if (!stream.CanWrite) throw new ArgumentException("stream"); using (BinaryWriter bw = new BinaryWriter(stream)) { CreateFromBitmap(image, mipMaps, format, bw); } }
/// <summary> /// Create DDS Texture From Image. /// </summary> /// <param name="image">Main Image.</param> /// <param name="mipMaps">Number of MipMaps.</param> /// <param name="format">Destination Format.</param> /// <returns>Return a Array With DDS Texture Data.</returns> public static byte[] CreateFromBitmap(Bitmap image, uint mipMaps, DDSImageDestination format) { byte[] lump = new byte[0]; using (MemoryStream ms = new MemoryStream(lump, true)) { CreateFromBitmap(image, mipMaps, format, ms); } return lump; }