Пример #1
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);
            }
        }
Пример #2
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);
        }
Пример #3
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);
        }