private Stream buildDdsImage(int mipMapIndex) { MipMap mipMap = maps[mipMapIndex]; DdsHeader ddsHeader = new DdsHeader(new DdsSaveConfig(parsedImageFormat, 0, 0, false, false), mipMap.sizeX, mipMap.sizeY); MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); ddsHeader.Write(writer); writer.Write(mipMap.uncompressedData); writer.Flush(); writer.BaseStream.Position = 0; return(stream); }
public Stream GetObjectStream() { if (maps == null || !maps.Any()) { return(null); } MipMap mipMap = maps.Where(mm => mm.uncompressedData != null && mm.uncompressedData.Length > 0).OrderByDescending(mm => mm.sizeX > mm.sizeY ? mm.sizeX : mm.sizeY).FirstOrDefault(); if (mipMap == null) { return(null); } return(buildDdsImage(maps.IndexOf(mipMap))); }
private void ReadMipMapFromReader(BinaryReader reader, MipMap map, GpkPackage package) { map.signature = reader.ReadInt32(); //0x9e2a83c1 Debug.Assert(map.signature == Constants.DEFAULT_SIGNATURE); map.blocksize = reader.ReadInt32(); map.compressedSize = reader.ReadInt32(); map.uncompressedSize_chunkheader = reader.ReadInt32(); map.uncompressedData = new byte[map.uncompressedSize]; map.blockCount = (map.uncompressedSize + map.blocksize - 1) / map.blocksize; int blockOffset = 0; for (int j = 0; j < map.blockCount; ++j) { var block = new ChunkBlock(); block.compressedSize = reader.ReadInt32(); block.uncompressedDataSize = reader.ReadInt32(); map.blocks.Add(block); } foreach (ChunkBlock block in map.blocks) { block.compressedData = reader.ReadBytes(block.compressedSize); block.decompressTextureFlags(map.flags); Array.ConstrainedCopy(block.uncompressedData, 0, map.uncompressedData, blockOffset, block.uncompressedDataSize); blockOffset += block.uncompressedDataSize; //save memory block.uncompressedData = null; } //we clear the compressed chunkblocks, so only uncompressed data is present //blocks need to be rebuild when saving if (package.LowMemMode) { map.blocks.Clear(); } }
public void ReadData(GpkPackage package, GpkExport export) { BinaryReader reader = new BinaryReader(new MemoryStream(export.Data)); IProperty formatProp = export.Properties.Find(t => ((GpkBaseProperty)t).name == "Format"); String format = ((GpkByteProperty)formatProp).nameValue; SaveFormat(export); startUnk = reader.ReadBytes(12); int mipMapCountOffset = reader.ReadInt32(); int length = reader.ReadInt32(); if (length > 0) { tgaPath = Reader.ReadString(reader, length); } else if (length < 0) { inUnicode = true; tgaPath = Reader.ReadUnicodeString(reader, (length * -1) * 2); } else { tgaPath = ""; } int count = reader.ReadInt32(); for (int i = 0; i < count; i++) { MipMap map = new MipMap(); //chunk //info map.flags = reader.ReadInt32(); map.uncompressedSize = reader.ReadInt32(); map.compChunkSize = reader.ReadInt32(); map.compChunkOffset = reader.ReadInt32(); var temp = ((CompressionTypes)map.flags & NothingToDo); if (map.flags == 0) { map.uncompressedData = reader.ReadBytes(map.uncompressedSize); } else if (((CompressionTypes)map.flags & CompressionTypes.StoreInSeparatefile) != 0) { //data in texturecache file //compChunkOffset == offset //compChunkSize == size //TextureFileCacheName prop has name var txtProp = export.Properties.Find(t => ((GpkBaseProperty)t).name == "TextureFileCacheName"); if (txtProp == null) { goto fail; } String txtCacheFile = ((GpkNameProperty)txtProp).value; //assumption: cache in same dir, happens for cookedpc compositegpks map.textureCacheProp = ((GpkNameProperty)txtProp); map.textureCachePath = $"{CoreSettings.Default.CookedPCPath}{txtCacheFile}.tfc"; if (File.Exists(map.textureCachePath)) { BinaryReader cacheReader = new BinaryReader(new FileStream(map.textureCachePath, FileMode.Open, FileAccess.Read, FileShare.Read)); cacheReader.BaseStream.Seek(map.compChunkOffset, SeekOrigin.Begin); map.signature = cacheReader.ReadInt32(); //0x9e2a83c1 cacheReader.BaseStream.Seek(-4, SeekOrigin.Current); if (map.signature == Constants.DEFAULT_SIGNATURE) { ReadMipMapFromReader(cacheReader, map, package); } cacheReader.Close(); } else { logger.Debug("{0}, MipMap {1}, Cache {2}, CompressionTypes.StoreInSeparatefile, could not find tfc!!", export.ObjectName, i, txtCacheFile); } } else if (((CompressionTypes)map.flags & CompressionTypes.SeperateData) != 0) { //data in seprate chunk in gpk logger.Warn("{0}, MipMap {1}, CompressionTypes.SeperateDatam, could not parse!!", export.ObjectName, i); } else if (((CompressionTypes)map.flags & NothingToDo) == 0) { //normal in gpk data ReadMipMapFromReader(reader, map, package); } else { logger.Trace("{0}, MipMap {0}, no data!!", export.ObjectName, i); } fail: map.sizeX = reader.ReadInt32(); map.sizeY = reader.ReadInt32(); maps.Add(map); } int toread = (int)(reader.BaseStream.Length - reader.BaseStream.Position); FooterPaddingUnk = reader.ReadBytes(toread); }