home *** CD-ROM | disk | FTP | other *** search
- /*
- * jdpipe.c
- *
- * Copyright (C) 1991, 1992, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
- *
- * This file contains decompression pipeline controllers.
- * These routines are invoked via the d_pipeline_controller method.
- *
- * There are two basic pipeline controllers. The simpler one handles a
- * single-scan JPEG file (single component or fully interleaved) with no
- * color quantization or 1-pass quantization. In this case, the file can
- * be processed in one top-to-bottom pass. The more complex controller is
- * used when 2-pass color quantization is requested and/or the JPEG file
- * has multiple scans (noninterleaved or partially interleaved). In this
- * case, the entire image must be buffered up in a "big" array.
- *
- * If you need to make a minimal implementation, the more complex controller
- * can be compiled out by disabling the appropriate configuration options.
- * We don't recommend this, since then you can't handle all legal JPEG files.
- */
-
- #include "jinclude.h"
-
-
- #ifdef D_MULTISCAN_FILES_SUPPORTED /* wish we could assume ANSI's defined() */
- #define NEED_COMPLEX_CONTROLLER
- #else
- #ifdef QUANT_2PASS_SUPPORTED
- #define NEED_COMPLEX_CONTROLLER
- #endif
- #endif
-
-
- /*
- * About the data structures:
- *
- * The processing chunk size for upsampling is referred to in this file as
- * a "row group": a row group is defined as Vk (v_samp_factor) sample rows of
- * any component while downsampled, or Vmax (max_v_samp_factor) unsubsampled
- * rows. In an interleaved scan each MCU row contains exactly DCTSIZE row
- * groups of each component in the scan. In a noninterleaved scan an MCU row
- * is one row of blocks, which might not be an integral number of row groups;
- * therefore, we read in Vk MCU rows to obtain the same amount of data as we'd
- * have in an interleaved scan.
- * To provide context for the upsampling step, we have to retain the last
- * two row groups of the previous MCU row while reading in the next MCU row
- * (or set of Vk MCU rows). To do this without copying data about, we create
- * a rather strange data structure. Exactly DCTSIZE+2 row groups of samples
- * are allocated, but we create two different sets of pointers to this array.
- * The second set swaps the last two pairs of row groups. By working
- * alternately with the two sets of pointers, we can access the data in the
- * desired order.
- *
- * Cross-block smoothing also needs context above and below the "current" row.
- * Since this is an optional feature, I've implemented it in a way that is
- * much simpler but requires more than the minimum amount of memory. We
- * simply allocate three extra MCU rows worth of coefficient blocks and use
- * them to "read ahead" one MCU row in the file. For a typical 1000-pixel-wide
- * image with 2x2,1x1,1x1 sampling, each MCU row is about 50Kb; an 80x86
- * machine may be unable to apply cross-block smoothing to wider images.
- */
-
-
- /*
- * These variables are logically local to the pipeline controller,
- * but we make them static so that scan_big_image can use them
- * without having to pass them through the quantization routines.
- */
-
- static int rows_in_mem; /* # of sample rows in full-size buffers */
- /* Work buffer for data being passed to output module. */
- /* This has color_out_comps components if not quantizing, */
- /* but only one component when quantizing. */
- static JSAMPIMAGE output_workspace;
-
- #ifdef NEED_COMPLEX_CONTROLLER
- /* Full-size image array holding upsampled, but not color-processed data. */
- static big_sarray_ptr *fullsize_image;
- static JSAMPIMAGE fullsize_ptrs; /* workspace for access_big_sarray() result */
- #endif
-
-
- /*
- * Utility routines: common code for pipeline controllers
- */
-
- LOCAL void
- interleaved_scan_setup (decompress_info_ptr cinfo)
- /* Compute all derived info for an interleaved (multi-component) scan */
- /* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */
- {
- short ci, mcublks;
- jpeg_component_info *compptr;
-
- if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
- ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
-
- cinfo->MCUs_per_row = (cinfo->image_width
- + cinfo->max_h_samp_factor*DCTSIZE - 1)
- / (cinfo->max_h_samp_factor*DCTSIZE);
-
- cinfo->MCU_rows_in_scan = (cinfo->image_height
- + cinfo->max_v_samp_factor*DCTSIZE - 1)
- / (cinfo->max_v_samp_factor*DCTSIZE);
-
- cinfo->blocks_in_MCU = 0;
-
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- compptr = cinfo->cur_comp_info[ci];
- /* for interleaved scan, sampling factors give # of blocks per component */
- compptr->MCU_width = compptr->h_samp_factor;
- compptr->MCU_height = compptr->v_samp_factor;
- compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
- /* compute physical dimensions of component */
- compptr->downsampled_width = jround_up(compptr->true_comp_width,
- (long) (compptr->MCU_width*DCTSIZE));
- compptr->downsampled_height = jround_up(compptr->true_comp_height,
- (long) (compptr->MCU_height*DCTSIZE));
- /* Sanity check */
- if (compptr->downsampled_width !=
- (cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
- ERREXIT(cinfo->emethods, "I'm confused about the image width");
- /* Prepare array describing MCU composition */
- mcublks = compptr->MCU_blocks;
- if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
- ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan");
- while (mcublks-- > 0) {
- cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
- }
- }
-
- (*cinfo->methods->d_per_scan_method_selection) (cinfo);
- }
-
-
- LOCAL void
- noninterleaved_scan_setup (decompress_info_ptr cinfo)
- /* Compute all derived info for a noninterleaved (single-component) scan */
- /* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */
- {
- jpeg_component_info *compptr = cinfo->cur_comp_info[0];
-
- /* for noninterleaved scan, always one block per MCU */
- compptr->MCU_width = 1;
- compptr->MCU_height = 1;
- compptr->MCU_blocks = 1;
- /* compute physical dimensions of component */
- compptr->downsampled_width = jround_up(compptr->true_comp_width,
- (long) DCTSIZE);
- compptr->downsampled_height = jround_up(compptr->true_comp_height,
- (long) DCTSIZE);
-
- cinfo->MCUs_per_row = compptr->downsampled_width / DCTSIZE;
- cinfo->MCU_rows_in_scan = compptr->downsampled_height / DCTSIZE;
-
- /* Prepare array describing MCU composition */
- cinfo->blocks_in_MCU = 1;
- cinfo->MCU_membership[0] = 0;
-
- (*cinfo->methods->d_per_scan_method_selection) (cinfo);
- }
-
-
-
- LOCAL JSAMPIMAGE
- alloc_sampimage (decompress_info_ptr cinfo,
- int num_comps, long num_rows, long num_cols)
- /* Allocate an in-memory sample image (all components same size) */
- {
- JSAMPIMAGE image;
- int ci;
-
- image = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
- (num_comps * SIZEOF(JSAMPARRAY));
- for (ci = 0; ci < num_comps; ci++) {
- image[ci] = (*cinfo->emethods->alloc_small_sarray) (num_cols, num_rows);
- }
- return image;
- }
-
-
- #if 0 /* this routine not currently needed */
-
- LOCAL void
- free_sampimage (decompress_info_ptr cinfo, JSAMPIMAGE image, int num_comps)
- /* Release a sample image created by alloc_sampimage */
- {
- int ci;
-
- for (ci = 0; ci < num_comps; ci++) {
- (*cinfo->emethods->free_small_sarray) (image[ci]);
- }
- (*cinfo->emethods->free_small) ((void *) image);
- }
-
- #endif
-
-
- LOCAL JBLOCKIMAGE
- alloc_MCU_row (decompress_info_ptr cinfo)
- /* Allocate one MCU row's worth of coefficient blocks */
- {
- JBLOCKIMAGE image;
- int ci;
-
- image = (JBLOCKIMAGE) (*cinfo->emethods->alloc_small)
- (cinfo->comps_in_scan * SIZEOF(JBLOCKARRAY));
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- image[ci] = (*cinfo->emethods->alloc_small_barray)
- (cinfo->cur_comp_info[ci]->downsampled_width / DCTSIZE,
- (long) cinfo->cur_comp_info[ci]->MCU_height);
- }
- return image;
- }
-
-
- #ifdef NEED_COMPLEX_CONTROLLER /* not used by simple controller */
-
- LOCAL void
- free_MCU_row (decompress_info_ptr cinfo, JBLOCKIMAGE image)
- /* Release a coefficient block array created by alloc_MCU_row */
- {
- int ci;
-
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- (*cinfo->emethods->free_small_barray) (image[ci]);
- }
- (*cinfo->emethods->free_small) ((void *) image);
- }
-
- #endif
-
-
- LOCAL void
- alloc_sampling_buffer (decompress_info_ptr cinfo, JSAMPIMAGE sampled_data[2])
- /* Create a downsampled-data buffer having the desired structure */
- /* (see comments at head of file) */
- {
- short ci, vs, i;
-
- /* Get top-level space for array pointers */
- sampled_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
- (cinfo->comps_in_scan * SIZEOF(JSAMPARRAY));
- sampled_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
- (cinfo->comps_in_scan * SIZEOF(JSAMPARRAY));
-
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- vs = cinfo->cur_comp_info[ci]->v_samp_factor; /* row group height */
- /* Allocate the real storage */
- sampled_data[0][ci] = (*cinfo->emethods->alloc_small_sarray)
- (cinfo->cur_comp_info[ci]->downsampled_width,
- (long) (vs * (DCTSIZE+2)));
- /* Create space for the scrambled-order pointers */
- sampled_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small)
- (vs * (DCTSIZE+2) * SIZEOF(JSAMPROW));
- /* Duplicate the first DCTSIZE-2 row groups */
- for (i = 0; i < vs * (DCTSIZE-2); i++) {
- sampled_data[1][ci][i] = sampled_data[0][ci][i];
- }
- /* Copy the last four row groups in swapped order */
- for (i = 0; i < vs * 2; i++) {
- sampled_data[1][ci][vs*DCTSIZE + i] = sampled_data[0][ci][vs*(DCTSIZE-2) + i];
- sampled_data[1][ci][vs*(DCTSIZE-2) + i] = sampled_data[0][ci][vs*DCTSIZE + i];
- }
- }
- }
-
-
- #ifdef NEED_COMPLEX_CONTROLLER /* not used by simple controller */
-
- LOCAL void
- free_sampling_buffer (decompress_info_ptr cinfo, JSAMPIMAGE sampled_data[2])
- /* Release a sampling buffer created by alloc_sampling_buffer */
- {
- short ci;
-
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- /* Free the real storage */
- (*cinfo->emethods->free_small_sarray) (sampled_data[0][ci]);
- /* Free the scrambled-order pointers */
- (*cinfo->emethods->free_small) ((void *) sampled_data[1][ci]);
- }
-
- /* Free the top-level space */
- (*cinfo->emethods->free_small) ((void *) sampled_data[0]);
- (*cinfo->emethods->free_small) ((void *) sampled_data[1]);
- }
-
- #endif
-
-
- /*
- * Several decompression processes need to range-limit values to the range
- * 0..MAXJSAMPLE; the input value may fall somewhat outside this range
- * due to noise introduced by quantization, roundoff error, etc. These
- * processes are inner loops and need to be as fast as possible. On most
- * machines, particularly CPUs with pipelines or instruction prefetch,
- * a (range-check-less) C table lookup
- * x = sample_range_limit[x];
- * is faster than explicit tests
- * if (x < 0) x = 0;
- * else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
- * These processes all use a common table prepared by the routine below.
- *
- * The table will work correctly for x within MAXJSAMPLE+1 of the legal
- * range. This is a much wider range than is needed for most cases,
- * but the wide range is handy for color quantization.
- * Note that the table is allocated in near data space on PCs; it's small
- * enough and used often enough to justify this.
- */
-
- LOCAL void
- prepare_range_limit_table (decompress_info_ptr cinfo)
- /* Allocate and fill in the sample_range_limit table */
- {
- JSAMPLE * table;
- int i;
-
- table = (JSAMPLE *) (*cinfo->emethods->alloc_small)
- (3 * (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
- cinfo->sample_range_limit = table + (MAXJSAMPLE+1);
- for (i = 0; i <= MAXJSAMPLE; i++) {
- table[i] = 0; /* sample_range_limit[x] = 0 for x<0 */
- table[i+(MAXJSAMPLE+1)] = (JSAMPLE) i; /* sample_range_limit[x] = x */
- table[i+(MAXJSAMPLE+1)*2] = MAXJSAMPLE; /* x beyond MAXJSAMPLE */
- }
- }
-
-
- LOCAL void
- duplicate_row (JSAMPARRAY image_data,
- long num_cols, int source_row, int num_rows)
- /* Duplicate the source_row at source_row+1 .. source_row+num_rows */
- /* This happens only at the bottom of the image, */
- /* so it needn't be super-efficient */
- {
- register int row;
-
- for (row = 1; row <= num_rows; row++) {
- jcopy_sample_rows(image_data, source_row, image_data, source_row + row,
- 1, num_cols);
- }
- }
-
-
- LOCAL void
- expand (decompress_info_ptr cinfo,
- JSAMPIMAGE sampled_data, JSAMPIMAGE fullsize_data,
- long fullsize_width,
- short above, short current, short below, short out)
- /* Do upsampling expansion of a single row group (of each component). */
- /* above, current, below are indexes of row groups in sampled_data; */
- /* out is the index of the target row group in fullsize_data. */
- /* Special case: above, below can be -1 to indicate top, bottom of image. */
- {
- jpeg_component_info *compptr;
- JSAMPARRAY above_ptr, below_ptr;
- JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for downsample expansion at top/bottom */
- short ci, vs, i;
-
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- compptr = cinfo->cur_comp_info[ci];
- vs = compptr->v_samp_factor; /* row group height */
-
- if (above >= 0)
- above_ptr = sampled_data[ci] + above * vs;
- else {
- /* Top of image: make a dummy above-context with copies of 1st row */
- /* We assume current=0 in this case */
- for (i = 0; i < vs; i++)
- dummy[i] = sampled_data[ci][0];
- above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
- }
-
- if (below >= 0)
- below_ptr = sampled_data[ci] + below * vs;
- else {
- /* Bot of image: make a dummy below-context with copies of last row */
- for (i = 0; i < vs; i++)
- dummy[i] = sampled_data[ci][(current+1)*vs-1];
- below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
- }
-
- (*cinfo->methods->upsample[ci])
- (cinfo, (int) ci,
- compptr->downsampled_width, (int) vs,
- fullsize_width, (int) cinfo->max_v_samp_factor,
- above_ptr,
- sampled_data[ci] + current * vs,
- below_ptr,
- fullsize_data[ci] + out * cinfo->max_v_samp_factor);
- }
- }
-
-
- LOCAL void
- emit_1pass (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE fullsize_data,
- JSAMPARRAY dummy)
- /* Do color processing and output of num_rows full-size rows. */
- /* This is not used when doing 2-pass color quantization. */
- /* The dummy argument simply lets this be called via scan_big_image. */
- {
- if (cinfo->quantize_colors) {
- (*cinfo->methods->color_quantize) (cinfo, num_rows, fullsize_data,
- output_workspace[0]);
- } else {
- (*cinfo->methods->color_convert) (cinfo, num_rows, cinfo->image_width,
- fullsize_data, output_workspace);
- }
-
- (*cinfo->methods->put_pixel_rows) (cinfo, num_rows, output_workspace);
- }
-
-
- /*
- * Support routines for complex controller.
- */
-
- #ifdef NEED_COMPLEX_CONTROLLER
-
- METHODDEF void
- scan_big_image (decompress_info_ptr cinfo, quantize_method_ptr quantize_method)
- /* Apply quantize_method to entire image stored in fullsize_image[]. */
- /* This is the "iterator" routine used by the 2-pass color quantizer. */
- /* We also use it directly in some cases. */
- {
- long pixel_rows_output;
- short ci;
-
- for (pixel_rows_output = 0; pixel_rows_output < cinfo->image_height;
- pixel_rows_output += rows_in_mem) {
- (*cinfo->methods->progress_monitor) (cinfo, pixel_rows_output,
- cinfo->image_height);
- /* Realign the big buffers */
- for (ci = 0; ci < cinfo->num_components; ci++) {
- fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray)
- (fullsize_image[ci], pixel_rows_output, FALSE);
- }
- /* Let the quantizer have its way with the data.
- * Note that output_workspace is simply workspace for the quantizer;
- * when it's ready to output, it must call put_pixel_rows itself.
- */
- (*quantize_method) (cinfo,
- (int) MIN((long) rows_in_mem,
- cinfo->image_height - pixel_rows_output),
- fullsize_ptrs, output_workspace[0]);
- }
-
- cinfo->completed_passes++;
- }
-
- #endif /* NEED_COMPLEX_CONTROLLER */
-
-
- /*
- * Support routines for cross-block smoothing.
- */
-
- #ifdef BLOCK_SMOOTHING_SUPPORTED
-
-
- LOCAL void
- smooth_mcu_row (decompress_info_ptr cinfo,
- JBLOCKIMAGE above, JBLOCKIMAGE input, JBLOCKIMAGE below,
- JBLOCKIMAGE output)
- /* Apply cross-block smoothing to one MCU row's worth of coefficient blocks. */
- /* above,below are NULL if at top/bottom of image. */
- {
- jpeg_component_info *compptr;
- short ci, ri, last;
- JBLOCKROW prev;
-
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- compptr = cinfo->cur_comp_info[ci];
- last = compptr->MCU_height - 1;
-
- if (above == NULL)
- prev = NULL;
- else
- prev = above[ci][last];
-
- for (ri = 0; ri < last; ri++) {
- (*cinfo->methods->smooth_coefficients) (cinfo, compptr,
- prev, input[ci][ri], input[ci][ri+1],
- output[ci][ri]);
- prev = input[ci][ri];
- }
-
- if (below == NULL)
- (*cinfo->methods->smooth_coefficients) (cinfo, compptr,
- prev, input[ci][last], (JBLOCKROW) NULL,
- output[ci][last]);
- else
- (*cinfo->methods->smooth_coefficients) (cinfo, compptr,
- prev, input[ci][last], below[ci][0],
- output[ci][last]);
- }
- }
-
-
- LOCAL void
- get_smoothed_row (decompress_info_ptr cinfo, JBLOCKIMAGE coeff_data,
- JBLOCKIMAGE bsmooth[3], int * whichb, long cur_mcu_row)
- /* Get an MCU row of coefficients, applying cross-block smoothing. */
- /* The output row is placed in coeff_data. bsmooth and whichb hold */
- /* working state, and cur_row is needed to check for image top/bottom. */
- /* This routine just takes care of the buffering logic. */
- {
- int prev, cur, next;
-
- /* Special case for top of image: need to pre-fetch a row & init whichb */
- if (cur_mcu_row == 0) {
- (*cinfo->methods->disassemble_MCU) (cinfo, bsmooth[0]);
- if (cinfo->MCU_rows_in_scan > 1) {
- (*cinfo->methods->disassemble_MCU) (cinfo, bsmooth[1]);
- smooth_mcu_row(cinfo, (JBLOCKIMAGE) NULL, bsmooth[0], bsmooth[1],
- coeff_data);
- } else {
- smooth_mcu_row(cinfo, (JBLOCKIMAGE) NULL, bsmooth[0], (JBLOCKIMAGE) NULL,
- coeff_data);
- }
- *whichb = 1; /* points to next bsmooth[] element to use */
- return;
- }
-
- cur = *whichb; /* set up references */
- prev = (cur == 0 ? 2 : cur - 1);
- next = (cur == 2 ? 0 : cur + 1);
- *whichb = next; /* advance whichb for next time */
-
- /* Special case for bottom of image: don't read another row */
- if (cur_mcu_row >= cinfo->MCU_rows_in_scan - 1) {
- smooth_mcu_row(cinfo, bsmooth[prev], bsmooth[cur], (JBLOCKIMAGE) NULL,
- coeff_data);
- return;
- }
-
- /* Normal case: read ahead a new row, smooth the one I got before */
- (*cinfo->methods->disassemble_MCU) (cinfo, bsmooth[next]);
- smooth_mcu_row(cinfo, bsmooth[prev], bsmooth[cur], bsmooth[next],
- coeff_data);
- }
-
-
- #endif /* BLOCK_SMOOTHING_SUPPORTED */
-
-
-
- /*
- * Decompression pipeline controller used for single-scan files
- * without 2-pass color quantization.
- */
-
- METHODDEF void
- simple_dcontroller (decompress_info_ptr cinfo)
- {
- long fullsize_width; /* # of samples per row in full-size buffers */
- long cur_mcu_row; /* counts # of MCU rows processed */
- long pixel_rows_output; /* # of pixel rows actually emitted */
- int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */
- /* Work buffer for dequantized coefficients (IDCT input) */
- JBLOCKIMAGE coeff_data;
- /* Work buffer for cross-block smoothing input */
- #ifdef BLOCK_SMOOTHING_SUPPORTED
- JBLOCKIMAGE bsmooth[3]; /* this is optional */
- int whichb;
- #endif
- /* Work buffer for downsampled image data (see comments at head of file) */
- JSAMPIMAGE sampled_data[2];
- /* Work buffer for upsampled data */
- JSAMPIMAGE fullsize_data;
- int whichss, ri;
- short i;
-
- /* Compute dimensions of full-size pixel buffers */
- /* Note these are the same whether interleaved or not. */
- rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
- fullsize_width = jround_up(cinfo->image_width,
- (long) (cinfo->max_h_samp_factor * DCTSIZE));
-
- /* Prepare for single scan containing all components */
- if (cinfo->comps_in_scan == 1) {
- noninterleaved_scan_setup(cinfo);
- /* Need to read Vk MCU rows to obtain Vk block rows */
- mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
- } else {
- interleaved_scan_setup(cinfo);
- /* in an interleaved scan, one MCU row provides Vk block rows */
- mcu_rows_per_loop = 1;
- }
- cinfo->total_passes++;
-
- /* Allocate working memory: */
- /* coeff_data holds a single MCU row of coefficient blocks */
- coeff_data = alloc_MCU_row(cinfo);
- /* if doing cross-block smoothing, need extra space for its input */
- #ifdef BLOCK_SMOOTHING_SUPPORTED
- if (cinfo->do_block_smoothing) {
- bsmooth[0] = alloc_MCU_row(cinfo);
- bsmooth[1] = alloc_MCU_row(cinfo);
- bsmooth[2] = alloc_MCU_row(cinfo);
- }
- #endif
- /* sampled_data is sample data before upsampling */
- alloc_sampling_buffer(cinfo, sampled_data);
- /* fullsize_data is sample data after upsampling */
- fullsize_data = alloc_sampimage(cinfo, (int) cinfo->num_components,
- (long) rows_in_mem, fullsize_width);
- /* output_workspace is the color-processed data */
- output_workspace = alloc_sampimage(cinfo, (int) cinfo->final_out_comps,
- (long) rows_in_mem, fullsize_width);
- prepare_range_limit_table(cinfo);
-
- /* Tell the memory manager to instantiate big arrays.
- * We don't need any big arrays in this controller,
- * but some other module (like the output file writer) may need one.
- */
- (*cinfo->emethods->alloc_big_arrays)
- ((long) 0, /* no more small sarrays */
- (long) 0, /* no more small barrays */
- (long) 0); /* no more "medium" objects */
- /* NB: if quantizer needs any "medium" size objects, it must get them */
- /* at color_quant_init time */
-
- /* Initialize to read scan data */
-
- (*cinfo->methods->entropy_decode_init) (cinfo);
- (*cinfo->methods->upsample_init) (cinfo);
- (*cinfo->methods->disassemble_init) (cinfo);
-
- /* Loop over scan's data: rows_in_mem pixel rows are processed per loop */
-
- pixel_rows_output = 0;
- whichss = 1; /* arrange to start with sampled_data[0] */
-
- for (cur_mcu_row = 0; cur_mcu_row < cinfo->MCU_rows_in_scan;
- cur_mcu_row += mcu_rows_per_loop) {
- (*cinfo->methods->progress_monitor) (cinfo, cur_mcu_row,
- cinfo->MCU_rows_in_scan);
-
- whichss ^= 1; /* switch to other downsampled-data buffer */
-
- /* Obtain v_samp_factor block rows of each component in the scan. */
- /* This is a single MCU row if interleaved, multiple MCU rows if not. */
- /* In the noninterleaved case there might be fewer than v_samp_factor */
- /* block rows remaining; if so, pad with copies of the last pixel row */
- /* so that upsampling doesn't have to treat it as a special case. */
-
- for (ri = 0; ri < mcu_rows_per_loop; ri++) {
- if (cur_mcu_row + ri < cinfo->MCU_rows_in_scan) {
- /* OK to actually read an MCU row. */
- #ifdef BLOCK_SMOOTHING_SUPPORTED
- if (cinfo->do_block_smoothing)
- get_smoothed_row(cinfo, coeff_data,
- bsmooth, &whichb, cur_mcu_row + ri);
- else
- #endif
- (*cinfo->methods->disassemble_MCU) (cinfo, coeff_data);
-
- (*cinfo->methods->reverse_DCT) (cinfo, coeff_data,
- sampled_data[whichss],
- ri * DCTSIZE);
- } else {
- /* Need to pad out with copies of the last downsampled row. */
- /* This can only happen if there is just one component. */
- duplicate_row(sampled_data[whichss][0],
- cinfo->cur_comp_info[0]->downsampled_width,
- ri * DCTSIZE - 1, DCTSIZE);
- }
- }
-
- /* Upsample the data */
- /* First time through is a special case */
-
- if (cur_mcu_row) {
- /* Expand last row group of previous set */
- expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width,
- (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
- (short) (DCTSIZE-1));
- /* and dump the previous set's expanded data */
- emit_1pass (cinfo, rows_in_mem, fullsize_data, (JSAMPARRAY) NULL);
- pixel_rows_output += rows_in_mem;
- /* Expand first row group of this set */
- expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width,
- (short) (DCTSIZE+1), (short) 0, (short) 1,
- (short) 0);
- } else {
- /* Expand first row group with dummy above-context */
- expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width,
- (short) (-1), (short) 0, (short) 1,
- (short) 0);
- }
- /* Expand second through next-to-last row groups of this set */
- for (i = 1; i <= DCTSIZE-2; i++) {
- expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width,
- (short) (i-1), (short) i, (short) (i+1),
- (short) i);
- }
- } /* end of outer loop */
-
- /* Expand the last row group with dummy below-context */
- /* Note whichss points to last buffer side used */
- expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width,
- (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
- (short) (DCTSIZE-1));
- /* and dump the remaining data (may be less than full height) */
- emit_1pass (cinfo, (int) (cinfo->image_height - pixel_rows_output),
- fullsize_data, (JSAMPARRAY) NULL);
-
- /* Clean up after the scan */
- (*cinfo->methods->disassemble_term) (cinfo);
- (*cinfo->methods->upsample_term) (cinfo);
- (*cinfo->methods->entropy_decode_term) (cinfo);
- (*cinfo->methods->read_scan_trailer) (cinfo);
- cinfo->completed_passes++;
- #ifdef STREAM_IMAGE
- { extern should_be;
- #ifdef OLD_STREAM_IMAGE
- ri = ftell(cinfo->input_file);
- if (should_be > 0 && ri != should_be) {
- # ifdef _DEBUG_
- fprintf(stderr, "cur_pos %d, should be %d\n", ri, should_be);
- # endif
- if (ri > 0)
- (*cinfo->img->seek)(cinfo->input_file, should_be - ri, SEEK_CUR);
- # ifdef NEW_FILE_SYSTEM
- else while (1) {
- ri = (*cinfo->img->seek)(cinfo->input_file, 0, SEEK_GETB);
- if (ri == 0xFF && 0xDA ==
- (*cinfo->img->seek)(cinfo->input_file, 0, SEEK_PEEK)) {
- (*cinfo->img->seek)(cinfo->input_file, 0xda, SEEK_UGETB);
- (*cinfo->img->seek)(cinfo->input_file, ri, SEEK_UGETB);
- break;
- }
- }
- # else
- else while (1) {
- ri = JGETC(cinfo);
- if (ri == 0xFF && JGETC(cinfo) == 0xDA) {
- JUNGETC(0xDA, cinfo);
- JUNGETC(ri, cinfo);
- break;
- }
- }
- # endif
- } else fprintf(stderr, "even ending\n");
- #else
- if (should_be >= ftell(cinfo->input_file))
- cinfo->bytes_in_buffer = 0; /* flush rest garbage */
- #endif
- }
- #endif
-
- /* Verify that we've seen the whole input file */
- if ((*cinfo->methods->read_scan_header) (cinfo))
- WARNMS(cinfo->emethods, "Multi_Frames");
-
- /* Release working memory */
- /* (no work -- we let free_all release what's needful) */
- }
-
-
- /*
- * Decompression pipeline controller used for multiple-scan files
- * and/or 2-pass color quantization.
- *
- * The current implementation places the "big" buffer at the stage of
- * upsampled, non-color-processed data. This is the only place that
- * makes sense when doing 2-pass quantization. For processing multiple-scan
- * files without 2-pass quantization, it would be possible to develop another
- * controller that buffers the downsampled data instead, thus reducing the size
- * of the temp files (by about a factor of 2 in typical cases). However,
- * our present upsampling logic is dependent on the assumption that
- * upsampling occurs during a scan, so it's much easier to do the
- * enlargement as the JPEG file is read. This also simplifies life for the
- * memory manager, which would otherwise have to deal with overlapping
- * access_big_sarray() requests.
- * At present it appears that most JPEG files will be single-scan,
- * so it doesn't seem worthwhile to worry about this optimization.
- */
-
- #ifdef NEED_COMPLEX_CONTROLLER
-
- METHODDEF void
- complex_dcontroller (decompress_info_ptr cinfo)
- {
- long fullsize_width; /* # of samples per row in full-size buffers */
- long cur_mcu_row; /* counts # of MCU rows processed */
- long pixel_rows_output; /* # of pixel rows actually emitted */
- int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */
- /* Work buffer for dequantized coefficients (IDCT input) */
- JBLOCKIMAGE coeff_data;
- /* Work buffer for cross-block smoothing input */
- #ifdef BLOCK_SMOOTHING_SUPPORTED
- JBLOCKIMAGE bsmooth[3]; /* this is optional */
- int whichb;
- #endif
- /* Work buffer for downsampled image data (see comments at head of file) */
- JSAMPIMAGE sampled_data[2];
- int whichss, ri;
- short ci, i;
- boolean single_scan;
-
- /* Compute dimensions of full-size pixel buffers */
- /* Note these are the same whether interleaved or not. */
- rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
- fullsize_width = jround_up(cinfo->image_width,
- (long) (cinfo->max_h_samp_factor * DCTSIZE));
-
- /* Allocate all working memory that doesn't depend on scan info */
- /* output_workspace is the color-processed data */
- output_workspace = alloc_sampimage(cinfo, (int) cinfo->final_out_comps,
- (long) rows_in_mem, fullsize_width);
- prepare_range_limit_table(cinfo);
-
- /* Get a big image: fullsize_image is sample data after upsampling. */
- fullsize_image = (big_sarray_ptr *) (*cinfo->emethods->alloc_small)
- (cinfo->num_components * SIZEOF(big_sarray_ptr));
- for (ci = 0; ci < cinfo->num_components; ci++) {
- fullsize_image[ci] = (*cinfo->emethods->request_big_sarray)
- (fullsize_width,
- jround_up(cinfo->image_height, (long) rows_in_mem),
- (long) rows_in_mem);
- }
- /* Also get an area for pointers to currently accessible chunks */
- fullsize_ptrs = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
- (cinfo->num_components * SIZEOF(JSAMPARRAY));
-
- /* Tell the memory manager to instantiate big arrays */
- (*cinfo->emethods->alloc_big_arrays)
- /* extra sarray space is for downsampled-data buffers: */
- ((long) (fullsize_width /* max width in samples */
- * cinfo->max_v_samp_factor*(DCTSIZE+2) /* max height */
- * cinfo->num_components), /* max components per scan */
- /* extra barray space is for MCU-row buffers: */
- (long) ((fullsize_width / DCTSIZE) /* max width in blocks */
- * cinfo->max_v_samp_factor /* max height */
- * cinfo->num_components /* max components per scan */
- * (cinfo->do_block_smoothing ? 4 : 1)),/* how many of these we need */
- /* no extra "medium"-object space */
- (long) 0);
- /* NB: if quantizer needs any "medium" size objects, it must get them */
- /* at color_quant_init time */
-
- /* If file is single-scan, we can do color quantization prescan on-the-fly
- * during the scan (we must be doing 2-pass quantization, else this method
- * would not have been selected). If it is multiple scans, we have to make
- * a separate pass after we've collected all the components. (We could save
- * some I/O by doing CQ prescan during the last scan, but the extra logic
- * doesn't seem worth the trouble.)
- */
-
- single_scan = (cinfo->comps_in_scan == cinfo->num_components);
-
- /* Account for passes needed (color quantizer adds its passes separately).
- * If multiscan file, we guess that each component has its own scan,
- * and increment completed_passes by the number of components in the scan.
- */
-
- if (single_scan)
- cinfo->total_passes++; /* the single scan */
- else {
- cinfo->total_passes += cinfo->num_components; /* guessed # of scans */
- if (cinfo->two_pass_quantize)
- cinfo->total_passes++; /* account for separate CQ prescan pass */
- }
- if (! cinfo->two_pass_quantize)
- cinfo->total_passes++; /* count output pass unless quantizer does it */
-
- /* Loop over scans in file */
-
- do {
-
- /* Prepare for this scan */
- if (cinfo->comps_in_scan == 1) {
- noninterleaved_scan_setup(cinfo);
- /* Need to read Vk MCU rows to obtain Vk block rows */
- mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
- } else {
- interleaved_scan_setup(cinfo);
- /* in an interleaved scan, one MCU row provides Vk block rows */
- mcu_rows_per_loop = 1;
- }
-
- /* Allocate scan-local working memory */
- /* coeff_data holds a single MCU row of coefficient blocks */
- coeff_data = alloc_MCU_row(cinfo);
- /* if doing cross-block smoothing, need extra space for its input */
- #ifdef BLOCK_SMOOTHING_SUPPORTED
- if (cinfo->do_block_smoothing) {
- bsmooth[0] = alloc_MCU_row(cinfo);
- bsmooth[1] = alloc_MCU_row(cinfo);
- bsmooth[2] = alloc_MCU_row(cinfo);
- }
- #endif
- /* sampled_data is sample data before upsampling */
- alloc_sampling_buffer(cinfo, sampled_data);
-
- /* line up the big buffers for components in this scan */
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray)
- (fullsize_image[cinfo->cur_comp_info[ci]->component_index],
- (long) 0, TRUE);
- }
-
- /* Initialize to read scan data */
-
- (*cinfo->methods->entropy_decode_init) (cinfo);
- (*cinfo->methods->upsample_init) (cinfo);
- (*cinfo->methods->disassemble_init) (cinfo);
-
- /* Loop over scan's data: rows_in_mem pixel rows are processed per loop */
-
- pixel_rows_output = 0;
- whichss = 1; /* arrange to start with sampled_data[0] */
-
- for (cur_mcu_row = 0; cur_mcu_row < cinfo->MCU_rows_in_scan;
- cur_mcu_row += mcu_rows_per_loop) {
- (*cinfo->methods->progress_monitor) (cinfo, cur_mcu_row,
- cinfo->MCU_rows_in_scan);
-
- whichss ^= 1; /* switch to other downsampled-data buffer */
-
- /* Obtain v_samp_factor block rows of each component in the scan. */
- /* This is a single MCU row if interleaved, multiple MCU rows if not. */
- /* In the noninterleaved case there might be fewer than v_samp_factor */
- /* block rows remaining; if so, pad with copies of the last pixel row */
- /* so that upsampling doesn't have to treat it as a special case. */
-
- for (ri = 0; ri < mcu_rows_per_loop; ri++) {
- if (cur_mcu_row + ri < cinfo->MCU_rows_in_scan) {
- /* OK to actually read an MCU row. */
- #ifdef BLOCK_SMOOTHING_SUPPORTED
- if (cinfo->do_block_smoothing)
- get_smoothed_row(cinfo, coeff_data,
- bsmooth, &whichb, cur_mcu_row + ri);
- else
- #endif
- (*cinfo->methods->disassemble_MCU) (cinfo, coeff_data);
-
- (*cinfo->methods->reverse_DCT) (cinfo, coeff_data,
- sampled_data[whichss],
- ri * DCTSIZE);
- } else {
- /* Need to pad out with copies of the last downsampled row. */
- /* This can only happen if there is just one component. */
- duplicate_row(sampled_data[whichss][0],
- cinfo->cur_comp_info[0]->downsampled_width,
- ri * DCTSIZE - 1, DCTSIZE);
- }
- }
-
- /* Upsample the data */
- /* First time through is a special case */
-
- if (cur_mcu_row) {
- /* Expand last row group of previous set */
- expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width,
- (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
- (short) (DCTSIZE-1));
- /* If single scan, can do color quantization prescan on-the-fly */
- if (single_scan)
- (*cinfo->methods->color_quant_prescan) (cinfo, rows_in_mem,
- fullsize_ptrs,
- output_workspace[0]);
- /* Realign the big buffers */
- pixel_rows_output += rows_in_mem;
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray)
- (fullsize_image[cinfo->cur_comp_info[ci]->component_index],
- pixel_rows_output, TRUE);
- }
- /* Expand first row group of this set */
- expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width,
- (short) (DCTSIZE+1), (short) 0, (short) 1,
- (short) 0);
- } else {
- /* Expand first row group with dummy above-context */
- expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width,
- (short) (-1), (short) 0, (short) 1,
- (short) 0);
- }
- /* Expand second through next-to-last row groups of this set */
- for (i = 1; i <= DCTSIZE-2; i++) {
- expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width,
- (short) (i-1), (short) i, (short) (i+1),
- (short) i);
- }
- } /* end of loop over scan's data */
-
- /* Expand the last row group with dummy below-context */
- /* Note whichss points to last buffer side used */
- expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width,
- (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
- (short) (DCTSIZE-1));
- /* If single scan, finish on-the-fly color quantization prescan */
- if (single_scan)
- (*cinfo->methods->color_quant_prescan) (cinfo,
- (int) (cinfo->image_height - pixel_rows_output),
- fullsize_ptrs, output_workspace[0]);
-
- /* Clean up after the scan */
- (*cinfo->methods->disassemble_term) (cinfo);
- (*cinfo->methods->upsample_term) (cinfo);
- (*cinfo->methods->entropy_decode_term) (cinfo);
- (*cinfo->methods->read_scan_trailer) (cinfo);
- if (single_scan)
- cinfo->completed_passes++;
- else
- cinfo->completed_passes += cinfo->comps_in_scan;
-
- /* Release scan-local working memory */
- free_MCU_row(cinfo, coeff_data);
- #ifdef BLOCK_SMOOTHING_SUPPORTED
- if (cinfo->do_block_smoothing) {
- free_MCU_row(cinfo, bsmooth[0]);
- free_MCU_row(cinfo, bsmooth[1]);
- free_MCU_row(cinfo, bsmooth[2]);
- }
- #endif
- free_sampling_buffer(cinfo, sampled_data);
-
- /* Repeat if there is another scan */
- } while ((!single_scan) && (*cinfo->methods->read_scan_header) (cinfo));
-
- if (single_scan) {
- /* If we expected just one scan, make SURE there's just one */
- if ((*cinfo->methods->read_scan_header) (cinfo))
- WARNMS(cinfo->emethods, "multi_frame");
- /* WARNMS(cinfo->emethods, "Didn't expect more than one scan"); */
- /* We did the CQ prescan on-the-fly, so we are all set. */
- } else {
- /* For multiple-scan file, do the CQ prescan as a separate pass. */
- /* The main reason why prescan is passed the output_workspace is */
- /* so that we can use scan_big_image to call it... */
- if (cinfo->two_pass_quantize)
- scan_big_image(cinfo, cinfo->methods->color_quant_prescan);
- }
-
- /* Now that we've collected the data, do color processing and output */
- if (cinfo->two_pass_quantize)
- (*cinfo->methods->color_quant_doit) (cinfo, scan_big_image);
- else
- scan_big_image(cinfo, emit_1pass);
-
- /* Release working memory */
- /* (no work -- we let free_all release what's needful) */
- }
-
- #endif /* NEED_COMPLEX_CONTROLLER */
-
-
- /*
- * The method selection routine for decompression pipeline controllers.
- * Note that at this point we've already read the JPEG header and first SOS,
- * so we can tell whether the input is one scan or not.
- */
-
- GLOBAL void
- jseldpipeline (decompress_info_ptr cinfo)
- {
- /* simplify subsequent tests on color quantization */
- if (! cinfo->quantize_colors)
- cinfo->two_pass_quantize = FALSE;
-
- if (cinfo->comps_in_scan == cinfo->num_components) {
- /* It's a single-scan file */
- if (cinfo->two_pass_quantize) {
- #ifdef NEED_COMPLEX_CONTROLLER
- cinfo->methods->d_pipeline_controller = complex_dcontroller;
- #else
- ERREXIT(cinfo->emethods, "2-pass quantization support was not compiled");
- #endif
- } else
- cinfo->methods->d_pipeline_controller = simple_dcontroller;
- } else {
- /* It's a multiple-scan file */
- #ifdef NEED_COMPLEX_CONTROLLER
- cinfo->methods->d_pipeline_controller = complex_dcontroller;
- #else
- ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled");
- #endif
- }
- }
-