static public Stream compressData(byte[] inputData) { MemoryStream ouputStream = new MemoryStream(); uint compressedSize = 0; uint dataBlockLeft = (uint)inputData.Length; uint newNumBlocks = ((uint)inputData.Length + maxBlockSize - 1) / maxBlockSize; List <Package.ChunkBlock> blocks = new List <Package.ChunkBlock>(); using (MemoryStream inputStream = new MemoryStream(inputData)) { // skip blocks header and table - filled later ouputStream.Seek(SizeOfChunk + SizeOfChunkBlock * newNumBlocks, SeekOrigin.Begin); for (int b = 0; b < newNumBlocks; b++) { Package.ChunkBlock block = new Package.ChunkBlock(); block.uncomprSize = Math.Min(maxBlockSize, dataBlockLeft); dataBlockLeft -= block.uncomprSize; block.uncompressedBuffer = inputStream.ReadToBuffer(block.uncomprSize); blocks.Add(block); } } Parallel.For(0, blocks.Count, b => { Package.ChunkBlock block = blocks[b]; block.compressedBuffer = new ZlibHelper.Zlib().Compress(block.uncompressedBuffer); if (block.compressedBuffer.Length == 0) { throw new Exception("Compression failed!"); } block.comprSize = (uint)block.compressedBuffer.Length; blocks[b] = block; }); for (int b = 0; b < blocks.Count; b++) { Package.ChunkBlock block = blocks[b]; ouputStream.Write(block.compressedBuffer, 0, (int)block.comprSize); compressedSize += block.comprSize; } ouputStream.SeekBegin(); ouputStream.WriteUInt32(compressedSize); ouputStream.WriteInt32(inputData.Length); foreach (Package.ChunkBlock block in blocks) { ouputStream.WriteUInt32(block.comprSize); ouputStream.WriteUInt32(block.uncomprSize); } return(ouputStream); }
static public byte[] decompressData(Stream stream, long compressedSize) { uint compressedChunkSize = stream.ReadUInt32(); uint uncompressedChunkSize = stream.ReadUInt32(); byte[] data = new byte[uncompressedChunkSize]; uint blocksCount = (uncompressedChunkSize + maxBlockSize - 1) / maxBlockSize; if ((compressedChunkSize + SizeOfChunk + SizeOfChunkBlock * blocksCount) != compressedSize) { throw new Exception("not match"); } List <Package.ChunkBlock> blocks = new List <Package.ChunkBlock>(); for (uint b = 0; b < blocksCount; b++) { Package.ChunkBlock block = new Package.ChunkBlock(); block.comprSize = stream.ReadUInt32(); block.uncomprSize = stream.ReadUInt32(); blocks.Add(block); } for (int b = 0; b < blocks.Count; b++) { Package.ChunkBlock block = blocks[b]; block.compressedBuffer = stream.ReadToBuffer(blocks[b].comprSize); block.uncompressedBuffer = new byte[maxBlockSize * 2]; blocks[b] = block; } Parallel.For(0, blocks.Count, b => { uint dstLen = 0; Package.ChunkBlock block = blocks[b]; dstLen = new ZlibHelper.Zlib().Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer); if (dstLen != block.uncomprSize) { throw new Exception("Decompressed data size not expected!"); } }); int dstPos = 0; for (int b = 0; b < blocks.Count; b++) { Buffer.BlockCopy(blocks[b].uncompressedBuffer, 0, data, dstPos, (int)blocks[b].uncomprSize); dstPos += (int)blocks[b].uncomprSize; } return(data); }
private byte[] decompressTexture(MemoryStream stream, StorageTypes type, int uncompressedSize, int compressedSize) { byte[] data = new byte[uncompressedSize]; uint blockTag = stream.ReadUInt32(); if (blockTag != textureTag) { throw new Exception("not match"); } uint blockSize = stream.ReadUInt32(); if (blockSize != maxBlockSize) { throw new Exception("not match"); } uint compressedChunkSize = stream.ReadUInt32(); uint uncompressedChunkSize = stream.ReadUInt32(); if (uncompressedChunkSize != uncompressedSize) { throw new Exception("not match"); } uint blocksCount = (uncompressedChunkSize + maxBlockSize - 1) / maxBlockSize; if ((compressedChunkSize + SizeOfChunk + SizeOfChunkBlock * blocksCount) != compressedSize) { throw new Exception("not match"); } List <Package.ChunkBlock> blocks = new List <Package.ChunkBlock>(); for (uint b = 0; b < blocksCount; b++) { Package.ChunkBlock block = new Package.ChunkBlock(); block.comprSize = stream.ReadUInt32(); block.uncomprSize = stream.ReadUInt32(); blocks.Add(block); } for (int b = 0; b < blocks.Count; b++) { Package.ChunkBlock block = blocks[b]; block.compressedBuffer = stream.ReadToBuffer(blocks[b].comprSize); block.uncompressedBuffer = new byte[maxBlockSize * 2]; blocks[b] = block; } if (type == StorageTypes.extLZO || type == StorageTypes.pccLZO) { for (int b = 0; b < blocks.Count; b++) { uint dstLen = 0; Package.ChunkBlock block = blocks[b]; dstLen = LZO2Helper.LZO2.Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer); if (dstLen != block.uncomprSize) { throw new Exception("Decompressed data size not expected!"); } } } else { Parallel.For(0, blocks.Count, b => { uint dstLen = 0; Package.ChunkBlock block = blocks[b]; if (type == StorageTypes.extZlib || type == StorageTypes.pccZlib) { dstLen = ZlibHelper.Zlib.Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer); } if (dstLen != block.uncomprSize) { throw new Exception("Decompressed data size not expected!"); } }); } int dstPos = 0; for (int b = 0; b < blocks.Count; b++) { Buffer.BlockCopy(blocks[b].uncompressedBuffer, 0, data, dstPos, (int)blocks[b].uncomprSize); dstPos += (int)blocks[b].uncomprSize; } return(data); }
public byte[] compressTexture(byte[] inputData, StorageTypes type) { using (MemoryStream ouputStream = new MemoryStream()) { uint compressedSize = 0; uint dataBlockLeft = (uint)inputData.Length; uint newNumBlocks = ((uint)inputData.Length + maxBlockSize - 1) / maxBlockSize; List <Package.ChunkBlock> blocks = new List <Package.ChunkBlock>(); using (MemoryStream inputStream = new MemoryStream(inputData)) { // skip blocks header and table - filled later ouputStream.Seek(SizeOfChunk + SizeOfChunkBlock * newNumBlocks, SeekOrigin.Begin); for (int b = 0; b < newNumBlocks; b++) { Package.ChunkBlock block = new Package.ChunkBlock(); block.uncomprSize = Math.Min(maxBlockSize, dataBlockLeft); dataBlockLeft -= block.uncomprSize; block.uncompressedBuffer = inputStream.ReadToBuffer(block.uncomprSize); blocks.Add(block); } } if (type == StorageTypes.extLZO || type == StorageTypes.pccLZO) { for (int b = 0; b < blocks.Count; b++) { Package.ChunkBlock block = blocks[b]; block.compressedBuffer = LZO2Helper.LZO2.Compress(block.uncompressedBuffer); if (block.compressedBuffer.Length == 0) { throw new Exception("Compression failed!"); } block.comprSize = (uint)block.compressedBuffer.Length; blocks[b] = block; } } else { Parallel.For(0, blocks.Count, b => { Package.ChunkBlock block = blocks[b]; if (type == StorageTypes.extZlib || type == StorageTypes.pccZlib) { block.compressedBuffer = ZlibHelper.Zlib.Compress(block.uncompressedBuffer); } else { throw new Exception("Compression type not expected!"); } if (block.compressedBuffer.Length == 0) { throw new Exception("Compression failed!"); } block.comprSize = (uint)block.compressedBuffer.Length; blocks[b] = block; }); } for (int b = 0; b < blocks.Count; b++) { Package.ChunkBlock block = blocks[b]; ouputStream.Write(block.compressedBuffer, 0, (int)block.comprSize); compressedSize += block.comprSize; } ouputStream.SeekBegin(); ouputStream.WriteUInt32(textureTag); ouputStream.WriteUInt32(maxBlockSize); ouputStream.WriteUInt32(compressedSize); ouputStream.WriteInt32(inputData.Length); foreach (Package.ChunkBlock block in blocks) { ouputStream.WriteUInt32(block.comprSize); ouputStream.WriteUInt32(block.uncomprSize); } return(ouputStream.ToArray()); } }