Пример #1
0
        private Bitmap ETCBytesToBitmap(byte[] etc, int width, int height)
        {
            var etcsize = ETC1.GetEncodedDataSize(width, height);
            var inBfr   = Java.Nio.ByteBuffer.AllocateDirect(etcsize + 16).Order(Java.Nio.ByteOrder.NativeOrder());
            var outBfr  = Java.Nio.ByteBuffer.AllocateDirect(width * height * 3).Order(Java.Nio.ByteOrder.NativeOrder());

            WriteETCHeader(inBfr, width, height);
            inBfr.Put(etc, 0, etcsize);
            inBfr.Position(0);
            ETC1.DecodeImage(inBfr, outBfr, width, height, 3, width * 3);
            outBfr.Position(0);
            byte[] outBytes = new byte[width * height * 3];
            outBfr.Get(outBytes);
            return(RGBBytesToBitmap(outBytes, width, height, false));
        }
Пример #2
0
        public static Bitmap GetBitmapETC(BXLIM bxlim, bool crop = true)
        {
            bool etc1a4 = bxlim.Footer.Format == XLIMEncoding.ETC1A4;

            byte[] data = bxlim.PixelData;
            ETC1.CheckETC1Lib();

            try
            {
                var    width  = Math.Max(NextLargestPow2(bxlim.Width), 16);
                var    height = Math.Max(NextLargestPow2(bxlim.Height), 16);
                Bitmap img    = new Bitmap(width, height);
                img = DecodeETC(bxlim, img, data, etc1a4);
                return(crop ? CropBMP(bxlim, img) : img);
            }
            catch { return(null); }
        }
Пример #3
0
        private static Bitmap DecodeETC(IXLIMHeader bclim, Bitmap img, byte[] textureData, bool etc1A4)
        {
            /* http://jul.rustedlogic.net/thread.php?id=17312
             * Much of this code is taken/modified from Tharsis. Thank you to Tharsis's creator, xdaniel.
             * https://github.com/xdanieldzd/Tharsis
             */

            /* Get compressed data & handle to it */

            //textureData = switchEndianness(textureData, 0x10);
            ushort[] input = new ushort[textureData.Length / sizeof(ushort)];
            Buffer.BlockCopy(textureData, 0, input, 0, textureData.Length);
            GCHandle pInput = GCHandle.Alloc(input, GCHandleType.Pinned);

            /* Marshal data around, invoke ETC1.dll for conversion, etc */
            uint size1 = 0;
            var  w     = (ushort)img.Width;
            var  h     = (ushort)img.Height;

            ETC1.ConvertETC1(IntPtr.Zero, ref size1, IntPtr.Zero, w, h, etc1A4); // true = etc1a4, false = etc1
            uint[]   output  = new uint[size1];
            GCHandle pOutput = GCHandle.Alloc(output, GCHandleType.Pinned);

            ETC1.ConvertETC1(pOutput.AddrOfPinnedObject(), ref size1, pInput.AddrOfPinnedObject(), w, h, etc1A4);
            pOutput.Free();
            pInput.Free();

            /* Unscramble if needed // could probably be done in ETC1Lib.dll, it's probably pretty ugly, but whatever... */
            /* Non-square code blocks could need some cleanup, verification, etc. as well... */
            uint[] finalized = new uint[output.Length];

            // Act if it's square because BCLIM swizzling is stupid
            Buffer.BlockCopy(output, 0, finalized, 0, finalized.Length);

            byte[] tmp = new byte[finalized.Length];
            Buffer.BlockCopy(finalized, 0, tmp, 0, tmp.Length);
            byte[] imgData = tmp;

            for (int i = 0; i < w; i++)
            {
                for (int j = 0; j < h; j++)
                {
                    int k = (j + (i * img.Height)) * 4;
                    img.SetPixel(i, j, Color.FromArgb(imgData[k + 3], imgData[k], imgData[k + 1], imgData[k + 2]));
                }
            }
            if (bclim is BFLIM)
            {
                return(img);
            }

            // Image is 13  instead of 12
            //          24             34
            img.RotateFlip(RotateFlipType.Rotate90FlipX);
            if (w > h)
            {
                // Image is now in appropriate order, but the shifting is messed up. Let's fix that.
                Bitmap img2 = new Bitmap(Math.Max(NextLargestPow2(bclim.Width), 16), Math.Max(NextLargestPow2(bclim.Height), 16));
                for (int y = 0; y < Math.Max(NextLargestPow2(bclim.Width), 16); y += 8)
                {
                    for (int x = 0; x < Math.Max(NextLargestPow2(bclim.Height), 16); x++)
                    {
                        for (int j = 0; j < 8; j++)
                        // Treat every 8 vertical pixels as 1 pixel for purposes of calculation, add to offset later.
                        {
                            int x1 = (x + (y / 8 * h)) % img2.Width;           // Reshift x
                            int y1 = (x + (y / 8 * h)) / img2.Width * 8;       // Reshift y
                            img2.SetPixel(x1, y1 + j, img.GetPixel(x, y + j)); // Reswizzle
                        }
                    }
                }
                return(img2);
            }

            if (h > w)
            {
                Bitmap img2 = new Bitmap(Math.Max(NextLargestPow2(bclim.Width), 16), Math.Max(NextLargestPow2(bclim.Height), 16));
                for (int y = 0; y < Math.Max(NextLargestPow2(bclim.Width), 16); y += 8)
                {
                    for (int x = 0; x < Math.Max(NextLargestPow2(bclim.Height), 16); x++)
                    {
                        for (int j = 0; j < 8; j++)
                        // Treat every 8 vertical pixels as 1 pixel for purposes of calculation, add to offset later.
                        {
                            int x1 = x % img2.Width;                           // Reshift x
                            int y1 = (x + (y / 8 * h)) / img2.Width * 8;       // Reshift y
                            img2.SetPixel(x1, y1 + j, img.GetPixel(x, y + j)); // Reswizzle
                        }
                    }
                }
                return(img2);
            }

            return(img);
        }
Пример #4
0
        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);
        }
Пример #5
0
        public Bitmap GetBitmap(int ArrayLevel = 0, int MipLevel = 0, int DepthLevel = 0)
        {
            uint width  = Math.Max(1, Width >> MipLevel);
            uint height = Math.Max(1, Height >> MipLevel);

            byte[] data        = GetImageData(ArrayLevel, MipLevel, DepthLevel);
            byte[] paletteData = GetPaletteData();
            if (Format == TEX_FORMAT.R8G8B8A8_UNORM)
            {
                return(BitmapExtension.GetBitmap(ConvertBgraToRgba(data), (int)width, (int)height));
            }

            try
            {
                if (data == null)
                {
                    throw new Exception("Data is null!");
                }

                if (PlatformSwizzle == PlatformSwizzle.Platform_3DS)
                {
                    var Image = BitmapExtension.GetBitmap(ConvertBgraToRgba(CTR_3DS.DecodeBlock(data, (int)width, (int)height, Format)),
                                                          (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                    Image.RotateFlip(RotateFlipType.RotateNoneFlipY); //It's upside down for some reason so flip it
                    return(Image);
                }

                if (PlatformSwizzle == PlatformSwizzle.Platform_Gamecube)
                {
                    return(BitmapExtension.GetBitmap(Decode_Gamecube.DecodeData(data, paletteData, width, height, Format, PaletteFormat),
                                                     (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb));
                }

                switch (Format)
                {
                case TEX_FORMAT.R4G4_UNORM:
                    return(BitmapExtension.GetBitmap(R4G4.Decompress(data, (int)width, (int)height, false),
                                                     (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb));

                case TEX_FORMAT.BC5_SNORM:
                    return(DDSCompressor.DecompressBC5(data, (int)width, (int)height, true));

                case TEX_FORMAT.ETC1_UNORM:
                    return(BitmapExtension.GetBitmap(ETC1.ETC1Decompress(data, (int)width, (int)height, false),
                                                     (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb));

                case TEX_FORMAT.ETC1_A4:
                    return(BitmapExtension.GetBitmap(ETC1.ETC1Decompress(data, (int)width, (int)height, true),
                                                     (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb));

                case TEX_FORMAT.R5G5B5A1_UNORM:
                case TEX_FORMAT.LA8:
                case TEX_FORMAT.L8:
                    return(BitmapExtension.GetBitmap(RGBAPixelDecoder.Decode(data, (int)width, (int)height, Format),
                                                     (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb));
                }

                if (Runtime.UseDirectXTexDecoder)
                {
                    return(BitmapExtension.GetBitmap(DecodeBlock(data, width, height, Format, new byte[0], Parameters),
                                                     (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb));
                }
                else
                {
                    return(DecodeNotDirectXTex(data, width, height, Format));
                }
            }
            catch (Exception ex)
            {
                /*       Forms.STErrorDialog.Show($"Texture failed to load!", "Texture [GetBitmap({MipLevel},{ArrayLevel})]", DebugInfo() + " \n" + ex);
                 *
                 *     try
                 *     {
                 *         return DecodeNotDirectXTex(data, width, height, Format);
                 *     }
                 *     catch
                 *     {
                 *         Forms.STErrorDialog.Show($"Texture failed to load!", "Texture [GetBitmap({MipLevel},{ArrayLevel})]", DebugInfo() + " \n" + ex);
                 *     }*/

                return(null);
            }
        }
Пример #6
0
        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);
        }