📄 deflate.c
字号:
* Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. Updates opt_len to take into account the repeat * counts. (The contribution of the bit length codes will be added later * during the construction of bl_tree.) */local void scan_tree( DeflateHandler encoder, ct_data near *tree, /* the tree to be scanned */ int max_code) /* and its largest code of non zero frequency */{ 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 = (ush)0xffff; /* 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) { encoder->bl_tree[curlen].Freq += count; } else if(curlen != 0) { if(curlen != prevlen) encoder->bl_tree[curlen].Freq++; encoder->bl_tree[REP_3_6].Freq++; } else if(count <= 10) { encoder->bl_tree[REPZ_3_10].Freq++; } else { encoder->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. */local void send_tree( DeflateHandler encoder, ct_data near *tree, /* the tree to be scanned */ int max_code) /* and its largest code of non zero frequency */{ 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; } else if(count < min_count) { do { SEND_CODE(curlen, encoder->bl_tree); } while(--count != 0); } else if(curlen != 0) { if(curlen != prevlen) { SEND_CODE(curlen, encoder->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); SEND_CODE(REP_3_6, encoder->bl_tree); send_bits(encoder, count-3, 2); } else if(count <= 10) { SEND_CODE(REPZ_3_10, encoder->bl_tree); send_bits(encoder, count-3, 3); } else { SEND_CODE(REPZ_11_138, encoder->bl_tree); send_bits(encoder, 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; } }}/* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */local int build_bl_tree(DeflateHandler encoder){ 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(encoder, (ct_data near *)encoder->dyn_ltree, encoder->l_desc.max_code); scan_tree(encoder, (ct_data near *)encoder->dyn_dtree, encoder->d_desc.max_code); /* Build the bit length tree: */ build_tree(encoder, (tree_desc near *)(&encoder->bl_desc)); /* 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.) */ for(max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { if(encoder->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ encoder->opt_len += 3*(max_blindex+1) + 5+5+4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", encoder->opt_len, encoder->static_len)); return max_blindex;}/* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */local void send_all_trees( DeflateHandler encoder, int lcodes, int dcodes, int blcodes) /* number of codes for each tree */{ int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); send_bits(encoder, lcodes-257, 5); /* not +255 as stated in appnote.txt */ send_bits(encoder, dcodes-1, 5); send_bits(encoder, blcodes-4, 4); /* not -3 as stated in appnote.txt */ for(rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(encoder, encoder->bl_tree[bl_order[rank]].Len, 3); } /* send the literal tree */ send_tree(encoder, (ct_data near *)encoder->dyn_ltree,lcodes-1); /* send the distance tree */ send_tree(encoder, (ct_data near *)encoder->dyn_dtree,dcodes-1);}/* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. */local void flush_block( DeflateHandler encoder, int eof) /* true if this is the last block for a file */{ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex; /* index of last bit length code of non zero freq */ ulg stored_len; /* length of input block */ stored_len = (ulg)(encoder->strstart - encoder->block_start); encoder->flag_buf[encoder->last_flags] = encoder->flags; /* Save the flags for the last 8 items */ /* Construct the literal and distance trees */ build_tree(encoder, (tree_desc near *)(&encoder->l_desc)); Tracev((stderr, "\nlit data: dyn %ld, stat %ld", encoder->opt_len, encoder->static_len)); build_tree(encoder, (tree_desc near *)(&encoder->d_desc)); Tracev((stderr, "\ndist data: dyn %ld, stat %ld", encoder->opt_len, encoder->static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(encoder); /* Determine the best encoding. Compute first the block length in bytes */ opt_lenb = (encoder->opt_len +3+7)>>3; static_lenb = (encoder->static_len+3+7)>>3; Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", opt_lenb, encoder->opt_len, static_lenb, encoder->static_len, stored_len, encoder->last_lit, encoder->last_dist)); if(static_lenb <= opt_lenb) opt_lenb = static_lenb; if(stored_len + 4 <= opt_lenb /* 4: two words for the lengths */ && encoder->block_start >= 0L) { unsigned int i; uch *p; /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ send_bits(encoder, (STORED_BLOCK<<1)+eof, 3); /* send block type */ bi_windup(encoder); /* align on byte boundary */ put_short((ush)stored_len); put_short((ush)~stored_len); /* copy block */ p = &encoder->window[(unsigned)encoder->block_start]; for(i = 0; i < stored_len; i++) put_byte(p[i]); } else if(static_lenb == opt_lenb) { send_bits(encoder, (STATIC_TREES<<1)+eof, 3); compress_block(encoder, (ct_data near *)encoder->static_ltree, (ct_data near *)encoder->static_dtree); } else { send_bits(encoder, (DYN_TREES<<1)+eof, 3); send_all_trees(encoder, encoder->l_desc.max_code+1, encoder->d_desc.max_code+1, max_blindex+1); compress_block(encoder, (ct_data near *)encoder->dyn_ltree, (ct_data near *)encoder->dyn_dtree); } init_block(encoder); if(eof) bi_windup(encoder);}/* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */local int ct_tally( DeflateHandler encoder, int dist, /* distance of matched string */ int lc) /* match length-MIN_MATCH or unmatched char (if dist==0) */{ encoder->l_buf[encoder->last_lit++] = (uch)lc; if(dist == 0) { /* lc is the unmatched char */ encoder->dyn_ltree[lc].Freq++; } else { /* Here, lc is the match length - MIN_MATCH */ dist--; /* dist = match distance - 1 */ Assert((ush)dist < (ush)MAX_DIST && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)D_CODE(dist) < (ush)D_CODES, "ct_tally: bad match"); encoder->dyn_ltree[encoder->length_code[lc]+LITERALS+1].Freq++; encoder->dyn_dtree[D_CODE(dist)].Freq++; encoder->d_buf[encoder->last_dist++] = (ush)dist; encoder->flags |= encoder->flag_bit; } encoder->flag_bit <<= 1; /* Output the flags if they fill a byte: */ if((encoder->last_lit & 7) == 0) { encoder->flag_buf[encoder->last_flags++] = encoder->flags; encoder->flags = 0; encoder->flag_bit = 1; } /* Try to guess if it is profitable to stop the current block here */ if(encoder->compr_level > 2 && (encoder->last_lit & 0xfff) == 0) { /* Compute an upper bound for the compressed length */ ulg out_length = (ulg)encoder->last_lit*8L; ulg in_length = (ulg)encoder->strstart - encoder->block_start; int dcode; for(dcode = 0; dcode < D_CODES; dcode++) { out_length += (ulg)encoder->dyn_dtree[dcode].Freq * (5L + extra_dbits[dcode]); } out_length >>= 3; Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", encoder->last_lit, encoder->last_dist, in_length, out_length, 100L - out_length*100L/in_length)); if(encoder->last_dist < encoder->last_lit/2 && out_length < in_length/2) return 1; } return (encoder->last_lit == LIT_BUFSIZE-1 || encoder->last_dist == DIST_BUFSIZE); /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. */}/* =========================================================================== * Send the block data compressed using the given Huffman trees */local void compress_block( DeflateHandler encoder, ct_data near *ltree, /* literal tree */ ct_data near *dtree) /* distance tree */{ unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ unsigned lx = 0; /* running index in l_buf */ unsigned dx = 0; /* running index in d_buf */ unsigned fx = 0; /* running index in flag_buf */ uch flag = 0; /* current flags */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if(encoder->last_lit != 0) do { if((lx & 7) == 0) flag = encoder->flag_buf[fx++]; lc = encoder->l_buf[lx++]; if((flag & 1) == 0) { SEND_CODE(lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ code = encoder->length_code[lc]; SEND_CODE(code+LITERALS+1, ltree); /* send the length code */ extra = extra_lbits[code]; if(extra != 0) { lc -= encoder->base_length[code]; send_bits(encoder, lc, extra); /* send the extra length bits */ } dist = encoder->d_buf[dx++]; /* Here, dist is the match distance - 1 */ code = D_CODE(dist); Assert (code < D_CODES, "bad d_code"); SEND_CODE(code, dtree); /* send the distance code */ extra = extra_dbits[code]; if(extra != 0) { dist -= encoder->base_dist[code]; send_bits(encoder, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ flag >>= 1; } while(lx < encoder->last_lit); SEND_CODE(END_BLOCK, ltree);}/* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */#define Buf_size (8 * sizeof(ush)) /* bit size of bi_buf */local void send_bits( DeflateHandler encoder, int value, /* value to send */ int le
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -