PageRenderTime 46ms CodeModel.GetById 20ms app.highlight 3ms RepoModel.GetById 7ms app.codeStats 1ms

/packages/pasjpeg/src/jdinput.pas

https://github.com/slibre/freepascal
Pascal | 416 lines | 244 code | 64 blank | 108 comment | 26 complexity | ff427832b00a28616cb65ce185e4d040 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, LGPL-3.0
  1Unit JdInput;
  2
  3{ Original: jdinput.c ; Copyright (C) 1991-1997, Thomas G. Lane. }
  4
  5{ This file is part of the Independent JPEG Group's software.
  6  For conditions of distribution and use, see the accompanying README file.
  7
  8  This file contains input control logic for the JPEG decompressor.
  9  These routines are concerned with controlling the decompressor's input
 10  processing (marker reading and coefficient decoding).  The actual input
 11  reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. }
 12
 13interface
 14
 15{$I jconfig.inc}
 16
 17uses
 18  jmorecfg,
 19  jpeglib,
 20  jdeferr,
 21  jerror,
 22  jinclude, jutils;
 23
 24{ Initialize the input controller module.
 25  This is called only once, when the decompression object is created. }
 26
 27{GLOBAL}
 28procedure jinit_input_controller (cinfo : j_decompress_ptr);
 29
 30implementation
 31
 32{ Private state }
 33
 34type
 35  my_inputctl_ptr = ^my_input_controller;
 36  my_input_controller = record
 37    pub : jpeg_input_controller; { public fields }
 38
 39    inheaders : boolean;                { TRUE until first SOS is reached }
 40  end; {my_input_controller;}
 41
 42
 43
 44{ Forward declarations }
 45{METHODDEF}
 46function consume_markers (cinfo : j_decompress_ptr) : int; far; forward;
 47
 48
 49{ Routines to calculate various quantities related to the size of the image. }
 50
 51{LOCAL}
 52procedure initial_setup (cinfo : j_decompress_ptr);
 53{ Called once, when first SOS marker is reached }
 54var
 55  ci : int;
 56  compptr : jpeg_component_info_ptr;
 57begin
 58  { Make sure image isn't bigger than I can handle }
 59  if (long(cinfo^.image_height) > long (JPEG_MAX_DIMENSION)) or
 60     (long(cinfo^.image_width) > long(JPEG_MAX_DIMENSION)) then
 61    ERREXIT1(j_common_ptr(cinfo), JERR_IMAGE_TOO_BIG, uInt(JPEG_MAX_DIMENSION));
 62
 63  { For now, precision must match compiled-in value... }
 64  if (cinfo^.data_precision <> BITS_IN_JSAMPLE) then
 65    ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PRECISION, cinfo^.data_precision);
 66
 67  { Check that number of components won't exceed internal array sizes }
 68  if (cinfo^.num_components > MAX_COMPONENTS) then
 69    ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, cinfo^.num_components,
 70             MAX_COMPONENTS);
 71
 72  { Compute maximum sampling factors; check factor validity }
 73  cinfo^.max_h_samp_factor := 1;
 74  cinfo^.max_v_samp_factor := 1;
 75  compptr := jpeg_component_info_ptr(cinfo^.comp_info);
 76  for ci := 0 to pred(cinfo^.num_components) do
 77  begin
 78    if (compptr^.h_samp_factor<=0) or (compptr^.h_samp_factor>MAX_SAMP_FACTOR) or
 79       (compptr^.v_samp_factor<=0) or (compptr^.v_samp_factor>MAX_SAMP_FACTOR) then
 80      ERREXIT(j_common_ptr(cinfo), JERR_BAD_SAMPLING);
 81    {cinfo^.max_h_samp_factor := MAX(cinfo^.max_h_samp_factor,
 82                                   compptr^.h_samp_factor);
 83    cinfo^.max_v_samp_factor := MAX(cinfo^.max_v_samp_factor,
 84                                   compptr^.v_samp_factor);}
 85    if cinfo^.max_h_samp_factor < compptr^.h_samp_factor then
 86      cinfo^.max_h_samp_factor := compptr^.h_samp_factor;
 87    if cinfo^.max_v_samp_factor < compptr^.v_samp_factor then
 88      cinfo^.max_v_samp_factor := compptr^.v_samp_factor;
 89    Inc(compptr);
 90  end;
 91
 92  { We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
 93    In the full decompressor, this will be overridden by jdmaster.c;
 94    but in the transcoder, jdmaster.c is not used, so we must do it here. }
 95
 96  cinfo^.min_DCT_scaled_size := DCTSIZE;
 97
 98  { Compute dimensions of components }
 99  compptr := jpeg_component_info_ptr(cinfo^.comp_info);
100  for ci := 0 to pred(cinfo^.num_components) do
101  begin
102    compptr^.DCT_scaled_size := DCTSIZE;
103    { Size in DCT blocks }
104    compptr^.width_in_blocks := JDIMENSION(
105      jdiv_round_up( long(cinfo^.image_width) * long(compptr^.h_samp_factor),
106                     long(cinfo^.max_h_samp_factor * DCTSIZE)) );
107    compptr^.height_in_blocks := JDIMENSION (
108      jdiv_round_up(long (cinfo^.image_height) * long(compptr^.v_samp_factor),
109                    long (cinfo^.max_v_samp_factor * DCTSIZE)) );
110    { downsampled_width and downsampled_height will also be overridden by
111      jdmaster.c if we are doing full decompression.  The transcoder library
112      doesn't use these values, but the calling application might. }
113
114    { Size in samples }
115    compptr^.downsampled_width := JDIMENSION (
116      jdiv_round_up(long (cinfo^.image_width) * long(compptr^.h_samp_factor),
117                    long (cinfo^.max_h_samp_factor)) );
118    compptr^.downsampled_height := JDIMENSION (
119      jdiv_round_up(long (cinfo^.image_height) * long(compptr^.v_samp_factor),
120                    long (cinfo^.max_v_samp_factor)) );
121    { Mark component needed, until color conversion says otherwise }
122    compptr^.component_needed := TRUE;
123    { Mark no quantization table yet saved for component }
124    compptr^.quant_table := NIL;
125    Inc(compptr);
126  end;
127
128  { Compute number of fully interleaved MCU rows. }
129  cinfo^.total_iMCU_rows := JDIMENSION(
130    jdiv_round_up(long(cinfo^.image_height),
131                  long(cinfo^.max_v_samp_factor*DCTSIZE)) );
132
133  { Decide whether file contains multiple scans }
134  if (cinfo^.comps_in_scan < cinfo^.num_components) or
135     (cinfo^.progressive_mode) then
136    cinfo^.inputctl^.has_multiple_scans := TRUE
137  else
138    cinfo^.inputctl^.has_multiple_scans := FALSE;
139end;
140
141
142{LOCAL}
143procedure per_scan_setup (cinfo : j_decompress_ptr);
144{ Do computations that are needed before processing a JPEG scan }
145{ cinfo^.comps_in_scan and cinfo^.cur_comp_info[] were set from SOS marker }
146var
147  ci, mcublks, tmp : int;
148  compptr : jpeg_component_info_ptr;
149begin
150  if (cinfo^.comps_in_scan = 1) then
151  begin
152    { Noninterleaved (single-component) scan }
153    compptr := cinfo^.cur_comp_info[0];
154
155    { Overall image size in MCUs }
156    cinfo^.MCUs_per_row := compptr^.width_in_blocks;
157    cinfo^.MCU_rows_in_scan := compptr^.height_in_blocks;
158
159    { For noninterleaved scan, always one block per MCU }
160    compptr^.MCU_width := 1;
161    compptr^.MCU_height := 1;
162    compptr^.MCU_blocks := 1;
163    compptr^.MCU_sample_width := compptr^.DCT_scaled_size;
164    compptr^.last_col_width := 1;
165    { For noninterleaved scans, it is convenient to define last_row_height
166      as the number of block rows present in the last iMCU row. }
167
168    tmp := int (compptr^.height_in_blocks mod compptr^.v_samp_factor);
169    if (tmp = 0) then
170      tmp := compptr^.v_samp_factor;
171    compptr^.last_row_height := tmp;
172
173    { Prepare array describing MCU composition }
174    cinfo^.blocks_in_MCU := 1;
175    cinfo^.MCU_membership[0] := 0;
176
177  end
178  else
179  begin
180
181    { Interleaved (multi-component) scan }
182    if (cinfo^.comps_in_scan <= 0) or (cinfo^.comps_in_scan > MAX_COMPS_IN_SCAN) then
183      ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, cinfo^.comps_in_scan,
184               MAX_COMPS_IN_SCAN);
185
186    { Overall image size in MCUs }
187    cinfo^.MCUs_per_row := JDIMENSION (
188      jdiv_round_up(long (cinfo^.image_width),
189                    long (cinfo^.max_h_samp_factor*DCTSIZE)) );
190    cinfo^.MCU_rows_in_scan := JDIMENSION (
191      jdiv_round_up(long (cinfo^.image_height),
192                    long (cinfo^.max_v_samp_factor*DCTSIZE)) );
193
194    cinfo^.blocks_in_MCU := 0;
195
196    for ci := 0 to pred(cinfo^.comps_in_scan) do
197    begin
198      compptr := cinfo^.cur_comp_info[ci];
199      { Sampling factors give # of blocks of component in each MCU }
200      compptr^.MCU_width := compptr^.h_samp_factor;
201      compptr^.MCU_height := compptr^.v_samp_factor;
202      compptr^.MCU_blocks := compptr^.MCU_width * compptr^.MCU_height;
203      compptr^.MCU_sample_width := compptr^.MCU_width * compptr^.DCT_scaled_size;
204      { Figure number of non-dummy blocks in last MCU column & row }
205      tmp := int (compptr^.width_in_blocks mod compptr^.MCU_width);
206      if (tmp = 0) then
207        tmp := compptr^.MCU_width;
208      compptr^.last_col_width := tmp;
209      tmp := int (compptr^.height_in_blocks mod compptr^.MCU_height);
210      if (tmp = 0) then
211        tmp := compptr^.MCU_height;
212      compptr^.last_row_height := tmp;
213      { Prepare array describing MCU composition }
214      mcublks := compptr^.MCU_blocks;
215      if (cinfo^.blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) then
216        ERREXIT(j_common_ptr(cinfo), JERR_BAD_MCU_SIZE);
217      while (mcublks > 0) do
218      begin
219        Dec(mcublks);
220        cinfo^.MCU_membership[cinfo^.blocks_in_MCU] := ci;
221        Inc(cinfo^.blocks_in_MCU);
222      end;
223    end;
224
225  end;
226end;
227
228
229{ Save away a copy of the Q-table referenced by each component present
230  in the current scan, unless already saved during a prior scan.
231
232  In a multiple-scan JPEG file, the encoder could assign different components
233  the same Q-table slot number, but change table definitions between scans
234  so that each component uses a different Q-table.  (The IJG encoder is not
235  currently capable of doing this, but other encoders might.)  Since we want
236  to be able to dequantize all the components at the end of the file, this
237  means that we have to save away the table actually used for each component.
238  We do this by copying the table at the start of the first scan containing
239  the component.
240  The JPEG spec prohibits the encoder from changing the contents of a Q-table
241  slot between scans of a component using that slot.  If the encoder does so
242  anyway, this decoder will simply use the Q-table values that were current
243  at the start of the first scan for the component.
244
245  The decompressor output side looks only at the saved quant tables,
246  not at the current Q-table slots. }
247
248{LOCAL}
249procedure latch_quant_tables (cinfo : j_decompress_ptr);
250var
251  ci, qtblno : int;
252  compptr : jpeg_component_info_ptr;
253  qtbl : JQUANT_TBL_PTR;
254begin
255  for ci := 0 to pred(cinfo^.comps_in_scan) do
256  begin
257    compptr := cinfo^.cur_comp_info[ci];
258    { No work if we already saved Q-table for this component }
259    if (compptr^.quant_table <> NIL) then
260      continue;
261    { Make sure specified quantization table is present }
262    qtblno := compptr^.quant_tbl_no;
263    if (qtblno < 0) or (qtblno >= NUM_QUANT_TBLS) or
264       (cinfo^.quant_tbl_ptrs[qtblno] = NIL) then
265      ERREXIT1(j_common_ptr(cinfo), JERR_NO_QUANT_TABLE, qtblno);
266    { OK, save away the quantization table }
267    qtbl := JQUANT_TBL_PTR(
268      cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
269                                  SIZEOF(JQUANT_TBL)) );
270    MEMCOPY(qtbl, cinfo^.quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
271    compptr^.quant_table := qtbl;
272  end;
273end;
274
275
276{ Initialize the input modules to read a scan of compressed data.
277  The first call to this is done by jdmaster.c after initializing
278  the entire decompressor (during jpeg_start_decompress).
279  Subsequent calls come from consume_markers, below. }
280
281{METHODDEF}
282procedure start_input_pass (cinfo : j_decompress_ptr); far;
283begin
284  per_scan_setup(cinfo);
285  latch_quant_tables(cinfo);
286  cinfo^.entropy^.start_pass (cinfo);
287  cinfo^.coef^.start_input_pass (cinfo);
288  cinfo^.inputctl^.consume_input := cinfo^.coef^.consume_data;
289end;
290
291
292{ Finish up after inputting a compressed-data scan.
293  This is called by the coefficient controller after it's read all
294  the expected data of the scan. }
295
296{METHODDEF}
297procedure finish_input_pass (cinfo : j_decompress_ptr); far;
298begin
299  cinfo^.inputctl^.consume_input := consume_markers;
300end;
301
302
303{ Read JPEG markers before, between, or after compressed-data scans.
304  Change state as necessary when a new scan is reached.
305  Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
306
307  The consume_input method pointer points either here or to the
308  coefficient controller's consume_data routine, depending on whether
309  we are reading a compressed data segment or inter-segment markers. }
310
311{METHODDEF}
312function consume_markers (cinfo : j_decompress_ptr) : int;
313var
314  val : int;
315  inputctl : my_inputctl_ptr;
316begin
317  inputctl := my_inputctl_ptr (cinfo^.inputctl);
318
319  if (inputctl^.pub.eoi_reached) then { After hitting EOI, read no further }
320  begin
321    consume_markers := JPEG_REACHED_EOI;
322    exit;
323  end;
324
325  val := cinfo^.marker^.read_markers (cinfo);
326
327  case (val) of
328  JPEG_REACHED_SOS:     { Found SOS }
329    begin
330      if (inputctl^.inheaders) then
331      begin     { 1st SOS }
332        initial_setup(cinfo);
333        inputctl^.inheaders := FALSE;
334        { Note: start_input_pass must be called by jdmaster.c
335          before any more input can be consumed.  jdapimin.c is
336          responsible for enforcing this sequencing. }
337      end
338      else
339      begin                     { 2nd or later SOS marker }
340        if (not inputctl^.pub.has_multiple_scans) then
341          ERREXIT(j_common_ptr(cinfo), JERR_EOI_EXPECTED); { Oops, I wasn't expecting this! }
342        start_input_pass(cinfo);
343      end;
344    end;
345  JPEG_REACHED_EOI:     { Found EOI }
346    begin
347      inputctl^.pub.eoi_reached := TRUE;
348      if (inputctl^.inheaders) then
349      begin     { Tables-only datastream, apparently }
350        if (cinfo^.marker^.saw_SOF) then
351          ERREXIT(j_common_ptr(cinfo), JERR_SOF_NO_SOS);
352      end
353      else
354      begin
355        { Prevent infinite loop in coef ctlr's decompress_data routine
356          if user set output_scan_number larger than number of scans. }
357
358        if (cinfo^.output_scan_number > cinfo^.input_scan_number) then
359          cinfo^.output_scan_number := cinfo^.input_scan_number;
360      end;
361    end;
362  JPEG_SUSPENDED:;
363  end;
364
365  consume_markers := val;
366end;
367
368
369{ Reset state to begin a fresh datastream. }
370
371{METHODDEF}
372procedure reset_input_controller (cinfo : j_decompress_ptr); far;
373var
374  inputctl : my_inputctl_ptr;
375begin
376  inputctl := my_inputctl_ptr (cinfo^.inputctl);
377
378  inputctl^.pub.consume_input := consume_markers;
379  inputctl^.pub.has_multiple_scans := FALSE; { "unknown" would be better }
380  inputctl^.pub.eoi_reached := FALSE;
381  inputctl^.inheaders := TRUE;
382  { Reset other modules }
383  cinfo^.err^.reset_error_mgr (j_common_ptr(cinfo));
384  cinfo^.marker^.reset_marker_reader (cinfo);
385  { Reset progression state -- would be cleaner if entropy decoder did this }
386  cinfo^.coef_bits := NIL;
387end;
388
389
390{ Initialize the input controller module.
391  This is called only once, when the decompression object is created. }
392
393{GLOBAL}
394procedure jinit_input_controller (cinfo : j_decompress_ptr);
395var
396  inputctl : my_inputctl_ptr;
397begin
398  { Create subobject in permanent pool }
399  inputctl := my_inputctl_ptr(
400    cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_PERMANENT,
401                                SIZEOF(my_input_controller)) );
402  cinfo^.inputctl := jpeg_input_controller_ptr(inputctl);
403  { Initialize method pointers }
404  inputctl^.pub.consume_input := consume_markers;
405  inputctl^.pub.reset_input_controller := reset_input_controller;
406  inputctl^.pub.start_input_pass := start_input_pass;
407  inputctl^.pub.finish_input_pass := finish_input_pass;
408  { Initialize state: can't use reset_input_controller since we don't
409    want to try to reset other modules yet. }
410
411  inputctl^.pub.has_multiple_scans := FALSE; { "unknown" would be better }
412  inputctl^.pub.eoi_reached := FALSE;
413  inputctl^.inheaders := TRUE;
414end;
415
416end.