コード例 #1
0
        public byte[] CompressChunk(Chunk chunk)
        {
            int numBlocks = (chunk.Uncompressed.Length + maxBlockSize - 1) / maxBlockSize;

            if (numBlocks > 8)
            {
                throw new FormatException("Maximum block number exceeded");
            }
            ChunkHeader head = new ChunkHeader();

            head.magic            = -1641380927;
            head.blocksize        = maxBlockSize;
            head.uncompressedsize = chunk.Uncompressed.Length;
            int          pos       = 0;
            MemoryStream mem       = new MemoryStream();
            List <Block> blockList = new List <Block>();
            int          startData = 16 + 8 * numBlocks;

            mem.Seek(startData, SeekOrigin.Begin);
            for (int i = 0; i < numBlocks; i++)
            {
                Block  block = new Block();
                byte[] result, temp;
                if (i != numBlocks - 1)
                {
                    block.uncompressedsize = maxBlockSize;
                    temp = new byte[maxBlockSize];
                }
                else
                {
                    block.uncompressedsize = head.uncompressedsize - pos;
                    temp = new byte[block.uncompressedsize];
                }

                Buffer.BlockCopy(chunk.Uncompressed, pos, temp, 0, temp.Length);
                result = LZO2.Compress(temp);
                if (result.Length == 0)
                {
                    throw new Exception("LZO compression error!");
                }
                block.compressedsize = result.Length;
                mem.WriteBytes(result);
                blockList.Add(block);
                pos += maxBlockSize;
            }
            head.compressedsize = (int)mem.Length;

            mem.Seek(0, SeekOrigin.Begin);
            mem.WriteValueS32(head.magic);
            mem.WriteValueS32(head.blocksize);
            mem.WriteValueS32(head.compressedsize);
            mem.WriteValueS32(head.uncompressedsize);
            foreach (Block block in blockList)
            {
                mem.WriteValueS32(block.compressedsize);
                mem.WriteValueS32(block.uncompressedsize);
            }

            return(mem.ToArray());
        }
コード例 #2
0
        /// <summary>
        /// Takes regular image data and returns it in a compressed form ready for archiving
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public byte[] CompressTex(byte[] data)
        {
            int chunkSize = 131072; //Set at this stage. Easy to change later
            int noChunks  = (data.Length + chunkSize - 1) / chunkSize;

            CompressedChunkBlock[] chunks = new CompressedChunkBlock[noChunks];
            int pos = 0;

            for (int i = 0; i < noChunks; i++)
            {
                if (data.Length - (pos + chunkSize) < 0)
                {
                    chunks[i].uncSize = data.Length - pos;
                    chunks[i].rawData = new byte[chunks[i].uncSize];
                    Buffer.BlockCopy(data, pos, chunks[i].rawData, 0, chunks[i].uncSize);
                    pos += chunks[i].uncSize;
                }
                else
                {
                    chunks[i].uncSize = chunkSize;
                    chunks[i].rawData = new byte[chunkSize];
                    Buffer.BlockCopy(data, pos, chunks[i].rawData, 0, chunkSize);
                    pos += chunks[i].uncSize;
                }
            }
            pos = 0;
            CompressedChunkBlock[] newChunks = new CompressedChunkBlock[noChunks];
            for (int i = 0; i < noChunks; i++)
            {
                newChunks[i].rawData = LZO2.Compress(chunks[i].rawData);
                if (newChunks[i].rawData.Length == 0)
                {
                    throw new Exception("LZO compression failed!");
                }
                newChunks[i].cprSize = newChunks[i].rawData.Length;
                newChunks[i].uncSize = chunks[i].uncSize;
                pos += newChunks[i].cprSize;
            }
            byte[] result;
            using (MemoryStream stream = new MemoryStream())
            {
                byte[] magic = { 0xC1, 0x83, 0x2A, 0x9E, 0x00, 0x00, 0x02, 0x00 };
                pos = Gibbed.IO.NumberHelpers.LittleEndian(pos);
                BinaryWriter bin = new BinaryWriter(stream);
                bin.Write(magic);
                bin.Write(pos);
                pos = Gibbed.IO.NumberHelpers.LittleEndian(data.Length); //unc size
                bin.Write(pos);
                for (int i = 0; i < noChunks; i++)
                {
                    int uncSize = newChunks[i].uncSize;
                    int cprSize = newChunks[i].cprSize;
                    uncSize = Gibbed.IO.NumberHelpers.LittleEndian(uncSize);
                    cprSize = Gibbed.IO.NumberHelpers.LittleEndian(cprSize);
                    bin.Write(cprSize);
                    bin.Write(uncSize);
                }
                for (int i = 0; i < noChunks; i++)
                {
                    bin.Write(newChunks[i].rawData);
                }
                result = stream.ToArray();
            }

            return(result);
        }
コード例 #3
0
        public static 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 <ChunkBlock> blocks = new List <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++)
                    {
                        ChunkBlock block = new 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 =>
                {
                    ChunkBlock block = blocks[b];
                    if (type == StorageTypes.extLZO || type == StorageTypes.pccLZO)
                    {
                        block.compressedBuffer = LZO2.Compress(block.uncompressedBuffer);
                    }
                    else if (type == StorageTypes.extZlib || type == StorageTypes.pccZlib)
                    {
                        block.compressedBuffer = 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++)
                {
                    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 (ChunkBlock block in blocks)
                {
                    ouputStream.WriteUInt32(block.comprSize);
                    ouputStream.WriteUInt32(block.uncomprSize);
                }

                return(ouputStream.ToArray());
            }
        }