public uint NextSymbol()
        {
            if (_symbolsToNextSelector == 0)
            {
                _symbolsToNextSelector = 50;
                _activeTree = _trees[_selectors[_nextSelector]];
                _nextSelector++;
            }

            _symbolsToNextSelector--;

            return _activeTree.NextSymbol(_bitstream);
        }
        private void Initialize(int maxSymbols)
        {
            int numTrees = (int)_bitstream.Read(3);
            if (numTrees < 2 || numTrees > 6)
            {
                throw new InvalidDataException("Invalid number of tables");
            }

            int numSelectors = (int)_bitstream.Read(15);
            if (numSelectors < 1)
            {
                throw new InvalidDataException("Invalid number of selectors");
            }

            _selectors = new byte[numSelectors];
            MoveToFront mtf = new MoveToFront(numTrees, true);
            for (int i = 0; i < numSelectors; ++i)
            {
                _selectors[i] = mtf.GetAndMove(CountSetBits(numTrees));
            }

            _trees = new HuffmanTree[numTrees];
            for (int t = 0; t < numTrees; ++t)
            {
                uint[] lengths = new uint[maxSymbols];

                uint len = _bitstream.Read(5);
                for (int i = 0; i < maxSymbols; ++i)
                {
                    if (len < 1 || len > 20)
                    {
                        throw new InvalidDataException("Invalid length constructing Huffman tree");
                    }

                    while (_bitstream.Read(1) != 0)
                    {
                        len = (_bitstream.Read(1) == 0) ? len + 1 : len - 1;

                        if (len < 1 || len > 20)
                        {
                            throw new InvalidDataException("Invalid length constructing Huffman tree");
                        }
                    }

                    lengths[i] = len;
                }

                _trees[t] = new HuffmanTree(lengths);
            }

            _symbolsToNextSelector = 0;
            _nextSelector = 0;
        }
Ejemplo n.º 3
0
        private void ReadLengths(HuffmanTree preTree, uint[] lengths, int offset, int count)
        {
            int i = 0;

            while (i < count)
            {
                uint value = preTree.NextSymbol(_bitStream);

                if (value == 17)
                {
                    uint numZeros = 4 + _bitStream.Read(4);
                    for (uint j = 0; j < numZeros; ++j)
                    {
                        lengths[offset + i] = 0;
                        ++i;
                    }
                }
                else if (value == 18)
                {
                    uint numZeros = 20 + _bitStream.Read(5);
                    for (uint j = 0; j < numZeros; ++j)
                    {
                        lengths[offset + i] = 0;
                        ++i;
                    }
                }
                else if (value == 19)
                {
                    uint same = _bitStream.Read(1);
                    value = preTree.NextSymbol(_bitStream);

                    if (value > 16)
                    {
                        throw new InvalidDataException("Invalid table encoding");
                    }

                    uint symbol = (17 + lengths[offset + i] - value) % 17;
                    for (uint j = 0; j < 4 + same; ++j)
                    {
                        lengths[offset + i] = symbol;
                        ++i;
                    }
                }
                else
                {
                    lengths[offset + i] = (17 + lengths[offset + i] - value) % 17;
                    ++i;
                }
            }
        }
Ejemplo n.º 4
0
        private HuffmanTree ReadDynamicHuffmanTree(int count, HuffmanTree preTree, HuffmanTree oldTree)
        {
            uint[] lengths;

            if (oldTree == null)
            {
                lengths = new uint[256 + (8 * _numPositionSlots)];
            }
            else
            {
                lengths = oldTree.Lengths;
            }

            ReadLengths(preTree, lengths, 0, count);

            return new HuffmanTree(lengths);
        }
Ejemplo n.º 5
0
 private void ReadLengthTree()
 {
     HuffmanTree preTree = ReadFixedHuffmanTree(20, 4);
     _lengthTree = ReadDynamicHuffmanTree(249, preTree, _lengthTree);
 }
Ejemplo n.º 6
0
        private void ReadMainTree()
        {
            uint[] lengths;

            if (_mainTree == null)
            {
                lengths = new uint[256 + (8 * _numPositionSlots)];
            }
            else
            {
                lengths = _mainTree.Lengths;
            }

            HuffmanTree preTree = ReadFixedHuffmanTree(20, 4);
            ReadLengths(preTree, lengths, 0, 256);
            preTree = ReadFixedHuffmanTree(20, 4);
            ReadLengths(preTree, lengths, 256, 8 * _numPositionSlots);

            _mainTree = new HuffmanTree(lengths);
        }
Ejemplo n.º 7
0
        private void DecodeCompressedBlock(BlockType blockType, int blockSize)
        {
            if (blockType == BlockType.AlignedOffset)
            {
                _alignedOffsetTree = ReadFixedHuffmanTree(8, 3);
            }

            ReadMainTree();
            ReadLengthTree();
            
            uint numRead = 0;
            while (numRead < (uint)blockSize)
            {
                uint symbol = _mainTree.NextSymbol(_bitStream);

                if (symbol < 256)
                {
                    _buffer[_bufferCount + numRead++] = (byte)symbol;
                }
                else
                {
                    uint lengthHeader = (symbol - 256) & 7;
                    uint matchLength = lengthHeader + 2 + ((lengthHeader == 7) ? _lengthTree.NextSymbol(_bitStream) : 0);
                    uint positionSlot = (symbol - 256) >> 3;

                    uint matchOffset;
                    if (positionSlot == 0)
                    {
                        matchOffset = _repeatedOffsets[0];
                    }
                    else if (positionSlot == 1)
                    {
                        matchOffset = _repeatedOffsets[1];
                        _repeatedOffsets[1] = _repeatedOffsets[0];
                        _repeatedOffsets[0] = matchOffset;
                    }
                    else if (positionSlot == 2)
                    {
                        matchOffset = _repeatedOffsets[2];
                        _repeatedOffsets[2] = _repeatedOffsets[0];
                        _repeatedOffsets[0] = matchOffset;
                    }
                    else
                    {
                        int extra = (int)s_extraBits[positionSlot];

                        uint formattedOffset;

                        if (blockType == BlockType.AlignedOffset)
                        {
                            uint verbatimBits = 0;
                            uint alignedBits = 0;

                            if (extra >= 3)
                            {
                                verbatimBits = _bitStream.Read(extra - 3) << 3;
                                alignedBits = _alignedOffsetTree.NextSymbol(_bitStream);
                            }
                            else if (extra > 0)
                            {
                                verbatimBits = _bitStream.Read(extra);
                            }

                            formattedOffset = s_positionSlots[positionSlot] + verbatimBits + alignedBits;
                        }
                        else
                        {
                            uint verbatimBits = (extra > 0) ? _bitStream.Read(extra) : 0;

                            formattedOffset = s_positionSlots[positionSlot] + verbatimBits;
                        }

                        matchOffset = formattedOffset - 2;

                        _repeatedOffsets[2] = _repeatedOffsets[1];
                        _repeatedOffsets[1] = _repeatedOffsets[0];
                        _repeatedOffsets[0] = matchOffset;
                    }

                    int destOffset = _bufferCount + (int)numRead;
                    int srcOffset = destOffset - (int)matchOffset;
                    for (int i = 0; i < matchLength; ++i)
                    {
                        _buffer[destOffset + i] = _buffer[srcOffset + i];
                    }

                    numRead += matchLength;
                }
            }
        }