예제 #1
0
                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);
                }
예제 #2
0
        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);
        }