public void ConvertAndSaveDdsImage() { var testFile = Path.GetFullPath($"Resources/{testFile1}.dds"); Directory.CreateDirectory(Path.GetFullPath("texc")); var bytes = File.ReadAllBytes(testFile); //var outFile = Path.GetFullPath(Path.Combine("texc", $"q204_columbarium_1080p_1.tga")); //var result = TexconvNative.ConvertAndSaveDdsImage(bytes, outFile, TexconvNative.ESaveFileTypes.TGA); var outFile2 = Path.GetFullPath(Path.Combine("texc", $"{GetTestFile()}.tga")); using var ms = new MemoryStream(bytes); ms.Seek(0, SeekOrigin.Begin); Assert.IsTrue(Texconv.ConvertFromDdsAndSave(ms, outFile2, TexconvNative.ESaveFileTypes.TGA)); // verify var metadata = new TexconvNative.TexMetadata() { width = 796, height = 300, depth = 1, arraySize = 1, mipLevels = 1, miscFlags = 0, miscFlags2 = 0, format = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM, dimension = TEX_DIMENSION.TEX_DIMENSION_TEXTURE2D }; //var md = Texconv.GetMetadataFromTGAFile(outFile); //Assert.AreEqual(md, new DDSMetadata(metadata, 32, true)); var md2 = Texconv.GetMetadataFromTGAFile(outFile2); Assert.AreEqual(md2, new DDSMetadata(metadata, 32, true)); }
public bool UncookMlmask(Stream cr2wStream, FileInfo outfile, MlmaskExportArgs args) { // read the cr2wfile var cr2w = _wolvenkitFileService.ReadRed4File(cr2wStream); if (cr2w == null || cr2w.RootChunk is not Multilayer_Mask mlmask || mlmask.RenderResourceBlob.RenderResourceBlobPC.Chunk is not rendRenderMultilayerMaskBlobPC blob) { return(false); } uint atlasWidth = blob.Header.AtlasWidth; uint atlasHeight = blob.Header.AtlasHeight; uint maskWidth = blob.Header.MaskWidth; uint maskHeight = blob.Header.MaskHeight; uint maskWidthLow = blob.Header.MaskWidthLow; uint maskHeightLow = blob.Header.MaskHeightLow; uint maskTileSize = blob.Header.MaskTileSize; uint maskCount = blob.Header.NumLayers; var atlasRaw = new byte[atlasWidth * atlasHeight]; //Decode compressed data into single channel uncompressed //Mlmask always BC4? if (!BlockCompression.DecodeBC(blob.AtlasData.Buffer.GetBytes(), ref atlasRaw, atlasWidth, atlasHeight, BlockCompression.BlockCompressionType.BC4)) { return(false); } //{ // var mFilename = filename + $"__.dds"; // var newpath = Path.Combine(path, mFilename); // using (var ddsStream = new FileStream($"{newpath}", FileMode.Create, FileAccess.Write)) // { // DDSUtils.GenerateAndWriteHeader(ddsStream, new DDSMetadata(atlasWidth, atlasHeight, 0, EFormat.R8_UNORM, 8, false, 0, false)); // // ddsStream.Write(atlasRaw); // } //} //Read tilesdata buffer into appropriate variable type var tileBuffer = blob.TilesData.Buffer; var tiles = new uint[tileBuffer.MemSize / 4]; using (var ms = new MemoryStream(tileBuffer.GetBytes())) using (var br = new BinaryReader(ms)) { ms.Seek(0, SeekOrigin.Begin); for (var i = 0; i < tiles.Length; i++) { tiles[i] = br.ReadUInt32(); } } // write texture to file var subdir = new DirectoryInfo(Path.GetFullPath(outfile.FullName)); if (!subdir.Exists) { Directory.CreateDirectory(subdir.FullName); } var maskData = new byte[maskWidth * maskHeight]; var masks = new List <string>(); for (var i = 0; i < maskCount; i++) { //Clear instead of allocate new is faster? //Mandatory cause decode does not always write to every pixel Array.Clear(maskData, 0, maskData.Length); try { Decode(ref maskData, maskWidth, maskHeight, maskWidthLow, maskHeightLow, atlasRaw, atlasWidth, atlasHeight, tiles, maskTileSize, i); } catch { return(false); } if (WolvenTesting.IsTesting) { continue; } // create dds stream using var ms = new MemoryStream(); DDSUtils.GenerateAndWriteHeader(ms, new DDSMetadata( maskWidth, maskHeight, 1, 1, 0, 0, 0, DXGI_FORMAT.DXGI_FORMAT_R8_UNORM, TEX_DIMENSION.TEX_DIMENSION_TEXTURE2D, 8, true)); ms.Write(maskData); var newpath = Path.Combine(subdir.FullName, $"{i}.dds"); if (args.UncookExtension == EMlmaskUncookExtension.dds) { using var ddsStream = new FileStream($"{newpath}", FileMode.Create, FileAccess.Write); ms.Seek(0, SeekOrigin.Begin); ms.CopyTo(ddsStream); masks.Add($"{subdir.Name}/{i}.dds"); } //else if (args.UncookExtension == EUncookExtension.tga) //{ // using (var ddsStream = new FileStream($"{newpath}.tga", FileMode.Create, FileAccess.Write)) // { // ms.Seek(0, SeekOrigin.Begin); // using (var ms2 = new MemoryStream(DDSUtils.ConvertFromDdsMemory(ms, EUncookExtension.tga))) // { // var br = new BinaryReader(ms2); // br.BaseStream.Seek(14, SeekOrigin.Begin); // ushort height = br.ReadUInt16(); // br.BaseStream.Seek(17, SeekOrigin.Begin); // byte descriptor = br.ReadByte(); // var bw = new BinaryWriter(ms2); // bw.BaseStream.Seek(10, SeekOrigin.Begin); // bw.Write(height); // bw.BaseStream.Seek(17, SeekOrigin.Begin); // bw.Write(descriptor ^ 0b00001000); // bw.Flush(); // ms2.Position = 0; // ms2.CopyTo(ddsStream); // } // } //} else { // convert ms.Seek(0, SeekOrigin.Begin); if (!Texconv.ConvertFromDdsAndSave(ms, newpath, args)) { return(false); } { masks.Add($"{subdir.Name}/{i}.png"); } } } // write metadata var masklist = Path.ChangeExtension(outfile.FullName, "masklist"); File.WriteAllLines(masklist, masks.ToArray()); return(true); }