📄 jcmaster.pas
字号:
end
else
{$endif}
begin
{ Prepare for single sequential-JPEG scan containing all components }
if (cinfo^.num_components > MAX_COMPS_IN_SCAN) then
ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, cinfo^.num_components,
MAX_COMPS_IN_SCAN);
cinfo^.comps_in_scan := cinfo^.num_components;
comp_infos := cinfo^.comp_info;
for ci := 0 to pred(cinfo^.num_components) do
begin
cinfo^.cur_comp_info[ci] := @(comp_infos^[ci]);
end;
cinfo^.Ss := 0;
cinfo^.Se := DCTSIZE2-1;
cinfo^.Ah := 0;
cinfo^.Al := 0;
end;
end;
{LOCAL}
procedure per_scan_setup (cinfo : j_compress_ptr);
{ Do computations that are needed before processing a JPEG scan }
{ cinfo^.comps_in_scan and cinfo^.cur_comp_info[] are already set }
var
ci, mcublks, tmp : int;
compptr : jpeg_component_info_ptr;
nominal : long;
begin
if (cinfo^.comps_in_scan = 1) then
begin
{ Noninterleaved (single-component) scan }
compptr := cinfo^.cur_comp_info[0];
{ Overall image size in MCUs }
cinfo^.MCUs_per_row := compptr^.width_in_blocks;
cinfo^.MCU_rows_in_scan := compptr^.height_in_blocks;
{ For noninterleaved scan, always one block per MCU }
compptr^.MCU_width := 1;
compptr^.MCU_height := 1;
compptr^.MCU_blocks := 1;
compptr^.MCU_sample_width := DCTSIZE;
compptr^.last_col_width := 1;
{ For noninterleaved scans, it is convenient to define last_row_height
as the number of block rows present in the last iMCU row. }
tmp := int (compptr^.height_in_blocks mod compptr^.v_samp_factor);
if (tmp = 0) then
tmp := compptr^.v_samp_factor;
compptr^.last_row_height := tmp;
{ Prepare array describing MCU composition }
cinfo^.blocks_in_MCU := 1;
cinfo^.MCU_membership[0] := 0;
end
else
begin
{ Interleaved (multi-component) scan }
if (cinfo^.comps_in_scan <= 0) or
(cinfo^.comps_in_scan > MAX_COMPS_IN_SCAN) then
ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT,
cinfo^.comps_in_scan, MAX_COMPS_IN_SCAN);
{ Overall image size in MCUs }
cinfo^.MCUs_per_row := JDIMENSION (
jdiv_round_up( long (cinfo^.image_width),
long (cinfo^.max_h_samp_factor*DCTSIZE)) );
cinfo^.MCU_rows_in_scan := JDIMENSION (
jdiv_round_up( long (cinfo^.image_height),
long (cinfo^.max_v_samp_factor*DCTSIZE)) );
cinfo^.blocks_in_MCU := 0;
for ci := 0 to pred(cinfo^.comps_in_scan) do
begin
compptr := cinfo^.cur_comp_info[ci];
{ Sampling factors give # of blocks of component in each MCU }
compptr^.MCU_width := compptr^.h_samp_factor;
compptr^.MCU_height := compptr^.v_samp_factor;
compptr^.MCU_blocks := compptr^.MCU_width * compptr^.MCU_height;
compptr^.MCU_sample_width := compptr^.MCU_width * DCTSIZE;
{ Figure number of non-dummy blocks in last MCU column & row }
tmp := int (compptr^.width_in_blocks mod compptr^.MCU_width);
if (tmp = 0) then
tmp := compptr^.MCU_width;
compptr^.last_col_width := tmp;
tmp := int (compptr^.height_in_blocks mod compptr^.MCU_height);
if (tmp = 0) then
tmp := compptr^.MCU_height;
compptr^.last_row_height := tmp;
{ Prepare array describing MCU composition }
mcublks := compptr^.MCU_blocks;
if (cinfo^.blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) then
ERREXIT(j_common_ptr(cinfo), JERR_BAD_MCU_SIZE);
while (mcublks > 0) do
begin
Dec(mcublks);
cinfo^.MCU_membership[cinfo^.blocks_in_MCU] := ci;
Inc(cinfo^.blocks_in_MCU);
end;
end;
end;
{ Convert restart specified in rows to actual MCU count. }
{ Note that count must fit in 16 bits, so we provide limiting. }
if (cinfo^.restart_in_rows > 0) then
begin
nominal := long(cinfo^.restart_in_rows) * long(cinfo^.MCUs_per_row);
if nominal < long(65535) then
cinfo^.restart_interval := uInt (nominal)
else
cinfo^.restart_interval := long(65535);
end;
end;
{ Per-pass setup.
This is called at the beginning of each pass. We determine which modules
will be active during this pass and give them appropriate start_pass calls.
We also set is_last_pass to indicate whether any more passes will be
required. }
{METHODDEF}
procedure prepare_for_pass (cinfo : j_compress_ptr); far;
var
master : my_master_ptr;
var
fallthrough : boolean;
begin
master := my_master_ptr (cinfo^.master);
fallthrough := true;
case (master^.pass_type) of
main_pass:
begin
{ Initial pass: will collect input data, and do either Huffman
optimization or data output for the first scan. }
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
if (not cinfo^.raw_data_in) then
begin
cinfo^.cconvert^.start_pass (cinfo);
cinfo^.downsample^.start_pass (cinfo);
cinfo^.prep^.start_pass (cinfo, JBUF_PASS_THRU);
end;
cinfo^.fdct^.start_pass (cinfo);
cinfo^.entropy^.start_pass (cinfo, cinfo^.optimize_coding);
if master^.total_passes > 1 then
cinfo^.coef^.start_pass (cinfo, JBUF_SAVE_AND_PASS)
else
cinfo^.coef^.start_pass (cinfo, JBUF_PASS_THRU);
cinfo^.main^.start_pass (cinfo, JBUF_PASS_THRU);
if (cinfo^.optimize_coding) then
begin
{ No immediate data output; postpone writing frame/scan headers }
master^.pub.call_pass_startup := FALSE;
end
else
begin
{ Will write frame/scan headers at first jpeg_write_scanlines call }
master^.pub.call_pass_startup := TRUE;
end;
end;
{$ifdef ENTROPY_OPT_SUPPORTED}
huff_opt_pass,
output_pass:
begin
if (master^.pass_type = huff_opt_pass) then
begin
{ Do Huffman optimization for a scan after the first one. }
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
if (cinfo^.Ss <> 0) or (cinfo^.Ah = 0) or (cinfo^.arith_code) then
begin
cinfo^.entropy^.start_pass (cinfo, TRUE);
cinfo^.coef^.start_pass (cinfo, JBUF_CRANK_DEST);
master^.pub.call_pass_startup := FALSE;
fallthrough := false;
end;
{ Special case: Huffman DC refinement scans need no Huffman table
and therefore we can skip the optimization pass for them. }
if fallthrough then
begin
master^.pass_type := output_pass;
Inc(master^.pass_number);
{FALLTHROUGH}
end;
end;
{$else}
output_pass:
begin
{$endif}
if fallthrough then
begin
{ Do a data-output pass. }
{ We need not repeat per-scan setup if prior optimization pass did it. }
if (not cinfo^.optimize_coding) then
begin
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
end;
cinfo^.entropy^.start_pass (cinfo, FALSE);
cinfo^.coef^.start_pass (cinfo, JBUF_CRANK_DEST);
{ We emit frame/scan headers now }
if (master^.scan_number = 0) then
cinfo^.marker^.write_frame_header (cinfo);
cinfo^.marker^.write_scan_header (cinfo);
master^.pub.call_pass_startup := FALSE;
end;
end;
else
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
end;
master^.pub.is_last_pass := (master^.pass_number = master^.total_passes-1);
{ Set up progress monitor's pass info if present }
if (cinfo^.progress <> NIL) then
begin
cinfo^.progress^.completed_passes := master^.pass_number;
cinfo^.progress^.total_passes := master^.total_passes;
end;
end;
{ Special start-of-pass hook.
This is called by jpeg_write_scanlines if call_pass_startup is TRUE.
In single-pass processing, we need this hook because we don't want to
write frame/scan headers during jpeg_start_compress; we want to let the
application write COM markers etc. between jpeg_start_compress and the
jpeg_write_scanlines loop.
In multi-pass processing, this routine is not used. }
{METHODDEF}
procedure pass_startup (cinfo : j_compress_ptr); far;
begin
cinfo^.master^.call_pass_startup := FALSE; { reset flag so call only once }
cinfo^.marker^.write_frame_header (cinfo);
cinfo^.marker^.write_scan_header (cinfo);
end;
{ Finish up at end of pass. }
{METHODDEF}
procedure finish_pass_master (cinfo : j_compress_ptr); far;
var
master : my_master_ptr;
begin
master := my_master_ptr (cinfo^.master);
{ The entropy coder always needs an end-of-pass call,
either to analyze statistics or to flush its output buffer. }
cinfo^.entropy^.finish_pass (cinfo);
{ Update state for next pass }
case (master^.pass_type) of
main_pass:
begin
{ next pass is either output of scan 0 (after optimization)
or output of scan 1 (if no optimization). }
master^.pass_type := output_pass;
if (not cinfo^.optimize_coding) then
Inc(master^.scan_number);
end;
huff_opt_pass:
{ next pass is always output of current scan }
master^.pass_type := output_pass;
output_pass:
begin
{ next pass is either optimization or output of next scan }
if (cinfo^.optimize_coding) then
master^.pass_type := huff_opt_pass;
Inc(master^.scan_number);
end;
end;
Inc(master^.pass_number);
end;
{ Initialize master compression control. }
{GLOBAL}
procedure jinit_c_master_control (cinfo : j_compress_ptr;
transcode_only : boolean);
var
master : my_master_ptr;
begin
master := my_master_ptr(
cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
SIZEOF(my_comp_master)) );
cinfo^.master := jpeg_comp_master_ptr(master);
master^.pub.prepare_for_pass := prepare_for_pass;
master^.pub.pass_startup := pass_startup;
master^.pub.finish_pass := finish_pass_master;
master^.pub.is_last_pass := FALSE;
{ Validate parameters, determine derived values }
initial_setup(cinfo);
if (cinfo^.scan_info <> NIL) then
begin
{$ifdef C_MULTISCAN_FILES_SUPPORTED}
validate_script(cinfo);
{$else}
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
{$endif}
end
else
begin
cinfo^.progressive_mode := FALSE;
cinfo^.num_scans := 1;
end;
if (cinfo^.progressive_mode) then { TEMPORARY HACK ??? }
cinfo^.optimize_coding := TRUE; { assume default tables no good for progressive mode }
{ Initialize my private state }
if (transcode_only) then
begin
{ no main pass in transcoding }
if (cinfo^.optimize_coding) then
master^.pass_type := huff_opt_pass
else
master^.pass_type := output_pass;
end
else
begin
{ for normal compression, first pass is always this type: }
master^.pass_type := main_pass;
end;
master^.scan_number := 0;
master^.pass_number := 0;
if (cinfo^.optimize_coding) then
master^.total_passes := cinfo^.num_scans * 2
else
master^.total_passes := cinfo^.num_scans;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -