Exemplo n.º 1
0
        /// <summary>
        /// Gets an image from a bitmap tag.
        /// </summary>
        /// <param name="Cache">The CacheFile containing the bitmap tag.</param>
        /// <param name="bitm">The bitmap tag.</param>
        /// <param name="Index">The index of the BitmapData chunk to use.</param>
        /// <param name="Alpha">Whether to include the alpha channel in the image.</param>
        /// <returns>The image from the bitmap tag as a Bitmap.</returns>
        public static Bitmap GetBitmapByTag(CacheBase Cache, bitmap bitm, int Index, PixelFormat PF)
        {
            try
            {
                var submap = bitm.Bitmaps[Index];

                byte[] raw;
                if (Cache.Version <= DefinitionSet.Halo2Vista)
                {
                    raw = Cache.GetRawFromID(submap.PixelsOffset, submap.RawSize);
                }
                else
                {
                    if (bitm.RawChunkBs.Count > 0)
                    {
                        int    rawID  = bitm.RawChunkBs[submap.InterleavedIndex].RawID;
                        byte[] buffer = Cache.GetRawFromID(rawID);
                        raw = new byte[submap.RawSize];
                        Array.Copy(buffer, submap.Index2 * submap.RawSize, raw, 0, submap.RawSize);
                    }
                    else
                    {
                        int rawID = bitm.RawChunkAs[Index].RawID;
                        raw = Cache.GetRawFromID(rawID, submap.RawSize);
                    }
                }

                int vHeight = submap.VirtualHeight;
                int vWidth  = submap.VirtualWidth;

                if (submap.Type == TextureType.CubeMap)
                {
                    return(DXTDecoder.DecodeCubeMap(raw, submap, PF, Cache.Version));
                }

                raw = DXTDecoder.DecodeBitmap(raw, submap, Cache.Version);

                Bitmap     bitmap2          = new Bitmap(submap.Width, submap.Height, PF);
                Rectangle  rect             = new Rectangle(0, 0, submap.Width, submap.Height);
                BitmapData bitmapdata       = bitmap2.LockBits(rect, ImageLockMode.WriteOnly, PF);
                byte[]     destinationArray = new byte[(submap.Width * submap.Height) * 4];

                for (int j = 0; j < submap.Height; j++)
                {
                    Array.Copy(raw, j * vWidth * 4, destinationArray, j * submap.Width * 4, submap.Width * 4);
                }

                Marshal.Copy(destinationArray, 0, bitmapdata.Scan0, destinationArray.Length);
                bitmap2.UnlockBits(bitmapdata);

                return(bitmap2);
            }
            catch
            {
                return(null);
            }
        }
Exemplo n.º 2
0
        public static Bitmap GetBitmapByTag(PakFile Pak, Texture pict, PixelFormat PF)
        {
            try
            {
                byte[] raw;
                Pak.Reader.SeekTo(pict.DataAddress);
                raw = Pak.Reader.ReadBytes(pict.RawSize);

                //change to BigEndian
                if (pict.isLittleEndian)
                {
                    int block = 2;
                    if (pict.Format == TextureFormat.A8R8G8B8 || pict.Format == TextureFormat.X8R8G8B8)
                    {
                        block = 4;
                    }

                    for (int i = 0; i < raw.Length; i += block)
                    {
                        Array.Reverse(raw, i, block);
                    }
                }

                if (pict.Type == TextureType.CubeMap)
                {
                    return(DXTDecoder.DecodeCubeMap(raw, pict, PF));
                }

                raw = DXTDecoder.DecodeBitmap(raw, pict);

                //PixelFormat PF = (Alpha) ? PixelFormat.Format32bppArgb : PixelFormat.Format32bppRgb;
                Bitmap     bitmap2          = new Bitmap(pict.Width, pict.Height, PF);
                Rectangle  rect             = new Rectangle(0, 0, pict.Width, pict.Height);
                BitmapData bitmapdata       = bitmap2.LockBits(rect, ImageLockMode.WriteOnly, PF);
                byte[]     destinationArray = new byte[(pict.Width * pict.Height) * 4];

                for (int j = 0; j < pict.Height; j++)
                {
                    Array.Copy(raw, j * pict.VirtualWidth * 4, destinationArray, j * pict.Width * 4, pict.Width * 4);
                }

                Marshal.Copy(destinationArray, 0, bitmapdata.Scan0, destinationArray.Length);
                bitmap2.UnlockBits(bitmapdata);

                return(bitmap2);
            }
            catch { return(null); }
        }
Exemplo n.º 3
0
        public static SKImage DecodeImage(byte[] sequence, int width, int height, int depth, EPixelFormat format)
        {
            byte[]      data;
            SKColorType colorType;

            switch (format)
            {
            case EPixelFormat.PF_DXT5:
                data      = DXTDecoder.DecodeDXT5(sequence, width, height, depth);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_DXT1:
                data      = DXTDecoder.DecodeDXT1(sequence, width, height, depth);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ASTC_8x8:
                var x = (int)TextureFormatHelper.GetBlockWidth(format);
                var y = (int)TextureFormatHelper.GetBlockHeight(format);
                var z = (int)TextureFormatHelper.GetBlockDepth(format);
                data      = ASTCDecoder.DecodeToRGBA8888(sequence, x, y, z, width, height, 1);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_B8G8R8A8:
                data      = sequence;
                colorType = SKColorType.Bgra8888;
                break;

            case EPixelFormat.PF_BC5:
                data      = BCDecoder.DecodeBC5(sequence, width, height);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_BC4:
                data      = BCDecoder.DecodeBC4(sequence, width, height);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_G8:
                data      = sequence;
                colorType = SKColorType.Gray8;
                break;

            case EPixelFormat.PF_FloatRGBA:
                data      = sequence;
                colorType = SKColorType.RgbaF16;
                break;

            case EPixelFormat.PF_BC7:
                data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_BC6H:
                data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: true,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC_FLOAT,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBX8); // Not sure whether that works, would actually be DETEX_PIXEL_FORMAT_FLOAT_RGBX32
                data      = Detex.DecodeBC6H(sequence, width, height);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_ETC1:
                data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC1,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC2_RGB:
                data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC2_RGBA:
                data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2_EAC,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            default:
                throw new NotImplementedException($"Cannot decode {format} format");
            }

            using var bitmap = new SKBitmap(new SKImageInfo(width, height, colorType, SKAlphaType.Unpremul));
            unsafe
            {
                fixed(byte *p = data)
                {
                    bitmap.SetPixels(new IntPtr(p));
                }
            }
            return(SKImage.FromBitmap(bitmap));
        }
Exemplo n.º 4
0
        public static void DecodeTexture(FTexture2DMipMap mip, EPixelFormat format, bool isNormalMap, out byte[] data, out SKColorType colorType)
        {
            switch (format)
            {
            case EPixelFormat.PF_DXT1:
                data      = DXTDecoder.DXT1(mip.Data.Data, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_DXT5:
                data      = DXTDecoder.DXT5(mip.Data.Data, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ASTC_4x4:
            case EPixelFormat.PF_ASTC_6x6:
            case EPixelFormat.PF_ASTC_8x8:
            case EPixelFormat.PF_ASTC_10x10:
            case EPixelFormat.PF_ASTC_12x12:
                data = ASTCDecoder.RGBA8888(
                    mip.Data.Data,
                    FormatHelper.GetBlockWidth(format),
                    FormatHelper.GetBlockHeight(format),
                    FormatHelper.GetBlockDepth(format),
                    mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;

                if (isNormalMap)
                {
                    // UE4 drops blue channel for normal maps before encoding, restore it
                    unsafe
                    {
                        var offset = 0;
                        fixed(byte *d = data)
                        {
                            for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
                            {
                                d[offset + 2] = BCDecoder.GetZNormal(d[offset], d[offset + 1]);
                                offset       += 4;
                            }
                        }
                    }
                }

                break;

            case EPixelFormat.PF_BC4:
                data      = BCDecoder.BC4(mip.Data.Data, mip.SizeX, mip.SizeY);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_BC5:
                data      = BCDecoder.BC5(mip.Data.Data, mip.SizeX, mip.SizeY);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_BC6H:
                // BC6H doesn't work no matter the pixel format, the closest we can get is either
                // Rgb565 DETEX_PIXEL_FORMAT_FLOAT_RGBX16 or Rgb565 DETEX_PIXEL_FORMAT_FLOAT_BGRX16

                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, true,
                                               DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC_FLOAT,
                                               DetexPixelFormat.DETEX_PIXEL_FORMAT_FLOAT_RGBX16);
                colorType = SKColorType.Rgb565;
                break;

            case EPixelFormat.PF_BC7:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC,
                                               DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC1:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC1,
                                               DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC2_RGB:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2,
                                               DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC2_RGBA:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2_EAC,
                                               DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_R16F:
            case EPixelFormat.PF_R16F_FILTER:
                unsafe
                {
                    fixed(byte *d = mip.Data.Data)
                    {
                        data = ConvertRawR16DataToRGB888X(mip.SizeX, mip.SizeY, d, mip.SizeX * 2);     // 2 BPP
                    }
                }

                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_B8G8R8A8:
                data      = mip.Data.Data;
                colorType = SKColorType.Bgra8888;
                break;

            case EPixelFormat.PF_G8:
                data      = mip.Data.Data;
                colorType = SKColorType.Gray8;
                break;

            case EPixelFormat.PF_FloatRGBA:
                unsafe
                {
                    fixed(byte *d = mip.Data.Data)
                    {
                        data = ConvertRawR16G16B16A16FDataToRGBA8888(mip.SizeX, mip.SizeY, d, mip.SizeX * 8, false);     // 8 BPP
                    }
                }

                colorType = SKColorType.Rgba8888;
                break;

            default: throw new NotImplementedException($"Unknown pixel format: {format}");
            }
        }
Exemplo n.º 5
0
            /// <summary>
            /// Sending texture to video card<para/>
            /// Отправка текстуры на видеокарту
            /// </summary>
            public void Send()
            {
                if (State != ReadyState.NotSent)
                {
                    return;
                }

                bool texEnabled = GL.IsEnabled(EnableCap.Texture2D);

                if (!texEnabled)
                {
                    GL.Enable(EnableCap.Texture2D);
                }

                // Searching in parent
                // Поиск в родителе
                TextureFile.Entry e = Parent.File.Textures[name.ToLower()];

                // Generating texture
                // Генерация текстуры
                gltex = GL.GenTexture();
                GL.BindTexture(TextureTarget.Texture2D, gltex);
                GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)All.Modulate);

                // Sending scans
                // Отправка сканов
                int mipLevel = 0;

                byte[] texData;
                bool   useCompression = false;
                PixelInternalFormat internalFormat = PixelInternalFormat.Four;
                PixelFormat         pixelFormat    = PixelFormat.Rgba;
                PixelType           pixelType      = PixelType.UnsignedByte;

                // Check for compression
                // Проверка на сжатие по DXT
                if (e.ScanCompression != TextureFile.Compression.Uncompressed)
                {
                    // Decoding if compression is not supported
                    // Раскодирование, если сжатие аппаратно не поддерживается
                    if (!Managers.TextureManager.CompressionSupported)
                    {
                        useCompression = false;
                    }
                    else
                    {
                        // Compression is supported, so we can send it directlty to GPU
                        // Сжатие аппаратно поддерживается, можно отсылать на видеокарту
                        useCompression = true;
                        internalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                        if (e.ScanCompression == TextureFile.Compression.DXT3)
                        {
                            internalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
                        }
                    }
                }
                else
                {
                    // Common texture, determine type by texture mode
                    // Обычная текстура, разбор типа по режиму
                    if ((e.Flags & (int)TextureFile.RasterFlags.Format1555) != 0)
                    {
                        pixelType = PixelType.UnsignedShort5551;
                    }
                    else if ((e.Flags & (int)TextureFile.RasterFlags.Format565) != 0)
                    {
                        pixelType = PixelType.UnsignedShort565;
                    }
                    else if ((e.Flags & (int)TextureFile.RasterFlags.Format4444) != 0)
                    {
                        pixelType = PixelType.UnsignedShort565;
                    }
                    else if ((e.Flags & (int)TextureFile.RasterFlags.FormatLum8) != 0)
                    {
                        pixelType      = PixelType.UnsignedByte;
                        internalFormat = PixelInternalFormat.Luminance8;
                        pixelFormat    = PixelFormat.Luminance;
                    }
                    else if ((e.Flags & (int)TextureFile.RasterFlags.Format888) != 0)
                    {
                        pixelType      = PixelType.UnsignedByte;
                        internalFormat = PixelInternalFormat.Three;
                        pixelFormat    = PixelFormat.Rgb;
                    }
                }

                // Sending scans
                // Отправка сканов
                foreach (TextureFile.Scan scan in e.Scans)
                {
                    // Decode scans if needed
                    // Раскодирование скана если требуется
                    if (e.ScanCompression != TextureFile.Compression.Uncompressed && !useCompression)
                    {
                        texData = DXTDecoder.Decode((int)scan.Size.X, (int)scan.Size.Y, scan.Data, (e.ScanCompression == TextureFile.Compression.DXT3) ? DXTDecoder.CompressionType.DXT3 : DXTDecoder.CompressionType.DXT1);
                    }
                    else
                    {
                        texData = scan.Data;
                    }

                    // Determine compression while sending
                    // Выборка сжатия при отправке
                    if (useCompression)
                    {
                        GL.CompressedTexImage2D(TextureTarget.Texture2D, mipLevel, internalFormat, (int)scan.Size.X, (int)scan.Size.Y, 0, texData.Length, texData);
                    }
                    else
                    {
                        GL.TexImage2D(TextureTarget.Texture2D, mipLevel, internalFormat, (int)scan.Size.X, (int)scan.Size.Y, 0, pixelFormat, pixelType, texData);
                    }
                    mipLevel++;
                }
                Mipmapped = e.Scans.Length > 1;
                if (!texEnabled)
                {
                    GL.Disable(EnableCap.Texture2D);
                }
                State = ReadyState.Complete;
            }
Exemplo n.º 6
0
        public override void Read(ArchiveReader reader)
        {
            // dont care
            if (reader.ReadByte() != 0)
            {
                throw new Exception("Expected 0 is not zero");
            }

            if (reader.ReadByte() != 0)
            {
                // Initialize prop
                base.Read(reader);

                if (Get("origin") is WzVector2D origin)
                {
                    CenterX = origin.X;
                    CenterY = origin.Y;
                }
            }
            else
            {
                base._objects = new Dictionary <string, object>();
            }

            Width = reader.ReadCompressedInt();
            if (Width >= 0x10000)
            {
                throw new Exception($"Invalid Width: {Width}");
            }

            Height = reader.ReadCompressedInt();
            if (Height >= 0x10000)
            {
                throw new Exception($"Invalid Height: {Height}");
            }

            PixFormat = (WzPixFormat)reader.ReadCompressedInt();

            if (!(
                    PixFormat == WzPixFormat.A4R4G4B4 ||
                    PixFormat == WzPixFormat.A8R8G8B8 ||
                    PixFormat == WzPixFormat.R5G6B5 ||
                    PixFormat == WzPixFormat.DXT3 ||
                    PixFormat == WzPixFormat.DXT5
                    ))
            {
                throw new Exception($"Invalid PixFormat: {PixFormat:D}");
            }

            MagLevel = reader.ReadCompressedInt();
            if (MagLevel < 0)
            {
                throw new Exception("MagLevel is < 0");
            }

            // Zeroes
            for (var i = 0; i < 4; i++)
            {
                if (reader.ReadCompressedInt() != 0)
                {
                    throw new Exception("Expected 0 is not zero");
                }
            }


            var dataSize = reader.ReadInt32();

            if (reader.ReadByte() != 0)
            {
                throw new Exception("Expected 0 is not zero");
            }

            Create(Width, Height, MagLevel, (WzPixFormat)0);

            using (var outputStream = new MemoryStream(ExpectedDataSize))
                using (var inputStream = new MemoryStream(dataSize))
                {
                    var isPlainZlibStream = reader.ReadByte() == 0x78;
                    reader.BaseStream.Position -= 1;

                    var blob = new byte[Math.Min(0x20000, dataSize)];

                    if (reader.HasCurrentCrypto && !isPlainZlibStream)
                    {
                        // Need to skip 1
                        for (var i = 1; i < dataSize;)
                        {
                            var blobSize = reader.ReadInt32();
                            i += 4;
                            Array.Resize(ref blob, blobSize);
                            reader.Read(blob, 0, blobSize);

                            reader.TryDecryptImage(blob);
                            inputStream.Write(blob, 0, blobSize);
                            i += blobSize;
                        }
                    }
                    else
                    {
                        for (var i = 0; i < dataSize;)
                        {
                            var blobSize = Math.Min(blob.Length, dataSize - i);
                            reader.Read(blob, 0, blobSize);
                            inputStream.Write(blob, 0, blobSize);
                            i += blobSize;
                        }
                    }


                    inputStream.Position = 2;
                    using (var deflate = new DeflateStream(inputStream, CompressionMode.Decompress))
                    {
                        deflate.CopyTo(outputStream);
                    }


                    var uncompressedSize = outputStream.Length;
                    outputStream.Position = 0;

                    Bitmap output = null;

                    byte[] arr;
                    switch (PixFormat)
                    {
                    case WzPixFormat.A4R4G4B4:
                        arr = ARGB16toARGB32(outputStream, uncompressedSize);
                        break;

                    case WzPixFormat.DXT5:
                    case WzPixFormat.DXT3:
                        arr = DXTDecoder.Decode(
                            TileWidth,
                            TileHeight,
                            outputStream.ToArray(),
                            PixFormat == WzPixFormat.DXT3 ?
                            DXTDecoder.CompressionType.DXT3 :
                            DXTDecoder.CompressionType.DXT5
                            );
                        break;

                    default:
                        arr = outputStream.ToArray();
                        break;
                    }


                    PixelFormat format;

                    switch (PixFormat)
                    {
                    case WzPixFormat.R5G6B5:
                        format = PixelFormat.Format16bppRgb565;
                        break;

                    case WzPixFormat.A4R4G4B4:
                    case WzPixFormat.A8R8G8B8:
                    default:
                        format = PixelFormat.Format32bppArgb;
                        break;
                    }

                    output = new Bitmap(TileWidth, TileHeight, format);
                    var rect    = new Rectangle(0, 0, output.Width, output.Height);
                    var bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat);

                    var arrRowLength = rect.Width * (Image.GetPixelFormatSize(output.PixelFormat) / 8);
                    var ptr          = bmpData.Scan0;
                    for (var i = 0; i < rect.Height; i++)
                    {
                        Marshal.Copy(arr, i * arrRowLength, ptr, arrRowLength);
                        ptr += bmpData.Stride;
                    }

                    output.UnlockBits(bmpData);

                    SetCanvas(0, 0, new WzRawCanvas
                    {
                        Bitmap   = output,
                        MagLevel = MagLevel,
                    });
                }
        }
Exemplo n.º 7
0
        public static void SaveImage(string Filename, PakFile Pak, Texture pict, BitmapFormat Format, bool Alpha)
        {
            byte[] raw;
            Pak.Reader.SeekTo(pict.DataAddress);
            raw = Pak.Reader.ReadBytes(pict.RawSize);

            //change to BigEndian
            if (pict.isLittleEndian)
            {
                int block = 2;
                if (pict.Format == TextureFormat.A8R8G8B8 || pict.Format == TextureFormat.X8R8G8B8)
                {
                    block = 4;
                }

                for (int i = 0; i < raw.Length; i += block)
                {
                    Array.Reverse(raw, i, block);
                }
            }


            if (Format == BitmapFormat.TIF || Format == BitmapFormat.PNG)
            {
                string      ext     = (Format == BitmapFormat.TIF) ? ".tif" : ".png";
                int         pLength = (Format == BitmapFormat.TIF) ? 4 : 4;
                ImageFormat IF      = (Format == BitmapFormat.TIF) ? ImageFormat.Tiff : ImageFormat.Png;
                PixelFormat PF      = (Alpha) ? PixelFormat.Format32bppArgb : PixelFormat.Format32bppRgb;

                if (!Filename.EndsWith(ext))
                {
                    Filename += ext;
                }

                if (pict.Type == TextureType.CubeMap)
                {
                    var img = DXTDecoder.DecodeCubeMap(raw, pict, PF);
                    if (!Directory.GetParent(Filename).Exists)
                    {
                        Directory.GetParent(Filename).Create();
                    }
                    img.Save(Filename, ImageFormat.Tiff);
                    return;
                }

                raw = DXTDecoder.DecodeBitmap(raw, pict);

                Bitmap     bitmap2          = new Bitmap(pict.Width, pict.Height, PF);
                Rectangle  rect             = new Rectangle(0, 0, pict.Width, pict.Height);
                BitmapData bitmapdata       = bitmap2.LockBits(rect, ImageLockMode.WriteOnly, PF);
                byte[]     destinationArray = new byte[(pict.Width * pict.Height) * pLength];

                for (int j = 0; j < pict.Height; j++)
                {
                    Array.Copy(raw, j * pict.VirtualWidth * pLength, destinationArray, j * pict.Width * pLength, pict.Width * pLength);
                }

                Marshal.Copy(destinationArray, 0, bitmapdata.Scan0, destinationArray.Length);
                bitmap2.UnlockBits(bitmapdata);

                if (!Directory.GetParent(Filename).Exists)
                {
                    Directory.GetParent(Filename).Create();
                }

                bitmap2.Save(Filename, IF);
            }
            else if (Format == BitmapFormat.DDS)
            {
                if (!Filename.EndsWith(".dds"))
                {
                    Filename += ".dds";
                }

                if (!Directory.GetParent(Filename).Exists)
                {
                    Directory.GetParent(Filename).Create();
                }

                var fs = new FileStream(Filename, FileMode.Create, FileAccess.Write);
                var bw = new BinaryWriter(fs);

                if (pict.Format != TextureFormat.A8R8G8B8)
                {
                    for (int i = 0; i < raw.Length; i += 2)
                    {
                        Array.Reverse(raw, i, 2);
                    }
                }
                else
                {
                    for (int i = 0; i < (raw.Length); i += 4)
                    {
                        Array.Reverse(raw, i, 4);
                    }
                }

                bw.Write(raw);

                bw.Close();
                bw.Dispose();
            }
            else if (Format == BitmapFormat.RAW)
            {
                if (!Filename.EndsWith(".bin"))
                {
                    Filename += ".bin";
                }

                if (!Directory.GetParent(Filename).Exists)
                {
                    Directory.GetParent(Filename).Create();
                }

                File.WriteAllBytes(Filename, raw);
            }
            else
            {
                throw new InvalidOperationException("Invalid BitmapFormat received.");
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Saves an image from a bitmap tag to disk.
        /// </summary>
        /// <param name="Filename">The full path and filename to save to.</param>
        /// <param name="Cache">The CacheFile containing the bitmap tag.</param>
        /// <param name="Tag">The bitmap tag.</param>
        /// <param name="Index">The index of the BitmapData chunk to use.</param>
        /// <param name="Format">The format to save the image in.</param>
        /// <param name="Alpha">Whether to include the alpha channel in the image. Only applies when saving in TIF format.</param>
        public static void SaveImage(string Filename, CacheBase Cache, bitmap bitm, int Index, BitmapFormat Format, bool Alpha)
        {
            var submap = bitm.Bitmaps[Index];

            byte[] raw;

            if (Cache.Version <= DefinitionSet.Halo2Vista)
            {
                raw = Cache.GetRawFromID(submap.PixelsOffset, submap.RawSize);
            }
            else
            {
                if (bitm.RawChunkBs.Count > 0)
                {
                    int    rawID  = bitm.RawChunkBs[submap.InterleavedIndex].RawID;
                    byte[] buffer = Cache.GetRawFromID(rawID);
                    raw = new byte[submap.RawSize];
                    Array.Copy(buffer, submap.Index2 * submap.RawSize, raw, 0, submap.RawSize);
                }
                else
                {
                    int rawID = bitm.RawChunkAs[Index].RawID;
                    raw = Cache.GetRawFromID(rawID, submap.RawSize);
                }
            }

            int vHeight = submap.VirtualHeight;
            int vWidth  = submap.VirtualWidth;

            if (Format == BitmapFormat.TIF || Format == BitmapFormat.PNG)
            {
                string      ext     = (Format == BitmapFormat.TIF) ? ".tif" : ".png";
                int         pLength = (Format == BitmapFormat.TIF) ? 4 : 4;
                ImageFormat IF      = (Format == BitmapFormat.TIF) ? ImageFormat.Tiff : ImageFormat.Png;

                if (!Filename.EndsWith(ext))
                {
                    Filename += ext;
                }

                if (submap.Type == TextureType.CubeMap)
                {
                    var img = DXTDecoder.DecodeCubeMap(raw, submap, Alpha ? PixelFormat.Format32bppArgb : PixelFormat.Format32bppRgb, Cache.Version);
                    if (!Directory.GetParent(Filename).Exists)
                    {
                        Directory.GetParent(Filename).Create();
                    }
                    img.Save(Filename, ImageFormat.Tiff);
                    return;
                }

                raw = DXTDecoder.DecodeBitmap(raw, submap, Cache.Version);

                PixelFormat PF = (Alpha) ? PixelFormat.Format32bppArgb : PixelFormat.Format32bppRgb;

                Bitmap     bitmap2          = new Bitmap(submap.Width, submap.Height, PF);
                Rectangle  rect             = new Rectangle(0, 0, submap.Width, submap.Height);
                BitmapData bitmapdata       = bitmap2.LockBits(rect, ImageLockMode.WriteOnly, PF);
                byte[]     destinationArray = new byte[(submap.Width * submap.Height) * pLength];

                for (int j = 0; j < submap.Height; j++)
                {
                    Array.Copy(raw, j * vWidth * pLength, destinationArray, j * submap.Width * pLength, submap.Width * pLength);
                }

                Marshal.Copy(destinationArray, 0, bitmapdata.Scan0, destinationArray.Length);
                bitmap2.UnlockBits(bitmapdata);

                if (!Directory.GetParent(Filename).Exists)
                {
                    Directory.GetParent(Filename).Create();
                }

                bitmap2.Save(Filename, IF);
            }
            else if (Format == BitmapFormat.DDS)
            {
                if (!Filename.EndsWith(".dds"))
                {
                    Filename += ".dds";
                }

                if (!Directory.GetParent(Filename).Exists)
                {
                    Directory.GetParent(Filename).Create();
                }

                var fs = new FileStream(Filename, FileMode.Create, FileAccess.Write);
                var bw = new BinaryWriter(fs);

                if (submap.Flags.Values[3])
                {
                    raw = DXTDecoder.ConvertToLinearTexture(raw, vWidth, vHeight, submap.Format);
                }

                if (submap.Format != TextureFormat.A8R8G8B8)
                {
                    for (int i = 0; i < raw.Length; i += 2)
                    {
                        Array.Reverse(raw, i, 2);
                    }
                }
                else
                {
                    for (int i = 0; i < (raw.Length); i += 4)
                    {
                        Array.Reverse(raw, i, 4);
                    }
                }

                new DDS(submap).Write(bw);
                bw.Write(raw);

                bw.Close();
                bw.Dispose();
            }
            else if (Format == BitmapFormat.RAW)
            {
                if (!Filename.EndsWith(".bin"))
                {
                    Filename += ".bin";
                }

                if (!Directory.GetParent(Filename).Exists)
                {
                    Directory.GetParent(Filename).Create();
                }

                File.WriteAllBytes(Filename, raw);
            }
            else
            {
                throw new InvalidOperationException("Invalid BitmapFormat received.");
            }
        }
Exemplo n.º 9
0
        public override void Read(BinaryReader reader)
        {
            // dont care
            Debug.Assert(reader.ReadByte() == 0); // just zero

            if (reader.ReadByte() != 0)
            {
                // Initialize prop
                base.Read(reader);
            }
            else
            {
                base._objects = new Dictionary <string, object>();
            }

            Width = reader.ReadCompressedInt();
            Debug.Assert(Width < 0x10000);
            Height = reader.ReadCompressedInt();
            Debug.Assert(Height < 0x10000);

            PixFormat = (WzPixFormat)reader.ReadCompressedInt();

            Debug.Assert(
                PixFormat == WzPixFormat.A4R4G4B4 ||
                PixFormat == WzPixFormat.A8R8G8B8 ||
                PixFormat == WzPixFormat.R5G6B5 ||
                PixFormat == WzPixFormat.DXT3 ||
                PixFormat == WzPixFormat.DXT5
                );

            MagLevel = reader.ReadCompressedInt();
            Debug.Assert(MagLevel >= 0);

            // Zeroes
            for (var i = 0; i < 4; i++)
            {
                Debug.Assert(reader.ReadCompressedInt() == 0);
            }


            var dataSize = reader.ReadInt32();

            Debug.Assert(reader.ReadByte() == 0); // just zero

            using (var outputStream = new MemoryStream(ExpectedDataSize))
                using (var inputStream = new MemoryStream(dataSize))
                {
                    var isPlainZlibStream = reader.ReadByte() == 0x78;
                    reader.BaseStream.Position -= 1;

                    var blob = new byte[Math.Min(0x2000, dataSize)];

                    if (WzEncryption.HasCurrentCrypto && !isPlainZlibStream)
                    {
                        // Need to skip 1
                        for (var i = 1; i < dataSize;)
                        {
                            var blobSize = reader.ReadInt32();
                            i += 4;
                            Array.Resize(ref blob, blobSize);
                            reader.Read(blob, 0, blobSize);

                            WzEncryption.TryDecryptImage(blob);
                            inputStream.Write(blob, 0, blobSize);
                            i += blobSize;
                        }
                    }
                    else
                    {
                        for (var i = 0; i < dataSize;)
                        {
                            var blobSize = Math.Min(blob.Length, dataSize - i);
                            reader.Read(blob, 0, blobSize);
                            inputStream.Write(blob, 0, blobSize);
                            i += blobSize;
                        }
                    }

                    inputStream.Position = 2;
                    using (var deflate = new DeflateStream(inputStream, CompressionMode.Decompress))
                    {
                        deflate.CopyTo(outputStream);
                    }


                    var uncompressedSize = outputStream.Length;
                    outputStream.Position = 0;

                    Bitmap output = null;

                    byte[] arr;
                    switch (PixFormat)
                    {
                    case WzPixFormat.A4R4G4B4:
                        arr = ARGB16toARGB32(outputStream, uncompressedSize);
                        break;

                    case WzPixFormat.DXT5:
                    case WzPixFormat.DXT3:
                        arr = DXTDecoder.Decode(
                            TileWidth,
                            TileHeight,
                            outputStream.ToArray(),
                            PixFormat == WzPixFormat.DXT3 ?
                            DXTDecoder.CompressionType.DXT3 :
                            DXTDecoder.CompressionType.DXT5
                            );
                        break;

                    default:
                        arr = outputStream.ToArray();
                        break;
                    }


                    PixelFormat format;

                    switch (PixFormat)
                    {
                    case WzPixFormat.R5G6B5:
                        format = PixelFormat.Format16bppRgb565;
                        break;

                    case WzPixFormat.A4R4G4B4:
                    case WzPixFormat.A8R8G8B8:
                    default:
                        format = PixelFormat.Format32bppArgb;
                        break;
                    }

                    output = new Bitmap(TileWidth, TileHeight, format);
                    var rect    = new Rectangle(0, 0, output.Width, output.Height);
                    var bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat);

                    // Apply MipMap stuff

                    var arrRowLength = rect.Width * Image.GetPixelFormatSize(output.PixelFormat) / 8;
                    var ptr          = bmpData.Scan0;
                    for (var i = 0; i < rect.Height; i++)
                    {
                        Marshal.Copy(arr, i * arrRowLength, ptr, arrRowLength);
                        ptr += bmpData.Stride;
                    }

                    output.UnlockBits(bmpData);

                    Tile = output;
                }
        }
Exemplo n.º 10
0
        private static void DecodeTexture(FTexture2DMipMap mip, EPixelFormat format, out byte[] data, out SKColorType colorType)
        {
            switch (format)
            {
            case EPixelFormat.PF_DXT1:
                data      = DXTDecoder.DXT1(mip.Data.Data, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_DXT5:
                data      = DXTDecoder.DXT5(mip.Data.Data, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ASTC_8x8:
                data = ASTCDecoder.RGBA8888(
                    mip.Data.Data,
                    FormatHelper.GetBlockWidth(format),
                    FormatHelper.GetBlockHeight(format),
                    FormatHelper.GetBlockDepth(format),
                    mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_BC4:
                data      = BCDecoder.BC4(mip.Data.Data, mip.SizeX, mip.SizeY);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_BC5:
                data      = BCDecoder.BC5(mip.Data.Data, mip.SizeX, mip.SizeY);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_BC6H:
                // BC6H doesn't work no matter the pixel format, the closest we can get is either
                // Rgb565 DETEX_PIXEL_FORMAT_FLOAT_RGBX16 or Rgb565 DETEX_PIXEL_FORMAT_FLOAT_BGRX16

                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, true,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC_FLOAT,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_FLOAT_RGBX16);
                colorType = SKColorType.Rgb565;
                break;

            case EPixelFormat.PF_BC7:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_ETC1:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC1,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC2_RGB:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC2_RGBA:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2_EAC,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_B8G8R8A8:
                data      = mip.Data.Data;
                colorType = SKColorType.Bgra8888;
                break;

            case EPixelFormat.PF_G8:
                data      = mip.Data.Data;
                colorType = SKColorType.Gray8;
                break;

            case EPixelFormat.PF_FloatRGBA:
                data      = mip.Data.Data;
                colorType = SKColorType.RgbaF16;
                break;

            default: throw new NotImplementedException($"Unknown pixel format: {format}");
            }
        }
Exemplo n.º 11
0
        public async Task LoadFromStream(Stream stream, bool lzma = false)
        {
            var br = new ExtendedBinaryReader(stream);

            // DTX Header

            iResType = br.ReadUInt32();

            iVersion = br.ReadInt32();

            width  = br.ReadUInt16();
            height = br.ReadUInt16();

            nMipmap  = br.ReadUInt16();
            nSection = br.ReadUInt16();

            flags     = br.ReadInt32();
            userFlags = br.ReadInt32();

            extra = br.ReadBytes(12);

            cmdStr = br.ReadBytes(128);

            if (iResType != 0 || iVersion != -5 || nMipmap == 0)
            {
                if (lzma)
                {
                    throw new Exception("Unsupported DTX Type");
                }
                else
                {
                    stream.Position = 0;

                    var lzmaStream = new LzmaDecodeStream(stream);
                    var ms         = new MemoryStream();

                    lzmaStream.CopyTo(ms);

                    await LoadFromStream(ms, true);

                    return;
                }
            }

            DXTDecoder decoder = null;

            if (storeType == 4)
            {
                decoder = new DXT1Decoder();
            }
            else if (storeType == 5)
            {
                decoder = new DXT3Decoder();
            }
            else if (storeType == 6)
            {
                decoder = new DXT5Decoder();
            }

            if (decoder != null)
            {
                rawBuffer = await decoder.DecodeFrame(stream, width, height);
            }
            else
            {
                rawBuffer = br.ReadBytes(width * height * 4);
            }

            br.Close();
        }
Exemplo n.º 12
0
        public static SKImage DecodeImage(byte[] sequence, int width, int height, int depth, EPixelFormat format)
        {
            byte[]      data;
            SKColorType colorType;

            switch (format)
            {
            case EPixelFormat.PF_DXT5:
                data      = DXTDecoder.DecodeDXT5(sequence, width, height, depth);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_DXT1:
                data      = DXTDecoder.DecodeDXT1(sequence, width, height, depth);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ASTC_8x8:
                var x = (int)TextureFormatHelper.GetBlockWidth(format);
                var y = (int)TextureFormatHelper.GetBlockHeight(format);
                var z = (int)TextureFormatHelper.GetBlockDepth(format);
                data      = ASTCDecoder.DecodeToRGBA8888(sequence, x, y, z, width, height, 1);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_B8G8R8A8:
                data      = sequence;
                colorType = SKColorType.Bgra8888;
                break;

            case EPixelFormat.PF_BC5:
                data      = BCDecoder.DecodeBC5(sequence, width, height);
                colorType = SKColorType.Bgra8888;
                break;

            case EPixelFormat.PF_BC4:
                data      = BCDecoder.DecodeBC4(sequence, width, height);
                colorType = SKColorType.Bgra8888;
                break;

            case EPixelFormat.PF_G8:
                data      = sequence;
                colorType = SKColorType.Gray8;
                break;

            case EPixelFormat.PF_FloatRGBA:
                data      = sequence;
                colorType = SKColorType.RgbaF16;
                break;

            default:
                throw new NotImplementedException($"Cannot decode {format} format");
            }

            using var bitmap = new SKBitmap(new SKImageInfo(width, height, colorType, SKAlphaType.Unpremul));
            unsafe
            {
                fixed(byte *p = data)
                {
                    bitmap.SetPixels(new IntPtr(p));
                }
            }
            return(SKImage.FromBitmap(bitmap));
        }
Exemplo n.º 13
0
        public static void DecodeTextureNSW(FTexture2DMipMap mip, EPixelFormat format, bool isNormalMap, out byte[] data, out SKColorType colorType)
        {
            switch (format)
            {
            case EPixelFormat.PF_DXT5:
            {
                var uBlockSize  = mip.SizeX / 4;
                var vBlockSize  = mip.SizeY / 4;
                var totalBlocks = mip.Data.Data.Length / 16;

                if (uBlockSize * vBlockSize > totalBlocks)
                {
                    throw new ParserException($"Texture unable to be untiled: {format}");
                }

                var d = PlatformDeswizzlers.DesizzleNSW(mip.Data.Data, mip.SizeX, mip.SizeY, 4, 4, 16);
                data      = DXTDecoder.DXT5(d, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;
            }

            case EPixelFormat.PF_DXT1:
            {
                var uBlockSize  = mip.SizeX / 4;
                var vBlockSize  = mip.SizeY / 4;
                var totalBlocks = mip.Data.Data.Length / 8;

                if (uBlockSize * vBlockSize > totalBlocks)
                {
                    throw new ParserException($"Texture unable to be untiled: {format}");
                }

                var d = PlatformDeswizzlers.DesizzleNSW(mip.Data.Data, mip.SizeX, mip.SizeY, 4, 4, 8);
                data      = DXTDecoder.DXT1(d, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;
            }

            case EPixelFormat.PF_B8G8R8A8:
            {
                var uBlockSize  = mip.SizeX / 4;
                var vBlockSize  = mip.SizeY / 4;
                var totalBlocks = mip.Data.Data.Length / 4;

                if (uBlockSize * vBlockSize > totalBlocks)
                {
                    throw new ParserException($"Texture unable to be untiled: {format}");
                }

                data      = PlatformDeswizzlers.DesizzleNSW(mip.Data.Data, mip.SizeX, mip.SizeY, 1, 1, 4);
                colorType = SKColorType.Bgra8888;
                break;
            }

            default:
            {
                TextureDecoder.DecodeTexture(mip, format, isNormalMap, out data, out colorType);
                break;
            }
            }
        }
Exemplo n.º 14
0
        public override bool Execute(List <string> args)
        {
            if (args.Count != 1)
            {
                return(false);
            }

            //
            // Verify and load the blam shader
            //

            var shaderName = args[0];

            CacheBase.IndexItem item = null;

            Console.WriteLine("Verifying blam shader tag...");

            foreach (var tag in BlamCache.IndexItems)
            {
                if ((tag.ParentClass == "rm") && tag.Filename == shaderName)
                {
                    item = tag;
                    break;
                }
            }

            if (item == null)
            {
                Console.WriteLine("Blam shader tag does not exist: " + shaderName);
                return(false);
            }

            var renderMethod = DefinitionsManager.rmsh(BlamCache, item);

            var templateItem = BlamCache.IndexItems.Find(i =>
                                                         i.ID == renderMethod.Properties[0].TemplateTagID);

            var template = DefinitionsManager.rmt2(BlamCache, templateItem);

            //
            // Determine the blam shader's base bitmap
            //

            var bitmapIndex   = -1;
            var bitmapArgName = "";

            for (var i = 0; i < template.UsageBlocks.Count; i++)
            {
                var entry = template.UsageBlocks[i];

                if (entry.Usage.StartsWith("base_map") ||
                    entry.Usage.StartsWith("diffuse_map") ||
                    entry.Usage == "foam_texture")
                {
                    bitmapIndex   = i;
                    bitmapArgName = entry.Usage;
                    break;
                }
            }

            //
            // Load and decode the blam shader's base bitmap
            //

            var bitmItem = BlamCache.IndexItems.Find(i =>
                                                     i.ID == renderMethod.Properties[0].ShaderMaps[bitmapIndex].BitmapTagID);

            var bitm   = DefinitionsManager.bitm(BlamCache, bitmItem);
            var submap = bitm.Bitmaps[0];

            byte[] raw;

            if (BlamCache.Version <= DefinitionSet.Halo2Vista)
            {
                raw = BlamCache.GetRawFromID(submap.PixelsOffset, submap.RawSize);
            }
            else
            {
                if (bitm.RawChunkBs.Count > 0)
                {
                    int    rawID  = bitm.RawChunkBs[submap.InterleavedIndex].RawID;
                    byte[] buffer = BlamCache.GetRawFromID(rawID);
                    raw = new byte[submap.RawSize];
                    Array.Copy(buffer, submap.Index2 * submap.RawSize, raw, 0, submap.RawSize);
                }
                else
                {
                    int rawID = bitm.RawChunkAs[0].RawID;
                    raw = BlamCache.GetRawFromID(rawID, submap.RawSize);
                }
            }

            var vHeight = submap.VirtualHeight;
            var vWidth  = submap.VirtualWidth;

            var ms = new MemoryStream();
            var bw = new BinaryWriter(ms);

            if (submap.Flags.Values[3])
            {
                raw = DXTDecoder.ConvertToLinearTexture(raw, vWidth, vHeight, submap.Format);
            }

            if (submap.Format != BitmapFormat.A8R8G8B8)
            {
                for (int i = 0; i < raw.Length; i += 2)
                {
                    Array.Reverse(raw, i, 2);
                }
            }
            else
            {
                for (int i = 0; i < (raw.Length); i += 4)
                {
                    Array.Reverse(raw, i, 4);
                }
            }

            new DDS(submap).Write(bw);
            bw.Write(raw);

            raw = ms.ToArray();

            bw.Close();
            bw.Dispose();

            //
            // ElDorado Serialization
            //

            using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                //
                // Create the new eldorado bitmap
                //

                var resourceManager = new ResourceDataManager();
                resourceManager.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);

                var newBitm = Info.Cache.DuplicateTag(cacheStream, Info.Cache.Tags[0x101F]);

                var bitmap = new TagDefinitions.Bitmap
                {
                    Flags     = TagDefinitions.Bitmap.RuntimeFlags.UseResource,
                    Sequences = new List <TagDefinitions.Bitmap.Sequence>
                    {
                        new TagDefinitions.Bitmap.Sequence
                        {
                            Name             = "",
                            FirstBitmapIndex = 0,
                            BitmapCount      = 1
                        }
                    },
                    Images = new List <TagDefinitions.Bitmap.Image>
                    {
                        new TagDefinitions.Bitmap.Image
                        {
                            Signature = new Tag("bitm").Value,
                            Unknown28 = -1
                        }
                    },
                    Resources = new List <TagDefinitions.Bitmap.BitmapResource>
                    {
                        new TagDefinitions.Bitmap.BitmapResource()
                    }
                };

                using (var imageStream = new MemoryStream(raw))
                {
                    var injector = new BitmapDdsInjector(resourceManager);
                    imageStream.Seek(0, SeekOrigin.Begin);
                    injector.InjectDds(Info.Serializer, Info.Deserializer, bitmap, 0, imageStream);
                }

                var context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, newBitm);
                Info.Serializer.Serialize(context, bitmap);

                //
                // Create the new eldorado shader
                //

                var newRmsh = Info.Cache.DuplicateTag(cacheStream, Info.Cache.Tags[0x331A]);
                context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, newRmsh);
                var shader = Info.Deserializer.Deserialize <TagDefinitions.Shader>(context);

                shader.ShaderProperties[0].ShaderMaps[0].Bitmap = newBitm;

                Info.Serializer.Serialize(context, shader);

                Console.WriteLine("Done! New shader tag is 0x" + newRmsh.Index.ToString("X8"));
            }

            return(true);
        }