/*
* jdpipe.c
*
* Copyright (C) 1991, 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 four basic pipeline controllers, one for each combination of:
* single-scan JPEG file (single component or fully interleaved)
* vs. multiple-scan JPEG file (noninterleaved or partially interleaved).
*
* 2-pass color quantization
* vs. no color quantization or 1-pass quantization.
*
* Note that these conditions determine the needs for "big" images:
* multiple scans imply a big image for recombining the color components;
* 2-pass color quantization needs a big image for saving the data for pass 2.
*
* All but the simplest controller (single-scan, no 2-pass quantization) can be
* compiled out through configuration options, if you need to make a minimal
* implementation. You should leave in multiple-scan support if at all
* possible, so that you can handle all legal JPEG files.
*/
#include "jinclude.h"
/*
* About the data structures:
*
* The processing chunk size for unsubsampling 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 subsampled, 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 unsubsampling 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.
* If you don't support 2-pass quantization, you could make them locals.
*/
static int rows_in_mem; /* # of sample rows in full-size buffers */
/* Full-size image array holding desubsampled, color-converted data. */
static big_sarray_ptr *fullsize_cnvt_image;
static JSAMPIMAGE fullsize_cnvt_ptrs; /* workspace for access_big_sarray() results */
/* Work buffer for color quantization output (full size, only 1 component). */
static JSAMPARRAY quantize_out;
/*
* 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->subsampled_width = jround_up(compptr->true_comp_width,
(long) (compptr->MCU_width*DCTSIZE));
compptr->subsampled_height = jround_up(compptr->true_comp_height,
(long) (compptr->MCU_height*DCTSIZE));
/* Sanity check */
if (compptr->subsampled_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->subsampled_width = jround_up(compptr->true_comp_width,
(long) DCTSIZE);
compptr->subsampled_height = jround_up(compptr->true_comp_height,
(long) DCTSIZE);
cinfo->MCUs_per_row = compptr->subsampled_width / DCTSIZE;
cinfo->MCU_rows_in_scan = compptr->subsampled_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 void
reverse_DCT (decompress_info_ptr cinfo,
JBLOCKIMAGE coeff_data, JSAMPIMAGE output_data,
int start_row)
/* Perform inverse DCT on each block in an MCU row's worth of data; */
/* output the results into a sample array starting at row start_row. */
/* NB: start_row can only be nonzero when dealing with a single-component */
/* scan; otherwise we'd have to provide for different offsets for different */
/* components, since the heights of interleaved MCU rows can vary. */
{
DCTBLOCK block;
JBLOCKROW browptr;
JSAMPARRAY srowptr;
long blocksperrow, bi;
short numrows, ri;
short ci;
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
{
/* calc size of an MCU row in this component */
blocksperrow = cinfo->cur_comp_info[ci]->subsampled_width / DCTSIZE;
numrows = cinfo->cur_comp_info[ci]->MCU_height;
/* iterate through all blocks in MCU row */
for (ri = 0; ri < numrows; ri++)
{
browptr = coeff_data[ci][ri];
srowptr = output_data[ci] + (ri * DCTSIZE + start_row);
for (bi = 0; bi < blocksperrow; bi++)
{
/* copy the data into a local DCTBLOCK. This allows for change of
* representation (if DCTELEM != JCOEF). On 80x86 machines it also
* brings the data back from FAR storage to NEAR storage.
*/
{ register JCOEFPTR elemptr = browptr[bi];
register DCTELEM *localblkptr = block;