public unsafe Bitmap ToBitmap(bool swap = false, bool alpha = false) { int width = (int)DecompressedSize / 32 / 2; int height = 32; if (swap) { height = width; width = 32; } Bitmap b = new Bitmap(width, height); BitmapData d = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); uint * result = (uint *)d.Scan0; int stride = d.Stride / 4; int offs = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (!alpha) { result[y * stride + x] = GFXUtil.ConvertColorFormat( IOUtil.ReadU16BE(TexData, offs), ColorFormat.RGBA5551, ColorFormat.ARGB8888); } else { byte c = TexData[offs]; byte a = TexData[offs + 1]; result[y * stride + x] = GFXUtil.ToColorFormat(a, c, c, c, ColorFormat.ARGB8888); } offs += 2; } } b.UnlockBits(d); return(b); }
public static unsafe Bitmap ToBitmap(byte[] Data, int Offset, int Width, int Height, ImageFormat Format, bool ExactSize = false) { if (Data == null || Data.Length < 1 || Offset < 0 || Offset >= Data.Length || Width < 1 || Height < 1) { return(null); } if (ExactSize && ((Width % 8) != 0 || (Height % 8) != 0)) { return(null); } int physicalwidth = Width; int physicalheight = Height; if (!ExactSize) { Width = 1 << (int)Math.Ceiling(Math.Log(Width, 2)); Height = 1 << (int)Math.Ceiling(Math.Log(Height, 2)); } Bitmap bitm = new Bitmap(physicalwidth, physicalheight); BitmapData d = bitm.LockBits(new Rectangle(0, 0, bitm.Width, bitm.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); uint * res = (uint *)d.Scan0; int offs = Offset;//0; int stride = d.Stride / 4; switch (Format) { case ImageFormat.RGBA8: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat( IOUtil.ReadU32LE(Data, offs + pos * 4), ColorFormat.RGBA8888, ColorFormat.ARGB8888); /*GFXUtil.ToArgb( * Data[offs + pos * 4], * Data[offs + pos * 4 + 3], * Data[offs + pos * 4 + 2], * Data[offs + pos * 4 + 1] * );*/ } offs += 64 * 4; } } break; case ImageFormat.RGB8: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat( IOUtil.ReadU24LE(Data, offs + pos * 3), ColorFormat.RGB888, ColorFormat.ARGB8888); /*GFXUtil.ToArgb( * Data[offs + pos * 3 + 2], * Data[offs + pos * 3 + 1], * Data[offs + pos * 3 + 0] * );*/ } offs += 64 * 3; } } break; case ImageFormat.RGBA5551: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat( IOUtil.ReadU16LE(Data, offs + pos * 2), ColorFormat.RGBA5551, ColorFormat.ARGB8888); //GFXUtil.RGBA5551ToArgb(IOUtil.ReadU16LE(Data, offs + pos * 2)); } offs += 64 * 2; } } break; case ImageFormat.RGB565: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat( IOUtil.ReadU16LE(Data, offs + pos * 2), ColorFormat.RGB565, ColorFormat.ARGB8888); //GFXUtil.RGB565ToArgb(IOUtil.ReadU16LE(Data, offs + pos * 2)); } offs += 64 * 2; } } break; case ImageFormat.RGBA4: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat( IOUtil.ReadU16LE(Data, offs + pos * 2), ColorFormat.RGBA4444, ColorFormat.ARGB8888); /*GFXUtil.ToArgb( * (byte)((Data[offs + pos * 2] & 0xF) * 0x11), * (byte)((Data[offs + pos * 2 + 1] >> 4) * 0x11), * (byte)((Data[offs + pos * 2 + 1] & 0xF) * 0x11), * (byte)((Data[offs + pos * 2] >> 4) * 0x11) * );*/ } offs += 64 * 2; } } break; case ImageFormat.LA8: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat( Data[offs + pos * 2], Data[offs + pos * 2 + 1], Data[offs + pos * 2 + 1], Data[offs + pos * 2 + 1], ColorFormat.ARGB8888 ); } offs += 64 * 2; } } break; case ImageFormat.HILO8: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat( Data[offs + pos * 2], Data[offs + pos * 2 + 1], Data[offs + pos * 2 + 1], Data[offs + pos * 2 + 1], ColorFormat.ARGB8888 ); } offs += 64 * 2; } } break; case ImageFormat.L8: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat( Data[offs + pos], Data[offs + pos], Data[offs + pos], ColorFormat.ARGB8888 ); } offs += 64; } } break; case ImageFormat.A8: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat( Data[offs + pos], 255, 255, 255, ColorFormat.ARGB8888 ); } offs += 64; } } break; case ImageFormat.LA4: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat( (byte)((Data[offs + pos] & 0xF) * 0x11), (byte)((Data[offs + pos] >> 4) * 0x11), (byte)((Data[offs + pos] >> 4) * 0x11), (byte)((Data[offs + pos] >> 4) * 0x11), ColorFormat.ARGB8888 ); } offs += 64; } } break; case ImageFormat.L4: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); int shift = (pos & 1) * 4; res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat( (byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11), (byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11), (byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11), ColorFormat.ARGB8888 ); } offs += 64 / 2; } } break; case ImageFormat.A4: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 64; i++) { int x2 = i % 8; if (x + x2 >= physicalwidth) { continue; } int y2 = i / 8; if (y + y2 >= physicalheight) { continue; } int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4); int shift = (pos & 1) * 4; res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat( (byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11), 255, 255, 255, ColorFormat.ARGB8888 ); } offs += 64 / 2; } } break; case ImageFormat.ETC1: //Some reference: http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt case ImageFormat.ETC1A4: { for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int i = 0; i < 8; i += 4) { for (int j = 0; j < 8; j += 4) { ulong alpha = 0xFFFFFFFFFFFFFFFF; if (Format == ImageFormat.ETC1A4) { alpha = IOUtil.ReadU64LE(Data, offs); offs += 8; } ulong data = IOUtil.ReadU64LE(Data, offs); bool diffbit = ((data >> 33) & 1) == 1; bool flipbit = ((data >> 32) & 1) == 1; //0: |||, 1: |-| int r1, r2, g1, g2, b1, b2; if (diffbit) //'differential' mode { int r = (int)((data >> 59) & 0x1F); int g = (int)((data >> 51) & 0x1F); int b = (int)((data >> 43) & 0x1F); r1 = (r << 3) | ((r & 0x1C) >> 2); g1 = (g << 3) | ((g & 0x1C) >> 2); b1 = (b << 3) | ((b & 0x1C) >> 2); r += (int)((data >> 56) & 0x7) << 29 >> 29; g += (int)((data >> 48) & 0x7) << 29 >> 29; b += (int)((data >> 40) & 0x7) << 29 >> 29; r2 = (r << 3) | ((r & 0x1C) >> 2); g2 = (g << 3) | ((g & 0x1C) >> 2); b2 = (b << 3) | ((b & 0x1C) >> 2); } else //'individual' mode { r1 = (int)((data >> 60) & 0xF) * 0x11; g1 = (int)((data >> 52) & 0xF) * 0x11; b1 = (int)((data >> 44) & 0xF) * 0x11; r2 = (int)((data >> 56) & 0xF) * 0x11; g2 = (int)((data >> 48) & 0xF) * 0x11; b2 = (int)((data >> 40) & 0xF) * 0x11; } int Table1 = (int)((data >> 37) & 0x7); int Table2 = (int)((data >> 34) & 0x7); for (int y3 = 0; y3 < 4; y3++) { for (int x3 = 0; x3 < 4; x3++) { if (x + j + x3 >= physicalwidth) { continue; } if (y + i + y3 >= physicalheight) { continue; } int val = (int)((data >> (x3 * 4 + y3)) & 0x1); bool neg = ((data >> (x3 * 4 + y3 + 16)) & 0x1) == 1; uint c; if ((flipbit && y3 < 2) || (!flipbit && x3 < 2)) { int add = ETC1Modifiers[Table1, val] * (neg ? -1 : 1); c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r1 + add), (byte)ColorClamp(g1 + add), (byte)ColorClamp(b1 + add), ColorFormat.ARGB8888); } else { int add = ETC1Modifiers[Table2, val] * (neg ? -1 : 1); c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r2 + add), (byte)ColorClamp(g2 + add), (byte)ColorClamp(b2 + add), ColorFormat.ARGB8888); } res[(i + y3) * stride + x + j + x3] = c; } } offs += 8; } } } res += stride * 8; } } break; } bitm.UnlockBits(d); return(bitm); }
public static unsafe Bitmap ToBitmap(byte[] Data, int Offset, int Width, int Height, ImageFormat Format, TileMode TileMode, uint SwizzleMode, bool ExactSize = false) { if (Data == null || Data.Length < 1 || Offset < 0 || Offset >= Data.Length || Width < 1 || Height < 1) { return(null); } if (ExactSize && ((Width % 8) != 0 || (Height % 8) != 0)) { return(null); } int physicalwidth = Width; int physicalheight = Height; if (!ExactSize) { Width = 1 << (int)Math.Ceiling(Math.Log(Width, 2)); Height = 1 << (int)Math.Ceiling(Math.Log(Height, 2)); } Bitmap bitm = new Bitmap(Width, Height);//physicalwidth, physicalheight); BitmapData d = bitm.LockBits(new Rectangle(0, 0, bitm.Width, bitm.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); uint * res = (uint *)d.Scan0; int offs = Offset;//0; int stride = d.Stride / 4; switch (Format) { case ImageFormat.RGB565: for (int y = 0; y < Height; y++) { for (int x = 0; x < Width; x++) { //if (x >= physicalwidth) continue; if (y >= physicalheight) { continue; } res[y * stride + x] = GFXUtil.ConvertColorFormat( IOUtil.ReadU16LE(Data, offs), ColorFormat.RGB565, ColorFormat.ARGB8888); offs += 2; } } break; case ImageFormat.DXT5: for (int y2 = 0; y2 < Height; y2 += 4) { for (int x2 = 0; x2 < Width; x2 += 4) { ulong a_data = IOUtil.ReadU64LE(Data, offs); byte[] AlphaPalette = new byte[8]; AlphaPalette[0] = (byte)(a_data & 0xFF); AlphaPalette[1] = (byte)((a_data >> 8) & 0xFF); a_data >>= 16; if (AlphaPalette[0] > AlphaPalette[1]) { AlphaPalette[2] = (byte)((6 * AlphaPalette[0] + 1 * AlphaPalette[1]) / 7); AlphaPalette[3] = (byte)((5 * AlphaPalette[0] + 2 * AlphaPalette[1]) / 7); AlphaPalette[4] = (byte)((4 * AlphaPalette[0] + 3 * AlphaPalette[1]) / 7); AlphaPalette[5] = (byte)((3 * AlphaPalette[0] + 4 * AlphaPalette[1]) / 7); AlphaPalette[6] = (byte)((2 * AlphaPalette[0] + 5 * AlphaPalette[1]) / 7); AlphaPalette[7] = (byte)((1 * AlphaPalette[0] + 6 * AlphaPalette[1]) / 7); } else { AlphaPalette[2] = (byte)((4 * AlphaPalette[0] + 1 * AlphaPalette[1]) / 5); AlphaPalette[3] = (byte)((3 * AlphaPalette[0] + 2 * AlphaPalette[1]) / 5); AlphaPalette[4] = (byte)((2 * AlphaPalette[0] + 3 * AlphaPalette[1]) / 5); AlphaPalette[5] = (byte)((1 * AlphaPalette[0] + 4 * AlphaPalette[1]) / 5); AlphaPalette[6] = 0; AlphaPalette[7] = 255; } offs += 8; ushort color0 = IOUtil.ReadU16LE(Data, offs); ushort color1 = IOUtil.ReadU16LE(Data, offs + 2); uint data = IOUtil.ReadU32LE(Data, offs + 4); uint[] Palette = new uint[4]; Palette[0] = GFXUtil.ConvertColorFormat(color0, ColorFormat.RGB565, ColorFormat.ARGB8888); Palette[1] = GFXUtil.ConvertColorFormat(color1, ColorFormat.RGB565, ColorFormat.ARGB8888); Color a = System.Drawing.Color.FromArgb((int)Palette[0]); Color b = System.Drawing.Color.FromArgb((int)Palette[1]); if (color0 > color1) //1/3 and 2/3 { Palette[2] = GFXUtil.ToColorFormat((a.R * 2 + b.R * 1) / 3, (a.G * 2 + b.G * 1) / 3, (a.B * 2 + b.B * 1) / 3, ColorFormat.ARGB8888); Palette[3] = GFXUtil.ToColorFormat((a.R * 1 + b.R * 2) / 3, (a.G * 1 + b.G * 2) / 3, (a.B * 1 + b.B * 2) / 3, ColorFormat.ARGB8888); } else //1/2 and transparent { Palette[2] = GFXUtil.ToColorFormat((a.R + b.R) / 2, (a.G + b.G) / 2, (a.B + b.B) / 2, ColorFormat.ARGB8888); Palette[3] = 0; } int q = 30; int aq = 45; for (int y3 = 0; y3 < 4; y3++) { for (int x3 = 0; x3 < 4; x3++) { //if (x2 + x3 >= physicalwidth) continue; if (y2 + y3 >= physicalheight) { continue; } res[(y2 + y3) * stride + x2 + x3] = (Palette[(data >> q) & 3] & 0xFFFFFF) | ((uint)AlphaPalette[(a_data >> aq) & 7] << 24); q -= 2; aq -= 3; } } offs += 8; } // } //} } break; /*case ImageFormat.ETC1://Some reference: http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt * case ImageFormat.ETC1A4: * { * for (int y = 0; y < Height; y += 8) * { * for (int x = 0; x < Width; x += 8) * { * for (int i = 0; i < 8; i += 4) * { * for (int j = 0; j < 8; j += 4) * { * ulong alpha = 0xFFFFFFFFFFFFFFFF; * ulong data = IOUtil.ReadU64BE(Data, offs); * if (Format == ImageFormat.ETC1A4) * { * offs += 8; * alpha = IOUtil.ReadU64BE(Data, offs); * } * bool diffbit = ((data >> 33) & 1) == 1; * bool flipbit = ((data >> 32) & 1) == 1; //0: |||, 1: |-| * int r1, r2, g1, g2, b1, b2; * if (diffbit) //'differential' mode * { * int r = (int)((data >> 59) & 0x1F); * int g = (int)((data >> 51) & 0x1F); * int b = (int)((data >> 43) & 0x1F); * r1 = (r << 3) | ((r & 0x1C) >> 2); * g1 = (g << 3) | ((g & 0x1C) >> 2); * b1 = (b << 3) | ((b & 0x1C) >> 2); * r += (int)((data >> 56) & 0x7) << 29 >> 29; * g += (int)((data >> 48) & 0x7) << 29 >> 29; * b += (int)((data >> 40) & 0x7) << 29 >> 29; * r2 = (r << 3) | ((r & 0x1C) >> 2); * g2 = (g << 3) | ((g & 0x1C) >> 2); * b2 = (b << 3) | ((b & 0x1C) >> 2); * } * else //'individual' mode * { * r1 = (int)((data >> 60) & 0xF) * 0x11; * g1 = (int)((data >> 52) & 0xF) * 0x11; * b1 = (int)((data >> 44) & 0xF) * 0x11; * r2 = (int)((data >> 56) & 0xF) * 0x11; * g2 = (int)((data >> 48) & 0xF) * 0x11; * b2 = (int)((data >> 40) & 0xF) * 0x11; * } * int Table1 = (int)((data >> 37) & 0x7); * int Table2 = (int)((data >> 34) & 0x7); * for (int y3 = 0; y3 < 4; y3++) * { * for (int x3 = 0; x3 < 4; x3++) * { * if (x + j + x3 >= physicalwidth) continue; * if (y + i + y3 >= physicalheight) continue; * * int val = (int)((data >> (x3 * 4 + y3)) & 0x1); * bool neg = ((data >> (x3 * 4 + y3 + 16)) & 0x1) == 1; * uint c; * if ((flipbit && y3 < 2) || (!flipbit && x3 < 2)) * { * int add = ETC1Modifiers[Table1, val] * (neg ? -1 : 1); * c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r1 + add), (byte)ColorClamp(g1 + add), (byte)ColorClamp(b1 + add), ColorFormat.ARGB8888); * } * else * { * int add = ETC1Modifiers[Table2, val] * (neg ? -1 : 1); * c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r2 + add), (byte)ColorClamp(g2 + add), (byte)ColorClamp(b2 + add), ColorFormat.ARGB8888); * } * res[(i + y3) * stride + x + j + x3] = c; * } * } * offs += 8; * } * } * } * res += stride * 8; * } * } * break; * */ } Detile(res, stride, Width, Height, physicalwidth, physicalheight, TileMode); bitm.UnlockBits(d); return(bitm); }
public static unsafe Bitmap ToBitmap(byte[] TexData, int TexOffset, byte[] PalData, int PalOffset, int Width, int Height, ImageFormat Format, PaletteFormat PalFormat, bool ExactSize = false) { Bitmap bitm = new Bitmap(Width, Height); BitmapData d = bitm.LockBits(new Rectangle(0, 0, bitm.Width, bitm.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); uint * res = (uint *)d.Scan0; int offs = TexOffset; int stride = d.Stride / 4; switch (Format) { case ImageFormat.I4: { for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int y2 = 0; y2 < 8; y2++) { for (int x2 = 0; x2 < 8; x2 += 2) { byte I1 = (byte)((TexData[offs] >> 4) * 0x11); byte I2 = (byte)((TexData[offs] & 0xF) * 0x11); res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(I1, I1, I1, ColorFormat.ARGB8888); res[(y + y2) * stride + x + x2 + 1] = GFXUtil.ToColorFormat(I2, I2, I2, ColorFormat.ARGB8888); offs++; } } } } break; } case ImageFormat.I8: { for (int y = 0; y < Height; y += 4) { for (int x = 0; x < Width; x += 8) { for (int y2 = 0; y2 < 4; y2++) { for (int x2 = 0; x2 < 8; x2++) { byte I = TexData[offs]; res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(I, I, I, ColorFormat.ARGB8888); offs++; } } } } break; } case ImageFormat.IA4: { for (int y = 0; y < Height; y += 4) { for (int x = 0; x < Width; x += 8) { for (int y2 = 0; y2 < 4; y2++) { for (int x2 = 0; x2 < 8; x2++) { byte I = (byte)((TexData[offs] & 0xF) * 0x11); byte A = (byte)((TexData[offs] >> 4) * 0x11); res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(A, I, I, I, ColorFormat.ARGB8888); offs++; } } } } break; } case ImageFormat.IA8: { for (int y = 0; y < Height; y += 4) { for (int x = 0; x < Width; x += 4) { for (int y2 = 0; y2 < 4; y2++) { for (int x2 = 0; x2 < 4; x2++) { byte I = TexData[offs + 1]; byte A = TexData[offs]; res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(A, I, I, I, ColorFormat.ARGB8888); offs += 2; } } } } break; } case ImageFormat.RGB565: { for (int y = 0; y < Height; y += 4) { for (int x = 0; x < Width; x += 4) { for (int y2 = 0; y2 < 4; y2++) { for (int x2 = 0; x2 < 4; x2++) { res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat( IOUtil.ReadU16BE(TexData, offs), ColorFormat.RGB565, ColorFormat.ARGB8888); //GFXUtil.RGB565ToArgb(IOUtil.ReadU16BE(TexData, offs)); offs += 2; } } } } break; } case ImageFormat.RGB5A3: { for (int y = 0; y < Height; y += 4) { for (int x = 0; x < Width; x += 4) { for (int y2 = 0; y2 < 4; y2++) { for (int x2 = 0; x2 < 4; x2++) { ushort data = IOUtil.ReadU16BE(TexData, offs); if ((data & 0x8000) != 0) { res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat(data, ColorFormat.XRGB1555, ColorFormat.ARGB8888); } else { res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat(data, ColorFormat.ARGB3444, ColorFormat.ARGB8888); } offs += 2; } } } } break; } case ImageFormat.CI4: { for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int y2 = 0; y2 < 8; y2++) { for (int x2 = 0; x2 < 8; x2 += 2) { byte index1 = (byte)(TexData[offs] >> 4); byte index2 = (byte)(TexData[offs] & 0xF); switch (PalFormat) { case PaletteFormat.RGB5A3: { ushort data = IOUtil.ReadU16BE(PalData, PalOffset + index1 * 2); if ((data & 0x8000) != 0) { res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat(data, ColorFormat.XRGB1555, ColorFormat.ARGB8888); } else { res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat(data, ColorFormat.ARGB3444, ColorFormat.ARGB8888); } data = IOUtil.ReadU16BE(PalData, PalOffset + index2 * 2); if ((data & 0x8000) != 0) { res[(y + y2) * stride + x + x2 + 1] = GFXUtil.ConvertColorFormat(data, ColorFormat.XRGB1555, ColorFormat.ARGB8888); } else { res[(y + y2) * stride + x + x2 + 1] = GFXUtil.ConvertColorFormat(data, ColorFormat.ARGB3444, ColorFormat.ARGB8888); } break; } } offs++; } } } } break; } case ImageFormat.CI8: { for (int y = 0; y < Height; y += 4) { for (int x = 0; x < Width; x += 8) { for (int y2 = 0; y2 < 4; y2++) { for (int x2 = 0; x2 < 8; x2++) { byte index = TexData[offs]; switch (PalFormat) { case PaletteFormat.RGB5A3: { ushort data = IOUtil.ReadU16BE(PalData, PalOffset + index * 2); if ((data & 0x8000) != 0) { res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat(data, ColorFormat.XRGB1555, ColorFormat.ARGB8888); } else { res[(y + y2) * stride + x + x2] = GFXUtil.ConvertColorFormat(data, ColorFormat.ARGB3444, ColorFormat.ARGB8888); } break; } } offs++; } } } } break; } case ImageFormat.CMP: for (int y = 0; y < Height; y += 8) { for (int x = 0; x < Width; x += 8) { for (int y2 = 0; y2 < 8; y2 += 4) { for (int x2 = 0; x2 < 8; x2 += 4) { ushort color0 = IOUtil.ReadU16BE(TexData, offs); ushort color1 = IOUtil.ReadU16BE(TexData, offs + 2); uint data = IOUtil.ReadU32BE(TexData, offs + 4); uint[] Palette = new uint[4]; Palette[0] = GFXUtil.ConvertColorFormat(color0, ColorFormat.RGB565, ColorFormat.ARGB8888); Palette[1] = GFXUtil.ConvertColorFormat(color1, ColorFormat.RGB565, ColorFormat.ARGB8888); Color a = Color.FromArgb((int)Palette[0]); Color b = Color.FromArgb((int)Palette[1]); if (color0 > color1) //1/3 and 2/3 { Palette[2] = GFXUtil.ToColorFormat((a.R * 2 + b.R * 1) / 3, (a.G * 2 + b.G * 1) / 3, (a.B * 2 + b.B * 1) / 3, ColorFormat.ARGB8888); Palette[3] = GFXUtil.ToColorFormat((a.R * 1 + b.R * 2) / 3, (a.G * 1 + b.G * 2) / 3, (a.B * 1 + b.B * 2) / 3, ColorFormat.ARGB8888); } else //1/2 and transparent { Palette[2] = GFXUtil.ToColorFormat((a.R + b.R) / 2, (a.G + b.G) / 2, (a.B + b.B) / 2, ColorFormat.ARGB8888); Palette[3] = 0; } int q = 30; for (int y3 = 0; y3 < 4; y3++) { for (int x3 = 0; x3 < 4; x3++) { res[(y + y2 + y3) * stride + x + x2 + x3] = Palette[(data >> q) & 3]; q -= 2; } } offs += 8; } } } } break; } bitm.UnlockBits(d); return(bitm); }