public void TestUnknownBlock() { var memStream = new MemoryStream(); memStream.WriteByte(127); memStream.WriteByte(0); memStream.WriteByte(0); memStream.WriteByte(0); memStream.Position = 0; var block = new BinaryReader(memStream).ReadBlock(); BlockDecompressor.Decompress(block); }
private bool ReadNextBlock() { if (remainingBytesOffset != remainingBytes.Length) // todo: replace with proper assert { throw new ApplicationException("Assertion failed: remainingBytesOffset != remainingBytes.Length"); } if (internalReader.BaseStream.Position == internalReader.BaseStream.Length) { return(false); // todo: more proper eof detection? } var block = internalReader.ReadBlock(); remainingBytes = BlockDecompressor.Decompress(block); remainingBytesOffset = 0; return(true); }
public static void SaveTexture(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong textureGUID) { bool convertTextures = true; string convertType = "dds"; bool lossless = false; if (flags is ExtractFlags extractFlags) { convertTextures = extractFlags.ConvertTextures && !extractFlags.Raw; convertType = extractFlags.ConvertTexturesType.ToLowerInvariant(); lossless = extractFlags.ConvertTexturesLossless; if (extractFlags.SkipTextures) { return; } } path += Path.DirectorySeparatorChar; FindLogic.Combo.TextureInfoNew textureInfo = info.Textures[textureGUID]; string filePath = Path.Combine(path, $"{textureInfo.GetNameIndex()}"); if (Program.Flags.Deduplicate) { if (ScratchDBInstance.HasRecord(textureGUID)) { return; } ScratchDBInstance[textureGUID] = new ScratchDB.ScratchPath($"{filePath}.{convertType}"); } CreateDirectoryFromFile(path); if (!convertTextures) { using (Stream textureStream = OpenFile(textureInfo.GUID)) { teTexture texture = new teTexture(textureStream, true); textureStream.Position = 0; WriteFile(textureStream, $"{filePath}.004"); if (!texture.PayloadRequired) { return; } using (Stream texturePayloadStream = OpenFile(texture.GetPayloadGUID(textureGUID))) WriteFile(texturePayloadStream, $"{filePath}.04D"); } } else { using (Stream textureStream = OpenFile(textureGUID)) { if (textureStream == null) { return; } teTexture texture = new teTexture(textureStream); if (texture.PayloadRequired) { texture.LoadPayload(OpenFile(texture.GetPayloadGUID(textureGUID))); } using (Stream convertedStream = texture.SaveToDDS()) { convertedStream.Position = 0; if (convertType == "dds" || convertedStream.Length == 0) { WriteFile(convertedStream, $"{filePath}.dds"); return; } uint fourCC = texture.Header.GetFormat().ToPixelFormat().FourCC; bool isBcffValid = TextureConfig.DXGI_BC4.Contains((int)texture.Header.Format) || TextureConfig.DXGI_BC5.Contains((int)texture.Header.Format) || fourCC == TextureConfig.FOURCC_ATI1 || fourCC == TextureConfig.FOURCC_ATI2; ImageFormat imageFormat = null; if (convertType == "tif") { imageFormat = ImageFormat.Tiff; } // if (convertType == "tga") imageFormat = Im.... oh // so there is no TGA image format. // guess the TGA users are stuck with the DirectXTex stuff for now. if (isBcffValid && imageFormat != null) { BlockDecompressor decompressor = new BlockDecompressor(convertedStream); decompressor.CreateImage(); decompressor.Image.Save($"{filePath}.{convertType}", imageFormat); return; } string losslessFlag = lossless ? "-wiclossless" : string.Empty; Process pProcess = new Process { StartInfo = { FileName = "Third Party\\texconv.exe", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardInput = true, RedirectStandardError = true, CreateNoWindow = true, Arguments = $"-- \"{Path.GetFileName(filePath)}.dds\" -y -wicmulti {losslessFlag} -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{path}" }, EnableRaisingEvents = true }; // erm, so if you add an end quote to this then it breaks. // but start one on it's own is fine (we need something for "Winged Victory") pProcess.Start(); convertedStream.Position = 0; convertedStream.CopyTo(pProcess.StandardInput.BaseStream); pProcess.StandardInput.BaseStream.Close(); // pProcess.WaitForExit(); // not using this is kinda dangerous but I don't care // when texconv writes with to the console -nologo is has done/failed conversion string line = pProcess.StandardOutput.ReadLine(); if (line?.Contains("FAILED") == true) { convertedStream.Position = 0; WriteFile(convertedStream, $"{filePath}.dds"); } } } } }
public override void Run(WorkerThread thread) { const string convertType = "tif"; Stream headerStream = OpenFile(HeaderGUID); Stream dataStream = null; if (DataGUID != 0) { dataStream = OpenFile(DataGUID); } string filePath = System.IO.Path.Combine(Path, $"{GUID.Index(HeaderGUID)}"); CreateDirectoryFromFile(filePath); TextureHeader header; Stream convertedStream; if (dataStream != null) { Texture textObj = new Texture(headerStream, dataStream); convertedStream = textObj.Save(); header = textObj.Header; headerStream.Dispose(); dataStream.Dispose(); } else { TextureLinear textObj = new TextureLinear(headerStream); convertedStream = textObj.Save(); header = textObj.Header; headerStream.Dispose(); } uint fourCC = header.Format().ToPixelFormat().fourCC; bool isBcffValid = Combo.TextureConfig.DXGI_BC4.Contains((int)header.format) || Combo.TextureConfig.DXGI_BC5.Contains((int)header.format) || fourCC == Combo.TextureConfig.FOURCC_ATI1 || fourCC == Combo.TextureConfig.FOURCC_ATI2; ImageFormat imageFormat = null; if (convertType == "tif") { imageFormat = ImageFormat.Tiff; } convertedStream.Position = 0; if (isBcffValid && imageFormat != null && convertedStream.Length != 0) { BlockDecompressor decompressor = new BlockDecompressor(convertedStream); decompressor.CreateImage(); decompressor.Image.Save($"{filePath}.{convertType}", imageFormat); return; } convertedStream.Position = 0; if (convertType == "tga" || convertType == "tif" || convertType == "dds") { // we need the dds for tif conversion WriteFile(convertedStream, $"{filePath}.dds"); } convertedStream.Close(); if (convertType != "tif" && convertType != "tga") { return; } Process pProcess = new Process { StartInfo = { FileName = "Third Party\\texconv.exe", UseShellExecute = false, RedirectStandardOutput = true, Arguments = $"\"{filePath}.dds\" -y -wicmulti -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{Path}" } }; // -wiclossless? // erm, so if you add an end quote to this then it breaks. // but start one on it's own is fine (we need something for "Winged Victory") pProcess.Start(); // pProcess.WaitForExit(); // not using this is kinda dangerous but I don't care // when texconv writes with to the console -nologo is has done/failed conversion // string line = pProcess.StandardOutput.ReadLine(); // if (line?.Contains($"{filePath}.dds FAILED") == false) { // fallback if convert fails File.Delete($"{filePath}.dds"); // } }
private static void ConvertTexture(string convertType, string filePath, string path, Stream headerStream, Stream dataStream) { CreateDirectoryFromFile(path); Stream convertedStream; TextureHeader header; if (dataStream != null) { Texture textObj = new Texture(headerStream, dataStream); convertedStream = textObj.Save(); header = textObj.Header; headerStream.Dispose(); dataStream.Dispose(); } else { TextureLinear textObj = new TextureLinear(headerStream); convertedStream = textObj.Save(); header = textObj.Header; headerStream.Dispose(); } uint fourCC = header.Format().ToPixelFormat().fourCC; bool isBcffValid = TextureConfig.DXGI_BC4.Contains((int)header.format) || TextureConfig.DXGI_BC5.Contains((int)header.format) || fourCC == TextureConfig.FOURCC_ATI1 || fourCC == TextureConfig.FOURCC_ATI2; ImageFormat imageFormat = null; if (convertType == "tif") { imageFormat = ImageFormat.Tiff; } // if (convertType == "tga") imageFormat = Im.... oh // so there is no TGA image format. // guess the TGA users are stuck with the DirectXTex stuff for now. if (convertedStream.Length == 0) { WriteFile(Stream.Null, $"{filePath}.{convertType}"); return; } convertedStream.Position = 0; if (isBcffValid && imageFormat != null) { BlockDecompressor decompressor = new BlockDecompressor(convertedStream); decompressor.CreateImage(); decompressor.Image.Save($"{filePath}.{convertType}", imageFormat); return; } convertedStream.Position = 0; if (convertType == "tga" || convertType == "tif" || convertType == "dds") { // we need the dds for tif conversion WriteFile(convertedStream, $"{filePath}.dds"); } convertedStream.Close(); if (convertType != "tif" && convertType != "tga") { return; } Process pProcess = new Process { StartInfo = { FileName = "Third Party\\texconv.exe", UseShellExecute = false, RedirectStandardOutput = true, Arguments = $"\"{filePath}.dds\" -y -wicmulti -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{path}" } }; // -wiclossless? // erm, so if you add an end quote to this then it breaks. // but start one on it's own is fine (we need something for "Winged Victory") pProcess.Start(); // pProcess.WaitForExit(); // not using this is kinda dangerous but I don't care // when texconv writes with to the console -nologo is has done/failed conversion string line = pProcess.StandardOutput.ReadLine(); if (line?.Contains($"{filePath}.dds FAILED") == false) { // fallback if convert fails File.Delete($"{filePath}.dds"); } }
public static void SaveTexture(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong textureGUID) { bool convertTextures = true; string convertType = "tif"; string multiSurfaceConvertType = "tif"; bool createMultiSurfaceSheet = false; bool lossless = false; int maxMips = 1; if (flags is ExtractFlags extractFlags) { if (extractFlags.SkipTextures) { return; } createMultiSurfaceSheet = extractFlags.SheetMultiSurface; convertTextures = !extractFlags.RawTextures && !extractFlags.Raw; convertType = extractFlags.ConvertTexturesType.ToLowerInvariant(); lossless = extractFlags.ConvertTexturesLossless; multiSurfaceConvertType = convertType; if (extractFlags.ForceDDSMultiSurface) { multiSurfaceConvertType = "dds"; } if (convertType == "dds" && extractFlags.SaveMips) { maxMips = 0xF; } } path += Path.DirectorySeparatorChar; FindLogic.Combo.TextureInfoNew textureInfo = info.Textures[textureGUID]; string filePath = Path.Combine(path, $"{textureInfo.GetNameIndex()}"); if (teResourceGUID.Type(textureGUID) != 0x4) { filePath += $".{teResourceGUID.Type(textureGUID):X3}"; } if (Program.Flags.Deduplicate) { if (ScratchDBInstance.HasRecord(textureGUID)) { return; } ScratchDBInstance[textureGUID] = new ScratchDB.ScratchPath($"{filePath}.{convertType}"); } CreateDirectoryFromFile(path); if (!convertTextures) { using (Stream textureStream = OpenFile(textureGUID)) { teTexture texture = new teTexture(textureStream, true); textureStream.Position = 0; WriteFile(textureStream, $"{filePath}.004"); if (!texture.PayloadRequired) { return; } for (int i = 0; i < texture.Payloads.Length; ++i) { using (Stream texturePayloadStream = OpenFile(texture.GetPayloadGUID(textureGUID, i))) WriteFile(texturePayloadStream, $"{filePath}_{i}.04D"); } } } else { using (Stream textureStream = OpenFile(textureGUID)) { if (textureStream == null) { return; } teTexture texture = new teTexture(textureStream); //if (texture.Header.Flags.HasFlag(teTexture.Flags.CUBEMAP)) return; // for diffing when they add/regen loads of cubemaps if (texture.PayloadRequired) { for (int i = 0; i < texture.Payloads.Length; ++i) { texture.LoadPayload(OpenFile(texture.GetPayloadGUID(textureGUID, i)), i); if (maxMips == 1) { break; } } } uint?width = null; uint?height = null; uint?surfaces = null; if (texture.Header.IsCubemap || texture.Header.IsArray || texture.HasMultipleSurfaces) { if (createMultiSurfaceSheet) { TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as a sheet because it has more than one surface"); height = (uint)(texture.Header.Height * texture.Header.Surfaces); surfaces = 1; texture.Header.Flags = 0; } else { TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as {multiSurfaceConvertType} because it has more than one surface"); convertType = multiSurfaceConvertType; } } using (Stream convertedStream = texture.SaveToDDS(maxMips == 1 ? 1 : texture.Header.MipCount, width, height, surfaces)) { convertedStream.Position = 0; if (convertType == "dds" || convertedStream.Length == 0) { WriteFile(convertedStream, $"{filePath}.dds"); return; } bool isBcffValid = teTexture.DXGI_BC4.Contains(texture.Header.Format) || teTexture.DXGI_BC5.Contains(texture.Header.Format) || teTexture.ATI2.Contains(texture.Header.GetTextureType()); ImageFormat imageFormat = null; if (convertType == "tif") { imageFormat = ImageFormat.Tiff; } if (convertType == "png") { imageFormat = ImageFormat.Png; } if (convertType == "jpg") { imageFormat = ImageFormat.Jpeg; } // if (convertType == "tga") imageFormat = Im.... oh // so there is no TGA image format. // guess the TGA users are stuck with the DirectXTex stuff for now. if (isBcffValid && imageFormat != null && !(texture.Header.IsCubemap || texture.Header.IsArray || texture.HasMultipleSurfaces)) { BlockDecompressor decompressor = new BlockDecompressor(convertedStream); decompressor.CreateImage(); decompressor.Image.Save($"{filePath}.{convertType}", imageFormat); return; } string losslessFlag = lossless ? "-wiclossless" : string.Empty; Process pProcess = new Process { StartInfo = { FileName = "Third Party\\texconv.exe", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardInput = true, RedirectStandardError = true, CreateNoWindow = true, Arguments = $"-- \"{Path.GetFileName(filePath)}.dds\" -y -wicmulti {losslessFlag} -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{(path.EndsWith(@"/") || path.EndsWith("\\") ? path.Substring(0, path.Length - 1) : path)}" }, EnableRaisingEvents = true }; pProcess.Start(); convertedStream.Position = 0; convertedStream.CopyTo(pProcess.StandardInput.BaseStream); pProcess.StandardInput.BaseStream.Flush(); pProcess.StandardInput.BaseStream.Close(); pProcess.WaitForExit(); // when texconv writes with to the console -nologo is has done/failed conversion string line = pProcess.StandardOutput.ReadToEnd(); if (line.Contains("FAILED")) { convertedStream.Position = 0; TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as dds because texconv failed."); WriteFile(convertedStream, $"{filePath}.dds"); } } } } }