123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702 |
- Unit JcMaster;
- { This file contains master control logic for the JPEG compressor.
- These routines are concerned with parameter validation, initial setup,
- and inter-pass control (determining the number of passes and the work
- to be done in each pass). }
- { Original: jcmaster.c ; Copyright (C) 1991-1997, Thomas G. Lane. }
- interface
- {$I jconfig.inc}
- uses
- jmorecfg,
- jinclude,
- jdeferr,
- jerror,
- jutils,
- jpeglib;
- { Initialize master compression control. }
- {GLOBAL}
- procedure jinit_c_master_control (cinfo : j_compress_ptr;
- transcode_only : boolean);
- implementation
- { Private state }
- type
- c_pass_type = (
- main_pass, { input data, also do first output step }
- huff_opt_pass, { Huffman code optimization pass }
- output_pass { data output pass }
- );
- type
- my_master_ptr = ^my_comp_master;
- my_comp_master = record
- pub : jpeg_comp_master; { public fields }
- pass_type : c_pass_type; { the type of the current pass }
- pass_number : int; { # of passes completed }
- total_passes : int; { total # of passes needed }
- scan_number : int; { current index in scan_info[] }
- end;
- { Support routines that do various essential calculations. }
- {LOCAL}
- procedure initial_setup (cinfo : j_compress_ptr);
- { Do computations that are needed before master selection phase }
- var
- ci : int;
- compptr : jpeg_component_info_ptr;
- samplesperrow : long;
- jd_samplesperrow : JDIMENSION;
- begin
- { Sanity check on image dimensions }
- if (cinfo^.image_height <= 0) or (cinfo^.image_width <= 0) or
- (cinfo^.num_components <= 0) or (cinfo^.input_components <= 0) then
- ERREXIT(j_common_ptr(cinfo), JERR_EMPTY_IMAGE);
- { Make sure image isn't bigger than I can handle }
- if ( long(cinfo^.image_height) > long(JPEG_MAX_DIMENSION)) or
- ( long(cinfo^.image_width) > long(JPEG_MAX_DIMENSION)) then
- ERREXIT1(j_common_ptr(cinfo), JERR_IMAGE_TOO_BIG,
- uInt(JPEG_MAX_DIMENSION));
- { Width of an input scanline must be representable as JDIMENSION. }
- samplesperrow := long (cinfo^.image_width) * long (cinfo^.input_components);
- jd_samplesperrow := JDIMENSION (samplesperrow);
- if ( long(jd_samplesperrow) <> samplesperrow) then
- ERREXIT(j_common_ptr(cinfo), JERR_WIDTH_OVERFLOW);
- { For now, precision must match compiled-in value... }
- if (cinfo^.data_precision <> BITS_IN_JSAMPLE) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PRECISION, cinfo^.data_precision);
- { Check that number of components won't exceed internal array sizes }
- if (cinfo^.num_components > MAX_COMPONENTS) then
- ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, cinfo^.num_components,
- MAX_COMPONENTS);
- { Compute maximum sampling factors; check factor validity }
- cinfo^.max_h_samp_factor := 1;
- cinfo^.max_v_samp_factor := 1;
- compptr := jpeg_component_info_ptr(cinfo^.comp_info);
- for ci := 0 to pred(cinfo^.num_components) do
- begin
- if (compptr^.h_samp_factor<=0) or (compptr^.h_samp_factor>MAX_SAMP_FACTOR)
- or (compptr^.v_samp_factor<=0) or (compptr^.v_samp_factor>MAX_SAMP_FACTOR) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_SAMPLING);
- { MAX }
- if cinfo^.max_h_samp_factor > compptr^.h_samp_factor then
- cinfo^.max_h_samp_factor := cinfo^.max_h_samp_factor
- else
- cinfo^.max_h_samp_factor := compptr^.h_samp_factor;
- { MAX }
- if cinfo^.max_v_samp_factor > compptr^.v_samp_factor then
- cinfo^.max_v_samp_factor := cinfo^.max_v_samp_factor
- else
- cinfo^.max_v_samp_factor := compptr^.v_samp_factor;
- Inc(compptr);
- end;
- { Compute dimensions of components }
- compptr := jpeg_component_info_ptr(cinfo^.comp_info);
- for ci := 0 to pred(cinfo^.num_components) do
- begin
- { Fill in the correct component_index value; don't rely on application }
- compptr^.component_index := ci;
- { For compression, we never do DCT scaling. }
- compptr^.DCT_scaled_size := DCTSIZE;
- { Size in DCT blocks }
- compptr^.width_in_blocks := JDIMENSION (
- jdiv_round_up(long (cinfo^.image_width) * long (compptr^.h_samp_factor),
- long (cinfo^.max_h_samp_factor * DCTSIZE)) );
- compptr^.height_in_blocks := JDIMENSION (
- jdiv_round_up(long (cinfo^.image_height) * long (compptr^.v_samp_factor),
- long (cinfo^.max_v_samp_factor * DCTSIZE)) );
- { Size in samples }
- compptr^.downsampled_width := JDIMENSION (
- jdiv_round_up(long(cinfo^.image_width) * long(compptr^.h_samp_factor),
- long(cinfo^.max_h_samp_factor)) );
- compptr^.downsampled_height := JDIMENSION (
- jdiv_round_up(long (cinfo^.image_height) * long(compptr^.v_samp_factor),
- long (cinfo^.max_v_samp_factor)) );
- { Mark component needed (this flag isn't actually used for compression) }
- compptr^.component_needed := TRUE;
- Inc(compptr);
- end;
- { Compute number of fully interleaved MCU rows (number of times that
- main controller will call coefficient controller). }
- cinfo^.total_iMCU_rows := JDIMENSION (
- jdiv_round_up(long (cinfo^.image_height),
- long (cinfo^.max_v_samp_factor*DCTSIZE)) );
- end;
- {$ifdef C_MULTISCAN_FILES_SUPPORTED}
- {LOCAL}
- procedure validate_script (cinfo : j_compress_ptr);
- { Verify that the scan script in cinfo^.scan_info[] is valid; also
- determine whether it uses progressive JPEG, and set cinfo^.progressive_mode. }
- type
- IntRow = array[0..DCTSIZE2-1] of int;
- introw_ptr = ^IntRow;
- var
- {const}scanptr : jpeg_scan_info_ptr;
- scanno, ncomps, ci, coefi, thisi : int;
- Ss, Se, Ah, Al : int;
- component_sent : array[0..MAX_COMPONENTS-1] of boolean;
- {$ifdef C_PROGRESSIVE_SUPPORTED}
- last_bitpos_int_ptr : int_ptr;
- last_bitpos_ptr : introw_ptr;
- last_bitpos : array[0..MAX_COMPONENTS-1] of IntRow;
- { -1 until that coefficient has been seen; then last Al for it }
- { The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
- seems wrong: the upper bound ought to depend on data precision.
- Perhaps they really meant 0..N+1 for N-bit precision.
- Here we allow 0..10 for 8-bit data; Al larger than 10 results in
- out-of-range reconstructed DC values during the first DC scan,
- which might cause problems for some decoders. }
- {$ifdef BITS_IN_JSAMPLE_IS_8}
- const
- MAX_AH_AL = 10;
- {$else}
- const
- MAX_AH_AL = 13;
- {$endif}
- {$endif}
- begin
- if (cinfo^.num_scans <= 0) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_SCAN_SCRIPT, 0);
- { For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
- for progressive JPEG, no scan can have this. }
- scanptr := cinfo^.scan_info;
- if (scanptr^.Ss <> 0) or (scanptr^.Se <> DCTSIZE2-1) then
- begin
- {$ifdef C_PROGRESSIVE_SUPPORTED}
- cinfo^.progressive_mode := TRUE;
- last_bitpos_int_ptr := @(last_bitpos[0][0]);
- for ci := 0 to pred(cinfo^.num_components) do
- for coefi := 0 to pred(DCTSIZE2) do
- begin
- last_bitpos_int_ptr^ := -1;
- Inc(last_bitpos_int_ptr);
- end;
- {$else}
- ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
- {$endif}
- end
- else
- begin
- cinfo^.progressive_mode := FALSE;
- for ci := 0 to pred(cinfo^.num_components) do
- component_sent[ci] := FALSE;
- end;
- for scanno := 1 to cinfo^.num_scans do
- begin
- { Validate component indexes }
- ncomps := scanptr^.comps_in_scan;
- if (ncomps <= 0) or (ncomps > MAX_COMPS_IN_SCAN) then
- ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
- for ci := 0 to pred(ncomps) do
- begin
- thisi := scanptr^.component_index[ci];
- if (thisi < 0) or (thisi >= cinfo^.num_components) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_SCAN_SCRIPT, scanno);
- { Components must appear in SOF order within each scan }
- if (ci > 0) and (thisi <= scanptr^.component_index[ci-1]) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_SCAN_SCRIPT, scanno);
- end;
- { Validate progression parameters }
- Ss := scanptr^.Ss;
- Se := scanptr^.Se;
- Ah := scanptr^.Ah;
- Al := scanptr^.Al;
- if (cinfo^.progressive_mode) then
- begin
- {$ifdef C_PROGRESSIVE_SUPPORTED}
- if (Ss < 0) or (Ss >= DCTSIZE2) or (Se < Ss) or (Se >= DCTSIZE2) or
- (Ah < 0) or (Ah > MAX_AH_AL) or (Al < 0) or (Al > MAX_AH_AL) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno);
- if (Ss < 0) or (Ss >= DCTSIZE2) or (Se < Ss) or (Se >= DCTSIZE2)
- or (Ah < 0) or (Ah > MAX_AH_AL) or (Al < 0) or (Al > MAX_AH_AL) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno);
- if (Ss = 0) then
- begin
- if (Se <> 0) then { DC and AC together not OK }
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno);
- end
- else
- begin
- if (ncomps <> 1) then { AC scans must be for only one component }
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno);
- end;
- for ci := 0 to pred(ncomps) do
- begin
- last_bitpos_ptr := @( last_bitpos[scanptr^.component_index[ci]]);
- if (Ss <> 0) and (last_bitpos_ptr^[0] < 0) then { AC without prior DC scan }
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno);
- for coefi := Ss to Se do
- begin
- if (last_bitpos_ptr^[coefi] < 0) then
- begin
- { first scan of this coefficient }
- if (Ah <> 0) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno);
- end
- else
- begin
- { not first scan }
- if (Ah <> last_bitpos_ptr^[coefi]) or (Al <> Ah-1) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno);
- end;
- last_bitpos_ptr^[coefi] := Al;
- end;
- end;
- {$endif}
- end
- else
- begin
- { For sequential JPEG, all progression parameters must be these: }
- if (Ss <> 0) or (Se <> DCTSIZE2-1) or (Ah <> 0) or (Al <> 0) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno);
- { Make sure components are not sent twice }
- for ci := 0 to pred(ncomps) do
- begin
- thisi := scanptr^.component_index[ci];
- if (component_sent[thisi]) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_SCAN_SCRIPT, scanno);
- component_sent[thisi] := TRUE;
- end;
- end;
- Inc(scanptr);
- end;
- { Now verify that everything got sent. }
- if (cinfo^.progressive_mode) then
- begin
- {$ifdef C_PROGRESSIVE_SUPPORTED
- { For progressive mode, we only check that at least some DC data
- got sent for each component; the spec does not require that all bits
- of all coefficients be transmitted. Would it be wiser to enforce
- transmission of all coefficient bits?? }
- for ci := 0 to pred(cinfo^.num_components) do
- begin
- if (last_bitpos[ci][0] < 0) then
- ERREXIT(j_common_ptr(cinfo), JERR_MISSING_DATA);
- end;
- {$endif}
- end
- else
- begin
- for ci := 0 to pred(cinfo^.num_components) do
- begin
- if (not component_sent[ci]) then
- ERREXIT(j_common_ptr(cinfo), JERR_MISSING_DATA);
- end;
- end;
- end;
- {$endif} { C_MULTISCAN_FILES_SUPPORTED }
- {LOCAL}
- procedure select_scan_parameters (cinfo : j_compress_ptr);
- { Set up the scan parameters for the current scan }
- var
- master : my_master_ptr;
- {const} scanptr : jpeg_scan_info_ptr;
- ci : int;
- var
- comp_infos : jpeg_component_info_list_ptr;
- begin
- {$ifdef C_MULTISCAN_FILES_SUPPORTED}
- if (cinfo^.scan_info <> NIL) then
- begin
- { Prepare for current scan --- the script is already validated }
- master := my_master_ptr (cinfo^.master);
- scanptr := cinfo^.scan_info;
- Inc(scanptr, master^.scan_number);
- cinfo^.comps_in_scan := scanptr^.comps_in_scan;
- comp_infos := cinfo^.comp_info;
- for ci := 0 to pred(scanptr^.comps_in_scan) do
- begin
- cinfo^.cur_comp_info[ci] :=
- @(comp_infos^[scanptr^.component_index[ci]]);
- end;
- cinfo^.Ss := scanptr^.Ss;
- cinfo^.Se := scanptr^.Se;
- cinfo^.Ah := scanptr^.Ah;
- cinfo^.Al := scanptr^.Al;
- 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.
|