public static System.Drawing.Bitmap Decode(byte[] picbin, byte[] palbin, uint type, ushort width, ushort height, byte csa = 0) { System.Drawing.Imaging.PixelFormat pf; System.Diagnostics.Debug.WriteLine("TexUt2.Decode: bw = " + (width / 128) + "; BH = " + (height / 64) + "; type = " + type + "; size = " + picbin.Length + "; width = " + width + "; height = " + height); switch (type) { case 19: pf = System.Drawing.Imaging.PixelFormat.Format8bppIndexed; picbin = Reform.Decode8(picbin, width / 128, height / 64); break; case 20: pf = System.Drawing.Imaging.PixelFormat.Format4bppIndexed; picbin = Reform.Decode4(picbin, width / 128, height / 128); break; default: throw new NotSupportedException("Unsupported image type."); } System.Drawing.Bitmap pic = new System.Drawing.Bitmap(width, height, pf); { System.Drawing.Imaging.BitmapData bitmapdata = pic.LockBits(System.Drawing.Rectangle.FromLTRB(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, pf); try { System.Runtime.InteropServices.Marshal.Copy(picbin, 0, bitmapdata.Scan0, Math.Min(picbin.Length, bitmapdata.Stride * height)); } finally { pic.UnlockBits(bitmapdata); } } /*The palette is swizzled, or something...*/ { byte[] destinationArray = new byte[1024]; for (int i = 0; i < 256; i++) { Buffer.BlockCopy(palbin, 4 * i, destinationArray, 4 * (i + tbl[i & 0x7F]), 4); } Buffer.BlockCopy(destinationArray, 0, palbin, 0, 1024); } type = 0; System.Drawing.Imaging.ColorPalette palette = pic.Palette; switch (pf) { case System.Drawing.Imaging.PixelFormat.Format8bppIndexed: type = 256; csa = 0; break; case System.Drawing.Imaging.PixelFormat.Format4bppIndexed: type = 16; csa *= 64; break; } for (int i = 0; i < type; i++) { int c = csa + (i * 4); //Because of rounding, when reading values back use Math.Ceiling(input/2) palette.Entries[i] = System.Drawing.Color.FromArgb((int)Math.Min(palbin[c + 3] * 2, 255), palbin[c], palbin[c + 1], palbin[c + 2]); } pic.Palette = palette; return(pic); }
private static void setData(BinaryReader br, long baseP, byte[] data) { ulong num = br.ReadUInt64(); int bw = ((int)(num >> 0x30)) & 0x3F; uint type = ((uint)(num >> 0x38)) & 0x3F; br.BaseStream.Position += 8 + 16 + 16 + 16; int size = (br.ReadUInt16() & 0x7FFF) << 4; br.BaseStream.Position += 0x12L; br.BaseStream.Position = baseP + br.ReadInt32(); Debug.WriteLine("writing:bw = " + bw + "; type = " + type + "; size = " + size); int ds = size / 8192; switch (type) { case 0: if (bw > 0) { data = Reform.Decode32(data, bw, ds / bw); } break; case 19: bw /= 2; if (bw > 0) { data = Reform.Decode8(data, bw, ds / bw); } break; case 20: bw /= 2; if (bw > 0) { data = Reform.Decode4(data, bw, ds / bw); } break; default: throw new NotSupportedException("Unknown type: " + type); } Debug.WriteLine("Writing " + size + " bytes..."); Debug.WriteLineIf(size < data.Length, "Expected " + size + " bytes, but got " + data.Length + " bytes; Truncating!"); Debug.WriteLineIf(size > data.Length, "Expected " + size + " bytes, but only got " + data.Length + " bytes!"); br.BaseStream.Write(data, 0, Math.Min(size, (int)Math.Min(data.Length, br.BaseStream.Length - br.BaseStream.Position))); }
private void parseD(long pos, long len, int index) { if (pos + len > this.file.BaseStream.Length) { throw new IndexOutOfRangeException("IMGD goes past file bounds"); } this.file.Seek(pos, SeekOrigin.Begin); if (this.file.ReadUInt32() != 0x44474D49) { throw new InvalidDataException("IMGD has bad signature"); } #if DEBUG uint pixelOffset, pixelLength, paletteOffset, paletteLength; ushort width, height, type; byte encode; Debug.WriteLine(String.Format("---IMGD---\nN0: {0}\npixelOffset: {1}\npixelLength: {2}\npaletteOffset: {3}\npaletteLength: {4}\nN5: {5}\nN6: {6}\nwidth: {7}\nheight: {8}\nN9: {9}\nN10: {10}\ntype: {11}\nN12: {12}\nN13: {13}\nN14: {14}\nN15: {15}\nN16: {16}\nencode: {17}\n---IMGD End---", this.file.ReadUInt32(), pixelOffset = this.file.ReadUInt32(), pixelLength = this.file.ReadUInt32(), paletteOffset = this.file.ReadUInt32(), paletteLength = this.file.ReadUInt32(), this.file.ReadUInt16(), this.file.ReadUInt16(), width = this.file.ReadUInt16(), height = this.file.ReadUInt16(), this.file.ReadUInt32(), this.file.ReadUInt16(), type = this.file.ReadUInt16(), this.file.ReadUInt32(), this.file.ReadUInt32(), this.file.ReadUInt32(), this.file.ReadUInt32(), this.file.ReadUInt32(), encode = this.file.ReadByte() )); #else this.file.Seek(4, SeekOrigin.Current); uint pixelOffset = this.file.ReadUInt32(), pixelLength = this.file.ReadUInt32(), paletteOffset = this.file.ReadUInt32(), paletteLength = this.file.ReadUInt32(); this.file.Seek(4, SeekOrigin.Current); ushort width = this.file.ReadUInt16(), height = this.file.ReadUInt16(); this.file.Seek(6, SeekOrigin.Current); ushort type = this.file.ReadUInt16(); this.file.Seek(20, SeekOrigin.Current); byte encode = this.file.ReadByte(); #endif if (pixelOffset + pixelLength > len) { throw new IndexOutOfRangeException("IMGD pixel data goes past file bounds"); } if (paletteOffset + paletteLength > len) { throw new IndexOutOfRangeException("IMGD palette data goes past file bounds"); } PixelFormat pf; switch (type) { case 19: pf = PixelFormat.Format8bppIndexed; break; case 20: pf = PixelFormat.Format4bppIndexed; break; default: throw new NotSupportedException("Unsupported IMGD type"); } Bitmap bmp = new Bitmap(width, height, pf); { this.file.Seek(pos + pixelOffset, SeekOrigin.Begin); byte[] buffer = this.file.ReadBytes((int)pixelLength); switch (pf) { case PixelFormat.Format8bppIndexed: if (encode == 7) { buffer = Reform.Decode8(Reform.Encode32(buffer, width / 128, height / 64), width / 128, height / 64); } break; case PixelFormat.Format4bppIndexed: if (encode == 7) { buffer = Reform.Decode4(Reform.Encode32(buffer, width / 128, height / 128), width / 128, height / 128); } else { Reform.swapHLUT(buffer); } break; } BitmapData pix = bmp.LockBits(System.Drawing.Rectangle.FromLTRB(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, pf); try { System.Runtime.InteropServices.Marshal.Copy(buffer, 0, pix.Scan0, (int)pixelLength); } finally { bmp.UnlockBits(pix); } } { this.file.Seek(pos + paletteOffset, SeekOrigin.Begin); byte[] buffer = this.file.ReadBytes((int)paletteLength); ColorPalette palette = bmp.Palette; //Because of rounding, when reading values back use Math.Ceiling(input/2) switch (pf) { case PixelFormat.Format8bppIndexed: for (int i = 0; i < 256; i++) { palette.Entries[Reform.paletteSwap34(i)] = Color.FromArgb((int)Math.Min(buffer[(i * 4) + 3] * 2, 255), buffer[i * 4], buffer[(i * 4) + 1], buffer[(i * 4) + 2]); Debug.WriteLineIf(buffer[(i * 4) + 3] > 128, "Transparency before transform is over 128: " + buffer[(i * 4) + 3]); } break; case PixelFormat.Format4bppIndexed: for (int i = 0; i < 16; i++) { palette.Entries[i] = Color.FromArgb((int)Math.Min(buffer[(i * 4) + 3] * 2, 255), buffer[i * 4], buffer[(i * 4) + 1], buffer[(i * 4) + 2]); Debug.WriteLineIf(buffer[(i * 4) + 3] > 128, "Transparency before transform is over 128: " + buffer[(i * 4) + 3]); } break; } bmp.Palette = palette; } this.bmps.Add(bmp); }