// =========================================================================== // Send the block data compressed using the given Huffman trees // ltree: literal tree // dtree: distance tree static void compress_block(deflate_state s, ct_data[] ltree, ct_data[] dtree) { uint dist; // distance of matched string int lc; // match length or unmatched char (if dist == 0) uint lx=0; // running index in l_buf uint code; // the code to send int extra; // number of extra bits to send if(s.last_lit!=0) { do { dist=s.d_buf[lx]; lc=s.l_buf[lx++]; if(dist==0) { send_code(s, lc, ltree); // send a literal byte //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { // Here, lc is the match length - MIN_MATCH code=_length_code[lc]; send_code(s, (int)(code+LITERALS+1), ltree); // send the length code extra=extra_lbits[code]; if(extra!=0) { lc-=base_length[code]; send_bits(s, lc, extra); // send the extra length bits } dist--; // dist is now the match distance - 1 code=(dist<256?_dist_code[dist]:_dist_code[256+(dist>>7)]); //Assert (code < D_CODES, "bad d_code"); send_code(s, (int)code, dtree); // send the distance code extra=extra_dbits[code]; if(extra!=0) { dist-=(uint)base_dist[code]; send_bits(s, (int)dist, extra); // send the extra distance bits } } // literal or match pair ? } while(lx<s.last_lit); } send_code(s, END_BLOCK, ltree); s.last_eob_len=ltree[END_BLOCK].Len; }
// =========================================================================== // Scan a literal or distance tree to determine the frequencies of the codes // in the bit length tree. // tree: the tree to be scanned // max_code: and its largest code of non zero frequency static void scan_tree(deflate_state s, ct_data[] 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 int count=0; // repeat count of the current code int max_count=7; // max repeat count int min_count=4; // min repeat count if(nextlen==0) { max_count=138; min_count=3; } tree[max_code+1].Len=(ushort)0xffff; // guard for(n=0; n<=max_code; n++) { curlen=nextlen; nextlen=tree[n+1].Len; if(++count<max_count&&curlen==nextlen) continue; if(count<min_count) s.bl_tree[curlen].Freq+=(ushort)count; else if(curlen!=0) { if(curlen!=prevlen) s.bl_tree[curlen].Freq++; s.bl_tree[REP_3_6].Freq++; } else if(count<=10) s.bl_tree[REPZ_3_10].Freq++; else s.bl_tree[REPZ_11_138].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; } } }
// =========================================================================== // Send a literal or distance tree in compressed form, using the codes in bl_tree. // tree: the tree to be scanned // max_code: and its largest code of non zero frequency static void send_tree(deflate_state s, ct_data[] 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 int count=0; // repeat count of the current code int max_count=7; // max repeat count int min_count=4; // min repeat count // tree[max_code+1].Len = -1; // guard already set if(nextlen==0) { max_count=138; min_count=3; } for(n=0; n<=max_code; n++) { curlen=nextlen; nextlen=tree[n+1].Len; if(++count<max_count&&curlen==nextlen) continue; if(count<min_count) { do { send_code(s, curlen, s.bl_tree); } while(--count!=0); } else if(curlen!=0) { if(curlen!=prevlen) { send_code(s, curlen, s.bl_tree); count--; } //Assert(count>=3&&count<=6, " 3_6?"); send_code(s, REP_3_6, s.bl_tree); send_bits(s, count-3, 2); } else if(count<=10) { send_code(s, REPZ_3_10, s.bl_tree); send_bits(s, count-3, 3); } else { send_code(s, REPZ_11_138, s.bl_tree); send_bits(s, count-11, 7); } 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; } } }
// =========================================================================== // Generate the codes for a given tree and bit counts (which need not be // optimal). // IN assertion: the array bl_count contains the bit length statistics for // the given tree and the field len is set for all tree elements. // OUT assertion: the field code is set for all tree elements of non // zero code length. // tree: the tree to decorate // max_code: largest code with non zero frequency // bl_count: number of codes at each bit length static void gen_codes(ct_data[] tree, int max_code, ushort[] bl_count) { ushort[] next_code=new ushort[MAX_BITS+1]; // next code value for each bit length ushort code=0; // running code value int bits; // bit index int n; // code index // The distribution counts are first used to generate the code values // without bit reversal. for(bits=1; bits<=MAX_BITS; bits++) next_code[bits]=code=(ushort)((code+bl_count[bits-1])<<1); // Check that the bit counts in bl_count are consistent. The last code // must be all ones. //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, "inconsistent bit counts"); //Tracev((stderr, "\ngen_codes: max_code %d ", max_code)); for(n=0; n<=max_code; n++) { int len=tree[n].Len; if(len==0) continue; // Now reverse the bits tree[n].Code=bi_reverse(next_code[len]++, len); //Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); } }
// =========================================================================== // Remove the smallest element from the heap and recreate the heap with // one less element. Updates heap and heap_len. //#define pqremove(s, tree, top) \ // top = s.heap[SMALLEST]; \ // s.heap[SMALLEST] = s.heap[s.heap_len--]; \ // pqdownheap(s, tree, SMALLEST); // =========================================================================== // Compares to subtrees, using the tree depth as tie breaker when // the subtrees have equal frequency. This minimizes the worst case length. //#define smaller(tree, n, m, depth) \ // (tree[n].Freq < tree[m].Freq || \ // (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) // =========================================================================== // Restore the heap property by moving down the tree starting at node k, // exchanging a node with the smallest of its two sons if necessary, stopping // when the heap property is re-established (each father smaller than its // two sons). // tree: the tree to restore // k: node to move down static void pqdownheap(deflate_state s, ct_data[] tree, int k) { int v=s.heap[k]; int j=k<<1; // left son of k while(j<=s.heap_len) { // Set j to the smallest of the two sons: //was if (j < s.heap_len && smaller(tree, s.heap[j+1], s.heap[j], s.depth)) if(j<s.heap_len&&(tree[s.heap[j+1]].Freq<tree[s.heap[j]].Freq|| (tree[s.heap[j+1]].Freq==tree[s.heap[j]].Freq&&s.depth[s.heap[j+1]]<=s.depth[s.heap[j]]))) j++; // Exit if v is smaller than both sons //was if (smaller(tree, v, s.heap[j], s.depth)) break; if(tree[v].Freq<tree[s.heap[j]].Freq|| (tree[v].Freq==tree[s.heap[j]].Freq&&s.depth[v]<=s.depth[s.heap[j]])) break; // Exchange v with the smallest son s.heap[k]=s.heap[j]; k=j; // And continue down the tree, setting j to the left son of k j<<=1; } s.heap[k]=v; }
// =========================================================================== // Local (static) routines in this file. // // Send a code of the given tree. c and tree must not have side effects //#define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) static void send_code(deflate_state s, int c, ct_data[] tree) { ushort value=tree[c].Code; ushort len=tree[c].Len; if(s.bi_valid>(int)Buf_size-len) { int val=value; s.bi_buf|=(ushort)(val<<s.bi_valid); //was put_short(s, s.bi_buf); s.pending_buf[s.pending++]=(byte)(s.bi_buf&0xff); s.pending_buf[s.pending++]=(byte)((ushort)s.bi_buf>>8); s.bi_buf=(ushort)(val>>(Buf_size-s.bi_valid)); s.bi_valid+=len-Buf_size; } else { s.bi_buf|=(ushort)(value<<s.bi_valid); s.bi_valid+=len; } }
public int max_length; // max bit length for the codes public static_tree_desc(ct_data[] static_tree, int[] extra_bits, int extra_base, int elems, int max_length) { this.static_tree=static_tree; this.extra_bits=extra_bits; this.extra_base=extra_base; this.elems=elems; this.max_length=max_length; }
public ct_data(ct_data data) { freq=data.freq; dad=data.dad; }