jdapistd.c revision f5b94eebe742df1a9bb3941fc0a0ec0137e936ef
1/*
2 * jdapistd.c
3 *
4 * Copyright (C) 1994-1996, Thomas G. Lane.
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 application interface code for the decompression half
9 * of the JPEG library.  These are the "standard" API routines that are
10 * used in the normal full-decompression case.  They are not used by a
11 * transcoding-only application.  Note that if an application links in
12 * jpeg_start_decompress, it will end up linking in the entire decompressor.
13 * We thus must separate this file from jdapimin.c to avoid linking the
14 * whole decompression library into a transcoder.
15 */
16
17#define JPEG_INTERNALS
18#include "jinclude.h"
19#include "jpeglib.h"
20
21
22/* Forward declarations */
23LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo));
24
25
26/*
27 * Decompression initialization.
28 * jpeg_read_header must be completed before calling this.
29 *
30 * If a multipass operating mode was selected, this will do all but the
31 * last pass, and thus may take a great deal of time.
32 *
33 * Returns FALSE if suspended.  The return value need be inspected only if
34 * a suspending data source is used.
35 */
36
37GLOBAL(boolean)
38jpeg_start_decompress (j_decompress_ptr cinfo)
39{
40  if (cinfo->global_state == DSTATE_READY) {
41    /* First call: initialize master control, select active modules */
42    jinit_master_decompress(cinfo);
43    if (cinfo->buffered_image) {
44      /* No more work here; expecting jpeg_start_output next */
45      cinfo->global_state = DSTATE_BUFIMAGE;
46      return TRUE;
47    }
48    cinfo->global_state = DSTATE_PRELOAD;
49  }
50  if (cinfo->global_state == DSTATE_PRELOAD) {
51    /* If file has multiple scans, absorb them all into the coef buffer */
52    if (cinfo->inputctl->has_multiple_scans) {
53#ifdef D_MULTISCAN_FILES_SUPPORTED
54      for (;;) {
55	int retcode;
56	/* Call progress monitor hook if present */
57	if (cinfo->progress != NULL)
58	  (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
59	/* Absorb some more input */
60	retcode = (*cinfo->inputctl->consume_input) (cinfo);
61	if (retcode == JPEG_SUSPENDED)
62	  return FALSE;
63	if (retcode == JPEG_REACHED_EOI)
64	  break;
65	/* Advance progress counter if appropriate */
66	if (cinfo->progress != NULL &&
67	    (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
68	  if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
69	    /* jdmaster underestimated number of scans; ratchet up one scan */
70	    cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
71	  }
72	}
73      }
74#else
75      ERREXIT(cinfo, JERR_NOT_COMPILED);
76#endif /* D_MULTISCAN_FILES_SUPPORTED */
77    }
78    cinfo->output_scan_number = cinfo->input_scan_number;
79  } else if (cinfo->global_state != DSTATE_PRESCAN)
80    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
81  /* Perform any dummy output passes, and set up for the final pass */
82  return output_pass_setup(cinfo);
83}
84
85/*
86 * Tile decompression initialization.
87 * jpeg_read_header must be completed before calling this.
88 */
89
90GLOBAL(boolean)
91jpeg_start_tile_decompress (j_decompress_ptr cinfo)
92{
93  if (cinfo->global_state == DSTATE_READY) {
94    /* First call: initialize master control, select active modules */
95    cinfo->tile_decode = TRUE;
96    jinit_master_decompress(cinfo);
97    if (cinfo->buffered_image) {
98      cinfo->global_state = DSTATE_BUFIMAGE;
99      return TRUE;
100    }
101    cinfo->global_state = DSTATE_PRELOAD;
102  }
103  if (cinfo->global_state == DSTATE_PRELOAD) {
104    cinfo->output_scan_number = cinfo->input_scan_number;
105  } else if (cinfo->global_state != DSTATE_PRESCAN)
106    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
107  /* Perform any dummy output passes, and set up for the final pass */
108  return output_pass_setup(cinfo);
109}
110
111
112/*
113 * Set up for an output pass, and perform any dummy pass(es) needed.
114 * Common subroutine for jpeg_start_decompress and jpeg_start_output.
115 * Entry: global_state = DSTATE_PRESCAN only if previously suspended.
116 * Exit: If done, returns TRUE and sets global_state for proper output mode.
117 *       If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.
118 */
119
120LOCAL(boolean)
121output_pass_setup (j_decompress_ptr cinfo)
122{
123  if (cinfo->global_state != DSTATE_PRESCAN) {
124    /* First call: do pass setup */
125    (*cinfo->master->prepare_for_output_pass) (cinfo);
126    cinfo->output_scanline = 0;
127    cinfo->global_state = DSTATE_PRESCAN;
128  }
129  /* Loop over any required dummy passes */
130  while (cinfo->master->is_dummy_pass) {
131#ifdef QUANT_2PASS_SUPPORTED
132    /* Crank through the dummy pass */
133    while (cinfo->output_scanline < cinfo->output_height) {
134      JDIMENSION last_scanline;
135      /* Call progress monitor hook if present */
136      if (cinfo->progress != NULL) {
137	cinfo->progress->pass_counter = (long) cinfo->output_scanline;
138	cinfo->progress->pass_limit = (long) cinfo->output_height;
139	(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
140      }
141      /* Process some data */
142      last_scanline = cinfo->output_scanline;
143      (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
144				    &cinfo->output_scanline, (JDIMENSION) 0);
145      if (cinfo->output_scanline == last_scanline)
146	return FALSE;		/* No progress made, must suspend */
147    }
148    /* Finish up dummy pass, and set up for another one */
149    (*cinfo->master->finish_output_pass) (cinfo);
150    (*cinfo->master->prepare_for_output_pass) (cinfo);
151    cinfo->output_scanline = 0;
152#else
153    ERREXIT(cinfo, JERR_NOT_COMPILED);
154#endif /* QUANT_2PASS_SUPPORTED */
155  }
156  /* Ready for application to drive output pass through
157   * jpeg_read_scanlines or jpeg_read_raw_data.
158   */
159  cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
160  return TRUE;
161}
162
163
164/*
165 * Read some scanlines of data from the JPEG decompressor.
166 *
167 * The return value will be the number of lines actually read.
168 * This may be less than the number requested in several cases,
169 * including bottom of image, data source suspension, and operating
170 * modes that emit multiple scanlines at a time.
171 *
172 * Note: we warn about excess calls to jpeg_read_scanlines() since
173 * this likely signals an application programmer error.  However,
174 * an oversize buffer (max_lines > scanlines remaining) is not an error.
175 */
176
177GLOBAL(JDIMENSION)
178jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
179		     JDIMENSION max_lines)
180{
181  JDIMENSION row_ctr;
182
183  if (cinfo->global_state != DSTATE_SCANNING)
184    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
185  if (cinfo->output_scanline >= cinfo->output_height) {
186    WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
187    return 0;
188  }
189
190  /* Call progress monitor hook if present */
191  if (cinfo->progress != NULL) {
192    cinfo->progress->pass_counter = (long) cinfo->output_scanline;
193    cinfo->progress->pass_limit = (long) cinfo->output_height;
194    (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
195  }
196
197  /* Process some data */
198  row_ctr = 0;
199  (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
200  cinfo->output_scanline += row_ctr;
201  return row_ctr;
202}
203/*
204 * Initialize the jpeg decoder to decompressing a rectangle with size of (width, height)
205 * and its upper-left corner located at (start_x, start_y).
206 * Align start_x and start_y to multiplies of iMCU width and height, respectively.
207 * Also, the new reader position will be returned in (start_x, start_y).
208 */
209
210GLOBAL(void)
211jpeg_init_read_tile_scanline(j_decompress_ptr cinfo, huffman_index *index,
212		     int *start_x, int *start_y, int *width, int *height)
213{
214  // Calculates the boundary of iMCU
215  int lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE;
216  int lines_per_iMCU_col = cinfo->max_h_samp_factor * DCTSIZE;
217  int row_offset = *start_y / lines_per_iMCU_row;
218  int col_left_boundary = ((*start_x / lines_per_iMCU_col)
219            / index->MCU_sample_size) * index->MCU_sample_size;
220  int col_right_boundary = (*start_x + *width + lines_per_iMCU_col - 1)
221            / lines_per_iMCU_col;
222
223  *height = (*start_y - row_offset * lines_per_iMCU_row) + *height;
224  *start_x = col_left_boundary * lines_per_iMCU_col;
225  *start_y = row_offset * lines_per_iMCU_row;
226  cinfo->image_width = jmin(cinfo->original_image_width -
227          col_left_boundary * lines_per_iMCU_col,
228          (col_right_boundary - col_left_boundary) * lines_per_iMCU_col);
229  cinfo->input_iMCU_row = row_offset;
230  cinfo->output_iMCU_row = row_offset;
231
232  // Updates JPEG decoder parameter
233  jinit_color_deconverter(cinfo);
234  jpeg_calc_output_dimensions(cinfo);
235  jinit_upsampler(cinfo);
236  (*cinfo->master->prepare_for_output_pass) (cinfo);
237  if (cinfo->progressive_mode)
238    (*cinfo->entropy->start_pass) (cinfo);
239  else
240    jpeg_decompress_per_scan_setup(cinfo);
241
242  int sampleSize = cinfo->image_width / cinfo->output_width;
243  *height /= sampleSize;
244  *width = cinfo->output_width;
245  cinfo->output_scanline = lines_per_iMCU_row * row_offset / sampleSize;
246  cinfo->inputctl->consume_input = cinfo->coef->consume_data;
247  cinfo->inputctl->consume_input_build_huffman_index =
248      cinfo->coef->consume_data_build_huffman_index;
249  cinfo->entropy->index = index;
250  cinfo->input_iMCU_row = row_offset;
251  cinfo->output_iMCU_row = row_offset;
252  cinfo->coef->MCU_column_left_boundary = col_left_boundary;
253  cinfo->coef->MCU_column_right_boundary = col_right_boundary;
254  cinfo->coef->column_left_boundary =
255      col_left_boundary / index->MCU_sample_size;
256  cinfo->coef->column_right_boundary =
257      jdiv_round_up(col_right_boundary, index->MCU_sample_size);
258}
259
260/*
261 * Read a scanline from the current position.
262 *
263 * Return the number of lines actually read.
264 */
265
266GLOBAL(JDIMENSION)
267jpeg_read_tile_scanline (j_decompress_ptr cinfo, huffman_index *index,
268        JSAMPARRAY scanlines, int start_x, int start_y, int width, int height)
269{
270  // Calculates the boundary of iMCU
271  int lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE;
272  int lines_per_iMCU_col = cinfo->max_h_samp_factor * DCTSIZE;
273  int col_left_boundary = ((start_x / lines_per_iMCU_col)
274          / index->MCU_sample_size) * index->MCU_sample_size;
275  int sampleSize = cinfo->image_width / cinfo->output_width;
276  int row_ctr = 0;
277
278  if (cinfo->progressive_mode) {
279    (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, 1);
280  } else {
281    if (cinfo->output_scanline % (lines_per_iMCU_row / sampleSize) == 0) {
282      // Set the read head to the next iMCU row
283      int iMCU_row_offset = cinfo->output_scanline /
284            (lines_per_iMCU_row / sampleSize);
285      int offset_data_col_position = col_left_boundary / index->MCU_sample_size;
286      huffman_offset_data offset_data =
287          index->scan[0].offset[iMCU_row_offset][offset_data_col_position];
288      (*cinfo->entropy->configure_huffman_decoder) (cinfo, offset_data);
289    }
290    (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, 1);
291  }
292
293  cinfo->output_scanline += row_ctr;
294  return row_ctr;
295}
296
297/*
298 * Alternate entry point to read raw data.
299 * Processes exactly one iMCU row per call, unless suspended.
300 */
301
302GLOBAL(JDIMENSION)
303jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
304		    JDIMENSION max_lines)
305{
306  JDIMENSION lines_per_iMCU_row;
307
308  if (cinfo->global_state != DSTATE_RAW_OK)
309    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
310  if (cinfo->output_scanline >= cinfo->output_height) {
311    WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
312    return 0;
313  }
314
315  /* Call progress monitor hook if present */
316  if (cinfo->progress != NULL) {
317    cinfo->progress->pass_counter = (long) cinfo->output_scanline;
318    cinfo->progress->pass_limit = (long) cinfo->output_height;
319    (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
320  }
321
322  /* Verify that at least one iMCU row can be returned. */
323  lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size;
324  if (max_lines < lines_per_iMCU_row)
325    ERREXIT(cinfo, JERR_BUFFER_SIZE);
326
327  /* Decompress directly into user's buffer. */
328  if (! (*cinfo->coef->decompress_data) (cinfo, data))
329    return 0;			/* suspension forced, can do nothing more */
330
331  /* OK, we processed one iMCU row. */
332  cinfo->output_scanline += lines_per_iMCU_row;
333  return lines_per_iMCU_row;
334}
335
336
337/* Additional entry points for buffered-image mode. */
338
339#ifdef D_MULTISCAN_FILES_SUPPORTED
340
341/*
342 * Initialize for an output pass in buffered-image mode.
343 */
344
345GLOBAL(boolean)
346jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
347{
348  if (cinfo->global_state != DSTATE_BUFIMAGE &&
349      cinfo->global_state != DSTATE_PRESCAN)
350    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
351  /* Limit scan number to valid range */
352  if (scan_number <= 0)
353    scan_number = 1;
354  if (cinfo->inputctl->eoi_reached &&
355      scan_number > cinfo->input_scan_number)
356    scan_number = cinfo->input_scan_number;
357  cinfo->output_scan_number = scan_number;
358  /* Perform any dummy output passes, and set up for the real pass */
359  return output_pass_setup(cinfo);
360}
361
362
363/*
364 * Finish up after an output pass in buffered-image mode.
365 *
366 * Returns FALSE if suspended.  The return value need be inspected only if
367 * a suspending data source is used.
368 */
369
370GLOBAL(boolean)
371jpeg_finish_output (j_decompress_ptr cinfo)
372{
373  if ((cinfo->global_state == DSTATE_SCANNING ||
374       cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
375    /* Terminate this pass. */
376    /* We do not require the whole pass to have been completed. */
377    (*cinfo->master->finish_output_pass) (cinfo);
378    cinfo->global_state = DSTATE_BUFPOST;
379  } else if (cinfo->global_state != DSTATE_BUFPOST) {
380    /* BUFPOST = repeat call after a suspension, anything else is error */
381    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
382  }
383  /* Read markers looking for SOS or EOI */
384  while (cinfo->input_scan_number <= cinfo->output_scan_number &&
385	 ! cinfo->inputctl->eoi_reached) {
386    if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
387      return FALSE;		/* Suspend, come back later */
388  }
389  cinfo->global_state = DSTATE_BUFIMAGE;
390  return TRUE;
391}
392
393#endif /* D_MULTISCAN_FILES_SUPPORTED */
394