// 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); } }
/// <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; } } }
// 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--; } } } }