Пример #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 = LZO1X.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 = LZO1X.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 = new byte[] { 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);
        }