1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#if !defined(_FX_JPEG_TURBO_) 2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * jdmainct.c 4e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 5e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Copyright (C) 1994-1996, Thomas G. Lane. 6e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This file is part of the Independent JPEG Group's software. 7e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * For conditions of distribution and use, see the accompanying README file. 8e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 9e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This file contains the main buffer controller for decompression. 10e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The main buffer lies between the JPEG decompressor proper and the 11e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * post-processor; it holds downsampled data in the JPEG colorspace. 12e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 13e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Note that this code is bypassed in raw-data mode, since the application 14e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * supplies the equivalent of the main buffer in that case. 15e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 16e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 17e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define JPEG_INTERNALS 18e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "jinclude.h" 19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "jpeglib.h" 20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * In the current system design, the main buffer need never be a full-image 24e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * buffer; any full-height buffers will be found inside the coefficient or 25e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * postprocessing controllers. Nonetheless, the main controller is not 26e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * trivial. Its responsibility is to provide context rows for upsampling/ 27e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * rescaling, and doing this in an efficient fashion is a bit tricky. 28e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 29e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Postprocessor input data is counted in "row groups". A row group 30e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) 31e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * sample rows of each component. (We require DCT_scaled_size values to be 32e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * chosen such that these numbers are integers. In practice DCT_scaled_size 33e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * values will likely be powers of two, so we actually have the stronger 34e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) 35e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Upsampling will typically produce max_v_samp_factor pixel rows from each 36e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * row group (times any additional scale factor that the upsampler is 37e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * applying). 38e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 39e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The coefficient controller will deliver data to us one iMCU row at a time; 40e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or 41e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * exactly min_DCT_scaled_size row groups. (This amount of data corresponds 42e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * to one row of MCUs when the image is fully interleaved.) Note that the 43e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * number of sample rows varies across components, but the number of row 44e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * groups does not. Some garbage sample rows may be included in the last iMCU 45e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * row at the bottom of the image. 46e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 47e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Depending on the vertical scaling algorithm used, the upsampler may need 48e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * access to the sample row(s) above and below its current input row group. 49e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The upsampler is required to set need_context_rows TRUE at global selection 50e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * time if so. When need_context_rows is FALSE, this controller can simply 51e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * obtain one iMCU row at a time from the coefficient controller and dole it 52e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * out as row groups to the postprocessor. 53e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 54e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * When need_context_rows is TRUE, this controller guarantees that the buffer 55e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * passed to postprocessing contains at least one row group's worth of samples 56e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * above and below the row group(s) being processed. Note that the context 57e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * rows "above" the first passed row group appear at negative row offsets in 58e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * the passed buffer. At the top and bottom of the image, the required 59e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * context rows are manufactured by duplicating the first or last real sample 60e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * row; this avoids having special cases in the upsampling inner loops. 61e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 62e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The amount of context is fixed at one row group just because that's a 63e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * convenient number for this controller to work with. The existing 64e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * upsamplers really only need one sample row of context. An upsampler 65e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * supporting arbitrary output rescaling might wish for more than one row 66e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * group of context when shrinking the image; tough, we don't handle that. 67e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * (This is justified by the assumption that downsizing will be handled mostly 68e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * by adjusting the DCT_scaled_size values, so that the actual scale factor at 69e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * the upsample step needn't be much less than one.) 70e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 71e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * To provide the desired context, we have to retain the last two row groups 72e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * of one iMCU row while reading in the next iMCU row. (The last row group 73e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * can't be processed until we have another row group for its below-context, 74e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * and so we have to save the next-to-last group too for its above-context.) 75e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * We could do this most simply by copying data around in our buffer, but 76e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * that'd be very slow. We can avoid copying any data by creating a rather 77e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * strange pointer structure. Here's how it works. We allocate a workspace 78e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number 79e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * of row groups per iMCU row). We create two sets of redundant pointers to 80e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * the workspace. Labeling the physical row groups 0 to M+1, the synthesized 81e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * pointer lists look like this: 82e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * M+1 M-1 83e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * master pointer --> 0 master pointer --> 0 84e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 1 1 85e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * ... ... 86e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * M-3 M-3 87e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * M-2 M 88e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * M-1 M+1 89e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * M M-2 90e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * M+1 M-1 91e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 0 0 92e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * We read alternate iMCU rows using each master pointer; thus the last two 93e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * row groups of the previous iMCU row remain un-overwritten in the workspace. 94e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The pointer lists are set up so that the required context rows appear to 95e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * be adjacent to the proper places when we pass the pointer lists to the 96e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * upsampler. 97e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 98e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The above pictures describe the normal state of the pointer lists. 99e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * At top and bottom of the image, we diddle the pointer lists to duplicate 100e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * the first or last sample row as necessary (this is cheaper than copying 101e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * sample rows around). 102e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 103e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that 104e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * situation each iMCU row provides only one row group so the buffering logic 105e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * must be different (eg, we must read two iMCU rows before we can emit the 106e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * first row group). For now, we simply do not support providing context 107e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * rows when min_DCT_scaled_size is 1. That combination seems unlikely to 108e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * be worth providing --- if someone wants a 1/8th-size preview, they probably 109e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * want it quick and dirty, so a context-free upsampler is sufficient. 110e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 111e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 112e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 113e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Private buffer controller object */ 114e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 115e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovtypedef struct { 116e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov struct jpeg_d_main_controller pub; /* public fields */ 117e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 118e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Pointer to allocated workspace (M or M+2 row groups). */ 119e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY buffer[MAX_COMPONENTS]; 120e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 121e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ 122e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ 123e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 124e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Remaining fields are only used in the context case. */ 125e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 126e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* These are the master pointers to the funny-order pointer lists. */ 127e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ 128e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 129e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int whichptr; /* indicates which pointer set is now in use */ 130e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int context_state; /* process_data state machine status */ 131e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ 132e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ 133e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} my_main_controller; 134e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 135e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovtypedef my_main_controller * my_main_ptr; 136e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 137e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* context_state values: */ 138e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ 139e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ 140e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ 141e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 142e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 143e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Forward declarations */ 144e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) process_data_simple_main 145e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, 146e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); 147e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) process_data_context_main 148e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, 149e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); 150e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#ifdef QUANT_2PASS_SUPPORTED 151e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) process_data_crank_post 152e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, 153e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); 154e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 155e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 156e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 157e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovLOCAL(void) 158e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovalloc_funny_pointers (j_decompress_ptr cinfo) 159e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Allocate space for the funny pointer lists. 160e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This is done only once, not once per pass. 161e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 162e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 163e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_main_ptr main = (my_main_ptr) cinfo->main; 164e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int ci, rgroup; 165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int M = cinfo->min_DCT_scaled_size; 166e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov jpeg_component_info *compptr; 167e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY xbuf; 168e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 169e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Get top-level space for component array pointers. 170e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * We alloc both arrays with one call to save a few cycles. 171e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 172e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->xbuffer[0] = (JSAMPIMAGE) 173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 174e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); 175e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components; 176e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 177e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 178e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ci++, compptr++) { 179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / 180e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->min_DCT_scaled_size; /* height of a row group of component */ 181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Get space for pointer lists --- M+4 row groups in each list. 182e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * We alloc both pointer lists with one call to save a few cycles. 183e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 184e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf = (JSAMPARRAY) 185e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 186e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); 187e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf += rgroup; /* want one row group at negative offsets */ 188e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->xbuffer[0][ci] = xbuf; 189e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf += rgroup * (M + 4); 190e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->xbuffer[1][ci] = xbuf; 191e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 192e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 193e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 194e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 195e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovLOCAL(void) 196e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovmake_funny_pointers (j_decompress_ptr cinfo) 197e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Create the funny pointer lists discussed in the comments above. 198e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The actual workspace is already allocated (in main->buffer), 199e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * and the space for the pointer lists is allocated too. 200e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This routine just fills in the curiously ordered lists. 201e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This will be repeated at the beginning of each pass. 202e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 203e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 204e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_main_ptr main = (my_main_ptr) cinfo->main; 205e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int ci, i, rgroup; 206e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int M = cinfo->min_DCT_scaled_size; 207e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov jpeg_component_info *compptr; 208e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY buf, xbuf0, xbuf1; 209e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 210e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 211e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ci++, compptr++) { 212e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / 213e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->min_DCT_scaled_size; /* height of a row group of component */ 214e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf0 = main->xbuffer[0][ci]; 215e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf1 = main->xbuffer[1][ci]; 216e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* First copy the workspace pointers as-is */ 217e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov buf = main->buffer[ci]; 218e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (i = 0; i < rgroup * (M + 2); i++) { 219e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf0[i] = xbuf1[i] = buf[i]; 220e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 221e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* In the second list, put the last four row groups in swapped order */ 222e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (i = 0; i < rgroup * 2; i++) { 223e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; 224e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; 225e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 226e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* The wraparound pointers at top and bottom will be filled later 227e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * (see set_wraparound_pointers, below). Initially we want the "above" 228e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * pointers to duplicate the first actual data line. This only needs 229e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * to happen in xbuffer[0]. 230e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 231e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (i = 0; i < rgroup; i++) { 232e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf0[i - rgroup] = xbuf0[0]; 233e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 234e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 235e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 236e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 237e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 238e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovLOCAL(void) 239e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovset_wraparound_pointers (j_decompress_ptr cinfo) 240e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Set up the "wraparound" pointers at top and bottom of the pointer lists. 241e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This changes the pointer list state from top-of-image to the normal state. 242e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 243e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 244e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_main_ptr main = (my_main_ptr) cinfo->main; 245e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int ci, i, rgroup; 246e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int M = cinfo->min_DCT_scaled_size; 247e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov jpeg_component_info *compptr; 248e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY xbuf0, xbuf1; 249e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 250e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 251e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ci++, compptr++) { 252e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / 253e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->min_DCT_scaled_size; /* height of a row group of component */ 254e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf0 = main->xbuffer[0][ci]; 255e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf1 = main->xbuffer[1][ci]; 256e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (i = 0; i < rgroup; i++) { 257e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; 258e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; 259e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf0[rgroup*(M+2) + i] = xbuf0[i]; 260e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf1[rgroup*(M+2) + i] = xbuf1[i]; 261e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 262e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 263e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 264e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 265e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 266e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovLOCAL(void) 267e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovset_bottom_pointers (j_decompress_ptr cinfo) 268e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Change the pointer lists to duplicate the last sample row at the bottom 269e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * of the image. whichptr indicates which xbuffer holds the final iMCU row. 270e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Also sets rowgroups_avail to indicate number of nondummy row groups in row. 271e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 272e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 273e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_main_ptr main = (my_main_ptr) cinfo->main; 274e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int ci, i, rgroup, iMCUheight, rows_left; 275e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov jpeg_component_info *compptr; 276e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY xbuf; 277e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 278e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 279e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ci++, compptr++) { 280e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Count sample rows in one iMCU row and in one row group */ 281e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; 282e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rgroup = iMCUheight / cinfo->min_DCT_scaled_size; 283e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Count nondummy sample rows remaining for this component */ 284e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); 285e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (rows_left == 0) rows_left = iMCUheight; 286e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Count nondummy row groups. Should get same answer for each component, 287e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * so we need only do it once. 288e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 289e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (ci == 0) { 290e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); 291e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 292e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Duplicate the last real sample row rgroup*2 times; this pads out the 293e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * last partial rowgroup and ensures at least one full rowgroup of context. 294e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 295e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf = main->xbuffer[main->whichptr][ci]; 296e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (i = 0; i < rgroup * 2; i++) { 297e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov xbuf[rows_left + i] = xbuf[rows_left-1]; 298e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 299e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 300e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 301e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 302e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 303e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 304e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Initialize for a processing pass. 305e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 306e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 307e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 308e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstart_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) 309e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 310e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_main_ptr main = (my_main_ptr) cinfo->main; 311e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 312e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov switch (pass_mode) { 313e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case JBUF_PASS_THRU: 314e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->upsample->need_context_rows) { 315e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->pub.process_data = process_data_context_main; 316e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ 317e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ 318e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->context_state = CTX_PREPARE_FOR_IMCU; 319e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->iMCU_row_ctr = 0; 320e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 321e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Simple case with no context needed */ 322e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->pub.process_data = process_data_simple_main; 323e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 324e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->buffer_full = FALSE; /* Mark buffer empty */ 325e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->rowgroup_ctr = 0; 326e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 327e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#ifdef QUANT_2PASS_SUPPORTED 328e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case JBUF_CRANK_DEST: 329e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* For last pass of 2-pass quantization, just crank the postprocessor */ 330e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->pub.process_data = process_data_crank_post; 331e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 332e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 333e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov default: 334e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); 335e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 336e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 337e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 338e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 339e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 340e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 341e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Process some data. 342e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This handles the simple case where no context is required. 343e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 344e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 345e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 346e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovprocess_data_simple_main (j_decompress_ptr cinfo, 347e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, 348e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION out_rows_avail) 349e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 350e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_main_ptr main = (my_main_ptr) cinfo->main; 351e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION rowgroups_avail; 352e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 353e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Read input data if we haven't filled the main buffer yet */ 354e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (! main->buffer_full) { 355e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer)) 356e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; /* suspension forced, can do nothing more */ 357e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ 358e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 359e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 360e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* There are always min_DCT_scaled_size row groups in an iMCU row. */ 361e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; 362e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Note: at the bottom of the image, we may pass extra garbage row groups 363e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * to the postprocessor. The postprocessor has to check for bottom 364e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * of image anyway (at row resolution), so no point in us doing it too. 365e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 366e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 367e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Feed the postprocessor */ 368e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->post->post_process_data) (cinfo, main->buffer, 369e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov &main->rowgroup_ctr, rowgroups_avail, 370e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov output_buf, out_row_ctr, out_rows_avail); 371e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 372e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ 373e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (main->rowgroup_ctr >= rowgroups_avail) { 374e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->buffer_full = FALSE; 375e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->rowgroup_ctr = 0; 376e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 377e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 378e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 379e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 380e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 381e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Process some data. 382e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This handles the case where context rows must be provided. 383e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 384e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 385e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 386e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovprocess_data_context_main (j_decompress_ptr cinfo, 387e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, 388e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION out_rows_avail) 389e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 390e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_main_ptr main = (my_main_ptr) cinfo->main; 391e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 392e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Read input data if we haven't filled the main buffer yet */ 393e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (! main->buffer_full) { 394e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (! (*cinfo->coef->decompress_data) (cinfo, 395e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->xbuffer[main->whichptr])) 396e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; /* suspension forced, can do nothing more */ 397e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ 398e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->iMCU_row_ctr++; /* count rows received */ 399e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 400e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 401e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Postprocessor typically will not swallow all the input data it is handed 402e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * in one call (due to filling the output buffer first). Must be prepared 403e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * to exit and restart. This switch lets us keep track of how far we got. 404e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Note that each case falls through to the next on successful completion. 405e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 406e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov switch (main->context_state) { 407e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case CTX_POSTPONED_ROW: 408e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Call postprocessor using previously set pointers for postponed row */ 409e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], 410e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov &main->rowgroup_ctr, main->rowgroups_avail, 411e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov output_buf, out_row_ctr, out_rows_avail); 412e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (main->rowgroup_ctr < main->rowgroups_avail) 413e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; /* Need to suspend */ 414e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->context_state = CTX_PREPARE_FOR_IMCU; 415e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (*out_row_ctr >= out_rows_avail) 416e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; /* Postprocessor exactly filled output buf */ 417e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /*FALLTHROUGH*/ 418e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case CTX_PREPARE_FOR_IMCU: 419e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Prepare to process first M-1 row groups of this iMCU row */ 420e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->rowgroup_ctr = 0; 421e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); 422e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Check for bottom of image: if so, tweak pointers to "duplicate" 423e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * the last sample row, and adjust rowgroups_avail to ignore padding rows. 424e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 425e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (main->iMCU_row_ctr == cinfo->total_iMCU_rows) 426e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov set_bottom_pointers(cinfo); 427e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->context_state = CTX_PROCESS_IMCU; 428e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /*FALLTHROUGH*/ 429e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case CTX_PROCESS_IMCU: 430e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Call postprocessor using previously set pointers */ 431e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], 432e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov &main->rowgroup_ctr, main->rowgroups_avail, 433e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov output_buf, out_row_ctr, out_rows_avail); 434e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (main->rowgroup_ctr < main->rowgroups_avail) 435e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; /* Need to suspend */ 436e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* After the first iMCU, change wraparound pointers to normal state */ 437e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (main->iMCU_row_ctr == 1) 438e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov set_wraparound_pointers(cinfo); 439e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Prepare to load new iMCU row using other xbuffer list */ 440e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->whichptr ^= 1; /* 0=>1 or 1=>0 */ 441e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->buffer_full = FALSE; 442e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Still need to process last row group of this iMCU row, */ 443e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* which is saved at index M+1 of the other xbuffer */ 444e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); 445e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); 446e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->context_state = CTX_POSTPONED_ROW; 447e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 448e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 449e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 450e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 451e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 452e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Process some data. 453e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Final pass of two-pass quantization: just call the postprocessor. 454e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Source data will be the postprocessor controller's internal buffer. 455e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 456e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 457e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#ifdef QUANT_2PASS_SUPPORTED 458e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 459e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 460e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovprocess_data_crank_post (j_decompress_ptr cinfo, 461e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, 462e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION out_rows_avail) 463e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 464e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, 465e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (JDIMENSION *) NULL, (JDIMENSION) 0, 466e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov output_buf, out_row_ctr, out_rows_avail); 467e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 468e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 469e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif /* QUANT_2PASS_SUPPORTED */ 470e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 471e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 472e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 473e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Initialize main buffer controller. 474e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 475e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 476e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovGLOBAL(void) 477e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovjinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) 478e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 479e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_main_ptr main; 480e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int ci, rgroup, ngroups; 481e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov jpeg_component_info *compptr; 482e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 483e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main = (my_main_ptr) 484e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 485e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov SIZEOF(my_main_controller)); 486e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->main = (struct jpeg_d_main_controller *) main; 487e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->pub.start_pass = start_pass_main; 488e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 489e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (need_full_buffer) /* shouldn't happen */ 490e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); 491e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 492e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Allocate the workspace. 493e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * ngroups is the number of row groups we need. 494e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 495e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->upsample->need_context_rows) { 496e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ 497e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_NOTIMPL); 498e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ 499e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ngroups = cinfo->min_DCT_scaled_size + 2; 500e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 501e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ngroups = cinfo->min_DCT_scaled_size; 502e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 503e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 504e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 505e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ci++, compptr++) { 506e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / 507e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->min_DCT_scaled_size; /* height of a row group of component */ 508e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov main->buffer[ci] = (*cinfo->mem->alloc_sarray) 509e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ((j_common_ptr) cinfo, JPOOL_IMAGE, 510e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov compptr->width_in_blocks * compptr->DCT_scaled_size, 511e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (JDIMENSION) (rgroup * ngroups)); 512e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 513e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 514e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 515e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif //_FX_JPEG_TURBO_ 516