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