public DDS(D3DFormat Format, Bitmap bitmap) { SquishFlags flags = SquishFlags.kDxt1; bool bCompressed = true; switch (Format) { case D3DFormat.DXT1: flags = SquishFlags.kDxt1; break; case D3DFormat.DXT3: flags = SquishFlags.kDxt3; break; case D3DFormat.DXT5: flags = SquishFlags.kDxt5; break; default: bCompressed = false; break; } format = Format; width = bitmap.Width; height = bitmap.Height; var mip = new MipMap(); mip.Width = width; mip.Height = height; byte[] data = new byte[mip.Width * mip.Height * 4]; BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, mip.Width, mip.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); Marshal.Copy(bmpdata.Scan0, data, 0, bmpdata.Stride * bmpdata.Height); bitmap.UnlockBits(bmpdata); if (bCompressed) { for (uint i = 0; i < data.Length - 4; i += 4) { byte r = data[i + 0]; data[i + 0] = data[i + 2]; data[i + 2] = r; } byte[] dest = new byte[Squish.Squish.GetStorageRequirements(mip.Width, mip.Height, flags | SquishFlags.kColourIterativeClusterFit | SquishFlags.kWeightColourByAlpha)]; Squish.Squish.CompressImage(data, mip.Width, mip.Height, ref dest, flags | SquishFlags.kColourIterativeClusterFit | SquishFlags.kWeightColourByAlpha); mip.Data = dest; } else { mip.Data = data; } mipMaps.Add(mip); }
public Bitmap Decompress(int mipLevel = 0, bool suppressAlpha = false) { MipMap mip = MipMaps[mipLevel]; Bitmap b = new Bitmap(mip.Width, mip.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); SquishFlags flags = 0; bool notCompressed = false; switch (Format) { case D3DFormat.DXT1: flags = SquishFlags.kDxt1; break; case D3DFormat.DXT5: flags = SquishFlags.kDxt5; break; case D3DFormat.A8R8G8B8: notCompressed = true; break; default: throw new NotImplementedException($"Can't decompress: {Format}"); } byte[] dest = new byte[mip.Width * mip.Height * 4]; byte[] data = mip.Data; if (notCompressed) { for (uint i = 0; i < data.Length - 4; i += 4) { uint colour = (uint)((data[i + 3] << 24) | (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0] << 0)); dest[i + 0] = (byte)((colour & PixelFormat.BBitMask) >> 0); dest[i + 1] = (byte)((colour & PixelFormat.GBitMask) >> 8); dest[i + 2] = (byte)((colour & PixelFormat.RBitMask) >> 16); dest[i + 3] = (byte)((colour & PixelFormat.ABitMask) >> 24); } } else { Squish.Squish.DecompressImage(dest, mip.Width, mip.Height, data, flags); for (uint i = 0; i < dest.Length - 4; i += 4) { byte r = dest[i + 0]; dest[i + 0] = dest[i + 2]; dest[i + 2] = r; } } BitmapData bmpdata = b.LockBits(new Rectangle(0, 0, mip.Width, mip.Height), ImageLockMode.ReadWrite, (suppressAlpha ? System.Drawing.Imaging.PixelFormat.Format32bppRgb : b.PixelFormat)); Marshal.Copy(dest, 0, bmpdata.Scan0, dest.Length); b.UnlockBits(bmpdata); return(b); }
public static DDS Load(byte[] data) { DDS dds = new DDS(); using (MemoryStream ms = new MemoryStream(data)) using (BinaryReader br = new BinaryReader(ms)) { if (!IsDDS(br)) { return(null); } dds.pixelFormat = new DDSPixelFormat(); br.ReadUInt32(); // header length dds.flags = (Flags)br.ReadUInt32(); dds.height = (int)br.ReadUInt32(); dds.width = (int)br.ReadUInt32(); dds.pitch = (int)br.ReadUInt32(); dds.depth = (int)br.ReadUInt32(); int mipCount = (int)br.ReadUInt32(); for (int i = 0; i < 11; i++) { br.ReadUInt32(); } br.ReadUInt32(); // pixel format length dds.pixelFormat.Flags = (PixelFormatFlags)br.ReadUInt32(); dds.pixelFormat.FourCC = (PixelFormatFourCC)br.ReadUInt32(); dds.pixelFormat.RGBBitCount = (int)br.ReadUInt32(); dds.pixelFormat.RBitMask = br.ReadUInt32(); dds.pixelFormat.GBitMask = br.ReadUInt32(); dds.pixelFormat.BBitMask = br.ReadUInt32(); dds.pixelFormat.ABitMask = br.ReadUInt32(); dds.caps = (DDSCaps)br.ReadUInt32(); dds.caps2 = (DDSCaps2)br.ReadUInt32(); br.ReadUInt32(); br.ReadUInt32(); br.ReadUInt32(); if (dds.pixelFormat.Flags.HasFlag(PixelFormatFlags.DDPF_FOURCC)) { dds.format = (D3DFormat)dds.pixelFormat.FourCC; } else if (dds.pixelFormat.Flags.HasFlag(PixelFormatFlags.DDPF_RGB) & dds.pixelFormat.Flags.HasFlag(PixelFormatFlags.DDPF_ALPHAPIXELS)) { dds.format = D3DFormat.A8R8G8B8; } for (int i = 0; i < Math.Max(1, mipCount); i++) { var mip = new MipMap { Width = dds.width >> i, Height = dds.height >> i }; switch (dds.format) { case D3DFormat.A8R8G8B8: mip.Data = br.ReadBytes(mip.Width * mip.Height * 4); break; case D3DFormat.DXT1: mip.Data = br.ReadBytes((((mip.Width + 3) / 4) * ((mip.Height + 3) / 4)) * 8); break; case D3DFormat.DXT3: case D3DFormat.DXT5: mip.Data = br.ReadBytes((((mip.Width + 3) / 4) * ((mip.Height + 3) / 4)) * 16); break; } dds.mipMaps.Add(mip); } } return(dds); }
public static DDS Load(byte[] data) { DDS dds = new DDS(); using (MemoryStream ms = new MemoryStream(data)) using (BinaryReader br = new BinaryReader(ms)) { if (!IsDDS(br)) { return null; } dds.pixelFormat = new DDSPixelFormat(); br.ReadUInt32(); // header length dds.flags = (Flags)br.ReadUInt32(); dds.height = (int)br.ReadUInt32(); dds.width = (int)br.ReadUInt32(); dds.pitch = (int)br.ReadUInt32(); dds.depth = (int)br.ReadUInt32(); int mipCount = (int)br.ReadUInt32(); for (int i = 0; i < 11; i++) { br.ReadUInt32(); } br.ReadUInt32(); // pixel format length dds.pixelFormat.Flags = (PixelFormatFlags)br.ReadUInt32(); dds.pixelFormat.FourCC = (PixelFormatFourCC)br.ReadUInt32(); dds.pixelFormat.RGBBitCount = (int)br.ReadUInt32(); dds.pixelFormat.RBitMask = br.ReadUInt32(); dds.pixelFormat.GBitMask = br.ReadUInt32(); dds.pixelFormat.BBitMask = br.ReadUInt32(); dds.pixelFormat.ABitMask = br.ReadUInt32(); dds.caps = (DDSCaps)br.ReadUInt32(); dds.caps2 = (DDSCaps2)br.ReadUInt32(); br.ReadUInt32(); br.ReadUInt32(); br.ReadUInt32(); if (dds.pixelFormat.Flags.HasFlag(PixelFormatFlags.DDPF_FOURCC)) { dds.format = (D3DFormat)dds.pixelFormat.FourCC; } else if (dds.pixelFormat.Flags.HasFlag(PixelFormatFlags.DDPF_RGB) & dds.pixelFormat.Flags.HasFlag(PixelFormatFlags.DDPF_ALPHAPIXELS)) { dds.format = D3DFormat.A8R8G8B8; } for (int i = 0; i < Math.Max(1, mipCount); i++) { var mip = new MipMap { Width = dds.width >> i, Height = dds.height >> i }; switch (dds.format) { case D3DFormat.A8R8G8B8: mip.Data = br.ReadBytes(mip.Width * mip.Height * 4); break; case D3DFormat.DXT1: mip.Data = br.ReadBytes((((mip.Width + 3) / 4) * ((mip.Height + 3) / 4)) * 8); break; case D3DFormat.DXT3: case D3DFormat.DXT5: mip.Data = br.ReadBytes((((mip.Width + 3) / 4) * ((mip.Height + 3) / 4)) * 16); break; } dds.mipMaps.Add(mip); } } return dds; }
public DDS(D3DFormat format, Bitmap bitmap) { SquishFlags flags = SquishFlags.kDxt1; bool compressed = true; switch (format) { case D3DFormat.DXT1: flags = SquishFlags.kDxt1; break; case D3DFormat.DXT3: flags = SquishFlags.kDxt3; break; case D3DFormat.DXT5: flags = SquishFlags.kDxt5; break; default: compressed = false; break; } Format = format; Width = bitmap.Width; Height = bitmap.Height; MipMap mip = new MipMap { Width = Width, Height = Height }; byte[] data = new byte[mip.Width * mip.Height * 4]; BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, mip.Width, mip.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); Marshal.Copy(bmpdata.Scan0, data, 0, bmpdata.Stride * bmpdata.Height); bitmap.UnlockBits(bmpdata); if (compressed) { for (uint i = 0; i < data.Length - 4; i += 4) { byte r = data[i + 0]; data[i + 0] = data[i + 2]; data[i + 2] = r; } byte[] dest = new byte[Squish.Squish.GetStorageRequirements(mip.Width, mip.Height, flags | SquishFlags.kColourIterativeClusterFit)]; Squish.Squish.CompressImage(data, mip.Width, mip.Height, dest, flags | SquishFlags.kColourIterativeClusterFit, true); mip.Data = dest; } else { mip.Data = data; } MipMaps.Add(mip); }