// Construct the Huffman tree for the bit lengths and return the index in // bl_order of the last bit length code to send. private static int Build_bl_tree(Deflate s) { int max_blindex; // index of last bit length code of non zero freq // Determine the bit length frequencies for literal and distance trees Scan_tree(s, s.DynLTree, s.DynLTree.MaxCode); Scan_tree(s, s.DynDTree, s.DynDTree.MaxCode); // Build the bit length tree: Build_tree(s, s.DynBLTree, StaticBlTreeDesc); // opt_len now includes the length of the tree representations, except // the lengths of the bit lengths codes and the 5+5+4 bits for the counts. // Determine the number of bit length codes to send. The pkzip format // requires that at least 4 bit length codes be sent. (appnote.txt says // 3 but the actual value used is 4.) DynamicTreeDesc blTree = s.DynBLTree; for (max_blindex = BLCODES - 1; max_blindex >= 3; max_blindex--) { if (blTree[GetBitLength(max_blindex)].Len != 0) { break; } } // Update opt_len to include the bit length tree and counts s.OptLen += (3 * (max_blindex + 1)) + 5 + 5 + 4; return(max_blindex); }
/// <summary> /// 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. /// </summary> /// <param name="s">The data compressor.</param> /// <param name="tree">The dynamic tree descriptor.</param> /// <param name="stree">The static tree descriptor.</param> public static void Build_tree(Deflate s, DynamicTreeDesc tree, StaticTreeDesc stree) { int elems = stree.MaxElements; 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.ConstBuffers.BlCountPointer; int * heap = s.ConstBuffers.HeapPointer; byte * depth = s.ConstBuffers.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].Freq != 0) { heap[++s.HeapLen] = max_code = n; depth[n] = 0; } else { tree[n].Len = 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. ref CodeData streeCodeRef = ref stree.GetCodeDataReference();
/// <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; } } }