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

📄 jchuff.pas

📁 用pascal寫的jpeg codec, 測試過的
💻 PAS
📖 第 1 页 / 共 3 页
字号:
    {emit_byte(state, c, return FALSE);}
    { Emit a byte, return FALSE if must suspend. }
    state.next_output_byte^ := JOCTET (c);
    Inc(state.next_output_byte);
    Dec(state.free_in_buffer);
    if (state.free_in_buffer = 0) then
      if not dump_buffer(state) then
      begin
        emit_bits := FALSE;
        exit;
      end;

    if (c = $FF) then          { need to stuff a zero byte? }
    begin
      {emit_byte(state, 0, return FALSE);}
      state.next_output_byte^ := JOCTET (0);
      Inc(state.next_output_byte);
      Dec(state.free_in_buffer);
      if (state.free_in_buffer = 0) then
	if not dump_buffer(state) then
	begin
          emit_bits := FALSE;
          exit;
        end;

    end;
    put_buffer := put_buffer shl 8;
    Dec(put_bits, 8);
  end;

  state.cur.put_buffer := put_buffer; { update state variables }
  state.cur.put_bits := put_bits;

  emit_bits := TRUE;
end;


{LOCAL}
function flush_bits (var state : working_state) : boolean;
begin
  if (not emit_bits(state, $7F, 7)) then { fill any partial byte with ones }
  begin
    flush_bits := FALSE;
    exit;
  end;
  state.cur.put_buffer := 0;	{ and reset bit-buffer to empty }
  state.cur.put_bits := 0;
  flush_bits := TRUE;
end;


{ Encode a single block's worth of coefficients }

{LOCAL}
function encode_one_block (var state : working_state;
                           const block : JBLOCK;
                           last_dc_val : int;
                           dctbl : c_derived_tbl_ptr;
                           actbl : c_derived_tbl_ptr) : boolean;
var
  {register} temp, temp2 : int;
  {register} nbits : int;
  {register} k, r, i : int;
begin
  { Encode the DC coefficient difference per section F.1.2.1 }

  temp2 := block[0] - last_dc_val;
  temp := temp2;

  if (temp < 0) then
  begin
    temp := -temp;		{ temp is abs value of input }
    { For a negative input, want temp2 := bitwise complement of abs(input) }
    { This code assumes we are on a two's complement machine }
    Dec(temp2);
  end;
  
  { Find the number of bits needed for the magnitude of the coefficient }
  nbits := 0;
  while (temp <> 0) do
  begin
    Inc(nbits);
    temp := temp shr 1;
  end;
  
  { Emit the Huffman-coded symbol for the number of bits }
  if not emit_bits(state, dctbl^.ehufco[nbits], dctbl^.ehufsi[nbits]) then
  begin
    encode_one_block := FALSE;
    exit;
  end;

  { Emit that number of bits of the value, if positive, }
  { or the complement of its magnitude, if negative. }
  if (nbits <> 0) then              { emit_bits rejects calls with size 0 }
    if not emit_bits(state, uInt(temp2), nbits) then
    begin
      encode_one_block := FALSE;
      exit;
    end;

  { Encode the AC coefficients per section F.1.2.2 }
  
  r := 0;			{ r := run length of zeros }

  for k := 1 to pred(DCTSIZE2) do
  begin
    temp := block[jpeg_natural_order[k]];
    if (temp = 0) then
    begin
      Inc(r);
    end
    else
    begin
      { if run length > 15, must emit special run-length-16 codes ($F0) }
      while (r > 15) do
      begin
	if not emit_bits(state, actbl^.ehufco[$F0], actbl^.ehufsi[$F0]) then
        begin
          encode_one_block := FALSE;
          exit;
        end;
	Dec(r, 16);
      end;

      temp2 := temp;
      if (temp < 0) then
      begin
	temp := -temp;		{ temp is abs value of input }
	{ This code assumes we are on a two's complement machine }
	Dec(temp2);
      end;

      { Find the number of bits needed for the magnitude of the coefficient }
      nbits := 0;		{ there must be at least one 1 bit }
      repeat
	Inc(nbits);
        temp := temp shr 1;
      until (temp = 0);

      { Emit Huffman symbol for run length / number of bits }
      i := (r shl 4) + nbits;
      if not emit_bits(state, actbl^.ehufco[i], actbl^.ehufsi[i]) then
      begin
        encode_one_block := FALSE;
        exit;
      end;

      { Emit that number of bits of the value, if positive, }
      { or the complement of its magnitude, if negative. }
      if not emit_bits(state, uInt(temp2), nbits) then
      begin
        encode_one_block := FALSE;
        exit;
      end;

      r := 0;
    end;
  end;

  { If the last coef(s) were zero, emit an end-of-block code }
  if (r > 0) then
    if not emit_bits(state, actbl^.ehufco[0], actbl^.ehufsi[0]) then
    begin
      encode_one_block := FALSE;
      exit;
    end;

  encode_one_block := TRUE;
end;


{ Emit a restart marker & resynchronize predictions. }

{LOCAL}
function emit_restart (var state : working_state;
                       restart_num : int) : boolean;
var
  ci : int;
begin
  if (not flush_bits(state)) then
  begin
    emit_restart  := FALSE;
    exit;
  end;

  {emit_byte(state, $FF, return FALSE);}
  { Emit a byte, return FALSE if must suspend. }
  state.next_output_byte^ := JOCTET ($FF);
  Inc(state.next_output_byte);
  Dec(state.free_in_buffer);
  if (state.free_in_buffer = 0) then
    if not dump_buffer(state) then
    begin
      emit_restart := FALSE;
      exit;
    end;

  {emit_byte(state, JPEG_RST0 + restart_num, return FALSE);}
  { Emit a byte, return FALSE if must suspend. }
  state.next_output_byte^ := JOCTET (JPEG_RST0 + restart_num);
  Inc(state.next_output_byte);
  Dec(state.free_in_buffer);
  if (state.free_in_buffer = 0) then
    if not dump_buffer(state) then
    begin
      emit_restart := FALSE;
      exit;
    end;

  { Re-initialize DC predictions to 0 }
  for ci := 0 to pred(state.cinfo^.comps_in_scan) do
    state.cur.last_dc_val[ci] := 0;

  { The restart counter is not updated until we successfully write the MCU. }

  emit_restart := TRUE;
end;


{ Encode and output one MCU's worth of Huffman-compressed coefficients. }

{METHODDEF}
function encode_mcu_huff (cinfo : j_compress_ptr;
                          const MCU_data: array of JBLOCKROW) : boolean;
var
  entropy : huff_entropy_ptr;
  state : working_state;
  blkn, ci : int;
  compptr : jpeg_component_info_ptr;
begin
  entropy := huff_entropy_ptr (cinfo^.entropy);
  { Load up working state }
  state.next_output_byte := cinfo^.dest^.next_output_byte;
  state.free_in_buffer := cinfo^.dest^.free_in_buffer;
  {ASSIGN_STATE(state.cur, entropy^.saved);}
  state.cur := entropy^.saved;
  state.cinfo := cinfo;

  { Emit restart marker if needed }
  if (cinfo^.restart_interval <> 0) then
  begin
    if (entropy^.restarts_to_go = 0) then
      if not emit_restart(state, entropy^.next_restart_num) then
      begin
	encode_mcu_huff := FALSE;
        exit;
      end;
  end;

  { Encode the MCU data blocks }
  for blkn := 0  to pred(cinfo^.blocks_in_MCU) do
  begin
    ci := cinfo^.MCU_membership[blkn];
    compptr := cinfo^.cur_comp_info[ci];
    if not encode_one_block(state,
                            MCU_data[blkn]^[0],
                            state.cur.last_dc_val[ci],
                            entropy^.dc_derived_tbls[compptr^.dc_tbl_no],
                            entropy^.ac_derived_tbls[compptr^.ac_tbl_no]) then
    begin
      encode_mcu_huff := FALSE;
      exit;
    end;
    { Update last_dc_val }
    state.cur.last_dc_val[ci] := MCU_data[blkn]^[0][0];
  end;

  { Completed MCU, so update state }
  cinfo^.dest^.next_output_byte := state.next_output_byte;
  cinfo^.dest^.free_in_buffer := state.free_in_buffer;
  {ASSIGN_STATE(entropy^.saved, state.cur);}
  entropy^.saved := state.cur;

  { Update restart-interval state too }
  if (cinfo^.restart_interval <> 0) then
  begin
    if (entropy^.restarts_to_go = 0) then
    begin
      entropy^.restarts_to_go := cinfo^.restart_interval;
      Inc(entropy^.next_restart_num);
      with entropy^ do
        next_restart_num := next_restart_num and 7;
    end;
    Dec(entropy^.restarts_to_go);
  end;

  encode_mcu_huff := TRUE;
end;


{ Finish up at the end of a Huffman-compressed scan. }

{METHODDEF}
procedure finish_pass_huff (cinfo : j_compress_ptr);
var
  entropy : huff_entropy_ptr;
  state : working_state;
begin
  entropy := huff_entropy_ptr (cinfo^.entropy);

  { Load up working state ... flush_bits needs it }
  state.next_output_byte := cinfo^.dest^.next_output_byte;
  state.free_in_buffer := cinfo^.dest^.free_in_buffer;
  {ASSIGN_STATE(state.cur, entropy^.saved);}
  state.cur := entropy^.saved;
  state.cinfo := cinfo;

  { Flush out the last data }
  if not flush_bits(state) then
    ERREXIT(j_common_ptr(cinfo), JERR_CANT_SUSPEND);

  { Update state }
  cinfo^.dest^.next_output_byte := state.next_output_byte;
  cinfo^.dest^.free_in_buffer := state.free_in_buffer;
  {ASSIGN_STATE(entropy^.saved, state.cur);}
  entropy^.saved := state.cur;
end;


{ Huffman coding optimization.

  This actually is optimization, in the sense that we find the best possible
  Huffman table(s) for the given data.  We first scan the supplied data and
  count the number of uses of each symbol that is to be Huffman-coded.
  (This process must agree with the code above.)  Then we build an
  optimal Huffman coding tree for the observed counts.

  The JPEG standard requires Huffman codes to be no more than 16 bits long.
  If some symbols have a very small but nonzero probability, the Huffman tree
  must be adjusted to meet the code length restriction.  We currently use
  the adjustment method suggested in the JPEG spec.  This method is *not*
  optimal; it may not choose the best possible limited-length code.  But
  since the symbols involved are infrequently used, it's not clear that
  going to extra trouble is worthwhile. }

{$ifdef ENTROPY_OPT_SUPPORTED}


{ Process a single block's worth of coefficients }

{LOCAL}
procedure htest_one_block (const block : JBLOCK;
                           last_dc_val : int;

⌨️ 快捷键说明

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