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();
}
}