1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if !defined(_FX_JPEG_TURBO_)
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * jcprepct.c
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Copyright (C) 1994-1996, Thomas G. Lane.
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * This file is part of the Independent JPEG Group's software.
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * For conditions of distribution and use, see the accompanying README file.
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * This file contains the compression preprocessing controller.
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * This controller manages the color conversion, downsampling,
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * and edge expansion steps.
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Most of the complexity here is associated with buffering input rows
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * as required by the downsampler.  See the comments at the head of
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * jcsample.c for the downsampler's needs.
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define JPEG_INTERNALS
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "jinclude.h"
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "jpeglib.h"
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* At present, jcsample.c can request context rows only for smoothing.
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * In the future, we might also need context rows for CCIR601 sampling
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * or other more-complex downsampling procedures.  The code to support
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * context rows should be compiled only if needed.
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef INPUT_SMOOTHING_SUPPORTED
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CONTEXT_ROWS_SUPPORTED
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * For the simple (no-context-row) case, we just need to buffer one
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * row group's worth of pixels for the downsampling step.  At the bottom of
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * the image, we pad to a full row group by replicating the last pixel row.
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * The downsampler's last output row is then replicated if needed to pad
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * out to a full iMCU row.
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * When providing context rows, we must buffer three row groups' worth of
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * pixels.  Three row groups are physically allocated, but the row pointer
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * arrays are made five row groups high, with the extra pointers above and
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * below "wrapping around" to point to the last and first real row groups.
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * This allows the downsampler to access the proper context rows.
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * At the top and bottom of the image, we create dummy context rows by
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * copying the first or last real pixel row.  This copying could be avoided
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * trouble on the compression side.
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Private buffer controller object */
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct {
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  struct jpeg_c_prep_controller pub; /* public fields */
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Downsampling input buffer.  This buffer holds color-converted data
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * until we have enough to do a downsample step.
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   */
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  JSAMPARRAY color_buf[MAX_COMPONENTS];
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  JDIMENSION rows_to_go;	/* counts rows remaining in source image */
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  int next_buf_row;		/* index of next row to store in color_buf */
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef CONTEXT_ROWS_SUPPORTED	/* only needed for context case */
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  int this_row_group;		/* starting row index of group to process */
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  int next_buf_stop;		/* downsample when we reach this index */
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} my_prep_controller;
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef my_prep_controller * my_prep_ptr;
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Initialize for a processing pass.
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovMETHODDEF(void)
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstart_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  if (pass_mode != JBUF_PASS_THRU)
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Initialize total-height counter for detecting bottom of image */
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  prep->rows_to_go = cinfo->image_height;
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Mark the conversion buffer empty */
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  prep->next_buf_row = 0;
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef CONTEXT_ROWS_SUPPORTED
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Preset additional state variables for context mode.
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * These aren't used in non-context mode, so we needn't test which mode.
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   */
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  prep->this_row_group = 0;
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Set next_buf_stop to stop after two row groups have been read in. */
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Expand an image vertically from height input_rows to height output_rows,
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * by duplicating the bottom row.
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovLOCAL(void)
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovexpand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		    int input_rows, int output_rows)
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  register int row;
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  for (row = input_rows; row < output_rows; row++) {
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    jcopy_sample_rows(image_data, input_rows-1, image_data, row,
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		      1, num_cols);
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Process some data in the simple no-context case.
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Preprocessor output data is counted in "row groups".  A row group
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * is defined to be v_samp_factor sample rows of each component.
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Downsampling will produce this much data from each max_v_samp_factor
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * input rows.
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovMETHODDEF(void)
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpre_process_data (j_compress_ptr cinfo,
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		  JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		  JDIMENSION in_rows_avail,
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		  JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		  JDIMENSION out_row_groups_avail)
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  int numrows, ci;
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  JDIMENSION inrows;
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  jpeg_component_info * compptr;
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  while (*in_row_ctr < in_rows_avail &&
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	 *out_row_group_ctr < out_row_groups_avail) {
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Do color conversion to fill the conversion buffer. */
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    inrows = in_rows_avail - *in_row_ctr;
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    numrows = (int) MIN((JDIMENSION) numrows, inrows);
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov				       prep->color_buf,
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov				       (JDIMENSION) prep->next_buf_row,
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov				       numrows);
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *in_row_ctr += numrows;
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    prep->next_buf_row += numrows;
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    prep->rows_to_go -= numrows;
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* If at bottom of image, pad to fill the conversion buffer. */
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (prep->rows_to_go == 0 &&
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	prep->next_buf_row < cinfo->max_v_samp_factor) {
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for (ci = 0; ci < cinfo->num_components; ci++) {
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov			   prep->next_buf_row, cinfo->max_v_samp_factor);
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      prep->next_buf_row = cinfo->max_v_samp_factor;
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* If we've filled the conversion buffer, empty it. */
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (prep->next_buf_row == cinfo->max_v_samp_factor) {
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      (*cinfo->downsample->downsample) (cinfo,
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov					prep->color_buf, (JDIMENSION) 0,
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov					output_buf, *out_row_group_ctr);
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      prep->next_buf_row = 0;
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      (*out_row_group_ctr)++;
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* If at bottom of image, pad the output to a full iMCU height.
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     * Note we assume the caller is providing a one-iMCU-height output buffer!
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     */
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (prep->rows_to_go == 0 &&
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	*out_row_group_ctr < out_row_groups_avail) {
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	   ci++, compptr++) {
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	expand_bottom_edge(output_buf[ci],
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov			   compptr->width_in_blocks * DCTSIZE,
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov			   (int) (*out_row_group_ctr * compptr->v_samp_factor),
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov			   (int) (out_row_groups_avail * compptr->v_samp_factor));
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      *out_row_group_ctr = out_row_groups_avail;
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;			/* can exit outer loop without test */
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef CONTEXT_ROWS_SUPPORTED
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Process some data in the context case.
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovMETHODDEF(void)
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpre_process_context (j_compress_ptr cinfo,
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		     JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		     JDIMENSION in_rows_avail,
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		     JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		     JDIMENSION out_row_groups_avail)
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  int numrows, ci;
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  int buf_height = cinfo->max_v_samp_factor * 3;
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  JDIMENSION inrows;
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  while (*out_row_group_ctr < out_row_groups_avail) {
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (*in_row_ctr < in_rows_avail) {
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Do color conversion to fill the conversion buffer. */
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      inrows = in_rows_avail - *in_row_ctr;
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      numrows = prep->next_buf_stop - prep->next_buf_row;
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      numrows = (int) MIN((JDIMENSION) numrows, inrows);
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov					 prep->color_buf,
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov					 (JDIMENSION) prep->next_buf_row,
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov					 numrows);
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Pad at top of image, if first time through */
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if (prep->rows_to_go == cinfo->image_height) {
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	for (ci = 0; ci < cinfo->num_components; ci++) {
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	  int row;
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	  for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	    jcopy_sample_rows(prep->color_buf[ci], 0,
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov			      prep->color_buf[ci], -row,
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov			      1, cinfo->image_width);
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	  }
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	}
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      *in_row_ctr += numrows;
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      prep->next_buf_row += numrows;
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      prep->rows_to_go -= numrows;
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Return for more data, unless we are at the bottom of the image. */
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if (prep->rows_to_go != 0)
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	break;
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* When at bottom of image, pad to fill the conversion buffer. */
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if (prep->next_buf_row < prep->next_buf_stop) {
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	for (ci = 0; ci < cinfo->num_components; ci++) {
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	  expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov			     prep->next_buf_row, prep->next_buf_stop);
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	}
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	prep->next_buf_row = prep->next_buf_stop;
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* If we've gotten enough data, downsample a row group. */
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (prep->next_buf_row == prep->next_buf_stop) {
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      (*cinfo->downsample->downsample) (cinfo,
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov					prep->color_buf,
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov					(JDIMENSION) prep->this_row_group,
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov					output_buf, *out_row_group_ctr);
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      (*out_row_group_ctr)++;
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Advance pointers with wraparound as necessary. */
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      prep->this_row_group += cinfo->max_v_samp_factor;
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if (prep->this_row_group >= buf_height)
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	prep->this_row_group = 0;
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if (prep->next_buf_row >= buf_height)
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	prep->next_buf_row = 0;
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Create the wrapped-around downsampling input buffer needed for context mode.
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovLOCAL(void)
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovcreate_context_buffer (j_compress_ptr cinfo)
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  int rgroup_height = cinfo->max_v_samp_factor;
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  int ci, i;
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  jpeg_component_info * compptr;
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  JSAMPARRAY true_buffer, fake_buffer;
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Grab enough space for fake row pointers for all the components;
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * we need five row groups' worth of pointers for each component.
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   */
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  fake_buffer = (JSAMPARRAY)
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov				(cinfo->num_components * 5 * rgroup_height) *
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov				SIZEOF(JSAMPROW));
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       ci++, compptr++) {
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Allocate the actual buffer space (3 row groups) for this component.
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     * We make the buffer wide enough to allow the downsampler to edge-expand
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     * horizontally within the buffer, if it so chooses.
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     */
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    true_buffer = (*cinfo->mem->alloc_sarray)
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ((j_common_ptr) cinfo, JPOOL_IMAGE,
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov		      cinfo->max_h_samp_factor) / compptr->h_samp_factor),
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       (JDIMENSION) (3 * rgroup_height));
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Copy true buffer row pointers into the middle of the fake row array */
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    MEMCOPY(fake_buffer + rgroup_height, true_buffer,
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	    3 * rgroup_height * SIZEOF(JSAMPROW));
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Fill in the above and below wraparound pointers */
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i = 0; i < rgroup_height; i++) {
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      fake_buffer[i] = true_buffer[2 * rgroup_height + i];
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      fake_buffer[4 * rgroup_height + i] = true_buffer[i];
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    prep->color_buf[ci] = fake_buffer + rgroup_height;
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fake_buffer += 5 * rgroup_height; /* point to space for next component */
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* CONTEXT_ROWS_SUPPORTED */
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Initialize preprocessing controller.
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovGLOBAL(void)
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovjinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  my_prep_ptr prep;
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  int ci;
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  jpeg_component_info * compptr;
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  if (need_full_buffer)		/* safety check */
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  prep = (my_prep_ptr)
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov				SIZEOF(my_prep_controller));
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cinfo->prep = (struct jpeg_c_prep_controller *) prep;
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  prep->pub.start_pass = start_pass_prep;
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Allocate the color conversion buffer.
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * We make the buffer wide enough to allow the downsampler to edge-expand
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * horizontally within the buffer, if it so chooses.
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   */
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  if (cinfo->downsample->need_context_rows) {
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Set up to provide context rows */
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef CONTEXT_ROWS_SUPPORTED
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    prep->pub.pre_process_data = pre_process_context;
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    create_context_buffer(cinfo);
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ERREXIT(cinfo, JERR_NOT_COMPILED);
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  } else {
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* No context, just make it tall enough for one row group */
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    prep->pub.pre_process_data = pre_process_data;
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	 ci++, compptr++) {
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	((j_common_ptr) cinfo, JPOOL_IMAGE,
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	 (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov			cinfo->max_h_samp_factor) / compptr->h_samp_factor),
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov	 (JDIMENSION) cinfo->max_v_samp_factor);
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif //_FX_JPEG_TURBO_
358