📄 jdcoefct.pas
字号:
{$ifdef BLOCK_SMOOTHING_SUPPORTED}
{ This code applies interblock smoothing as described by section K.8
of the JPEG standard: the first 5 AC coefficients are estimated from
the DC values of a DCT block and its 8 neighboring blocks.
We apply smoothing only for progressive JPEG decoding, and only if
the coefficients it can estimate are not yet known to full precision. }
{ Natural-order array positions of the first 5 zigzag-order coefficients }
const
Q01_POS = 1;
Q10_POS = 8;
Q20_POS = 16;
Q11_POS = 9;
Q02_POS = 2;
{ Determine whether block smoothing is applicable and safe.
We also latch the current states of the coef_bits[] entries for the
AC coefficients; otherwise, if the input side of the decompressor
advances into a new scan, we might think the coefficients are known
more accurately than they really are. }
{LOCAL}
function smoothing_ok (cinfo : j_decompress_ptr) : boolean;
var
coef : my_coef_ptr;
smoothing_useful : boolean;
ci, coefi : int;
compptr : jpeg_component_info_ptr;
qtable : JQUANT_TBL_PTR;
coef_bits : coef_bits_ptr;
coef_bits_latch : Latch_Ptr;
begin
coef := my_coef_ptr (cinfo^.coef);
smoothing_useful := FALSE;
if (not cinfo^.progressive_mode) or (cinfo^.coef_bits = NIL) then
begin
smoothing_ok := FALSE;
exit;
end;
{ Allocate latch area if not already done }
if (coef^.coef_bits_latch = NIL) then
coef^.coef_bits_latch := Latch_Ptr(
cinfo^.mem^.alloc_small (j_common_ptr (cinfo), JPOOL_IMAGE,
cinfo^.num_components *
(SAVED_COEFS * SIZEOF(int))) );
coef_bits_latch := (coef^.coef_bits_latch);
compptr := cinfo^.comp_info;
for ci := 0 to pred(cinfo^.num_components) do
begin
{ All components' quantization values must already be latched. }
qtable := compptr^.quant_table;
if (qtable = NIL) then
begin
smoothing_ok := FALSE;
exit;
end;
{ Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. }
if (qtable^.quantval[0] = 0) or
(qtable^.quantval[Q01_POS] = 0) or
(qtable^.quantval[Q10_POS] = 0) or
(qtable^.quantval[Q20_POS] = 0) or
(qtable^.quantval[Q11_POS] = 0) or
(qtable^.quantval[Q02_POS] = 0) then
begin
smoothing_ok := FALSE;
exit;
end;
{ DC values must be at least partly known for all components. }
coef_bits := @cinfo^.coef_bits^[ci]; { Nomssi }
if (coef_bits^[0] < 0) then
begin
smoothing_ok := FALSE;
exit;
end;
{ Block smoothing is helpful if some AC coefficients remain inaccurate. }
for coefi := 1 to 5 do
begin
coef_bits_latch^[coefi] := coef_bits^[coefi];
if (coef_bits^[coefi] <> 0) then
smoothing_useful := TRUE;
end;
Inc(coef_bits_latch {SAVED_COEFS});
Inc(compptr);
end;
smoothing_ok := smoothing_useful;
end;
{ Variant of decompress_data for use when doing block smoothing. }
{METHODDEF}
function decompress_smooth_data (cinfo : j_decompress_ptr;
output_buf : JSAMPIMAGE) : int;
var
coef : my_coef_ptr;
last_iMCU_row : JDIMENSION;
block_num, last_block_column : JDIMENSION;
ci, block_row, block_rows, access_rows : int;
buffer : JBLOCKARRAY;
buffer_ptr, prev_block_row, next_block_row : JBLOCKROW;
output_ptr : JSAMPARRAY;
output_col : JDIMENSION;
compptr : jpeg_component_info_ptr;
inverse_DCT : inverse_DCT_method_ptr;
first_row, last_row : boolean;
workspace : JBLOCK;
coef_bits : Latch_Ptr; { coef_bits_ptr; }
quanttbl : JQUANT_TBL_PTR;
Q00,Q01,Q02,Q10,Q11,Q20, num : INT32;
DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9 : int;
Al, pred : int;
var
delta : JDIMENSION;
begin
coef := my_coef_ptr (cinfo^.coef);
last_iMCU_row := cinfo^.total_iMCU_rows - 1;
{ Force some input to be done if we are getting ahead of the input. }
while (cinfo^.input_scan_number <= cinfo^.output_scan_number) and
(not cinfo^.inputctl^.eoi_reached) do
begin
if (cinfo^.input_scan_number = cinfo^.output_scan_number) then
begin
{ If input is working on current scan, we ordinarily want it to
have completed the current row. But if input scan is DC,
we want it to keep one row ahead so that next block row's DC
values are up to date. }
if (cinfo^.Ss = 0) then
delta := 1
else
delta := 0;
if (cinfo^.input_iMCU_row > cinfo^.output_iMCU_row+delta) then
break;
end;
if (cinfo^.inputctl^.consume_input(cinfo) = JPEG_SUSPENDED) then
begin
decompress_smooth_data := JPEG_SUSPENDED;
exit;
end;
end;
{ OK, output from the virtual arrays. }
compptr := cinfo^.comp_info;
for ci := 0 to (cinfo^.num_components-1) do
begin
{ Don't bother to IDCT an uninteresting component. }
if (not compptr^.component_needed) then
continue;
{ Count non-dummy DCT block rows in this iMCU row. }
if (cinfo^.output_iMCU_row < last_iMCU_row) then
begin
block_rows := compptr^.v_samp_factor;
access_rows := block_rows * 2; { this and next iMCU row }
last_row := FALSE;
end
else
begin
{ NB: can't use last_row_height here; it is input-side-dependent! }
block_rows := int (compptr^.height_in_blocks mod compptr^.v_samp_factor);
if (block_rows = 0) then
block_rows := compptr^.v_samp_factor;
access_rows := block_rows; { this iMCU row only }
last_row := TRUE;
end;
{ Align the virtual buffer for this component. }
if (cinfo^.output_iMCU_row > 0) then
begin
Inc(access_rows, compptr^.v_samp_factor); { prior iMCU row too }
buffer := cinfo^.mem^.access_virt_barray
(j_common_ptr (cinfo), coef^.whole_image[ci],
(cinfo^.output_iMCU_row - 1) * compptr^.v_samp_factor,
JDIMENSION (access_rows), FALSE);
Inc(JBLOCKROW_PTR(buffer), compptr^.v_samp_factor); { point to current iMCU row }
first_row := FALSE;
end
else
begin
buffer := cinfo^.mem^.access_virt_barray
(j_common_ptr (cinfo), coef^.whole_image[ci],
JDIMENSION (0), JDIMENSION (access_rows), FALSE);
first_row := TRUE;
end;
{ Fetch component-dependent info }
coef_bits := coef^.coef_bits_latch;
Inc(coef_bits, ci); { ci * SAVED_COEFS}
quanttbl := compptr^.quant_table;
Q00 := quanttbl^.quantval[0];
Q01 := quanttbl^.quantval[Q01_POS];
Q10 := quanttbl^.quantval[Q10_POS];
Q20 := quanttbl^.quantval[Q20_POS];
Q11 := quanttbl^.quantval[Q11_POS];
Q02 := quanttbl^.quantval[Q02_POS];
inverse_DCT := cinfo^.idct^.inverse_DCT[ci];
output_ptr := output_buf^[ci];
{ Loop over all DCT blocks to be processed. }
for block_row := 0 to (block_rows-1) do
begin
buffer_ptr := buffer^[block_row];
if (first_row) and (block_row = 0) then
prev_block_row := buffer_ptr
else
prev_block_row := buffer^[block_row-1];
if (last_row) and (block_row = block_rows-1) then
next_block_row := buffer_ptr
else
next_block_row := buffer^[block_row+1];
{ We fetch the surrounding DC values using a sliding-register approach.
Initialize all nine here so as to do the right thing on narrow pics.}
DC3 := int(prev_block_row^[0][0]);
DC2 := DC3;
DC1 := DC2;
DC6 := int(buffer_ptr^[0][0]);
DC5 := DC6;
DC4 := DC5;
DC9 := int(next_block_row^[0][0]);
DC8 := DC9;
DC7 := DC8 ;
output_col := 0;
last_block_column := compptr^.width_in_blocks - 1;
for block_num := 0 to last_block_column do
begin
{ Fetch current DCT block into workspace so we can modify it. }
jcopy_block_row(buffer_ptr, JBLOCKROW (@workspace), JDIMENSION(1));
{ Update DC values }
if (block_num < last_block_column) then
begin
DC3 := int (prev_block_row^[1][0]);
DC6 := int (buffer_ptr^[1][0]);
DC9 := int (next_block_row^[1][0]);
end;
{ Compute coefficient estimates per K.8.
An estimate is applied only if coefficient is still zero,
and is not known to be fully accurate. }
{ AC01 }
Al := coef_bits^[1];
if (Al <> 0) and (workspace[1] = 0) then
begin
num := 36 * Q00 * (DC4 - DC6);
if (num >= 0) then
begin
pred := int (((Q01 shl 7) + num) div (Q01 shl 8));
if (Al > 0) and (pred >= (1 shl Al)) then
pred := (1 shl Al)-1;
end
else
begin
pred := int (((Q01 shl 7) - num) div (Q01 shl 8));
if (Al > 0) and (pred >= (1 shl Al)) then
pred := (1 shl Al)-1;
pred := -pred;
end;
workspace[1] := JCOEF (pred);
end;
{ AC10 }
Al := coef_bits^[2];
if (Al <> 0) and (workspace[8] = 0) then
begin
num := 36 * Q00 * (DC2 - DC8);
if (num >= 0) then
begin
pred := int (((Q10 shl 7) + num) div (Q10 shl 8));
if (Al > 0) and (pred >= (1 shl Al)) then
pred := (1 shl Al)-1;
end
else
begin
pred := int (((Q10 shl 7) - num) div (Q10 shl 8));
if (Al > 0) and (pred >= (1 shl Al)) then
pred := (1 shl Al)-1;
pred := -pred;
end;
workspace[8] := JCOEF (pred);
end;
{ AC20 }
Al := coef_bits^[3];
if (Al <> 0) and (workspace[16] = 0) then
begin
num := 9 * Q00 * (DC2 + DC8 - 2*DC5);
if (num >= 0) then
begin
pred := int (((Q20 shl 7) + num) div (Q20 shl 8));
if (Al > 0) and (pred >= (1 shl Al)) then
pred := (1 shl Al)-1;
end
else
begin
pred := int (((Q20 shl 7) - num) div (Q20 shl 8));
if (Al > 0) and (pred >= (1 shl Al)) then
pred := (1 shl Al)-1;
pred := -pred;
end;
workspace[16] := JCOEF (pred);
end;
{ AC11 }
Al := coef_bits^[4];
if (Al <> 0) and (workspace[9] = 0) then
begin
num := 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
if (num >= 0) then
begin
pred := int (((Q11 shl 7) + num) div (Q11 shl 8));
if (Al > 0) and (pred >= (1 shl Al)) then
pred := (1 shl Al)-1;
end
else
begin
pred := int (((Q11 shl 7) - num) div (Q11 shl 8));
if (Al > 0) and (pred >= (1 shl Al)) then
pred := (1 shl Al)-1;
pred := -pred;
end;
workspace[9] := JCOEF (pred);
end;
{ AC02 }
Al := coef_bits^[5];
if (Al <> 0) and (workspace[2] = 0) then
begin
num := 9 * Q00 * (DC4 + DC6 - 2*DC5);
if (num >= 0) then
begin
pred := int (((Q02 shl 7) + num) div (Q02 shl 8));
if (Al > 0) and (pred >= (1 shl Al)) then
pred := (1 shl Al)-1;
end
else
begin
pred := int (((Q02 shl 7) - num) div (Q02 shl 8));
if (Al > 0) and (pred >= (1 shl Al)) then
pred := (1 shl Al)-1;
pred := -pred;
end;
workspace[2] := JCOEF (pred);
end;
{ OK, do the IDCT }
inverse_DCT (cinfo, compptr, JCOEFPTR (@workspace),
output_ptr, output_col);
{ Advance for next column }
DC1 := DC2; DC2 := DC3;
DC4 := DC5; DC5 := DC6;
DC7 := DC8; DC8 := DC9;
Inc(JBLOCK_PTR(buffer_ptr));
Inc(JBLOCK_PTR(prev_block_row));
Inc(JBLOCK_PTR(next_block_row));
Inc(output_col, compptr^.DCT_scaled_size);
end;
Inc(JSAMPROW_PTR(output_ptr), compptr^.DCT_scaled_size);
end;
Inc(compptr);
end;
Inc(cinfo^.output_iMCU_row);
if (cinfo^.output_iMCU_row < cinfo^.total_iMCU_rows) then
begin
decompress_smooth_data := JPEG_ROW_COMPLETED;
exit;
end;
decompress_smooth_data := JPEG_SCAN_COMPLETED;
end;
{$endif} { BLOCK_SMOOTHING_SUPPORTED }
{ Initialize coefficient buffer controller. }
{GLOBAL}
procedure jinit_d_coef_controller (cinfo : j_decompress_ptr;
need_full_buffer : boolean);
var
coef : my_coef_ptr;
{$ifdef D_MULTISCAN_FILES_SUPPORTED}
var
ci, access_rows : int;
compptr : jpeg_component_info_ptr;
{$endif}
var
buffer : JBLOCK_PTR;
i : int;
begin
coef := my_coef_ptr(
cinfo^.mem^.alloc_small (j_common_ptr (cinfo), JPOOL_IMAGE,
SIZEOF(my_coef_controller)) );
cinfo^.coef := jpeg_d_coef_controller_ptr(coef);
coef^.pub.start_input_pass := start_input_pass;
coef^.pub.start_output_pass := start_output_pass;
{$ifdef BLOCK_SMOOTHING_SUPPORTED}
coef^.coef_bits_latch := NIL;
{$endif}
{ Create the coefficient buffer. }
if (need_full_buffer) then
begin
{$ifdef D_MULTISCAN_FILES_SUPPORTED}
{ Allocate a full-image virtual array for each component, }
{ padded to a multiple of samp_factor DCT blocks in each direction. }
{ Note we ask for a pre-zeroed array. }
compptr := cinfo^.comp_info;
for ci := 0 to pred(cinfo^.num_components) do
begin
access_rows := compptr^.v_samp_factor;
{$ifdef BLOCK_SMOOTHING_SUPPORTED}
{ If block smoothing could be used, need a bigger window }
if (cinfo^.progressive_mode) then
access_rows := access_rows * 3;
{$endif}
coef^.whole_image[ci] := cinfo^.mem^.request_virt_barray
(j_common_ptr (cinfo), JPOOL_IMAGE, TRUE,
JDIMENSION (jround_up( long(compptr^.width_in_blocks),
long(compptr^.h_samp_factor) )),
JDIMENSION (jround_up( long(compptr^.height_in_blocks),
long(compptr^.v_samp_factor) )),
JDIMENSION (access_rows));
Inc(compptr);
end;
coef^.pub.consume_data := consume_data;
coef^.pub.decompress_data := decompress_data;
coef^.pub.coef_arrays := @(coef^.whole_image);
{ link to virtual arrays }
{$else}
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
{$endif}
end
else
begin
{ We only need a single-MCU buffer. }
buffer := JBLOCK_PTR (
cinfo^.mem^.alloc_large (j_common_ptr (cinfo), JPOOL_IMAGE,
D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)) );
for i := 0 to pred(D_MAX_BLOCKS_IN_MCU) do
begin
coef^.MCU_buffer[i] := JBLOCKROW(buffer);
Inc(buffer);
end;
coef^.pub.consume_data := dummy_consume_data;
coef^.pub.decompress_data := decompress_onepass;
coef^.pub.coef_arrays := NIL; { flag for no virtual arrays }
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -