⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kptrees.pas

📁 dephi vcl控件
💻 PAS
📖 第 1 页 / 共 3 页
字号:
            Inc(bl_tree[REPZ_3_10].fc.freq)
        Else
            Inc(bl_tree[REPZ_11_138].fc.freq);

        icount := 0; prevlen := curlen;
        if (nextlen = 0) then
         begin
            max_count := 138;
            min_count := 3;
         end
        Else if (curlen = nextlen) then
         begin
            max_count := 6;
            min_count := 3;
         end
        Else
         begin
            max_count := 7;
            min_count := 4;
         end;

     end;
end;


{* ===========================================================================
 * Construct the Huffman tree for the bit lengths and return the index in
 * bl_order of the last bit length code to send.
 *}
function build_bl_tree: LongInt;
{var}
  {max_blindex:   LongInt;}  { index of last bit length code of non zero freq }
begin
   { Determine the bit length frequencies for literal and distance trees }
    scan_tree(ct_dataArrayPtr(@dyn_ltree), l_desc.max_code);  { added typecast 5/18/98  2.13 }
    scan_tree(ct_dataArrayPtr(@dyn_dtree), d_desc.max_code);  { added typecast 5/18/98  2.13 }

    { Build the bit length tree: }
    build_tree(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.)
     *}
    Result := BL_CODES-1;
    while (Result >= 3) do
     begin
        if (bl_tree[bl_order[Result]].dl.len <> 0) then
           break;
        Dec(Result);
     end;
    { Update opt_len to include the bit length tree and counts }
    Inc(opt_len,3*(Result+1)+5+5+4);
    {Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len));}

    {Result := max_blindex;}
end;

{* ===========================================================================
 * Send the block data compressed using the given Huffman trees
 *}
procedure compress_block(ltree, dtree: ct_dataArrayPtr);
var
    { ltree      = literal tree }
    { dtree      = distance tree }
    dist:     usigned;            { distance of matched string }
    lc:       LongInt;             { match length or unmatched char (if dist == 0) }
    lx:       usigned;            { running index in l_buf }
    dx:       usigned;            { running index in d_buf }
    fx:       usigned;            { running index in flag_buf }
    flag:     Byte;                { current flags }
    code:     usigned;            { the code to send }
    extra:    LongInt;             { number of extra bits to send }
begin
    lx := 0;
    dx := 0;
    fx := 0;
    flag := 0;
    if (last_lit <> 0) then
     Repeat
        if ((lx and 7) = 0) then
         begin
           flag := flag_buf^[fx];
           Inc(fx);
         end;
        lc := l_buf^[lx];
        Inc(lx);
        if ((flag and 1) = 0) then
         begin
            send_code(lc, ltree); { send a literal byte }
            {send_bits( Integer(ltree^[lc].fc.code), Integer(ltree^[lc].dl.len) );}
            {Tracecv(isgraph(lc), (stderr," '%c' ", lc));}
         end
        Else
         begin
            { Here, lc is the match length - MIN_MATCH }
            code := length_code[lc];
            send_code(code+LITERALS+1, ltree); { send the length code }
            {send_bits( Integer(ltree^[code+LITERALS+1].fc.code), Integer(ltree^[code+LITERALS+1].dl.len) );}
            extra := extra_lbits[code];
            if (extra <> 0) then
             begin
                Dec(lc,base_length[code]);
                send_bits(lc, extra);        { send the extra length bits }
             end;
            dist := d_buf^[dx];
            Inc(dx);
            { Here, dist is the match distance - 1 }
            code := d_code(dist);

            {$IFDEF ASSERTS}
            Assert (code < D_CODES, 'bad d_code-compress_block');
            {$ENDIF}

            send_code(code, dtree);       { send the distance code }
            {send_bits( Integer(dtree^[code].fc.code), Integer(dtree^[code].dl.len) );}
            extra := extra_dbits[code];
            if (extra <> 0) then
             begin
                Dec(dist,base_dist[code]);
                send_bits(dist, extra);   { send the extra distance bits }
             end;
         end; { literal or match pair ? }
        flag := flag shr 1;
     Until lx >= last_lit;  {while (lx < last_lit)}

    send_code(END_BLOCK, ltree);
    {send_bits( Integer(ltree^[END_BLOCK].fc.code), Integer(ltree^[END_BLOCK].dl.len) );}
end;

{* ===========================================================================
 * Send a literal or distance tree in compressed form, using the codes in
 * bl_tree.
 *}
procedure send_tree (tree: ct_dataArrayPtr; max_code: LongInt);
var
    { tree       = the tree to be scanned }
    { max_code   = and its largest code of non zero frequency }
    n: Integer;                       { iterates over all tree elements }
    prevlen: LongInt;                 { last emitted length }
    curlen:  LongInt;                 { length of current code }
    nextlen: LongInt;                 { length of next code }
    icount:   LongInt;                 { repeat count of the current code }
    max_count:  LongInt;              { max repeat count }
    min_count:  LongInt;              { min repeat count }
begin
    prevlen := -1;
    nextlen := tree^[0].dl.len;
    icount := 0;
    max_count := 7;
    min_count := 4;
    { tree[max_code+1].Len = -1; }  { guard already set }
    if (nextlen = 0) then
     begin
        max_count := 138;
        min_count := 3;
     end;

    for n := 0 to max_code do
     begin
        curlen := nextlen;
        nextlen := tree^[n+1].dl.len;
        Inc(icount);
        if (icount < max_count) and (curlen = nextlen) then
            continue
        Else if (icount < min_count) then
           Repeat
            If (bl_tree[curlen].dl.len > 0) and (bl_tree[curlen].dl.len < 16) then
              send_code(curlen, ct_dataArrayPtr(@bl_tree));   { added typecast 5/18/98  2.13 }
              {send_bits( Integer(ct_dataArrayPtr(@bl_tree)^[curlen].fc.code),}
              {           Integer(ct_dataArrayPtr(@bl_tree)^[curlen].dl.len) );}
            {else
              ShowMessage('Length out of range! - ' + IFileName);}
            Dec(icount);
           Until icount = 0
        Else if (curlen <> 0) then
           begin
            if (curlen <> prevlen) then
             begin
                send_code(curlen, ct_dataArrayPtr(@bl_tree));  { added typecast 5/18/98 2.13 }
                {send_bits( Integer(ct_dataArrayPtr(@bl_tree)^[curlen].fc.code),}
                {           Integer(ct_dataArrayPtr(@bl_tree)^[curlen].dl.len) );}
                Dec(icount);
             end;

            {$IFDEF ASSERTS}
            Assert((icount >= 3) and (icount <= 6), ' 3_6? - send_tree');
            {$ENDIF}

            If (bl_tree[REP_3_6].dl.len > 0) and (bl_tree[REP_3_6].dl.len < 16) then
              send_code(REP_3_6, ct_dataArrayPtr(@bl_tree));   { added typecast 5/18/98  2.13 }
              {send_bits( Integer(ct_dataArrayPtr(@bl_tree)^[REP_3_6].fc.code), }
              {           Integer(ct_dataArrayPtr(@bl_tree)^[REP_3_6].dl.len) ); }
            {else
              ShowMessage('Length out of range! -' + IFileName);}
            send_bits(icount-3, 2);
           end
        Else if (icount <= 10) then
           begin
            send_code(REPZ_3_10, ct_dataArrayPtr(@bl_tree));  { added typecast 5/18/98  2.13 }
            {send_bits( Integer(ct_dataArrayPtr(@bl_tree)^[REPZ_3_10].fc.code), }
            {             Integer(ct_dataArrayPtr(@bl_tree)^[REPZ_3_10].dl.len) ); }
            send_bits(icount-3, 3);
           end
        Else
           begin
            send_code(REPZ_11_138, ct_dataArrayPtr(@bl_tree)); { added typecast 5/18/98  2.13 }
            {send_bits( Integer(ct_dataArrayPtr(@bl_tree)^[REPZ_11_138].fc.code), }
            {            Integer(ct_dataArrayPtr(@bl_tree)^[REPZ_11_138].dl.len) ); }
            send_bits(icount-11, 7);
           end;

        icount := 0; prevlen := curlen;
        if (nextlen = 0) then
           begin
            max_count := 138;
            min_count := 3;
           end
        Else if (curlen = nextlen) then
           begin
            max_count := 6;
            min_count := 3;
           end
        Else
           begin
            max_count := 7;
            min_count := 4;
           end;
     end;
end;

{* ===========================================================================
 * 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.
 *}
procedure send_all_trees(lcodes, dcodes, blcodes: LongInt);
var
  { lcodes, dcodes, blcodes  = number of codes for each tree }
  rank:    LongInt;   { index in bl_order }
begin
    {$IFDEF ASSERTS}
    Assert ((lcodes >= 257) and (dcodes >= 1) and (blcodes >= 4),
              'not enough codes-send_all_trees');
    Assert ((lcodes <= L_CODES) and (dcodes <= D_CODES) and (blcodes <= BL_CODES),
            'too many codes-send_all_trees');
    {$ENDIF} 

    send_bits(lcodes-257, 5);
    { not +255 as stated in appnote.txt 1.93a or -256 in 2.04c }
    send_bits(dcodes-1,   5);
    send_bits(blcodes-4,  4); { not -3 as stated in appnote.txt }
    for rank := 0 to blcodes-1 do
     begin
        {Tracev((stderr, "\nbl code %2d ", bl_order[rank]));}
        send_bits(bl_tree[bl_order[rank]].dl.len, 3);
     end;
    {Tracev((stderr, "\nbl tree: sent %ld", bits_sent));}

    send_tree(ct_dataArrayPtr(@dyn_ltree), lcodes-1); { send the literal tree } { added typecast 5/18/98  2.13 }
    {Tracev((stderr, "\nlit tree: sent %ld", bits_sent));}

    send_tree(ct_dataArrayPtr(@dyn_dtree), dcodes-1); { send the distance tree } { added typecast 5/18/98  2.13 }
    {Tracev((stderr, "\ndist tree: sent %ld", bits_sent));}
end;

function flush_the_block( buf: BytePtr; stored_len: LongInt; eofblock: Integer ): LongInt;
var
  opt_lenb, static_lenb:  LongInt;
  max_blindex:            LongInt;
begin
  flag_buf^[last_flags] := flags;
  If ( tmpfile_info.internal_file_attributes = UNKNOWN ) then
     set_file_type;

  build_tree( l_desc );
  build_tree( d_desc );

  max_blindex := build_bl_tree;

  opt_lenb := (opt_len+3+7) shr 3;
  static_lenb := (static_len+3+7) shr 3;
  Inc(input_len,stored_len);

  If (static_lenb <= opt_lenb) then
     opt_lenb := static_lenb;

  If (stored_len <= opt_lenb) and (eofblock <> 0) and (compressed_len = 0) then
   begin
     copy_block( buf, stored_len, 0 );
     compressed_len := stored_len shl 3;
     tmpfile_info.compression_method := STORE;
   end
  Else If (stored_len+4 <= opt_lenb) and (buf <> nil) then
   begin
     { The test buf <> nil 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((STORED_BLOCK shl 1) + eofblock, 3);  { send block type }
     compressed_len := (compressed_len + 3 + 7) and (not LongInt(7));
     Inc(compressed_len,(stored_len + 4) shl 3);
     copy_block(buf, stored_len, 1); { with header }
   end
  Else If (static_lenb = opt_lenb) then
   begin
     send_bits((STATIC_TREES shl 1) + eofblock, 3);
     compress_block(ct_dataArrayPtr(@static_ltree), ct_dataArrayPtr(@static_dtree));   { added typecast 5/18/98  2.13 }
     Inc(compressed_len,3 + static_len);
   end
  Else
   begin
     send_bits((DYN_TREES shl 1)+eofblock, 3);
     send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1);
     compress_block(ct_dataArrayPtr(@dyn_ltree), ct_dataArrayPtr(@dyn_dtree));  { added typecast 5/18/98  2.13 }
     Inc(compressed_len,3 + opt_len);
   end;
  init_block;
  if (eofblock <> 0) then
   begin
     ZeroMemory(@window^[0], 2*WSIZE-1);
     bi_windup;
     Inc(compressed_len,7);  { align on byte boundary }
   end;
  Result := compressed_len shr 3;
end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -