Exemplo n.º 1
0
        // Construct one Huffman tree and assigns the code bit strings and lengths.
        // Update the total bit length for the current block.
        // IN assertion: the field freq is set for all tree elements.
        // OUT assertions: the fields len and code are set to the optimal bit length
        //     and corresponding code. The length opt_len is updated; static_len is
        //     also updated if stree is not null. The field max_code is set.
        internal void Build_tree(Deflate s)
        {
            using (MemoryHandle treeHandle = this.DynTree.AsMemory().Pin())
                using (MemoryHandle streeHandle = this.StatDesc.StaticTreeValue.AsMemory().Pin())
                {
                    ushort *tree = (ushort *)treeHandle.Pointer;
                    ushort *stree = (ushort *)streeHandle.Pointer;
                    int     elems = this.StatDesc.Elems;
                    int     n, m;          // iterate over heap elements
                    var     max_code = -1; // largest code with non zero frequency
                    int     node;          // new node being created
                    ushort *blCount = s.BlCountPointer;
                    int *   heap    = s.HeapPointer;
                    byte *  depth   = s.DepthPointer;

                    // Construct the initial heap, with least frequent element in
                    // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
                    // heap[0] is not used.
                    s.HeapLen = 0;
                    s.HeapMax = HEAPSIZE;

                    for (n = 0; n < elems; n++)
                    {
                        if (tree[n * 2] != 0)
                        {
                            heap[++s.HeapLen] = max_code = n;
                            depth[n]          = 0;
                        }
                        else
                        {
                            tree[(n * 2) + 1] = 0;
                        }
                    }

                    // The pkzip format requires that at least one distance code exists,
                    // and that at least one bit should be sent even if there is only one
                    // possible code. So to avoid special checks later on we force at least
                    // two codes of non zero frequency.
                    while (s.HeapLen < 2)
                    {
                        node           = heap[++s.HeapLen] = max_code < 2 ? ++max_code : 0;
                        tree[node * 2] = 1;
                        depth[node]    = 0;
                        s.OptLen--;
                        if (stree != null)
                        {
                            s.StaticLen -= stree[(node * 2) + 1];
                        }

                        // node is 0 or 1 so it does not have extra bits
                    }

                    this.MaxCode = max_code;

                    // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
                    // establish sub-heaps of increasing lengths:
                    for (n = s.HeapLen / 2; n >= 1; n--)
                    {
                        s.Pqdownheap(tree, n);
                    }

                    // Construct the Huffman tree by repeatedly combining the least two
                    // frequent nodes.
                    node = elems; // next internal node of the tree
                    do
                    {
                        // n = node of least frequency
                        n       = heap[1];
                        heap[1] = heap[s.HeapLen--];
                        s.Pqdownheap(tree, 1);
                        m = heap[1];           // m = node of next least frequency

                        heap[--s.HeapMax] = n; // keep the nodes sorted by frequency
                        heap[--s.HeapMax] = m;

                        // Create a new node father of n and m
                        tree[node * 2]    = (ushort)(tree[n * 2] + tree[m * 2]);
                        depth[node]       = (byte)(Math.Max(depth[n], depth[m]) + 1);
                        tree[(n * 2) + 1] = tree[(m * 2) + 1] = (ushort)node;

                        // and insert the new node in the heap
                        heap[1] = node++;
                        s.Pqdownheap(tree, 1);
                    }while (s.HeapLen >= 2);

                    heap[--s.HeapMax] = heap[1];

                    // At this point, the fields freq and dad are set. We can now
                    // generate the bit lengths.
                    this.Gen_bitlen(s);

                    // The field len is now set, we can generate the bit codes
                    Gen_codes(tree, max_code, blCount);
                }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Scan a literal or distance tree to determine the frequencies of the codes
        /// in the bit length tree.
        /// </summary>
        /// <param name="s">The data compressor.</param>
        /// <param name="tree">The tree to be scanned.</param>
        /// <param name="max_code">And its largest code of non zero frequency</param>
        public static void Scan_tree(Deflate s, DynamicTreeDesc tree, int max_code)
        {
            int             n;                       // iterates over all tree elements
            int             prevlen = -1;            // last emitted length
            int             curlen;                  // length of current code
            int             nextlen   = tree[0].Len; // length of next code
            ushort          count     = 0;           // repeat count of the current code
            int             max_count = 7;           // max repeat count
            int             min_count = 4;           // min repeat count
            DynamicTreeDesc blTree    = s.DynBLTree;

            if (nextlen == 0)
            {
                max_count = 138;
                min_count = 3;
            }

            tree[max_code + 1].Len = ushort.MaxValue; // guard

            for (n = 0; n <= max_code; n++)
            {
                curlen  = nextlen;
                nextlen = tree[n + 1].Len;
                if (++count < max_count && curlen == nextlen)
                {
                    continue;
                }
                else if (count < min_count)
                {
                    blTree[curlen].Freq += count;
                }
                else if (curlen != 0)
                {
                    if (curlen != prevlen)
                    {
                        blTree[curlen].Freq++;
                    }

                    blTree[REP36].Freq++;
                }
                else if (count <= 10)
                {
                    blTree[REPZ310].Freq++;
                }
                else
                {
                    blTree[REPZ11138].Freq++;
                }

                count   = 0;
                prevlen = curlen;
                if (nextlen == 0)
                {
                    max_count = 138;
                    min_count = 3;
                }
                else if (curlen == nextlen)
                {
                    max_count = 6;
                    min_count = 3;
                }
                else
                {
                    max_count = 7;
                    min_count = 4;
                }
            }
        }
Exemplo n.º 3
0
        // Compute the optimal bit lengths for a tree and update the total bit length
        // for the current block.
        // IN assertion: the fields freq and dad are set, heap[heap_max] and
        //    above are the tree nodes sorted by increasing frequency.
        // OUT assertions: the field len is set to the optimal bit length, the
        //     array bl_count contains the frequencies for each bit length.
        //     The length opt_len is updated; static_len is also updated if stree is
        //     not null.
        private void Gen_bitlen(Deflate s)
        {
            using (MemoryHandle treeHandle = this.DynTree.AsMemory().Pin())
                using (MemoryHandle streeHandle = this.StatDesc.StaticTreeValue.AsMemory().Pin())
                    using (MemoryHandle extraHandle = this.StatDesc.ExtraBits.AsMemory().Pin())
                    {
                        ushort *tree         = (ushort *)treeHandle.Pointer;
                        ushort *stree        = (ushort *)streeHandle.Pointer;
                        int *   extra        = (int *)extraHandle.Pointer;
                        int     base_Renamed = this.StatDesc.ExtraBase;
                        int     max_length   = this.StatDesc.MaxLength;
                        int     h;            // heap index
                        int     n, m;         // iterate over the tree elements
                        int     bits;         // bit length
                        int     xbits;        // extra bits
                        ushort  f;            // frequency
                        int     overflow = 0; // number of elements with bit length too large
                        ushort *blCount  = s.BlCountPointer;
                        int *   heap     = s.HeapPointer;

                        for (bits = 0; bits <= MAXBITS; bits++)
                        {
                            blCount[bits] = 0;
                        }

                        // In a first pass, compute the optimal bit lengths (which may
                        // overflow in the case of the bit length tree).
                        tree[(heap[s.HeapMax] * 2) + 1] = 0; // root of the heap

                        for (h = s.HeapMax + 1; h < HEAPSIZE; h++)
                        {
                            n    = heap[h];
                            bits = tree[(tree[(n * 2) + 1] * 2) + 1] + 1;
                            if (bits > max_length)
                            {
                                bits = max_length;
                                overflow++;
                            }

                            tree[(n * 2) + 1] = (ushort)bits;

                            // We overwrite tree[n*2+1] which is no longer needed
                            if (n > this.MaxCode)
                            {
                                continue; // not a leaf node
                            }

                            blCount[bits]++;
                            xbits = 0;
                            if (n >= base_Renamed)
                            {
                                xbits = extra[n - base_Renamed];
                            }

                            f         = tree[n * 2];
                            s.OptLen += f * (bits + xbits);
                            if (stree != null)
                            {
                                s.StaticLen += f * (stree[(n * 2) + 1] + xbits);
                            }
                        }

                        if (overflow == 0)
                        {
                            return;
                        }

                        // This happens for example on obj2 and pic of the Calgary corpus
                        // Find the first bit length which could increase:
                        do
                        {
                            bits = max_length - 1;
                            while (blCount[bits] == 0)
                            {
                                bits--;
                            }

                            blCount[bits]--;                                     // move one leaf down the tree
                            blCount[bits + 1] = (ushort)(blCount[bits + 1] + 2); // move one overflow item as its brother
                            blCount[max_length]--;

                            // The brother of the overflow item also moves one step up,
                            // but this does not affect bl_count[max_length]
                            overflow -= 2;
                        }while (overflow > 0);

                        for (bits = max_length; bits != 0; bits--)
                        {
                            n = blCount[bits];
                            while (n != 0)
                            {
                                m = heap[--h];
                                if (m > this.MaxCode)
                                {
                                    continue;
                                }

                                if (tree[(m * 2) + 1] != bits)
                                {
                                    s.OptLen          = (int)(s.OptLen + ((bits - (long)tree[(m * 2) + 1]) * tree[m * 2]));
                                    tree[(m * 2) + 1] = (ushort)bits;
                                }

                                n--;
                            }
                        }
                    }
        }