📄 jchuff.pas
字号:
{register} put_bits : int;
var
c : int;
begin
put_buffer := INT32 (code);
put_bits := state.cur.put_bits;
{ if size is 0, caller used an invalid Huffman table entry }
if (size = 0) then
ERREXIT(j_common_ptr(state.cinfo), JERR_HUFF_MISSING_CODE);
put_buffer := put_buffer and pred(INT32(1) shl size);
{ mask off any extra bits in code }
Inc(put_bits, size); { new number of bits in buffer }
put_buffer := put_buffer shl (24 - put_bits);
{ align incoming bits }
put_buffer := put_buffer or state.cur.put_buffer;
{ and merge with old buffer contents }
while (put_bits >= 8) do
begin
c := int ((put_buffer shr 16) and $FF);
{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;
{ Check for out-of-range coefficient values.
Since we're encoding a difference, the range limit is twice as much. }
if (nbits > MAX_COEF_BITS+1) then
ERREXIT(j_common_ptr(state.cinfo), JERR_BAD_DCT_COEF);
{ 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);
{ Check for out-of-range coefficient values }
if (nbits > MAX_COEF_BITS) then
ERREXIT(j_common_ptr(state.cinfo), JERR_BAD_DCT_COEF);
{ 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.
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 a Huffman coding tree for the observed counts.
Symbols which are not needed at all for the particular image are not
assigned any code, which saves space in the DHT marker as well as in
the compressed data. }
{$ifdef ENTROPY_OPT_SUPPORTED}
{ Process a single block's worth of coefficients }
{LOCAL}
procedure htest_one_block (cinfo : j_compress_ptr;
const block : JBLOCK;
last_dc_val : int;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -