예제 #1
0
        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);
        }
예제 #2
0
        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));
        }
예제 #3
0
        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);
        }
예제 #4
0
        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));
        }
예제 #5
0
        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);
            }
        }
예제 #6
0
        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));
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }
예제 #9
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);
        }