public void ConvertToDds(EUncookExtension type) { var testFile = Path.GetFullPath($"Resources/{GetTestFile()}.{type.ToString()}"); Directory.CreateDirectory(Path.GetFullPath("texc")); var bytes = File.ReadAllBytes(testFile); //var blob = new TexconvNative.Blob(); //var len = TexconvNative.ConvertToDds(bytes, ref blob, TexconvNative.ESaveFileTypes.TGA, DXGI_FORMAT.DXGI_FORMAT_UNKNOWN); //var outFile = Path.GetFullPath(Path.Combine("texc", "q204_columbarium_1080p_0.dds")); //File.WriteAllBytes(outFile, blob.GetBytes()); var ms = new MemoryStream(bytes); ms.Seek(0, SeekOrigin.Begin); var r1 = Texconv.ConvertToDds(ms, type, DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM); var outFile1 = Path.GetFullPath(Path.Combine("texc", $"{GetTestFile()}_1.{type}.dds")); File.WriteAllBytes(outFile1, r1); ms.Seek(0, SeekOrigin.Begin); var r3 = Texconv.ConvertToDds(ms, type, DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM); var outFile3 = Path.GetFullPath(Path.Combine("texc", $"{GetTestFile()}_3.{type}.dds")); File.WriteAllBytes(outFile3, r3); ms.Seek(0, SeekOrigin.Begin); var r7 = Texconv.ConvertToDds(ms, type, DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM); var outFile7 = Path.GetFullPath(Path.Combine("texc", $"{GetTestFile()}_7.{type}.dds")); File.WriteAllBytes(outFile7, r7); }
public void GetMetadataFromTGAFile() { var testFile = Path.GetFullPath($"Resources/{testFile1}.tga"); //var md = TexconvNative.GetMetadataFromTGAFile(testFile); //Assert.AreEqual(md, s_tga_md); //var bpp = TexconvNative.BitsPerPixel(md.format); //Assert.AreEqual((int)bpp, s_tgaBpp); var md = Texconv.GetMetadataFromTGAFile(testFile); Assert.AreEqual(md, new DDSMetadata(s_tga_md, s_tgaBpp, true)); }
public void ComputePitch() { var testFile = Path.GetFullPath($"Resources/{testFile1}.dds"); var md = Texconv.GetMetadataFromDDSFile(testFile); // slicepitch 1048576 var slicepitch = Texconv.ComputeSlicePitch((int)md.Width, (int)md.Height, md.Format); Assert.AreEqual(238800, slicepitch); //rowpitch var rowpitch = Texconv.ComputeRowPitch((int)md.Width, (int)md.Height, md.Format); Assert.AreEqual(3184, rowpitch); }
public void GetMetadataFromDDSMemory() { var testFile = Path.GetFullPath($"Resources/{testFile1}.dds"); var bytes = File.ReadAllBytes(testFile); //var md = TexconvNative.GetMetadataFromDDSMemory(bytes, bytes.Length); //Assert.AreEqual(md, s_dds_md); //var bpp = TexconvNative.BitsPerPixel(md.format); //Assert.AreEqual((int)bpp, s_ddsBpp); var md = Texconv.GetMetadataFromDDSMemory(bytes); Assert.AreEqual(md, new DDSMetadata(s_dds_md, s_ddsBpp, true)); }
public void ConvertFromDds(EUncookExtension type) { var testFile = Path.GetFullPath($"Resources/{GetTestFile()}.dds"); var bytes = File.ReadAllBytes(testFile); //foreach (var type in Enum.GetValues<EUncookExtension>()) { var outFile = Path.GetFullPath(Path.Combine("texc", $"{GetTestFile()}.{type.ToString()}")); //var blob = new TexconvNative.Blob(); //var len = TexconvNative.ConvertFromDds(bytes, ref blob, Texconv.ToSaveFormat(type)); using var ms = new MemoryStream(bytes); var buffer = Texconv.ConvertFromDds(ms, type); File.WriteAllBytes(outFile, buffer); } }
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 void Import(FileInfo txtimageList, FileInfo outFile) { // relative and absolute paths var paths = File.ReadAllLines(txtimageList.FullName); var baseDir = txtimageList.Directory; var files = paths.Select(x => Path.Combine(baseDir.FullName, x)); #region InitandVerify _mlmask = new MlMaskContainer(); var textures = new List <RawTexContainer>(); var white = new RawTexContainer { Pixels = new byte[16], Width = 4, Height = 4 }; Array.Fill <byte>(white.Pixels, 255); textures.Add(white); var lineIdx = 1; foreach (var f in files) { if (!File.Exists(f)) { throw new FileNotFoundException($"Line{{lineIdx}}: \"{f}\" Make sure the file path is valid and exists (paths are specified line by line in ascending layer order in masklist)"); } var ms = new MemoryStream(File.ReadAllBytes(f)); var s = Path.GetExtension(f).ToLower(); var euncook = Enum.Parse <EUncookExtension>(Path.GetExtension(f).ToLower().TrimStart('.')); if (euncook != EUncookExtension.dds) { ms = new MemoryStream(Texconv.ConvertToDds(ms, euncook, DXGI_FORMAT.DXGI_FORMAT_R8_UNORM)); } else { // why dds to dds?, to make sure format is r8_unorm ms = new MemoryStream(Texconv.ConvertToDds(new MemoryStream(Texconv.ConvertFromDds(ms, EUncookExtension.tga)), EUncookExtension.tga, DXGI_FORMAT.DXGI_FORMAT_R8_UNORM)); } ms.Seek(0, SeekOrigin.Begin); DDSUtils.TryReadDdsHeader(ms, out var header); if (header.dwWidth != header.dwHeight) { throw new Exception($"Texture {f}: width={header.dwWidth},height={header.dwHeight} must have an aspect ratio of 1:1"); } // One bitset check if (((header.dwWidth - 1) & header.dwHeight) != 0 || header.dwWidth == 0) { throw new Exception($"Texture {f}: width={header.dwWidth},height={header.dwHeight} must have dimensions in powers of 2"); } //if (header.dwMipMapCount > 1) // throw new Exception($"Texture {f}: Mipmaps={header.dwMipMapCount}, mimap count must be equal to 1"); //if ((ms.Length - headerLength) != (header.dwWidth * header.dwHeight)) // throw new Exception("Not R8_UNORM 8bpp image format or more than 1mipmaps or rowstride is not equal to width or its a dx10 dds(unsupported)"); var br = new BinaryReader(ms); ms.Seek(s_headerLength, SeekOrigin.Begin); var bytes = br.ReadBytes((int)(header.dwWidth * header.dwHeight)); var whiteCheck = true; for (var i = 0; i < bytes.Length; i++) { if (bytes[i] != 255) { whiteCheck = false; break; } } if (whiteCheck) { throw new Exception("No need to provide the 1st/any blank white mask layer, tool will generate 1st blank white layer automatically"); } var tex = new RawTexContainer { Width = header.dwWidth, Height = header.dwHeight, Pixels = bytes }; textures.Add(tex); lineIdx++; } _mlmask.Layers = textures.ToArray(); #endregion Create(); Write(outFile); }
public static bool ConvertMultilayerMaskToDdsStreams(Multilayer_Mask mask, out List <Stream> streams) { streams = new List <Stream>(); if (mask.RenderResourceBlob.RenderResourceBlobPC.GetValue() 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); } //atlasRaw = blob.AtlasData.Buffer.GetBytes(); //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(); } } var maskData = new byte[maskWidth * maskHeight]; 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 { throw; } if (WolvenTesting.IsTesting) { continue; } 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); ms.Seek(0, SeekOrigin.Begin); //var stream = new MemoryStream(DDSUtils.ConvertToDdsMemory(ms, EUncookExtension.tga, DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM, false, false)); ms = new MemoryStream( Texconv.ConvertToDds( new MemoryStream(Texconv.ConvertFromDds(ms, EUncookExtension.tga)), EUncookExtension.tga, DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM)); streams.Add(ms); } return(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); }