private static void DecodeNibbleRun(UInt8_E_L_InputBitStream inputBits, UInt8_E_L_OutputBitStream outputBits, byte count, byte nibble, ref int bitsWritten) { bitsWritten += count * 4; // Write single nibble, if needed if ((count & 1) != 0) { outputBits.Write(nibble, 4); } // Write pairs of nibbles count >>= 1; nibble |= (byte)(nibble << 4); while (count-- != 0) { outputBits.Write(nibble, 8); } }
private static void DecodeInternal(Stream input, Stream output, DecodingCodeTreeNode codeTree, ushort numberOfTiles, bool xorOutput) { UInt8_E_L_InputBitStream inputBits = new UInt8_E_L_InputBitStream(input); UInt8_E_L_OutputBitStream outputBits; XorStream xorStream = null; try { if (xorOutput) { xorStream = new XorStream(output); outputBits = new UInt8_E_L_OutputBitStream(xorStream); } else { outputBits = new UInt8_E_L_OutputBitStream(output); } // The output is: number of tiles * 0x20 (1 << 5) bytes per tile * 8 (1 << 3) bits per byte int outputSize = numberOfTiles << 8; // in bits int bitsWritten = 0; DecodingCodeTreeNode currentNode = codeTree; while (bitsWritten < outputSize) { NibbleRun nibbleRun = currentNode.NibbleRun; if (nibbleRun.Count == 0xFF) { // Bit pattern 0b111111; inline RLE. // First 3 bits are repetition count, followed by the inlined nibble. byte count = (byte)(inputBits.Read(3) + 1); byte nibble = inputBits.Read(4); DecodeNibbleRun(inputBits, outputBits, count, nibble, ref bitsWritten); currentNode = codeTree; } else if (nibbleRun.Count != 0) { // Output the encoded nibble run DecodeNibbleRun(inputBits, outputBits, nibbleRun.Count, nibbleRun.Nibble, ref bitsWritten); currentNode = codeTree; } else { // Read the next bit and go down one level in the tree currentNode = currentNode[inputBits.Get()]; if (currentNode == null) { throw new CompressionException(Properties.Resources.InvalidCode); } } } outputBits.Flush(false); } finally { if (xorStream != null) { xorStream.Dispose(); } } }