private static Color[] ConvertXBGR1555(byte[] Data) { Color[] data = new Color[Data.Length / 2]; for (int i = 0; i < Data.Length; i += 2) { data[i / 2] = Color.FromArgb((int)GFXUtil.ConvertColorFormat(IOUtil.ReadU16LE(Data, i), ColorFormat.XBGR1555, ColorFormat.ARGB8888)); } return(data); }
public void MaterialColor1(uint cmd) { ushort spec = (ushort)(cmd & 0x7FFF); bool shine = (cmd & 0x8000) != 0; ushort emiss = (ushort)((cmd >> 16) & 0x7FFF); UsesSpecularReflectionTable = shine; SpecularColor = System.Drawing.Color.FromArgb((int)GFXUtil.ConvertColorFormat(spec, ColorFormat.XBGR1555, ColorFormat.ARGB8888)); EmissionColor = System.Drawing.Color.FromArgb((int)GFXUtil.ConvertColorFormat(emiss, ColorFormat.XBGR1555, ColorFormat.ARGB8888)); }
public void MaterialColor0(uint cmd) { ushort diff = (ushort)(cmd & 0x7FFF); bool vtx = (cmd & 0x8000) != 0; ushort amb = (ushort)((cmd >> 16) & 0x7FFF); DiffuseColor = System.Drawing.Color.FromArgb((int)GFXUtil.ConvertColorFormat(diff, ColorFormat.XBGR1555, ColorFormat.ARGB8888)); AmbientColor = System.Drawing.Color.FromArgb((int)GFXUtil.ConvertColorFormat(amb, ColorFormat.XBGR1555, ColorFormat.ARGB8888)); if (vtx) { Color(DiffuseColor); } }
public static ushort StringColorToXBGR(string c) { var rgbVals = new[] { byte.Parse(c.Split(' ')[0]) * 8, byte.Parse(c.Split(' ')[1]) * 8, byte.Parse(c.Split(' ')[2]) * 8 }; var color = (ushort)GFXUtil.ConvertColorFormat((uint)Color.FromArgb(rgbVals[0], rgbVals[1], rgbVals[2]).ToArgb(), ColorFormat.ARGB8888, ColorFormat.ABGR1555); return(color); }
public void Write(EndianBinaryWriter er) { er.Write(Signature, Encoding.ASCII, false); er.Write(Unknown1); er.Write(NrLaps); er.Write(Unknown2); er.Write((Byte)(FogEnabled ? 1 : 0)); er.Write(FogTableGenMode); er.Write(FogSlope); er.Write(UnknownData1, 0, 8); er.WriteFx32(FogDensity); er.Write((UInt16)(GFXUtil.ConvertColorFormat((uint)FogColor.ToArgb(), ColorFormat.ARGB8888, ColorFormat.XBGR1555) | 0x8000)); er.Write(FogAlpha); er.Write((UInt16)GFXUtil.ConvertColorFormat((uint)KclColor1.ToArgb(), ColorFormat.ARGB8888, ColorFormat.XBGR1555)); er.Write((UInt16)GFXUtil.ConvertColorFormat((uint)KclColor2.ToArgb(), ColorFormat.ARGB8888, ColorFormat.XBGR1555)); er.Write((UInt16)GFXUtil.ConvertColorFormat((uint)KclColor3.ToArgb(), ColorFormat.ARGB8888, ColorFormat.XBGR1555)); er.Write((UInt16)GFXUtil.ConvertColorFormat((uint)KclColor4.ToArgb(), ColorFormat.ARGB8888, ColorFormat.XBGR1555)); er.WriteFx32(FrustumFar); er.Write(UnknownData2, 0, 4); }
private void MDL0MaterialEditor_Load(object sender, EventArgs e) { checkBox3.Checked = (Material.polyAttr & 1) != 0; checkBox4.Checked = (Material.polyAttr & 2) != 0; checkBox5.Checked = (Material.polyAttr & 4) != 0; checkBox6.Checked = (Material.polyAttr & 8) != 0; comboBox1.SelectedIndex = (int)((Material.polyAttr >> 4) & 0x3); comboBox2.SelectedIndex = (int)((Material.polyAttr >> 6) & 0x3); checkBox7.Checked = ((Material.polyAttr >> 11) & 0x1) == 1; checkBox8.Checked = ((Material.polyAttr >> 12) & 0x1) == 1; checkBox9.Checked = ((Material.polyAttr >> 13) & 0x1) == 1; comboBox3.SelectedIndex = (int)((Material.polyAttr >> 14) & 0x1); checkBox10.Checked = ((Material.polyAttr >> 15) & 0x1) == 1; trackBar1.Value = (int)((Material.polyAttr >> 16) & 31); trackBar2.Value = (int)((Material.polyAttr >> 24) & 63); checkBox1.Checked = (Material.diffAmb & 0x8000) != 0; button1.BackColor = Color.FromArgb((int)GFXUtil.ConvertColorFormat(Material.diffAmb & 0x7FFF, ColorFormat.XBGR1555, ColorFormat.ARGB8888)); //(int)GFXUtil.XBGR1555ToArgb((ushort)(Material.diffAmb & 0x7FFF))); button2.BackColor = Color.FromArgb((int)GFXUtil.ConvertColorFormat((Material.diffAmb >> 16) & 0x7FFF, ColorFormat.XBGR1555, ColorFormat.ARGB8888)); checkBox2.Checked = (Material.specEmi & 0x8000) != 0; button3.BackColor = Color.FromArgb((int)GFXUtil.ConvertColorFormat(Material.specEmi & 0x7FFF, ColorFormat.XBGR1555, ColorFormat.ARGB8888)); button4.BackColor = Color.FromArgb((int)GFXUtil.ConvertColorFormat((Material.specEmi >> 16) & 0x7FFF, ColorFormat.XBGR1555, ColorFormat.ARGB8888)); uint wrapS = (Material.texImageParam >> 16) & 1; if (wrapS != 0) { wrapS += (Material.texImageParam >> 18) & 1; } comboBox4.SelectedIndex = (int)wrapS; uint wrapT = (Material.texImageParam >> 17) & 1; if (wrapT != 0) { wrapT += (Material.texImageParam >> 19) & 1; } comboBox5.SelectedIndex = (int)wrapT; }
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 STAG(EndianBinaryReader er) { Signature = er.ReadString(Encoding.ASCII, 4); if (Signature != "STAG") { throw new SignatureNotCorrectException(Signature, "STAG", er.BaseStream.Position - 4); } Unknown1 = er.ReadUInt16(); NrLaps = er.ReadInt16(); Unknown2 = er.ReadByte(); FogEnabled = er.ReadByte() == 1; FogTableGenMode = er.ReadByte(); FogSlope = er.ReadByte(); UnknownData1 = er.ReadBytes(0x8); FogDensity = er.ReadFx32(); FogColor = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt16(), ColorFormat.XBGR1555, ColorFormat.ARGB8888)); FogAlpha = er.ReadUInt16(); KclColor1 = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt16(), ColorFormat.XBGR1555, ColorFormat.ARGB8888)); KclColor2 = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt16(), ColorFormat.XBGR1555, ColorFormat.ARGB8888)); KclColor3 = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt16(), ColorFormat.XBGR1555, ColorFormat.ARGB8888)); KclColor4 = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt16(), ColorFormat.XBGR1555, ColorFormat.ARGB8888)); FrustumFar = er.ReadFx32(); UnknownData2 = er.ReadBytes(0x4); }
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 byte[] FromBitmap(Bitmap Picture, ImageFormat Format, bool ExactSize = false) { if (ExactSize && ((Picture.Width % 8) != 0 || (Picture.Height % 8) != 0)) { return(null); } int physicalwidth = Picture.Width; int physicalheight = Picture.Height; int ConvWidth = Picture.Width; int ConvHeight = Picture.Height; if (!ExactSize) { ConvWidth = 1 << (int)Math.Ceiling(Math.Log(Picture.Width, 2)); ConvHeight = 1 << (int)Math.Ceiling(Math.Log(Picture.Height, 2)); } BitmapData d = Picture.LockBits(new Rectangle(0, 0, Picture.Width, Picture.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); uint * res = (uint *)d.Scan0; byte[] result = new byte[ConvWidth * ConvHeight * GetBpp(Format) / 8]; int offs = 0; switch (Format) { case ImageFormat.RGBA8: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); result[offs + pos * 4 + 0] = c.A; result[offs + pos * 4 + 1] = c.B; result[offs + pos * 4 + 2] = c.G; result[offs + pos * 4 + 3] = c.R; } offs += 64 * 4; } } break; case ImageFormat.RGB8: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); result[offs + pos * 3 + 0] = c.B; result[offs + pos * 3 + 1] = c.G; result[offs + pos * 3 + 2] = c.R; } offs += 64 * 3; } } break; case ImageFormat.RGBA5551: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvHeight; 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); IOUtil.WriteU16LE(result, offs + pos * 2, (ushort)GFXUtil.ConvertColorFormat(res[(y + y2) * d.Stride / 4 + x + x2], ColorFormat.ARGB8888, ColorFormat.RGBA5551)); } offs += 64 * 2; } } break; case ImageFormat.RGB565: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); IOUtil.WriteU16LE(result, offs + pos * 2, (ushort)GFXUtil.ConvertColorFormat(res[(y + y2) * d.Stride / 4 + x + x2], ColorFormat.ARGB8888, ColorFormat.RGB565)); //GFXUtil.ArgbToRGB565(res[(y + y2) * d.Stride / 4 + x + x2])); } offs += 64 * 2; } } break; case ImageFormat.RGBA4: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); IOUtil.WriteU16LE(result, offs + pos * 2, (ushort)GFXUtil.ConvertColorFormat(res[(y + y2) * d.Stride / 4 + x + x2], ColorFormat.ARGB8888, ColorFormat.RGBA4444)); } offs += 64 * 2; } } break; case ImageFormat.LA8: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); result[offs + pos * 2] = c.A; result[offs + pos * 2 + 1] = c.B; result[offs + pos * 2 + 1] = c.G; result[offs + pos * 2 + 1] = c.R; } offs += 64 * 2; } } break; //case ImageFormat.HILO8: // for (int y = 0; y < ConvHeight; y += 8) // { // for (int x = 0; x < ConvWidth; 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); // Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); // result[offs + pos * 2] = c.A; // result[offs + pos * 2 + 1] = c.B; // result[offs + pos * 2 + 1] = c.G; // result[offs + pos * 2 + 1] = c.R; // } // offs += 64 * 2; // } // } // break; //case ImageFormat.L8: // for (int y = 0; y < ConvHeight; y += 8) // { // for (int x = 0; x < ConvWidth; 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); // Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); // result[offs + pos] = c.B; // result[offs + pos] = c.G; // result[offs + pos] = c.R; // } // offs += 64; // } // } // break; //case ImageFormat.A8: // for (int y = 0; y < ConvHeight; y += 8) // { // for (int x = 0; x < ConvWidth; 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); // Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); // result[offs + pos] = c.A; // } // offs += 64; // } // } // break; //case ImageFormat.LA4: // for (int y = 0; y < ConvHeight; y += 8) // { // for (int x = 0; x < ConvWidth; 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); // Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); // } // offs += 64; // } // } // break; //case ImageFormat.L4: // for (int y = 0; y < ConvHeight; y += 8) // { // for (int x = 0; x < ConvWidth; 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); // Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); // } // offs += 64 / 2; // } // } // break; //case ImageFormat.A4: // for (int y = 0; y < ConvHeight; y += 8) // { // for (int x = 0; x < ConvWidth; 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); // Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); // } // offs += 64 / 2; // } // } // break; case ImageFormat.ETC1: case ImageFormat.ETC1A4: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; x += 8) { for (int i = 0; i < 8; i += 4) { for (int j = 0; j < 8; j += 4) { if (Format == ImageFormat.ETC1A4) { ulong alpha = 0; int iiii = 0; for (int xx = 0; xx < 4; xx++) { for (int yy = 0; yy < 4; yy++) { uint color; if (x + j + xx >= physicalwidth) { color = 0x00FFFFFF; } else if (y + i + yy >= physicalheight) { color = 0x00FFFFFF; } else { color = res[((y + i + yy) * (d.Stride / 4)) + x + j + xx]; } uint a = color >> 24; a >>= 4; alpha |= (ulong)a << (iiii * 4); iiii++; } } IOUtil.WriteU64LE(result, offs, alpha); offs += 8; } Color[] pixels = new Color[4 * 4]; for (int yy = 0; yy < 4; yy++) { for (int xx = 0; xx < 4; xx++) { if (x + j + xx >= physicalwidth) { pixels[yy * 4 + xx] = Color.Transparent; } else if (y + i + yy >= physicalheight) { pixels[yy * 4 + xx] = Color.Transparent; } else { pixels[yy * 4 + xx] = Color.FromArgb((int)res[((y + i + yy) * (d.Stride / 4)) + x + j + xx]); } } } IOUtil.WriteU64LE(result, offs, ETC1.GenETC1(pixels)); offs += 8; } } } } break; default: throw new NotImplementedException("This format is not implemented yet."); } return(result); }
public void Color(uint color) { Color(System.Drawing.Color.FromArgb((int)GFXUtil.ConvertColorFormat(color, ColorFormat.XBGR1555, ColorFormat.ARGB8888))); }
public static unsafe byte[] FromBitmap(Bitmap Picture, TextureFormat Format, bool ExactSize = false) { if (ExactSize && ((Picture.Width % 8) != 0 || (Picture.Height % 8) != 0)) { return(null); } int physicalwidth = Picture.Width; int physicalheight = Picture.Height; int ConvWidth = Picture.Width; int ConvHeight = Picture.Height; if (!ExactSize) { ConvWidth = 1 << (int)Math.Ceiling(Math.Log(Picture.Width, 2)); ConvHeight = 1 << (int)Math.Ceiling(Math.Log(Picture.Height, 2)); } BitmapData d = Picture.LockBits(new Rectangle(0, 0, Picture.Width, Picture.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); uint * res = (uint *)d.Scan0; byte[] result = new byte[ConvWidth * ConvHeight * GetBpp(Format) / 8]; int offs = 0; switch (Format) { case TextureFormat.Rgba8: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); if ((y + y2) * d.Stride / 4 + x + x2 > d.Height * d.Stride) { Console.WriteLine("{0} > {1} overflow", (y + y2) * d.Stride / 4 + x + x2, d.Height * d.Stride); Environment.Exit(1); } Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); // magic line. removing this causes the white boxes to go away, but every texture gets a black outline if (c == Color.FromArgb(0, 0, 0, 0)) { c = Color.FromArgb(0, 0xff, 0xff, 0xff); } result[offs + pos * 4 + 0] = c.A; result[offs + pos * 4 + 1] = c.B; result[offs + pos * 4 + 2] = c.G; result[offs + pos * 4 + 3] = c.R; } offs += 64 * 4; } } break; case TextureFormat.Rgb8: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); result[offs + pos * 3 + 0] = c.B; result[offs + pos * 3 + 1] = c.G; result[offs + pos * 3 + 2] = c.R; } offs += 64 * 3; } } break; case TextureFormat.Rgb565: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); IOUtil.WriteU16LE(result, offs + pos * 2, (ushort)GFXUtil.ConvertColorFormat(res[(y + y2) * d.Stride / 4 + x + x2], ColorFormat.ARGB8888, ColorFormat.RGB565)); //GFXUtil.ArgbToRGB565(res[(y + y2) * d.Stride / 4 + x + x2])); } offs += 64 * 2; } } break; case TextureFormat.Rgba4: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); IOUtil.WriteU16LE(result, offs + pos * 2, (ushort)GFXUtil.ConvertColorFormat(res[(y + y2) * d.Stride / 4 + x + x2], ColorFormat.ARGB8888, ColorFormat.RGBA4444)); } offs += 64 * 2; } } break; case TextureFormat.La8: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); result[offs + pos * 2 + 0] = c.A; result[offs + pos * 2 + 1] = c.R; } offs += 64 * 2; } } break; case TextureFormat.Hilo8: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); result[offs + pos * 2 + 0] = c.R; result[offs + pos * 2 + 1] = c.G; } offs += 64 * 2; } } break; case TextureFormat.L8: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); result[offs + pos * 1 + 0] = c.R; } offs += 64 * 1; } } break; case TextureFormat.A8: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; 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); Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]); result[offs + pos * 1 + 0] = c.A; } offs += 64 * 1; } } break; case TextureFormat.Etc1: case TextureFormat.Etc1A4: for (int y = 0; y < ConvHeight; y += 8) { for (int x = 0; x < ConvWidth; x += 8) { for (int i = 0; i < 8; i += 4) { for (int j = 0; j < 8; j += 4) { if (Format == TextureFormat.Etc1A4) { ulong alpha = 0; int iiii = 0; for (int xx = 0; xx < 4; xx++) { for (int yy = 0; yy < 4; yy++) { uint color; if (x + j + xx >= physicalwidth) { color = 0x00FFFFFF; } else if (y + i + yy >= physicalheight) { color = 0x00FFFFFF; } else { color = res[((y + i + yy) * (d.Stride / 4)) + x + j + xx]; } uint a = color >> 24; a >>= 4; alpha |= (ulong)a << (iiii * 4); iiii++; } } IOUtil.WriteU64LE(result, offs, alpha); offs += 8; } Color[] pixels = new Color[4 * 4]; for (int yy = 0; yy < 4; yy++) { for (int xx = 0; xx < 4; xx++) { if (x + j + xx >= physicalwidth) { pixels[yy * 4 + xx] = Color.Transparent; } else if (y + i + yy >= physicalheight) { pixels[yy * 4 + xx] = Color.Transparent; } else { pixels[yy * 4 + xx] = Color.FromArgb((int)res[((y + i + yy) * (d.Stride / 4)) + x + j + xx]); } } } IOUtil.WriteU64LE(result, offs, ETC1.GenETC1(pixels)); offs += 8; } } } } break; default: throw new NotImplementedException("This format is not implemented yet."); } return(result); }
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 List <DisplayListCommand> Decode(byte[] dl) { var m = new MemoryStream(dl); var er = new EndianBinaryReaderEx(m, Endianness.LittleEndian); var commandQueue = new Queue <G3dCommand>(); var decoded = new List <DisplayListCommand>(); while (m.Position < dl.Length) { commandQueue.Enqueue((G3dCommand)er.ReadByte()); commandQueue.Enqueue((G3dCommand)er.ReadByte()); commandQueue.Enqueue((G3dCommand)er.ReadByte()); commandQueue.Enqueue((G3dCommand)er.ReadByte()); //Decode the 4 enqueued commands for (var j = 0; j < 4; j++) { var cmd = commandQueue.Dequeue(); switch (cmd) { default: case G3dCommand.PushMatrix: case G3dCommand.End: decoded.Add(new DisplayListCommand { G3dCommand = cmd }); break; case G3dCommand.TexCoord: decoded.Add(new DisplayListCommand { G3dCommand = cmd, RealArgs = new[] { er.ReadFixedPoint(true, 11, 4), er.ReadFixedPoint(true, 11, 4) } }); break; case G3dCommand.VertexXY: case G3dCommand.VertexXZ: case G3dCommand.VertexYZ: decoded.Add(new DisplayListCommand { G3dCommand = cmd, RealArgs = er.ReadFx16s(2) }); break; case G3dCommand.Begin: case G3dCommand.RestoreMatrix: decoded.Add(new DisplayListCommand { G3dCommand = cmd, IntArgs = er.ReadUInt32s(1) }); break; case G3dCommand.VertexDiff: var vec2 = VecFx10.ToVector3(er.ReadUInt32()) / 8; decoded.Add(new DisplayListCommand { G3dCommand = cmd, RealArgs = new[] { vec2.X, vec2.Y, vec2.Z } }); break; case G3dCommand.VertexShort: var vec3 = VecFx10.ToVector3(er.ReadUInt32(), 3, 6); decoded.Add(new DisplayListCommand { G3dCommand = cmd, RealArgs = new[] { vec3.X, vec3.Y, vec3.Z } }); break; case G3dCommand.Normal: var vec = VecFx10.ToVector3(er.ReadUInt32()); decoded.Add(new DisplayListCommand { G3dCommand = cmd, RealArgs = new[] { vec.X, vec.Y, vec.Z } }); break; case G3dCommand.Color: var color = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt32(), ColorFormat.ABGR1555, ColorFormat.ARGB8888)); decoded.Add(new DisplayListCommand { G3dCommand = cmd, IntArgs = new uint[] { color.R, color.G, color.B } }); break; case G3dCommand.Vertex: decoded.Add(new DisplayListCommand { G3dCommand = cmd, RealArgs = er.ReadFx16s(3) }); er.ReadUInt16(); break; } } } m.Close(); return(decoded); }
public static byte[] Encode(IEnumerable <DisplayListCommand> commands) { var m = new MemoryStream(); var ew = new EndianBinaryWriterEx(m, Endianness.LittleEndian); int offset = 0; int packed = 0; var cmdList = commands.ToList(); var nops = (cmdList.Count % 4) == 0 ? 0 : 4 - (cmdList.Count % 4); //Add NOPs at the end for (int i = 0; i < nops; i++) { cmdList.Add(new DisplayListCommand(G3dCommand.Nop)); } var commandQueue = new Queue <DisplayListCommand>(); bool param0Flag = false; void Flush() { packed = 0; var count = commandQueue.Count; for (int i = 0; i < count; i++) { var cmd = commandQueue.Dequeue(); //m.Position = offset; switch (cmd.G3dCommand) { default: case G3dCommand.Identity: case G3dCommand.PushMatrix: case G3dCommand.End: case G3dCommand.Nop: break; case G3dCommand.TexCoord: ew.WriteFixedPoint(cmd.RealArgs[0], true, 11, 4); ew.WriteFixedPoint(cmd.RealArgs[1], true, 11, 4); offset += 4; break; case G3dCommand.VertexXY: case G3dCommand.VertexXZ: case G3dCommand.VertexYZ: ew.WriteFx16s(cmd.RealArgs); offset += 4; break; case G3dCommand.Begin: case G3dCommand.RestoreMatrix: ew.Write(cmd.IntArgs[0]); offset += 4; break; case G3dCommand.VertexDiff: var vec2 = VecFx10.FromVector3((cmd.RealArgs[0] * 8, cmd.RealArgs[1] * 8, cmd.RealArgs[2] * 8)); ew.Write(vec2); offset += 4; break; case G3dCommand.VertexShort: var vec3 = VecFx10.FromVector3((cmd.RealArgs[0], cmd.RealArgs[1], cmd.RealArgs[2]), 3, 6); ew.Write(vec3); offset += 4; break; case G3dCommand.Normal: var vec = VecFx10.FromVector3((cmd.RealArgs[0], cmd.RealArgs[1], cmd.RealArgs[2])); ew.Write(vec); offset += 4; break; case G3dCommand.Color: var color = GFXUtil.ConvertColorFormat( (uint)Color.FromArgb(0, (int)cmd.IntArgs[0], (int)cmd.IntArgs[1], (int)cmd.IntArgs[2]).ToArgb(), ColorFormat.ARGB8888, ColorFormat.ABGR1555); ew.Write(color); offset += 4; break; case G3dCommand.Vertex: ew.WriteFx16s(cmd.RealArgs); ew.Write((ushort)0); offset += 8; break; } } if (param0Flag) { ew.Write(0); offset += 4; param0Flag = false; } } foreach (var command in cmdList) { if (command.G3dCommand != G3dCommand.Nop) { param0Flag = packed > 0 && (command.G3dCommand == G3dCommand.Identity || command.G3dCommand == G3dCommand.PushMatrix || command.G3dCommand == G3dCommand.End); } //m.Position = offset; commandQueue.Enqueue(command); ew.Write((byte)command.G3dCommand); packed++; offset++; if (packed == 4) { Flush(); } } var dl = m.ToArray(); m.Close(); return(dl); }
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); }