Ejemplo n.º 1
0
        ////////////////////////////////////////////////////////////////////
        // Build code array from bit length frequency distribution
        ////////////////////////////////////////////////////////////////////

        public void BuildCodes()
        {
            // build bit length frequency array
            Array.Clear(BitLengthFreq, 0, BitLengthFreq.Length);
            for (Int32 Code = 0; Code < MaxUsedCodes; Code++)
            {
                if (CodeLength[Code] != 0)
                {
                    BitLengthFreq[CodeLength[Code] - 1]++;
                }
            }

            // build array of initial code for each block of codes
            Int32 InitCode = 0;

            for (Int32 BitNo = 0; BitNo < MaxBitLength; BitNo++)
            {
                // save the initial code of the block
                FirstCode[BitNo] = InitCode;

                // advance the code by the frequancy times 2 to the power of 15 less bit length
                InitCode += BitLengthFreq[BitNo] << (15 - BitNo);
            }

            // it must add up to 2 ** 16
            if (InitCode != 65536)
            {
                throw new ApplicationException("Inconsistent bl_counts!");
            }

            // now fill up the entire code array
            Array.Clear(Codes, 0, Codes.Length);
            for (Int32 Index = 0; Index < MaxUsedCodes; Index++)
            {
                Int32 Bits = CodeLength[Index];
                if (Bits > 0)
                {
                    Codes[Index]         = BitReverse.Reverse16Bits(FirstCode[Bits - 1]);
                    FirstCode[Bits - 1] += 1 << (16 - Bits);
                }
            }

            // exit
            return;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Build code array from bit length frequency distribution
        /// </summary>
        /// <exception cref="System.Exception">Inconsistent bl_counts!</exception>
        public void BuildCodes()
        {
            // build bit length frequency array
            Array.Clear(_bitLengthFreq, 0, _bitLengthFreq.Length);
            for (int code = 0; code < MaxUsedCodes; code++)
            {
                if (_codeLength[code] != 0)
                {
                    _bitLengthFreq[_codeLength[code] - 1]++;
                }
            }

            // build array of initial code for each block of codes
            int initCode = 0;

            for (int bitNo = 0; bitNo < _maxBitLength; bitNo++)
            {
                // save the initial code of the block
                _firstCode[bitNo] = initCode;

                // advance the code by the frequancy times 2 to the power of 15 less bit length
                initCode += _bitLengthFreq[bitNo] << (15 - bitNo);
            }

            // it must add up to 2 ** 16
            if (initCode != 65536)
            {
                throw new Exception("Inconsistent bl_counts!");
            }

            // now fill up the entire code array
            Array.Clear(_codes, 0, _codes.Length);
            for (int index = 0; index < MaxUsedCodes; index++)
            {
                int bits = _codeLength[index];
                if (bits > 0)
                {
                    _codes[index]         = BitReverse.Reverse16Bits(_firstCode[bits - 1]);
                    _firstCode[bits - 1] += 1 << (16 - bits);
                }
            }
        }
Ejemplo n.º 3
0
        ////////////////////////////////////////////////////////////////////
        // Constructs a Huffman tree from the array of code lengths.
        ////////////////////////////////////////////////////////////////////

        public void BuildTree
        (
            Byte[]  CodeLengths,
            Int32 Offset,
            Int32 Length
        )
        {
            // Build frequency array for bit length 1 to 15
            // Note: BitLengthCount[0] will never be used.
            // All elements of CodeLength are greater than zero.
            // In other words no code has zero length
            Array.Clear(BitLengthCount, 0, BitLengthCount.Length);
            for (Int32 Index = 0; Index < Length; Index++)
            {
                BitLengthCount[CodeLengths[Offset + Index]]++;
            }

            // build array of inital codes for each group of equal code length
            Int32 InitCode = 0;

            for (Int32 Bits = 1; Bits <= MAX_BITLEN; Bits++)
            {
                InitialCode[Bits] = InitCode;
                InitCode         += BitLengthCount[Bits] << (16 - Bits);
            }
            if (InitCode != 65536)
            {
                throw new ApplicationException("Code lengths don't add up properly.");
            }

            // longest code bit count
            Int32 MaxBits;

            for (MaxBits = MAX_BITLEN; BitLengthCount[MaxBits] == 0; MaxBits--)
            {
                ;
            }

            // number of hash bits at the root of the decode tree
            // the longest code but no more than 9 bits
            Int32 ActiveHashBits = Math.Min(9, MaxBits);

            // the decoding process is using this bit mask
            ActiveBitMask = 1 << ActiveHashBits;

            // hash table at the begining of the tree
            Array.Clear(ActiveTree, 0, ActiveTree.Length);

            // pointer to the area above the hash table for codes longer than hash bits
            Int32 EndPtr = ActiveBitMask;

            // fill the tree
            for (Int32 Index = 0; Index < Length; Index++)
            {
                // code length in bits
                Int32 Bits = CodeLengths[Offset + Index];

                // code not in use
                if (Bits == 0)
                {
                    continue;
                }

                // reverse the code from the most significant part to the least significant part of the integer
                Int32 Code = BitReverse.Reverse16Bits(InitialCode[Bits]);

                // the number of bits is less than the hash bits
                // we need to add artificial entries for the missing bits
                if (Bits < ActiveHashBits)
                {
                    Int32 NextInc = (1 << Bits);
                    for (Int32 Next = Code; Next < ActiveBitMask; Next += NextInc)
                    {
                        ActiveTree[Next] = ~(Index << 4 | Bits);
                    }
                }

                // the number of bits is equal to the hash bits
                else if (Bits == ActiveHashBits)
                {
                    ActiveTree[Code] = ~(Index << 4 | Bits);
                }

                // the number of bits is greater than the hash bits
                else
                {
                    // hash pointer to the start of the tree table
                    Int32 HashPtr = Code & (ActiveBitMask - 1);

                    // get the value at this location
                    Int32 Next = ActiveTree[HashPtr];

                    // the location is not initialized
                    if (Next == 0)
                    {
                        // get a free node at the area above the hash area and link it to the tree
                        ActiveTree[HashPtr] = EndPtr;
                        Next    = EndPtr;
                        EndPtr += 2;
                    }

                    // navigate through the tree above the hash area
                    // add empty nodes as required
                    Int32 BitMaskEnd = 1 << (Bits - 1);
                    for (Int32 BitMask = ActiveBitMask; BitMask != BitMaskEnd; BitMask <<= 1)
                    {
                        // current bit is one, adjust the next pointer
                        if ((Code & BitMask) != 0)
                        {
                            Next++;
                        }

                        // get the value at this location
                        Int32 Next1 = ActiveTree[Next];

                        // the location was initialized before, continue to follow the path
                        if (Next1 > 0)
                        {
                            Next = Next1;
                            continue;
                        }

                        // add free node from the area above the hash table and link it to the tree
                        ActiveTree[Next] = EndPtr;
                        Next             = EndPtr;
                        EndPtr          += 2;
                    }

                    // we are now at a leaf point, add the symbol and the number of bits
                    if ((Code & BitMaskEnd) != 0)
                    {
                        Next++;
                    }
                    ActiveTree[Next] = ~(Index << 4 | Bits);
                }

                // update initial code for the next code with the same number of bits
                InitialCode[Bits] += 1 << (16 - Bits);
            }

            // exit
            return;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Constructs a Huffman tree from the array of code lengths.
        /// </summary>
        /// <param name="codeLengths">The code lengths.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="length">The length.</param>
        public void BuildTree(byte[] codeLengths, int offset, int length)
        {
            // Build frequency array for bit length 1 to 15
            // Note: BitLengthCount[0] will never be used.
            // All elements of CodeLength are greater than zero.
            // In other words no code has zero length
            Array.Clear(_bitLengthCount, 0, _bitLengthCount.Length);
            for (int index = 0; index < length; index++)
            {
                _bitLengthCount[codeLengths[offset + index]]++;
            }

            // build array of inital codes for each group of equal code length
            int initCode = 0;

            for (int bits = 1; bits <= MaxBitlen; bits++)
            {
                _initialCode[bits] = initCode;
                initCode          += _bitLengthCount[bits] << (16 - bits);
            }

            // Warning
            // If BitLengthCount array was constructed properly InitCode should be equal to 65536.
            // During all my initial testing of decompressing ZIP archives coming from other programs
            // that was the case. I finally run into one file that was compressed by old version
            // of PKZIP version 2.50 4-15-1998 that the following commented statement threw exception.
            // I would strongly recomment to anyone making modification to the compression/decompression
            // software to activate this statement during the testing.
            //
            //if(InitCode != 65536) throw new Exception("Code lengths don't add up properly.");
            //

            // longest code bit count
            int maxBits;

            for (maxBits = MaxBitlen; _bitLengthCount[maxBits] == 0; maxBits--)
            {
            }

            // number of hash bits at the root of the decode tree
            // the longest code but no more than 9 bits
            int activeHashBits = Math.Min(9, maxBits);

            // the decoding process is using this bit mask
            ActiveBitMask = 1 << activeHashBits;

            // hash table at the begining of the tree
            Array.Clear(ActiveTree, 0, ActiveTree.Length);

            // pointer to the area above the hash table for codes longer than hash bits
            int endPtr = ActiveBitMask;

            // fill the tree
            for (int index = 0; index < length; index++)
            {
                // code length in bits
                int Bits = codeLengths[offset + index];

                // code not in use
                if (Bits == 0)
                {
                    continue;
                }

                // reverse the code from the most significant part to the least significant part of the integer
                int code = BitReverse.Reverse16Bits(_initialCode[Bits]);

                // the number of bits is less than the hash bits
                // we need to add artificial entries for the missing bits
                if (Bits < activeHashBits)
                {
                    int nextInc = (1 << Bits);
                    for (int next = code; next < ActiveBitMask; next += nextInc)
                    {
                        ActiveTree[next] = ~(index << 4 | Bits);
                    }
                }

                // the number of bits is equal to the hash bits
                else if (Bits == activeHashBits)
                {
                    ActiveTree[code] = ~(index << 4 | Bits);
                }

                // the number of bits is greater than the hash bits
                else
                {
                    // hash pointer to the start of the tree table
                    int hashPtr = code & (ActiveBitMask - 1);

                    // get the value at this location
                    int next = ActiveTree[hashPtr];

                    // the location is not initialized
                    if (next == 0)
                    {
                        // get a free node at the area above the hash area and link it to the tree
                        ActiveTree[hashPtr] = endPtr;
                        next    = endPtr;
                        endPtr += 2;
                    }

                    // navigate through the tree above the hash area
                    // add empty nodes as required
                    int bitMaskEnd = 1 << (Bits - 1);
                    for (int bitMask = ActiveBitMask; bitMask != bitMaskEnd; bitMask <<= 1)
                    {
                        // current bit is one, adjust the next pointer
                        if ((code & bitMask) != 0)
                        {
                            next++;
                        }

                        // get the value at this location
                        int next1 = ActiveTree[next];

                        // the location was initialized before, continue to follow the path
                        if (next1 > 0)
                        {
                            next = next1;
                            continue;
                        }

                        // add free node from the area above the hash table and link it to the tree
                        ActiveTree[next] = endPtr;
                        next             = endPtr;
                        endPtr          += 2;
                    }

                    // we are now at a leaf point, add the symbol and the number of bits
                    if ((code & bitMaskEnd) != 0)
                    {
                        next++;
                    }
                    ActiveTree[next] = ~(index << 4 | Bits);
                }

                // update initial code for the next code with the same number of bits
                _initialCode[Bits] += 1 << (16 - Bits);
            }
        }