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));
        }
Beispiel #2
0
        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);
        }