private static Bitmap MakeBitmapPalettized(int width, int height, byte[] buffer, Palette palette)
        {
            var bitmap        = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
            var bitmapPalette = bitmap.Palette;

            for (int i = 0; i < palette.Colors.Length; i++)
            {
                var  abgr = palette.Colors[i];
                uint b    = (abgr & 0x00FF0000) >> 16;
                uint r    = (abgr & 0x000000FF) << 16;
                var  argb = (int)((abgr & 0xFF00FF00) | b | r);
                bitmapPalette.Entries[i] = Color.FromArgb(argb);
            }
            bitmap.Palette = bitmapPalette;
            var area = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            var data = bitmap.LockBits(area, ImageLockMode.WriteOnly, bitmap.PixelFormat);

            Marshal.Copy(buffer, 0, data.Scan0, width * height);
            bitmap.UnlockBits(data);
            return(bitmap);
        }
        private static byte[] ExportPalettized(Texture texture, Palette palette)
        {
            if (texture.BitsPerPixel != 4 && texture.BitsPerPixel != 8)
            {
                throw new NotSupportedException();
            }

            var data = new byte[texture.TotalWidth * texture.TotalHeight * 4];

            int x = 0;
            int y = 0;

            int blockLength = (int)(texture.BlockWidth * texture.BlockHeight * (texture.BitsPerPixel / 8.0f));

            for (int i = 0; i < texture.Data.Length; i += blockLength)
            {
                var block = new byte[blockLength];
                Array.Copy(texture.Data, i, block, 0, Math.Min(blockLength, texture.Data.Length - i));

                int rx = 0;
                int ry = 0;
                for (int j = 0; j < block.Length; j++)
                {
                    if (texture.BitsPerPixel == 8)
                    {
                        if (ry >= texture.BlockHeight)
                        {
                            throw new InvalidOperationException();
                        }

                        int o = ((y + ry) * texture.TotalWidth) + (x + rx);
                        data[o] = block[j];

                        rx++;
                        if (rx >= texture.BlockWidth)
                        {
                            rx = 0;
                            ry++;
                        }
                    }
                    else if (texture.BitsPerPixel == 4)
                    {
                        // a
                        {
                            if (ry >= texture.BlockHeight)
                            {
                                throw new InvalidOperationException();
                            }

                            int o = ((y + ry) * texture.TotalWidth) + (x + rx);

                            data[o] = (byte)((block[j] & 0x0F) >> 0);

                            rx++;
                            if (rx >= texture.BlockWidth)
                            {
                                rx = 0;
                                ry++;
                            }
                        }

                        // b
                        {
                            if (ry >= texture.BlockHeight)
                            {
                                throw new InvalidOperationException();
                            }

                            int o = ((y + ry) * texture.TotalWidth) + (x + rx);

                            data[o] = (byte)((block[j] & 0xF0) >> 4);

                            rx++;
                            if (rx >= texture.BlockWidth)
                            {
                                rx = 0;
                                ry++;
                            }
                        }
                    }
                }

                x += texture.BlockWidth;
                if (x >= texture.TotalWidth)
                {
                    x  = 0;
                    y += texture.BlockHeight;
                }
            }

            return(data);
        }