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