1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * jcsample.c 3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 4e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Copyright (C) 1991-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 downsampling routines. 9e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 10e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Downsampling input data is counted in "row groups". A row group 11e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * is defined to be max_v_samp_factor pixel rows of each component, 12e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * from which the downsampler produces v_samp_factor sample rows. 13e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * A single row group is processed in each call to the downsampler module. 14e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 15e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The downsampler is responsible for edge-expansion of its output data 16e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * to fill an integral number of DCT blocks horizontally. The source buffer 17e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * may be modified if it is helpful for this purpose (the source buffer is 18e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * allocated wide enough to correspond to the desired output width). 19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The caller (the prep controller) is responsible for vertical padding. 20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The downsampler may request "context rows" by setting need_context_rows 22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * during startup. In this case, the input arrays will contain at least 23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * one row group's worth of pixels above and below the passed-in data; 24e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * the caller will create dummy rows at image top and bottom by replicating 25e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * the first or last real pixel row. 26e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 27e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * An excellent reference for image resampling is 28e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Digital Image Warping, George Wolberg, 1990. 29e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. 30e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 31e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The downsampling algorithm used here is a simple average of the source 32e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * pixels covered by the output pixel. The hi-falutin sampling literature 33e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * refers to this as a "box filter". In general the characteristics of a box 34e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * filter are not very good, but for the specific cases we normally use (1:1 35e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not 36e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * nearly so bad. If you intend to use other sampling ratios, you'd be well 37e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * advised to improve this code. 38e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 39e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * A simple input-smoothing capability is provided. This is mainly intended 40e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * for cleaning up color-dithered GIF input files (if you find it inadequate, 41e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * we suggest using an external filtering program such as pnmconvol). When 42e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * enabled, each input pixel P is replaced by a weighted sum of itself and its 43e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, 44e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * where SF = (smoothing_factor / 1024). 45e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Currently, smoothing is only supported for 2h2v sampling factors. 46e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 47e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 48e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define JPEG_INTERNALS 49e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "jinclude.h" 50e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "jpeglib.h" 51e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 52e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 53e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Pointer to routine to downsample a single component */ 54e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovtypedef JMETHOD(void, downsample1_ptr, 55e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (j_compress_ptr cinfo, jpeg_component_info * compptr, 56e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY input_data, JSAMPARRAY output_data)); 57e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 58e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Private subobject */ 59e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 60e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovtypedef struct { 61e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov struct jpeg_downsampler pub; /* public fields */ 62e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 63e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Downsampling method pointers, one per component */ 64e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample1_ptr methods[MAX_COMPONENTS]; 65e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} my_downsampler; 66e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 67e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovtypedef my_downsampler * my_downsample_ptr; 68e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 69e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 70e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 71e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Initialize for a downsampling pass. 72e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 73e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 74e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 75e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstart_pass_downsample (j_compress_ptr cinfo) 76e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 77e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* no work for now */ 78e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 79e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 80e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 81e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 82e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Expand a component horizontally from width input_cols to width output_cols, 83e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * by duplicating the rightmost samples. 84e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 85e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 86e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovLOCAL(void) 87e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovexpand_right_edge (JSAMPARRAY image_data, int num_rows, 88e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION input_cols, JDIMENSION output_cols) 89e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 90e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW ptr; 91e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPLE pixval; 92e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register int count; 93e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int row; 94e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int numcols = (int) (output_cols - input_cols); 95e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 96e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (numcols > 0) { 97e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (row = 0; row < num_rows; row++) { 98e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ptr = image_data[row] + input_cols; 99e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ 100e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (count = numcols; count > 0; count--) 101e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *ptr++ = pixval; 102e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 103e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 104e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 105e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 106e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 107e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 108e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Do downsampling for a whole row group (all components). 109e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 110e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * In this version we simply downsample each component independently. 111e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 112e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 113e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 114e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovsep_downsample (j_compress_ptr cinfo, 115e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPIMAGE input_buf, JDIMENSION in_row_index, 116e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) 117e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 118e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; 119e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int ci; 120e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov jpeg_component_info * compptr; 121e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY in_ptr, out_ptr; 122e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 123e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 124e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ci++, compptr++) { 125e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov in_ptr = input_buf[ci] + in_row_index; 126e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); 127e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); 128e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 129e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 130e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 131e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 132e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 133e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Downsample pixel values of a single component. 134e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * One row group is processed per call. 135e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This version handles arbitrary integral sampling ratios, without smoothing. 136e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Note that this version is not actually used for customary sampling ratios. 137e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 138e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 139e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 140e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovint_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, 141e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY input_data, JSAMPARRAY output_data) 142e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 143e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; 144e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ 145e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; 146e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPROW inptr, outptr; 147e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov INT32 outvalue; 148e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 149e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; 150e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; 151e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov numpix = h_expand * v_expand; 152e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov numpix2 = numpix/2; 153e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 154e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Expand input data enough to let all the output samples be generated 155e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * by the standard loop. Special-casing padded output would be more 156e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * efficient. 157e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 158e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov expand_right_edge(input_data, cinfo->max_v_samp_factor, 159e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->image_width, output_cols * h_expand); 160e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 161e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inrow = 0; 162e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { 163e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr = output_data[outrow]; 164e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (outcol = 0, outcol_h = 0; outcol < output_cols; 165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outcol++, outcol_h += h_expand) { 166e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outvalue = 0; 167e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (v = 0; v < v_expand; v++) { 168e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr = input_data[inrow+v] + outcol_h; 169e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (h = 0; h < h_expand; h++) { 170e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outvalue += (INT32) GETJSAMPLE(*inptr++); 171e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 172e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); 174e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 175e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inrow += v_expand; 176e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 177e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 178e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 180e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Downsample pixel values of a single component. 182e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This version handles the special case of a full-size component, 183e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * without smoothing. 184e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 185e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 186e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 187e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovfullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, 188e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY input_data, JSAMPARRAY output_data) 189e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 190e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Copy the data */ 191e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov jcopy_sample_rows(input_data, 0, output_data, 0, 192e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->max_v_samp_factor, cinfo->image_width); 193e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Edge-expand */ 194e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov expand_right_edge(output_data, cinfo->max_v_samp_factor, 195e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->image_width, compptr->width_in_blocks * DCTSIZE); 196e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 197e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 198e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 199e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 200e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Downsample pixel values of a single component. 201e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This version handles the common case of 2:1 horizontal and 1:1 vertical, 202e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * without smoothing. 203e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 204e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * A note about the "bias" calculations: when rounding fractional values to 205e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * integer, we do not want to always round 0.5 up to the next integer. 206e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * If we did that, we'd introduce a noticeable bias towards larger values. 207e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Instead, this code is arranged so that 0.5 will be rounded up or down at 208e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * alternate pixel locations (a simple ordered dither pattern). 209e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 210e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 211e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 212e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovh2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, 213e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY input_data, JSAMPARRAY output_data) 214e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 215e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int outrow; 216e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION outcol; 217e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; 218e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW inptr, outptr; 219e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register int bias; 220e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 221e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Expand input data enough to let all the output samples be generated 222e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * by the standard loop. Special-casing padded output would be more 223e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * efficient. 224e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 225e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov expand_right_edge(input_data, cinfo->max_v_samp_factor, 226e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->image_width, output_cols * 2); 227e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 228e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { 229e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr = output_data[outrow]; 230e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr = input_data[outrow]; 231e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bias = 0; /* bias = 0,1,0,1,... for successive samples */ 232e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (outcol = 0; outcol < output_cols; outcol++) { 233e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) 234e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov + bias) >> 1); 235e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bias ^= 1; /* 0=>1, 1=>0 */ 236e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr += 2; 237e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 238e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 239e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 240e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 241e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 242e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 243e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Downsample pixel values of a single component. 244e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This version handles the standard case of 2:1 horizontal and 2:1 vertical, 245e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * without smoothing. 246e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 247e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 248e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 249e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovh2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, 250e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY input_data, JSAMPARRAY output_data) 251e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 252e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int inrow, outrow; 253e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION outcol; 254e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; 255e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW inptr0, inptr1, outptr; 256e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register int bias; 257e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 258e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Expand input data enough to let all the output samples be generated 259e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * by the standard loop. Special-casing padded output would be more 260e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * efficient. 261e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 262e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov expand_right_edge(input_data, cinfo->max_v_samp_factor, 263e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->image_width, output_cols * 2); 264e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 265e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inrow = 0; 266e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { 267e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr = output_data[outrow]; 268e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr0 = input_data[inrow]; 269e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr1 = input_data[inrow+1]; 270e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bias = 1; /* bias = 1,2,1,2,... for successive samples */ 271e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (outcol = 0; outcol < output_cols; outcol++) { 272e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + 273e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) 274e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov + bias) >> 2); 275e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bias ^= 3; /* 1=>2, 2=>1 */ 276e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr0 += 2; inptr1 += 2; 277e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 278e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inrow += 2; 279e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 280e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 281e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 282e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 283e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#ifdef INPUT_SMOOTHING_SUPPORTED 284e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 285e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 286e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Downsample pixel values of a single component. 287e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This version handles the standard case of 2:1 horizontal and 2:1 vertical, 288e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * with smoothing. One row of context is required. 289e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 290e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 291e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 292e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovh2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, 293e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY input_data, JSAMPARRAY output_data) 294e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 295e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int inrow, outrow; 296e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION colctr; 297e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; 298e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; 299e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov INT32 membersum, neighsum, memberscale, neighscale; 300e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 301e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Expand input data enough to let all the output samples be generated 302e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * by the standard loop. Special-casing padded output would be more 303e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * efficient. 304e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 305e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, 306e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->image_width, output_cols * 2); 307e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 308e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* We don't bother to form the individual "smoothed" input pixel values; 309e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * we can directly compute the output which is the average of the four 310e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * smoothed values. Each of the four member pixels contributes a fraction 311e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * (1-8*SF) to its own smoothed image and a fraction SF to each of the three 312e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final 313e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * output. The four corner-adjacent neighbor pixels contribute a fraction 314e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * SF to just one smoothed pixel, or SF/4 to the final output; while the 315e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * eight edge-adjacent neighbors contribute SF to each of two smoothed 316e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * pixels, or SF/2 overall. In order to use integer arithmetic, these 317e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * factors are scaled by 2^16 = 65536. 318e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Also recall that SF = smoothing_factor / 1024. 319e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 320e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 321e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ 322e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ 323e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 324e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inrow = 0; 325e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { 326e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr = output_data[outrow]; 327e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr0 = input_data[inrow]; 328e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr1 = input_data[inrow+1]; 329e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov above_ptr = input_data[inrow-1]; 330e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov below_ptr = input_data[inrow+2]; 331e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 332e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Special case for first column: pretend column -1 is same as column 0 */ 333e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + 334e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); 335e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + 336e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + 337e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + 338e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); 339e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum += neighsum; 340e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + 341e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); 342e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = membersum * memberscale + neighsum * neighscale; 343e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); 344e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; 345e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 346e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (colctr = output_cols - 2; colctr > 0; colctr--) { 347e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* sum of pixels directly mapped to this output element */ 348e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + 349e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); 350e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* sum of edge-neighbor pixels */ 351e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + 352e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + 353e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + 354e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); 355e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* The edge-neighbors count twice as much as corner-neighbors */ 356e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum += neighsum; 357e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Add in the corner-neighbors */ 358e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + 359e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); 360e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* form final output scaled up by 2^16 */ 361e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = membersum * memberscale + neighsum * neighscale; 362e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* round, descale and output it */ 363e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); 364e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; 365e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 366e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 367e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Special case for last column */ 368e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + 369e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); 370e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + 371e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + 372e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + 373e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); 374e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum += neighsum; 375e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + 376e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); 377e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = membersum * memberscale + neighsum * neighscale; 378e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outptr = (JSAMPLE) ((membersum + 32768) >> 16); 379e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 380e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inrow += 2; 381e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 382e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 383e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 384e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 385e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 386e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Downsample pixel values of a single component. 387e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This version handles the special case of a full-size component, 388e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * with smoothing. One row of context is required. 389e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 390e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 391e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 392e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovfullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, 393e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY input_data, JSAMPARRAY output_data) 394e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 395e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int outrow; 396e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION colctr; 397e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; 398e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW inptr, above_ptr, below_ptr, outptr; 399e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov INT32 membersum, neighsum, memberscale, neighscale; 400e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int colsum, lastcolsum, nextcolsum; 401e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 402e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Expand input data enough to let all the output samples be generated 403e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * by the standard loop. Special-casing padded output would be more 404e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * efficient. 405e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 406e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, 407e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->image_width, output_cols); 408e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 409e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Each of the eight neighbor pixels contributes a fraction SF to the 410e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * smoothed pixel, while the main pixel contributes (1-8*SF). In order 411e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. 412e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Also recall that SF = smoothing_factor / 1024. 413e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 414e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 415e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ 416e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ 417e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 418e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { 419e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr = output_data[outrow]; 420e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr = input_data[outrow]; 421e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov above_ptr = input_data[outrow-1]; 422e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov below_ptr = input_data[outrow+1]; 423e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 424e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Special case for first column */ 425e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + 426e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*inptr); 427e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = GETJSAMPLE(*inptr++); 428e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + 429e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*inptr); 430e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum = colsum + (colsum - membersum) + nextcolsum; 431e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = membersum * memberscale + neighsum * neighscale; 432e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); 433e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov lastcolsum = colsum; colsum = nextcolsum; 434e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 435e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (colctr = output_cols - 2; colctr > 0; colctr--) { 436e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = GETJSAMPLE(*inptr++); 437e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov above_ptr++; below_ptr++; 438e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + 439e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov GETJSAMPLE(*inptr); 440e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum = lastcolsum + (colsum - membersum) + nextcolsum; 441e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = membersum * memberscale + neighsum * neighscale; 442e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); 443e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov lastcolsum = colsum; colsum = nextcolsum; 444e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 445e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 446e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Special case for last column */ 447e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = GETJSAMPLE(*inptr); 448e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov neighsum = lastcolsum + (colsum - membersum) + colsum; 449e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov membersum = membersum * memberscale + neighsum * neighscale; 450e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outptr = (JSAMPLE) ((membersum + 32768) >> 16); 451e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 452e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 453e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 454e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 455e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif /* INPUT_SMOOTHING_SUPPORTED */ 456e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 457e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 458e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 459e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Module initialization routine for downsampling. 460e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Note that we must select a routine for each component. 461e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 462e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 463e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovGLOBAL(void) 464e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovjinit_downsampler (j_compress_ptr cinfo) 465e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 466e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_downsample_ptr downsample; 467e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int ci; 468e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov jpeg_component_info * compptr; 469e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov boolean smoothok = TRUE; 470e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 471e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample = (my_downsample_ptr) 472e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 473e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov SIZEOF(my_downsampler)); 474e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->downsample = (struct jpeg_downsampler *) downsample; 475e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->pub.start_pass = start_pass_downsample; 476e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->pub.downsample = sep_downsample; 477e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->pub.need_context_rows = FALSE; 478e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 479e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->CCIR601_sampling) 480e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); 481e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 482e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Verify we can handle the sampling factors, and set up method pointers */ 483e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 484e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ci++, compptr++) { 485e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (compptr->h_samp_factor == cinfo->max_h_samp_factor && 486e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov compptr->v_samp_factor == cinfo->max_v_samp_factor) { 487e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#ifdef INPUT_SMOOTHING_SUPPORTED 488e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->smoothing_factor) { 489e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->methods[ci] = fullsize_smooth_downsample; 490e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->pub.need_context_rows = TRUE; 491e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else 492e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 493e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->methods[ci] = fullsize_downsample; 494e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && 495e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov compptr->v_samp_factor == cinfo->max_v_samp_factor) { 496e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov smoothok = FALSE; 497e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->methods[ci] = h2v1_downsample; 498e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && 499e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { 500e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#ifdef INPUT_SMOOTHING_SUPPORTED 501e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->smoothing_factor) { 502e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->methods[ci] = h2v2_smooth_downsample; 503e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->pub.need_context_rows = TRUE; 504e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else 505e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 506e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->methods[ci] = h2v2_downsample; 507e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && 508e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { 509e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov smoothok = FALSE; 510e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov downsample->methods[ci] = int_downsample; 511e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else 512e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); 513e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 514e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 515e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#ifdef INPUT_SMOOTHING_SUPPORTED 516e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->smoothing_factor && !smoothok) 517e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); 518e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 519e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 520