Ejemplo n.º 1
0
        private uint GetHeaderSize()
        {
            uint size = 0;

            // DDS.DDS_MAGIC
            size += 4;
            size += DDS_HEADER.GetSize();

            // If DXT10 add that size too
            switch ((DXGI_FORMAT)format)
            {
            case DXGI_FORMAT.BC1_UNORM_SRGB:
            case DXGI_FORMAT.BC3_UNORM_SRGB:
            case DXGI_FORMAT.BC4_UNORM:
            case DXGI_FORMAT.BC5_SNORM:
            case DXGI_FORMAT.BC7_UNORM:
            case DXGI_FORMAT.BC7_UNORM_SRGB:
                size += DDS_HEADER_DXT10.GetSize();
                break;
            }
            return(size);
        }
Ejemplo n.º 2
0
        private void WriteHeader(BinaryWriter bw)
        {
            var ddsHeader = new DDS_HEADER();

            ddsHeader.dwSize             = DDS_HEADER.GetSize();
            ddsHeader.dwHeaderFlags      = DDS.DDS_HEADER_FLAGS_TEXTURE | DDS.DDS_HEADER_FLAGS_LINEARSIZE | DDS.DDS_HEADER_FLAGS_MIPMAP;
            ddsHeader.dwHeight           = height;
            ddsHeader.dwWidth            = width;
            ddsHeader.dwMipMapCount      = numMips;
            ddsHeader.PixelFormat.dwSize = DDS_PIXELFORMAT.GetSize();
            ddsHeader.dwSurfaceFlags     = DDS.DDS_SURFACE_FLAGS_TEXTURE | DDS.DDS_SURFACE_FLAGS_MIPMAP;

            switch ((DXGI_FORMAT)format)
            {
            case DXGI_FORMAT.BC1_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '1');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height / 2);    // 4bpp
                break;

            case DXGI_FORMAT.BC2_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '3');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.BC3_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '5');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.BC5_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('A', 'T', 'I', '2');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.BC1_UNORM_SRGB:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', '1', '0');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height / 2);    // 4bpp
                break;

            case DXGI_FORMAT.BC3_UNORM_SRGB:
            case DXGI_FORMAT.BC4_UNORM:
            case DXGI_FORMAT.BC5_SNORM:
            case DXGI_FORMAT.BC7_UNORM:
            case DXGI_FORMAT.BC7_UNORM_SRGB:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', '1', '0');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.R8G8B8A8_UNORM:
            case DXGI_FORMAT.R8G8B8A8_UNORM_SRGB:
                ddsHeader.PixelFormat.dwFlags       = DDS.DDS_RGBA;
                ddsHeader.PixelFormat.dwRGBBitCount = 32;
                ddsHeader.PixelFormat.dwRBitMask    = 0x000000FF;
                ddsHeader.PixelFormat.dwGBitMask    = 0x0000FF00;
                ddsHeader.PixelFormat.dwBBitMask    = 0x00FF0000;
                ddsHeader.PixelFormat.dwABitMask    = 0xFF000000;
                ddsHeader.dwPitchOrLinearSize       = (uint)(width * height * 4); // 32bpp
                break;

            case DXGI_FORMAT.B8G8R8A8_UNORM:
            case DXGI_FORMAT.B8G8R8X8_UNORM:
                ddsHeader.PixelFormat.dwFlags       = DDS.DDS_RGBA;
                ddsHeader.PixelFormat.dwRGBBitCount = 32;
                ddsHeader.PixelFormat.dwRBitMask    = 0x00FF0000;
                ddsHeader.PixelFormat.dwGBitMask    = 0x0000FF00;
                ddsHeader.PixelFormat.dwBBitMask    = 0x000000FF;
                ddsHeader.PixelFormat.dwABitMask    = 0xFF000000;
                ddsHeader.dwPitchOrLinearSize       = (uint)(width * height * 4); // 32bpp
                break;

            case DXGI_FORMAT.R8_UNORM:
                ddsHeader.PixelFormat.dwFlags       = DDS.DDS_RGB;
                ddsHeader.PixelFormat.dwRGBBitCount = 8;
                ddsHeader.PixelFormat.dwRBitMask    = 0xFF;
                ddsHeader.dwPitchOrLinearSize       = (uint)(width * height); // 8bpp
                break;

            default:
                throw new UnsupportedDDSException("Unsupported DDS header format. File: " + this.FullPath);
            }

            bw.Write((uint)DDS.DDS_MAGIC);
            ddsHeader.Write(bw);

            switch ((DXGI_FORMAT)format)
            {
            case DXGI_FORMAT.BC1_UNORM_SRGB:
            case DXGI_FORMAT.BC3_UNORM_SRGB:
            case DXGI_FORMAT.BC4_UNORM:
            case DXGI_FORMAT.BC5_SNORM:
            case DXGI_FORMAT.BC7_UNORM:
            case DXGI_FORMAT.BC7_UNORM_SRGB:
                var dxt10 = new DDS_HEADER_DXT10()
                {
                    dxgiFormat        = format,
                    resourceDimension = (uint)DXT10_RESOURCE_DIMENSION.DIMENSION_TEXTURE2D,
                    miscFlag          = 0,
                    arraySize         = 1,
                    miscFlags2        = DDS.DDS_ALPHA_MODE_UNKNOWN
                };
                dxt10.Write(bw);
                break;
            }
        }
Ejemplo n.º 3
0
        private void WriteHeader(BinaryWriter bw)
        {
            var ddsHeader = new DDS_HEADER();

            ddsHeader.dwSize             = DDS_HEADER.GetSize();
            ddsHeader.dwHeaderFlags      = DDS.DDS_HEADER_FLAGS_TEXTURE | DDS.DDS_HEADER_FLAGS_LINEARSIZE | DDS.DDS_HEADER_FLAGS_MIPMAP;
            ddsHeader.dwHeight           = height;
            ddsHeader.dwWidth            = width;
            ddsHeader.dwMipMapCount      = numMips;
            ddsHeader.PixelFormat.dwSize = DDS_PIXELFORMAT.GetSize();
            ddsHeader.dwSurfaceFlags     = DDS.DDS_SURFACE_FLAGS_TEXTURE | DDS.DDS_SURFACE_FLAGS_MIPMAP;
            ddsHeader.dwCubemapFlags     = isCubemap == 1 ? (uint)(DDSCAPS2.CUBEMAP
                                                                   | DDSCAPS2.CUBEMAP_NEGATIVEX | DDSCAPS2.CUBEMAP_POSITIVEX
                                                                   | DDSCAPS2.CUBEMAP_NEGATIVEY | DDSCAPS2.CUBEMAP_POSITIVEY
                                                                   | DDSCAPS2.CUBEMAP_NEGATIVEZ | DDSCAPS2.CUBEMAP_POSITIVEZ
                                                                   | DDSCAPS2.CUBEMAP_ALLFACES) : 0u;

            switch ((DXGI_FORMAT)format)
            {
            case DXGI_FORMAT.BC1_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '1');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height / 2);    // 4bpp
                break;

            case DXGI_FORMAT.BC2_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '3');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.BC3_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '5');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.BC5_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('A', 'T', 'I', '2');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.BC1_UNORM_SRGB:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', '1', '0');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height / 2);    // 4bpp
                break;

            case DXGI_FORMAT.BC3_UNORM_SRGB:
            case DXGI_FORMAT.BC4_UNORM:
            case DXGI_FORMAT.BC5_SNORM:
            case DXGI_FORMAT.BC6H_UF16:
            case DXGI_FORMAT.BC7_UNORM:
            case DXGI_FORMAT.BC7_UNORM_SRGB:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', '1', '0');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.R8G8B8A8_UNORM:
            case DXGI_FORMAT.R8G8B8A8_UNORM_SRGB:
                ddsHeader.PixelFormat.dwFlags       = DDS.DDS_RGBA;
                ddsHeader.PixelFormat.dwRGBBitCount = 32;
                ddsHeader.PixelFormat.dwRBitMask    = 0x000000FF;
                ddsHeader.PixelFormat.dwGBitMask    = 0x0000FF00;
                ddsHeader.PixelFormat.dwBBitMask    = 0x00FF0000;
                ddsHeader.PixelFormat.dwABitMask    = 0xFF000000;
                ddsHeader.dwPitchOrLinearSize       = (uint)(width * height * 4); // 32bpp
                break;

            case DXGI_FORMAT.B8G8R8A8_UNORM:
            case DXGI_FORMAT.B8G8R8X8_UNORM:
                ddsHeader.PixelFormat.dwFlags       = DDS.DDS_RGBA;
                ddsHeader.PixelFormat.dwRGBBitCount = 32;
                ddsHeader.PixelFormat.dwRBitMask    = 0x00FF0000;
                ddsHeader.PixelFormat.dwGBitMask    = 0x0000FF00;
                ddsHeader.PixelFormat.dwBBitMask    = 0x000000FF;
                ddsHeader.PixelFormat.dwABitMask    = 0xFF000000;
                ddsHeader.dwPitchOrLinearSize       = (uint)(width * height * 4); // 32bpp
                break;

            case DXGI_FORMAT.R8_UNORM:
                ddsHeader.PixelFormat.dwFlags       = DDS.DDS_RGB;
                ddsHeader.PixelFormat.dwRGBBitCount = 8;
                ddsHeader.PixelFormat.dwRBitMask    = 0xFF;
                ddsHeader.dwPitchOrLinearSize       = (uint)(width * height); // 8bpp
                break;

            default:
                throw new UnsupportedDDSException("Unsupported DDS header format. File: " + this.FullPath);
            }

            // If tileMode is NOT TILE_MODE_DEFAULT assume Xbox format
            if (tileMode != TILE_MODE_DEFAULT)
            {
                switch ((DXGI_FORMAT)format)
                {
                case DXGI_FORMAT.BC1_UNORM:
                case DXGI_FORMAT.BC1_UNORM_SRGB:
                case DXGI_FORMAT.BC2_UNORM:
                case DXGI_FORMAT.BC3_UNORM:
                case DXGI_FORMAT.BC3_UNORM_SRGB:
                case DXGI_FORMAT.BC4_UNORM:
                case DXGI_FORMAT.BC5_SNORM:
                case DXGI_FORMAT.BC5_UNORM:
                case DXGI_FORMAT.BC7_UNORM:
                case DXGI_FORMAT.BC7_UNORM_SRGB:
                    ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('X', 'B', 'O', 'X');
                    break;
                }
            }

            bw.Write((uint)DDS.DDS_MAGIC);
            ddsHeader.Write(bw);

            switch ((DXGI_FORMAT)format)
            {
            case DXGI_FORMAT.BC1_UNORM_SRGB:
            case DXGI_FORMAT.BC3_UNORM_SRGB:
            case DXGI_FORMAT.BC4_UNORM:
            case DXGI_FORMAT.BC5_SNORM:
            case DXGI_FORMAT.BC6H_UF16:
            case DXGI_FORMAT.BC7_UNORM:
            case DXGI_FORMAT.BC7_UNORM_SRGB:
                new DDS_HEADER_DXT10()
                {
                    dxgiFormat        = format,
                    resourceDimension = (uint)DXT10_RESOURCE_DIMENSION.DIMENSION_TEXTURE2D,
                    miscFlag          = isCubemap == 1 ? DDS.DDS_RESOURCE_MISC_TEXTURECUBE : 0u,
                    arraySize         = 1,
                    miscFlags2        = DDS.DDS_ALPHA_MODE_UNKNOWN
                }.Write(bw);
                break;

            default:
                if (tileMode != TILE_MODE_DEFAULT)
                {
                    new DDS_HEADER_DXT10()
                    {
                        dxgiFormat        = format,
                        resourceDimension = (uint)DXT10_RESOURCE_DIMENSION.DIMENSION_TEXTURE2D,
                        miscFlag          = isCubemap == 1 ? DDS.DDS_RESOURCE_MISC_TEXTURECUBE : 0u,
                        arraySize         = 1,
                        miscFlags2        = DDS.DDS_ALPHA_MODE_UNKNOWN
                    }.Write(bw);
                }
                break;
            }

            // If tileMode is NOT TILE_MODE_DEFAULT assume Xbox format
            if (tileMode != TILE_MODE_DEFAULT)
            {
                bw.Write((uint)tileMode);
                bw.Write(XBOX_BASE_ALIGNMENT);
                dataSizePosition = bw.BaseStream.Position;
                bw.Write((uint)0);
                bw.Write(XBOX_XDK_VERSION);
            }
        }
Ejemplo n.º 4
0
        protected override void WriteDataToStream(Stream stream)
        {
            DDS_HEADER ddsHeader = new DDS_HEADER();

            ddsHeader.dwSize             = ddsHeader.GetSize();
            ddsHeader.dwHeaderFlags      = DDS.DDS_HEADER_FLAGS_TEXTURE | DDS.DDS_HEADER_FLAGS_LINEARSIZE | DDS.DDS_HEADER_FLAGS_MIPMAP;
            ddsHeader.dwHeight           = height;
            ddsHeader.dwWidth            = width;
            ddsHeader.dwMipMapCount      = numMips;
            ddsHeader.PixelFormat.dwSize = ddsHeader.PixelFormat.GetSize();
            ddsHeader.dwSurfaceFlags     = DDS.DDS_SURFACE_FLAGS_TEXTURE | DDS.DDS_SURFACE_FLAGS_MIPMAP;

            switch ((DXGI_FORMAT)format)
            {
            case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '1');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height / 2);    // 4bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '3');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '5');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM:
                ddsHeader.PixelFormat.dwFlags = DDS.DDS_FOURCC;
                if ((this.Archive as BA2).UseATIFourCC)
                {
                    ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('A', 'T', 'I', '2');     // this is more correct but the only thing I have found that supports it is the nvidia photoshop plugin
                }
                else
                {
                    ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '5');
                }
                ddsHeader.dwPitchOrLinearSize = (uint)(width * height);     // 8bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM:
                // totally wrong but not worth writing out the DX10 header
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('B', 'C', '7', '\0');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM:
                ddsHeader.PixelFormat.dwFlags       = DDS.DDS_RGBA;
                ddsHeader.PixelFormat.dwRGBBitCount = 32;
                ddsHeader.PixelFormat.dwRBitMask    = 0x00FF0000;
                ddsHeader.PixelFormat.dwGBitMask    = 0x0000FF00;
                ddsHeader.PixelFormat.dwBBitMask    = 0x000000FF;
                ddsHeader.PixelFormat.dwABitMask    = 0xFF000000;
                ddsHeader.dwPitchOrLinearSize       = (uint)(width * height * 4); // 32bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_R8_UNORM:
                ddsHeader.PixelFormat.dwFlags       = DDS.DDS_RGB;
                ddsHeader.PixelFormat.dwRGBBitCount = 8;
                ddsHeader.PixelFormat.dwRBitMask    = 0xFF;
                ddsHeader.dwPitchOrLinearSize       = (uint)(width * height); // 8bpp
                break;

            default:
                return;
            }

            var temp = new MemoryStream();

            using (var bw = new BinaryWriter(temp))
            {
                bw.Write((uint)DDS.DDS_MAGIC);
                ddsHeader.Write(bw);

                for (int i = 0; i < numChunks; i++)
                {
                    byte[] compressed   = new byte[this.Chunks[i].packSz];
                    byte[] full         = new byte[this.Chunks[i].fullSz];
                    bool   isCompressed = this.Chunks[i].packSz != 0;

                    this.BinaryReader.BaseStream.Seek((long)this.Chunks[i].offset, SeekOrigin.Begin);

                    if (!isCompressed)
                    {
                        this.BinaryReader.Read(full, 0, full.Length);
                    }
                    else
                    {
                        this.BinaryReader.Read(compressed, 0, compressed.Length);
                        // Uncompress
                        this.Archive.Inflater.Reset();
                        this.Archive.Inflater.SetInput(compressed);
                        this.Archive.Inflater.Inflate(full);
                    }

                    bw.Write(full);
                }

                byte[] bytes = temp.GetBuffer();
                stream.Write(bytes, 0, bytes.Length);
            }
        }
Ejemplo n.º 5
0
        public override void Extract(string destination, bool preserveFolder)
        {
            DDS_HEADER ddsHeader = new DDS_HEADER();

            ddsHeader.dwSize             = ddsHeader.GetSize();
            ddsHeader.dwHeaderFlags      = DDS.DDS_HEADER_FLAGS_TEXTURE | DDS.DDS_HEADER_FLAGS_LINEARSIZE | DDS.DDS_HEADER_FLAGS_MIPMAP;
            ddsHeader.dwHeight           = height;
            ddsHeader.dwWidth            = width;
            ddsHeader.dwMipMapCount      = numMips;
            ddsHeader.PixelFormat.dwSize = ddsHeader.PixelFormat.GetSize();
            ddsHeader.dwSurfaceFlags     = DDS.DDS_SURFACE_FLAGS_TEXTURE | DDS.DDS_SURFACE_FLAGS_MIPMAP;

            switch ((DXGI_FORMAT)format)
            {
            case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '1');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height / 2);    // 4bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '3');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM:
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '5');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM:
                ddsHeader.PixelFormat.dwFlags = DDS.DDS_FOURCC;
                if ((this.Archive as BA2).UseATIFourCC)
                {
                    ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('A', 'T', 'I', '2');     // this is more correct but the only thing I have found that supports it is the nvidia photoshop plugin
                }
                else
                {
                    ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '5');
                }
                ddsHeader.dwPitchOrLinearSize = (uint)(width * height);     // 8bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM:
                // totally wrong but not worth writing out the DX10 header
                ddsHeader.PixelFormat.dwFlags  = DDS.DDS_FOURCC;
                ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('B', 'C', '7', '\0');
                ddsHeader.dwPitchOrLinearSize  = (uint)(width * height);    // 8bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM:
                ddsHeader.PixelFormat.dwFlags       = DDS.DDS_RGBA;
                ddsHeader.PixelFormat.dwRGBBitCount = 32;
                ddsHeader.PixelFormat.dwRBitMask    = 0x00FF0000;
                ddsHeader.PixelFormat.dwGBitMask    = 0x0000FF00;
                ddsHeader.PixelFormat.dwBBitMask    = 0x000000FF;
                ddsHeader.PixelFormat.dwABitMask    = 0xFF000000;
                ddsHeader.dwPitchOrLinearSize       = (uint)(width * height * 4); // 32bpp
                break;

            case DXGI_FORMAT.DXGI_FORMAT_R8_UNORM:
                ddsHeader.PixelFormat.dwFlags       = DDS.DDS_RGB;
                ddsHeader.PixelFormat.dwRGBBitCount = 8;
                ddsHeader.PixelFormat.dwRBitMask    = 0xFF;
                ddsHeader.dwPitchOrLinearSize       = (uint)(width * height); // 8bpp
                break;

            default:
                return;
            }

            string path = preserveFolder ? this.FullPath : this.FileName;

            if (!string.IsNullOrEmpty(destination))
            {
                path = Path.Combine(destination, path);
            }

            if (!Directory.Exists(Path.GetDirectoryName(path)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(path));
            }

            using (var bw = new BinaryWriter(File.Create(path)))
            {
                bw.Write((uint)DDS.DDS_MAGIC);
                ddsHeader.Write(bw);

                for (int i = 0; i < numChunks; i++)
                {
                    byte[] compressed   = new byte[this.Chunks[i].packSz];
                    byte[] full         = new byte[this.Chunks[i].fullSz];
                    bool   isCompressed = this.Chunks[i].packSz != 0;

                    this.BinaryReader.BaseStream.Seek((long)this.Chunks[i].offset, SeekOrigin.Begin);

                    if (!isCompressed)
                    {
                        this.BinaryReader.Read(full, 0, full.Length);
                    }
                    else
                    {
                        this.BinaryReader.Read(compressed, 0, compressed.Length);
                        // Uncompress
                        this.Archive.Inflater.Reset();
                        this.Archive.Inflater.SetInput(compressed);
                        this.Archive.Inflater.Inflate(full);
                    }

                    bw.Write(full);
                }
            }
        }