public byte[] GetImageBytesForMip(Texture2DMipInfo info, MEGame game, bool useLowerMipsIfTFCMissing, string gamePathToUse = null, List <string> additionalTFCs = null) { byte[] imageBytes = null; try { imageBytes = GetTextureData(info, game, gamePathToUse, true, additionalTFCs); } catch (FileNotFoundException e) { if (useLowerMipsIfTFCMissing) { //External archive not found - using built in mips (will be hideous, but better than nothing) info = Mips.FirstOrDefault(x => x.storageType == StorageTypes.pccUnc); if (info != null) { imageBytes = GetTextureData(info, game, gamePathToUse); } } else { throw e; //rethrow } } if (imageBytes == null) { throw new Exception(GetLocalizedCouldNotFetchTextureDataMessage(info?.Export.InstancedFullPath, info?.Export.FileRef.FilePath)); } return(imageBytes); }
public static uint GetMipCRC(Texture2DMipInfo mip, string textureFormat, string gamePathToUse = null) { byte[] data = GetTextureData(mip, mip.Export.Game, gamePathToUse); if (data == null) { return(0); } if (textureFormat == "PF_NormalMap_HQ") { // only ME1 and ME2 return((uint)~ParallelCRC.Compute(data, 0, data.Length / 2)); } return((uint)~ParallelCRC.Compute(data)); }
public static List <Texture2DMipInfo> GetTexture2DMipInfos(ExportEntry exportEntry, string cacheName) { UTexture2D texBin = exportEntry.GetBinaryData <UTexture2D>(); var mips = new List <Texture2DMipInfo>(); for (int i = 0; i < texBin.Mips.Count; i++) { UTexture2D.Texture2DMipMap binMip = texBin.Mips[i]; Texture2DMipInfo mip = new Texture2DMipInfo { Export = exportEntry, index = i, storageType = binMip.StorageType, uncompressedSize = binMip.UncompressedSize, compressedSize = binMip.CompressedSize, externalOffset = binMip.DataOffset, Mip = binMip.Mip, TextureCacheName = cacheName, //If this is ME1, this will simply be ignored in the setter width = binMip.SizeX, height = binMip.SizeY }; if (mip.width == 4 && mips.Exists(m => m.width == mip.width)) { mip.width = mips.Last().width / 2; } if (mip.height == 4 && mips.Exists(m => m.height == mip.height)) { mip.height = mips.Last().height / 2; } if (mip.width == 0) { mip.width = 1; } if (mip.height == 0) { mip.height = 1; } mips.Add(mip); } return(mips); }
public static byte[] GetTextureData(Texture2DMipInfo mipToLoad, MEGame game, string gamePathToUse = null, bool decompress = true, List <string> additionalTFCs = null) { var imagebytes = new byte[decompress ? mipToLoad.uncompressedSize : mipToLoad.compressedSize]; //Debug.WriteLine("getting texture data for " + mipToLoad.Export.FullPath); if (mipToLoad.storageType == StorageTypes.pccUnc) { Buffer.BlockCopy(mipToLoad.Mip, 0, imagebytes, 0, mipToLoad.uncompressedSize); } else if (mipToLoad.storageType == StorageTypes.pccLZO || mipToLoad.storageType == StorageTypes.pccZlib) { if (decompress) { try { TextureCompression.DecompressTexture(imagebytes, new MemoryStream(mipToLoad.Mip), mipToLoad.storageType, mipToLoad.uncompressedSize, mipToLoad.compressedSize); } catch (Exception e) { throw new Exception(GetLocalizedTextureExceptionInternalMessage(e.Message, mipToLoad.storageType.ToString())); } } else { Buffer.BlockCopy(mipToLoad.Mip, 0, imagebytes, 0, mipToLoad.compressedSize); } } else if (mipToLoad.storageType == StorageTypes.extUnc || mipToLoad.storageType == StorageTypes.extLZO || mipToLoad.storageType == StorageTypes.extZlib || mipToLoad.storageType == StorageTypes.extLZMA) { string filename = null; List <string> loadedFiles = MELoadedFiles.GetAllGameFiles(gamePathToUse, game, false, true); if (mipToLoad.Export.Game == MEGame.ME1) { var fullPath = loadedFiles.FirstOrDefault(x => Path.GetFileName(x).Equals(mipToLoad.TextureCacheName, StringComparison.InvariantCultureIgnoreCase)); if (fullPath != null) { filename = fullPath; } else { throw new FileNotFoundException(GetLocalizedCouldNotFindME1TexturePackageMessage(mipToLoad.TextureCacheName)); } } else { string archive = mipToLoad.TextureCacheName + @".tfc"; var localDirectoryTFCPath = Path.Combine(Path.GetDirectoryName(mipToLoad.Export.FileRef.FilePath), archive); if (File.Exists(localDirectoryTFCPath)) { filename = localDirectoryTFCPath; } else if (additionalTFCs != null && additionalTFCs.Any(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase))) { filename = additionalTFCs.First(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase)); } else { var tfcs = loadedFiles.Where(x => x.EndsWith(@".tfc")).ToList(); var fullPath = loadedFiles.FirstOrDefault(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase)); if (fullPath != null) { filename = fullPath; } else { throw new FileNotFoundException(GetLocalizedCouldNotFindME2ME3TextureCacheMessage(archive)); } } } //exceptions above will prevent filename from being null here try { using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read)) { try { fs.Seek(mipToLoad.externalOffset, SeekOrigin.Begin); if (mipToLoad.storageType == StorageTypes.extLZO || mipToLoad.storageType == StorageTypes.extZlib) { if (decompress) { using (MemoryStream tmpStream = fs.ReadToMemoryStream(mipToLoad.compressedSize)) { try { TextureCompression.DecompressTexture(imagebytes, tmpStream, mipToLoad.storageType, mipToLoad.uncompressedSize, mipToLoad.compressedSize); } catch (Exception e) { throw new Exception(GetLocalizedTextureExceptionExternalMessage(e.Message, filename, mipToLoad.storageType.ToString(), mipToLoad.externalOffset.ToString())); } } } else { fs.Read(imagebytes, 0, mipToLoad.compressedSize); } } else { fs.Read(imagebytes, 0, mipToLoad.uncompressedSize); } } catch (Exception e) { throw new Exception(GetLocalizedTextureExceptionExternalMessage(e.Message, filename, mipToLoad.storageType.ToString(), mipToLoad.externalOffset.ToString())); } } } catch (Exception e) { throw new Exception(GetLocalizedTextureExceptionExternalMessage(e.Message, filename, mipToLoad.storageType.ToString(), mipToLoad.externalOffset.ToString())); } } return(imagebytes); }