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; } }
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); } }
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); } }
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); } } }