Esempio n. 1
0
        private static void DecodeHeader(Stream input, Stream output, DecodingCodeTreeNode codeTree)
        {
            byte outputValue = 0;
            byte inputValue;

            // Loop until a byte with value 0xFF is encountered
            while ((inputValue = NeutralEndian.Read1(input)) != 0xFF)
            {
                if ((inputValue & 0x80) != 0)
                {
                    outputValue = (byte)(inputValue & 0xF);
                    inputValue  = NeutralEndian.Read1(input);
                }

                codeTree.SetCode(
                    NeutralEndian.Read1(input),
                    inputValue & 0xF,
                    new NibbleRun(outputValue, (byte)(((inputValue & 0x70) >> 4) + 1)));
            }

            // Store a special nibble run for inline RLE sequences (code = 0b111111, length = 6)
            // Length = 0xFF in the nibble run is just a marker value that will be handled specially in DecodeInternal
            codeTree.SetCode(0x3F, 6, new NibbleRun(0, 0xFF));
        }
Esempio n. 2
0
        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();
                }
            }
        }