170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * jcprepct.c
370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Copyright (C) 1994-1996, Thomas G. Lane.
570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This file is part of the Independent JPEG Group's software.
670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * For conditions of distribution and use, see the accompanying README file.
770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This file contains the compression preprocessing controller.
970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This controller manages the color conversion, downsampling,
1070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * and edge expansion steps.
1170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
1270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Most of the complexity here is associated with buffering input rows
1370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * as required by the downsampler.  See the comments at the head of
1470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * jcsample.c for the downsampler's needs.
1570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
1670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
1770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define JPEG_INTERNALS
1870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include "jinclude.h"
1970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include "jpeglib.h"
2070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
2170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
2270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* At present, jcsample.c can request context rows only for smoothing.
2370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * In the future, we might also need context rows for CCIR601 sampling
2470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * or other more-complex downsampling procedures.  The code to support
2570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * context rows should be compiled only if needed.
2670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
2770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef INPUT_SMOOTHING_SUPPORTED
2870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define CONTEXT_ROWS_SUPPORTED
2970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
3070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
3170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
3270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
3370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * For the simple (no-context-row) case, we just need to buffer one
3470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * row group's worth of pixels for the downsampling step.  At the bottom of
3570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * the image, we pad to a full row group by replicating the last pixel row.
3670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * The downsampler's last output row is then replicated if needed to pad
3770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * out to a full iMCU row.
3870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
3970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * When providing context rows, we must buffer three row groups' worth of
4070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * pixels.  Three row groups are physically allocated, but the row pointer
4170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * arrays are made five row groups high, with the extra pointers above and
4270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * below "wrapping around" to point to the last and first real row groups.
4370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This allows the downsampler to access the proper context rows.
4470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * At the top and bottom of the image, we create dummy context rows by
4570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * copying the first or last real pixel row.  This copying could be avoided
4670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
4770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * trouble on the compression side.
4870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
4970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
5070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
5170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Private buffer controller object */
5270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
5370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinetypedef struct {
5470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  struct jpeg_c_prep_controller pub; /* public fields */
5570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
5670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Downsampling input buffer.  This buffer holds color-converted data
5770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * until we have enough to do a downsample step.
5870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
5970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JSAMPARRAY color_buf[MAX_COMPONENTS];
6070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
6170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION rows_to_go;	/* counts rows remaining in source image */
6270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int next_buf_row;		/* index of next row to store in color_buf */
6370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
6470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef CONTEXT_ROWS_SUPPORTED	/* only needed for context case */
6570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int this_row_group;		/* starting row index of group to process */
6670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int next_buf_stop;		/* downsample when we reach this index */
6770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
6870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} my_prep_controller;
6970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
7070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinetypedef my_prep_controller * my_prep_ptr;
7170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
7270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
7370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
7470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Initialize for a processing pass.
7570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
7670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
7770a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(void)
7870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestart_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
7970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
8070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
8170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
8270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (pass_mode != JBUF_PASS_THRU)
8370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
8470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
8570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Initialize total-height counter for detecting bottom of image */
8670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  prep->rows_to_go = cinfo->image_height;
8770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Mark the conversion buffer empty */
8870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  prep->next_buf_row = 0;
8970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef CONTEXT_ROWS_SUPPORTED
9070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Preset additional state variables for context mode.
9170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * These aren't used in non-context mode, so we needn't test which mode.
9270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
9370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  prep->this_row_group = 0;
9470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Set next_buf_stop to stop after two row groups have been read in. */
9570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
9670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
9770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
9870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
9970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
10070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
10170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Expand an image vertically from height input_rows to height output_rows,
10270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * by duplicating the bottom row.
10370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
10470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
10570a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
10670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineexpand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
10770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    int input_rows, int output_rows)
10870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
10970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  register int row;
11070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
11170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (row = input_rows; row < output_rows; row++) {
11270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    jcopy_sample_rows(image_data, input_rows-1, image_data, row,
11370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		      1, num_cols);
11470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
11570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
11670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
11770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
11870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
11970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Process some data in the simple no-context case.
12070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
12170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Preprocessor output data is counted in "row groups".  A row group
12270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * is defined to be v_samp_factor sample rows of each component.
12370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Downsampling will produce this much data from each max_v_samp_factor
12470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * input rows.
12570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
12670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
12770a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(void)
12870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinepre_process_data (j_compress_ptr cinfo,
12970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
13070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  JDIMENSION in_rows_avail,
13170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
13270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  JDIMENSION out_row_groups_avail)
13370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
13470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
13570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int numrows, ci;
13670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION inrows;
13770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info * compptr;
13870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
13970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  while (*in_row_ctr < in_rows_avail &&
14070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 *out_row_group_ctr < out_row_groups_avail) {
14170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* Do color conversion to fill the conversion buffer. */
14270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    inrows = in_rows_avail - *in_row_ctr;
14370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
14470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    numrows = (int) MIN((JDIMENSION) numrows, inrows);
14570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
14670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				       prep->color_buf,
14770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				       (JDIMENSION) prep->next_buf_row,
14870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				       numrows);
14970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    *in_row_ctr += numrows;
15070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    prep->next_buf_row += numrows;
15170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    prep->rows_to_go -= numrows;
15270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* If at bottom of image, pad to fill the conversion buffer. */
15370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (prep->rows_to_go == 0 &&
15470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	prep->next_buf_row < cinfo->max_v_samp_factor) {
15570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (ci = 0; ci < cinfo->num_components; ci++) {
15670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
15770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			   prep->next_buf_row, cinfo->max_v_samp_factor);
15870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
15970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      prep->next_buf_row = cinfo->max_v_samp_factor;
16070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
16170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* If we've filled the conversion buffer, empty it. */
16270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (prep->next_buf_row == cinfo->max_v_samp_factor) {
16370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      (*cinfo->downsample->downsample) (cinfo,
16470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine					prep->color_buf, (JDIMENSION) 0,
16570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine					output_buf, *out_row_group_ctr);
16670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      prep->next_buf_row = 0;
16770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      (*out_row_group_ctr)++;
16870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
16970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* If at bottom of image, pad the output to a full iMCU height.
17070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * Note we assume the caller is providing a one-iMCU-height output buffer!
17170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     */
17270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (prep->rows_to_go == 0 &&
17370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	*out_row_group_ctr < out_row_groups_avail) {
17470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
17570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   ci++, compptr++) {
17670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	expand_bottom_edge(output_buf[ci],
17770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			   compptr->width_in_blocks * DCTSIZE,
17870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			   (int) (*out_row_group_ctr * compptr->v_samp_factor),
17970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			   (int) (out_row_groups_avail * compptr->v_samp_factor));
18070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
18170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      *out_row_group_ctr = out_row_groups_avail;
18270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      break;			/* can exit outer loop without test */
18370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
18470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
18570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
18670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
18770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
18870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef CONTEXT_ROWS_SUPPORTED
18970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
19070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
19170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Process some data in the context case.
19270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
19370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
19470a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(void)
19570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinepre_process_context (j_compress_ptr cinfo,
19670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		     JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
19770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		     JDIMENSION in_rows_avail,
19870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		     JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
19970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		     JDIMENSION out_row_groups_avail)
20070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
20170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
20270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int numrows, ci;
20370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int buf_height = cinfo->max_v_samp_factor * 3;
20470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION inrows;
20570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
20670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  while (*out_row_group_ctr < out_row_groups_avail) {
20770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (*in_row_ctr < in_rows_avail) {
20870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      /* Do color conversion to fill the conversion buffer. */
20970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      inrows = in_rows_avail - *in_row_ctr;
21070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      numrows = prep->next_buf_stop - prep->next_buf_row;
21170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      numrows = (int) MIN((JDIMENSION) numrows, inrows);
21270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
21370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine					 prep->color_buf,
21470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine					 (JDIMENSION) prep->next_buf_row,
21570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine					 numrows);
21670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      /* Pad at top of image, if first time through */
21770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      if (prep->rows_to_go == cinfo->image_height) {
21870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	for (ci = 0; ci < cinfo->num_components; ci++) {
21970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  int row;
22070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
22170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    jcopy_sample_rows(prep->color_buf[ci], 0,
22270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			      prep->color_buf[ci], -row,
22370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			      1, cinfo->image_width);
22470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
22570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	}
22670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
22770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      *in_row_ctr += numrows;
22870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      prep->next_buf_row += numrows;
22970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      prep->rows_to_go -= numrows;
23070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    } else {
23170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      /* Return for more data, unless we are at the bottom of the image. */
23270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      if (prep->rows_to_go != 0)
23370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	break;
23470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      /* When at bottom of image, pad to fill the conversion buffer. */
23570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      if (prep->next_buf_row < prep->next_buf_stop) {
23670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	for (ci = 0; ci < cinfo->num_components; ci++) {
23770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
23870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			     prep->next_buf_row, prep->next_buf_stop);
23970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	}
24070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	prep->next_buf_row = prep->next_buf_stop;
24170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
24270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
24370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* If we've gotten enough data, downsample a row group. */
24470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (prep->next_buf_row == prep->next_buf_stop) {
24570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      (*cinfo->downsample->downsample) (cinfo,
24670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine					prep->color_buf,
24770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine					(JDIMENSION) prep->this_row_group,
24870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine					output_buf, *out_row_group_ctr);
24970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      (*out_row_group_ctr)++;
25070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      /* Advance pointers with wraparound as necessary. */
25170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      prep->this_row_group += cinfo->max_v_samp_factor;
25270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      if (prep->this_row_group >= buf_height)
25370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	prep->this_row_group = 0;
25470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      if (prep->next_buf_row >= buf_height)
25570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	prep->next_buf_row = 0;
25670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
25770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
25870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
25970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
26070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
26170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
26270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
26370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Create the wrapped-around downsampling input buffer needed for context mode.
26470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
26570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
26670a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
26770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinecreate_context_buffer (j_compress_ptr cinfo)
26870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
26970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
27070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int rgroup_height = cinfo->max_v_samp_factor;
27170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci, i;
27270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info * compptr;
27370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JSAMPARRAY true_buffer, fake_buffer;
27470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
27570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Grab enough space for fake row pointers for all the components;
27670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * we need five row groups' worth of pointers for each component.
27770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
27870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  fake_buffer = (JSAMPARRAY)
27970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
28070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				(cinfo->num_components * 5 * rgroup_height) *
28170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				SIZEOF(JSAMPROW));
28270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
28370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
28470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine       ci++, compptr++) {
28570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* Allocate the actual buffer space (3 row groups) for this component.
28670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * We make the buffer wide enough to allow the downsampler to edge-expand
28770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * horizontally within the buffer, if it so chooses.
28870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     */
28970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    true_buffer = (*cinfo->mem->alloc_sarray)
29070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      ((j_common_ptr) cinfo, JPOOL_IMAGE,
29170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine       (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
29270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		      cinfo->max_h_samp_factor) / compptr->h_samp_factor),
29370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine       (JDIMENSION) (3 * rgroup_height));
29470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* Copy true buffer row pointers into the middle of the fake row array */
29570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    MEMCOPY(fake_buffer + rgroup_height, true_buffer,
29670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    3 * rgroup_height * SIZEOF(JSAMPROW));
29770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* Fill in the above and below wraparound pointers */
29870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (i = 0; i < rgroup_height; i++) {
29970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      fake_buffer[i] = true_buffer[2 * rgroup_height + i];
30070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      fake_buffer[4 * rgroup_height + i] = true_buffer[i];
30170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
30270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    prep->color_buf[ci] = fake_buffer + rgroup_height;
30370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    fake_buffer += 5 * rgroup_height; /* point to space for next component */
30470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
30570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
30670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
30770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif /* CONTEXT_ROWS_SUPPORTED */
30870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
30970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
31070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
31170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Initialize preprocessing controller.
31270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
31370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
31470a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineGLOBAL(void)
31570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinejinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
31670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
31770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  my_prep_ptr prep;
31870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci;
31970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info * compptr;
32070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
32170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (need_full_buffer)		/* safety check */
32270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
32370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
32470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  prep = (my_prep_ptr)
32570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
32670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				SIZEOF(my_prep_controller));
32770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  cinfo->prep = (struct jpeg_c_prep_controller *) prep;
32870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  prep->pub.start_pass = start_pass_prep;
32970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
33070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Allocate the color conversion buffer.
33170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * We make the buffer wide enough to allow the downsampler to edge-expand
33270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * horizontally within the buffer, if it so chooses.
33370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
33470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (cinfo->downsample->need_context_rows) {
33570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* Set up to provide context rows */
33670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef CONTEXT_ROWS_SUPPORTED
33770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    prep->pub.pre_process_data = pre_process_context;
33870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    create_context_buffer(cinfo);
33970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#else
34070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ERREXIT(cinfo, JERR_NOT_COMPILED);
34170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
34270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  } else {
34370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* No context, just make it tall enough for one row group */
34470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    prep->pub.pre_process_data = pre_process_data;
34570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
34670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 ci++, compptr++) {
34770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
34870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	((j_common_ptr) cinfo, JPOOL_IMAGE,
34970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
35070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			cinfo->max_h_samp_factor) / compptr->h_samp_factor),
35170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) cinfo->max_v_samp_factor);
35270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
35370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
35470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
355