Esempio n. 1
0
        private static void DecodeNibbleRun(UInt8InputBitStream inputBits, UInt8OutputBitStream 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);
            }
        }
Esempio n. 2
0
        private static void Decode(Stream input, Stream output, long size)
        {
            long end = input.Position + size;
            UInt8InputBitStream bitStream    = new UInt8InputBitStream(input);
            List <byte>         outputBuffer = new List <byte>();

            while (input.Position < end)
            {
                if (bitStream.Unshift())
                {
                    if (input.Position >= end)
                    {
                        break;
                    }

                    outputBuffer.Add(NeutralEndian.Read1(input));
                }
                else
                {
                    if (input.Position >= end)
                    {
                        break;
                    }

                    ushort offset = NeutralEndian.Read1(input);

                    if (input.Position >= end)
                    {
                        break;
                    }

                    byte count = NeutralEndian.Read1(input);

                    // We've just read 2 bytes: %llllllll %hhhhcccc
                    // offset = %hhhhllllllll + 0x12, count = %cccc + 3
                    offset |= (ushort)((count & 0xF0) << 4);
                    offset += 0x12;
                    offset |= (ushort)(outputBuffer.Count & 0xF000);
                    count  &= 0xf;
                    count  += 3;

                    if (offset >= outputBuffer.Count)
                    {
                        offset -= 0x1000;
                    }

                    outputBuffer.AddRange(new byte[count]);
                    if (offset < outputBuffer.Count)
                    {
                        for (int sourceIndex = offset, destinationIndex = outputBuffer.Count - count;
                             destinationIndex < outputBuffer.Count;
                             sourceIndex++, destinationIndex++)
                        {
                            outputBuffer[destinationIndex] = outputBuffer[sourceIndex];
                        }
                    }
                }
            }

            byte[] bytes = outputBuffer.ToArray();
            output.Write(bytes, 0, bytes.Length);
        }
Esempio n. 3
0
        private static void DecodeInternal(Stream input, Stream output, DecodingCodeTreeNode codeTree, ushort numberOfTiles, bool xorOutput)
        {
            UInt8InputBitStream  inputBits = new UInt8InputBitStream(input);
            UInt8OutputBitStream outputBits;
            XorStream            xorStream = null;

            try
            {
                if (xorOutput)
                {
                    xorStream  = new XorStream(output);
                    outputBits = new UInt8OutputBitStream(xorStream);
                }
                else
                {
                    outputBits = new UInt8OutputBitStream(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();
                }
            }
        }