12cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane/* 22cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane * jcsample.c 32cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane * 4da13af6b8d5427af89bbdc5698b4e09d0ea814feDRC * This file was part of the Independent JPEG Group's software: 5489583f5165e05d37302e8eeec58104ea0109127Thomas G. Lane * Copyright (C) 1991-1996, Thomas G. Lane. 6da13af6b8d5427af89bbdc5698b4e09d0ea814feDRC * libjpeg-turbo Modifications: 759a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB 85ef463056ae22f24c3915ba7ab03eefd5bb6fde7DRC * Copyright (C) 2014, MIPS Technologies, Inc., California 92cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane * For conditions of distribution and use, see the accompanying README file. 102cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane * 1188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This file contains downsampling routines. 1236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * 1336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Downsampling input data is counted in "row groups". A row group 1436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * is defined to be max_v_samp_factor pixel rows of each component, 1536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * from which the downsampler produces v_samp_factor sample rows. 1636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * A single row group is processed in each call to the downsampler module. 1736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * 1836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * The downsampler is responsible for edge-expansion of its output data 1936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * to fill an integral number of DCT blocks horizontally. The source buffer 2036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * may be modified if it is helpful for this purpose (the source buffer is 2136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * allocated wide enough to correspond to the desired output width). 2236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * The caller (the prep controller) is responsible for vertical padding. 2336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * 2436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * The downsampler may request "context rows" by setting need_context_rows 2536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * during startup. In this case, the input arrays will contain at least 2636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * one row group's worth of pixels above and below the passed-in data; 2736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * the caller will create dummy rows at image top and bottom by replicating 2836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * the first or last real pixel row. 2988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * 3088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * An excellent reference for image resampling is 3188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Digital Image Warping, George Wolberg, 1990. 3288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. 3388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * 3488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * The downsampling algorithm used here is a simple average of the source 3588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * pixels covered by the output pixel. The hi-falutin sampling literature 3688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * refers to this as a "box filter". In general the characteristics of a box 3788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * filter are not very good, but for the specific cases we normally use (1:1 3888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not 3988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * nearly so bad. If you intend to use other sampling ratios, you'd be well 4088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * advised to improve this code. 4188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * 4288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * A simple input-smoothing capability is provided. This is mainly intended 4388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * for cleaning up color-dithered GIF input files (if you find it inadequate, 4488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * we suggest using an external filtering program such as pnmconvol). When 4588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * enabled, each input pixel P is replaced by a weighted sum of itself and its 4688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, 4788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * where SF = (smoothing_factor / 1024). 4888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Currently, smoothing is only supported for 2h2v sampling factors. 492cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane */ 502cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 5136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#define JPEG_INTERNALS 522cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane#include "jinclude.h" 5336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#include "jpeglib.h" 5459a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman#include "jsimd.h" 5536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 5636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 5736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* Pointer to routine to downsample a single component */ 58bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRCtypedef void (*downsample1_ptr) (j_compress_ptr cinfo, 59bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC jpeg_component_info * compptr, 60bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC JSAMPARRAY input_data, 61bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC JSAMPARRAY output_data); 6236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 6336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* Private subobject */ 6436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 6536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanetypedef struct { 66b775351012af176720429ac21d11682a0b75b4b7DRC struct jpeg_downsampler pub; /* public fields */ 6736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 6836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane /* Downsampling method pointers, one per component */ 6936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane downsample1_ptr methods[MAX_COMPONENTS]; 7036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane} my_downsampler; 7136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 7236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanetypedef my_downsampler * my_downsample_ptr; 732cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 742cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 752cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane/* 7636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Initialize for a downsampling pass. 772cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane */ 782cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 79489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) 8036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanestart_pass_downsample (j_compress_ptr cinfo) 812cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane{ 822cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane /* no work for now */ 832cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane} 842cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 852cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 862cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane/* 8736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Expand a component horizontally from width input_cols to width output_cols, 8836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * by duplicating the rightmost samples. 8936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */ 9036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 91489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneLOCAL(void) 9236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneexpand_right_edge (JSAMPARRAY image_data, int num_rows, 93b775351012af176720429ac21d11682a0b75b4b7DRC JDIMENSION input_cols, JDIMENSION output_cols) 9436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{ 9536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane register JSAMPROW ptr; 9636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane register JSAMPLE pixval; 9736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane register int count; 9836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane int row; 9936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane int numcols = (int) (output_cols - input_cols); 10036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 10136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane if (numcols > 0) { 10236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane for (row = 0; row < num_rows; row++) { 10336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane ptr = image_data[row] + input_cols; 104b775351012af176720429ac21d11682a0b75b4b7DRC pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ 10536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane for (count = numcols; count > 0; count--) 106b775351012af176720429ac21d11682a0b75b4b7DRC *ptr++ = pixval; 10736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane } 10836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane } 10936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane} 11036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 11136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 11236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* 11336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Do downsampling for a whole row group (all components). 11436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * 11536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * In this version we simply downsample each component independently. 11636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */ 11736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 118489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) 11936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanesep_downsample (j_compress_ptr cinfo, 120b775351012af176720429ac21d11682a0b75b4b7DRC JSAMPIMAGE input_buf, JDIMENSION in_row_index, 121b775351012af176720429ac21d11682a0b75b4b7DRC JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) 12236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{ 12336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; 12436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane int ci; 12536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane jpeg_component_info * compptr; 12636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane JSAMPARRAY in_ptr, out_ptr; 12736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 12836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 12936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane ci++, compptr++) { 13036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane in_ptr = input_buf[ci] + in_row_index; 13136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); 13236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); 13336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane } 13436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane} 13536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 13636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 13736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* 13888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Downsample pixel values of a single component. 13936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * One row group is processed per call. 14088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This version handles arbitrary integral sampling ratios, without smoothing. 14188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Note that this version is not actually used for customary sampling ratios. 1422cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane */ 1432cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 144489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) 14536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneint_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, 146b775351012af176720429ac21d11682a0b75b4b7DRC JSAMPARRAY input_data, JSAMPARRAY output_data) 1472cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane{ 1482cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; 149b775351012af176720429ac21d11682a0b75b4b7DRC JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ 15036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; 1512cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane JSAMPROW inptr, outptr; 1522cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane INT32 outvalue; 1532cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 1542cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; 1552cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; 1562cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane numpix = h_expand * v_expand; 1572cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane numpix2 = numpix/2; 1582cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 15936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane /* Expand input data enough to let all the output samples be generated 16036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * by the standard loop. Special-casing padded output would be more 16136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * efficient. 16236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */ 16336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane expand_right_edge(input_data, cinfo->max_v_samp_factor, 164b775351012af176720429ac21d11682a0b75b4b7DRC cinfo->image_width, output_cols * h_expand); 16536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 1662cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane inrow = 0; 16736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { 1682cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane outptr = output_data[outrow]; 16988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane for (outcol = 0, outcol_h = 0; outcol < output_cols; 170b775351012af176720429ac21d11682a0b75b4b7DRC outcol++, outcol_h += h_expand) { 1712cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane outvalue = 0; 1722cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane for (v = 0; v < v_expand; v++) { 173b775351012af176720429ac21d11682a0b75b4b7DRC inptr = input_data[inrow+v] + outcol_h; 174b775351012af176720429ac21d11682a0b75b4b7DRC for (h = 0; h < h_expand; h++) { 175b775351012af176720429ac21d11682a0b75b4b7DRC outvalue += (INT32) GETJSAMPLE(*inptr++); 176b775351012af176720429ac21d11682a0b75b4b7DRC } 1772cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane } 178bd543f030e7e435c2c6a6a7d52ad927ae97cd927Thomas G. Lane *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); 1792cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane } 1802cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane inrow += v_expand; 1812cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane } 1822cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane} 1832cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 1842cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 1852cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane/* 18688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Downsample pixel values of a single component. 18736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * This version handles the special case of a full-size component, 18836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * without smoothing. 18936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */ 19036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 191489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) 19236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanefullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, 193b775351012af176720429ac21d11682a0b75b4b7DRC JSAMPARRAY input_data, JSAMPARRAY output_data) 19436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{ 19536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane /* Copy the data */ 19636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane jcopy_sample_rows(input_data, 0, output_data, 0, 197b775351012af176720429ac21d11682a0b75b4b7DRC cinfo->max_v_samp_factor, cinfo->image_width); 19836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane /* Edge-expand */ 19936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane expand_right_edge(output_data, cinfo->max_v_samp_factor, 200b775351012af176720429ac21d11682a0b75b4b7DRC cinfo->image_width, compptr->width_in_blocks * DCTSIZE); 20136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane} 20236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 20336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 20436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* 20536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Downsample pixel values of a single component. 20688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This version handles the common case of 2:1 horizontal and 1:1 vertical, 20788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * without smoothing. 20836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * 20936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * A note about the "bias" calculations: when rounding fractional values to 21036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * integer, we do not want to always round 0.5 up to the next integer. 21136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * If we did that, we'd introduce a noticeable bias towards larger values. 21236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Instead, this code is arranged so that 0.5 will be rounded up or down at 21336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * alternate pixel locations (a simple ordered dither pattern). 21488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane */ 21588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 216489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) 21736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneh2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, 218b775351012af176720429ac21d11682a0b75b4b7DRC JSAMPARRAY input_data, JSAMPARRAY output_data) 21988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane{ 22088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane int outrow; 22136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane JDIMENSION outcol; 22236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; 22388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane register JSAMPROW inptr, outptr; 22436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane register int bias; 22588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 22636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane /* Expand input data enough to let all the output samples be generated 22736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * by the standard loop. Special-casing padded output would be more 22836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * efficient. 22936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */ 23036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane expand_right_edge(input_data, cinfo->max_v_samp_factor, 231b775351012af176720429ac21d11682a0b75b4b7DRC cinfo->image_width, output_cols * 2); 23288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 23336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { 23488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane outptr = output_data[outrow]; 23588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inptr = input_data[outrow]; 236b775351012af176720429ac21d11682a0b75b4b7DRC bias = 0; /* bias = 0,1,0,1,... for successive samples */ 23788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane for (outcol = 0; outcol < output_cols; outcol++) { 23888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) 239b775351012af176720429ac21d11682a0b75b4b7DRC + bias) >> 1); 240b775351012af176720429ac21d11682a0b75b4b7DRC bias ^= 1; /* 0=>1, 1=>0 */ 24188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inptr += 2; 24288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } 24388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } 24488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane} 24588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 24688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 24788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane/* 24888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Downsample pixel values of a single component. 24988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This version handles the standard case of 2:1 horizontal and 2:1 vertical, 25088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * without smoothing. 2512cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane */ 2522cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 253489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) 25436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneh2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, 255b775351012af176720429ac21d11682a0b75b4b7DRC JSAMPARRAY input_data, JSAMPARRAY output_data) 2562cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane{ 25788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane int inrow, outrow; 25836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane JDIMENSION outcol; 25936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; 26088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane register JSAMPROW inptr0, inptr1, outptr; 26136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane register int bias; 26288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 26336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane /* Expand input data enough to let all the output samples be generated 26436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * by the standard loop. Special-casing padded output would be more 26536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * efficient. 26636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */ 26736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane expand_right_edge(input_data, cinfo->max_v_samp_factor, 268b775351012af176720429ac21d11682a0b75b4b7DRC cinfo->image_width, output_cols * 2); 26988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 27088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inrow = 0; 27136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { 27288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane outptr = output_data[outrow]; 27388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inptr0 = input_data[inrow]; 27488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inptr1 = input_data[inrow+1]; 275b775351012af176720429ac21d11682a0b75b4b7DRC bias = 1; /* bias = 1,2,1,2,... for successive samples */ 27688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane for (outcol = 0; outcol < output_cols; outcol++) { 27788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + 278b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) 279b775351012af176720429ac21d11682a0b75b4b7DRC + bias) >> 2); 280b775351012af176720429ac21d11682a0b75b4b7DRC bias ^= 3; /* 1=>2, 2=>1 */ 28188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inptr0 += 2; inptr1 += 2; 28288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } 28388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inrow += 2; 28488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } 28588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane} 28688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 28788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 28888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#ifdef INPUT_SMOOTHING_SUPPORTED 28988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 29088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane/* 29188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Downsample pixel values of a single component. 29288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This version handles the standard case of 2:1 horizontal and 2:1 vertical, 29336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * with smoothing. One row of context is required. 29488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane */ 29588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 296489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) 29736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneh2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, 298b775351012af176720429ac21d11682a0b75b4b7DRC JSAMPARRAY input_data, JSAMPARRAY output_data) 29988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane{ 30088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane int inrow, outrow; 30136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane JDIMENSION colctr; 30236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; 30388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; 30488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane INT32 membersum, neighsum, memberscale, neighscale; 30588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 30636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane /* Expand input data enough to let all the output samples be generated 30736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * by the standard loop. Special-casing padded output would be more 30836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * efficient. 30936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */ 31036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, 311b775351012af176720429ac21d11682a0b75b4b7DRC cinfo->image_width, output_cols * 2); 31288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 31388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* We don't bother to form the individual "smoothed" input pixel values; 31488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * we can directly compute the output which is the average of the four 31588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * smoothed values. Each of the four member pixels contributes a fraction 31688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * (1-8*SF) to its own smoothed image and a fraction SF to each of the three 31788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final 31888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * output. The four corner-adjacent neighbor pixels contribute a fraction 31988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * SF to just one smoothed pixel, or SF/4 to the final output; while the 32088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * eight edge-adjacent neighbors contribute SF to each of two smoothed 32188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * pixels, or SF/2 overall. In order to use integer arithmetic, these 32288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * factors are scaled by 2^16 = 65536. 32388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Also recall that SF = smoothing_factor / 1024. 32488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane */ 32588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 32688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ 32788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ 32888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 32988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inrow = 0; 33036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { 33188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane outptr = output_data[outrow]; 33288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inptr0 = input_data[inrow]; 33388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inptr1 = input_data[inrow+1]; 33436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane above_ptr = input_data[inrow-1]; 33536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane below_ptr = input_data[inrow+2]; 33688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 33788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* Special case for first column: pretend column -1 is same as column 0 */ 33888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + 339b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); 34088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + 341b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + 342b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + 343b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); 34488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum += neighsum; 34588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + 346b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); 34788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = membersum * memberscale + neighsum * neighscale; 34836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); 34988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; 35088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 35188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane for (colctr = output_cols - 2; colctr > 0; colctr--) { 35288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* sum of pixels directly mapped to this output element */ 35388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + 354b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); 35588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* sum of edge-neighbor pixels */ 35688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + 357b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + 358b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + 359b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); 36088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* The edge-neighbors count twice as much as corner-neighbors */ 36188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum += neighsum; 36288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* Add in the corner-neighbors */ 36388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + 364b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); 36588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* form final output scaled up by 2^16 */ 36688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = membersum * memberscale + neighsum * neighscale; 36788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* round, descale and output it */ 36836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); 36988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; 37088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } 37188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 37288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* Special case for last column */ 37388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + 374b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); 37588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + 376b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + 377b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + 378b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); 37988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum += neighsum; 38088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + 381b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); 38288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = membersum * memberscale + neighsum * neighscale; 38336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *outptr = (JSAMPLE) ((membersum + 32768) >> 16); 38488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 38588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inrow += 2; 38688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } 38788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane} 38888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 38988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 39088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane/* 39188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Downsample pixel values of a single component. 39288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This version handles the special case of a full-size component, 39336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * with smoothing. One row of context is required. 39488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane */ 39588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 396489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) 39736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanefullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, 398b775351012af176720429ac21d11682a0b75b4b7DRC JSAMPARRAY input_data, JSAMPARRAY output_data) 39988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane{ 40088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane int outrow; 40136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane JDIMENSION colctr; 40236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; 40388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane register JSAMPROW inptr, above_ptr, below_ptr, outptr; 40488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane INT32 membersum, neighsum, memberscale, neighscale; 40588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane int colsum, lastcolsum, nextcolsum; 40688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 40736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane /* Expand input data enough to let all the output samples be generated 40836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * by the standard loop. Special-casing padded output would be more 40936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * efficient. 41036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */ 41136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, 412b775351012af176720429ac21d11682a0b75b4b7DRC cinfo->image_width, output_cols); 41388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 41488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* Each of the eight neighbor pixels contributes a fraction SF to the 41588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * smoothed pixel, while the main pixel contributes (1-8*SF). In order 41688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. 41788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Also recall that SF = smoothing_factor / 1024. 41888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane */ 41988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 42088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ 42188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ 42288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 42336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { 42488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane outptr = output_data[outrow]; 42588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane inptr = input_data[outrow]; 42636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane above_ptr = input_data[outrow-1]; 42736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane below_ptr = input_data[outrow+1]; 42888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 42988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* Special case for first column */ 43088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + 431b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*inptr); 43288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = GETJSAMPLE(*inptr++); 43388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + 434b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*inptr); 43588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum = colsum + (colsum - membersum) + nextcolsum; 43688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = membersum * memberscale + neighsum * neighscale; 43736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); 43888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane lastcolsum = colsum; colsum = nextcolsum; 43988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 44088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane for (colctr = output_cols - 2; colctr > 0; colctr--) { 44188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = GETJSAMPLE(*inptr++); 44288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane above_ptr++; below_ptr++; 44388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + 444b775351012af176720429ac21d11682a0b75b4b7DRC GETJSAMPLE(*inptr); 44588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum = lastcolsum + (colsum - membersum) + nextcolsum; 44688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = membersum * memberscale + neighsum * neighscale; 44736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); 44888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane lastcolsum = colsum; colsum = nextcolsum; 44988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } 45088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 45188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane /* Special case for last column */ 45288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = GETJSAMPLE(*inptr); 45388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane neighsum = lastcolsum + (colsum - membersum) + colsum; 45488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane membersum = membersum * memberscale + neighsum * neighscale; 45536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *outptr = (JSAMPLE) ((membersum + 32768) >> 16); 45688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 45788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } 45888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane} 45988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 46088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#endif /* INPUT_SMOOTHING_SUPPORTED */ 46188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 46288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane 4632cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane/* 46436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Module initialization routine for downsampling. 4652cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane * Note that we must select a routine for each component. 4662cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane */ 4672cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 468489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneGLOBAL(void) 46936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanejinit_downsampler (j_compress_ptr cinfo) 4702cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane{ 47136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane my_downsample_ptr downsample; 47236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane int ci; 4732cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane jpeg_component_info * compptr; 47488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane boolean smoothok = TRUE; 4752cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 47636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane downsample = (my_downsample_ptr) 47736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 4785de454b291f48382648a5d1dc2aa0fca8b5786d4DRC sizeof(my_downsampler)); 47936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane cinfo->downsample = (struct jpeg_downsampler *) downsample; 48036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane downsample->pub.start_pass = start_pass_downsample; 48136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane downsample->pub.downsample = sep_downsample; 48236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane downsample->pub.need_context_rows = FALSE; 48336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane 4842cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane if (cinfo->CCIR601_sampling) 48536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); 4862cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 48736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane /* Verify we can handle the sampling factors, and set up method pointers */ 48836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 48936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane ci++, compptr++) { 4902cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane if (compptr->h_samp_factor == cinfo->max_h_samp_factor && 491b775351012af176720429ac21d11682a0b75b4b7DRC compptr->v_samp_factor == cinfo->max_v_samp_factor) { 49288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#ifdef INPUT_SMOOTHING_SUPPORTED 49336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane if (cinfo->smoothing_factor) { 494b775351012af176720429ac21d11682a0b75b4b7DRC downsample->methods[ci] = fullsize_smooth_downsample; 495b775351012af176720429ac21d11682a0b75b4b7DRC downsample->pub.need_context_rows = TRUE; 49636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane } else 49788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#endif 498b775351012af176720429ac21d11682a0b75b4b7DRC downsample->methods[ci] = fullsize_downsample; 49988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && 500b775351012af176720429ac21d11682a0b75b4b7DRC compptr->v_samp_factor == cinfo->max_v_samp_factor) { 50188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane smoothok = FALSE; 50259a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman if (jsimd_can_h2v1_downsample()) 50359a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman downsample->methods[ci] = jsimd_h2v1_downsample; 50459a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman else 50559a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman downsample->methods[ci] = h2v1_downsample; 50688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && 507b775351012af176720429ac21d11682a0b75b4b7DRC compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { 50888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#ifdef INPUT_SMOOTHING_SUPPORTED 50936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane if (cinfo->smoothing_factor) { 510a3c3bbc2f43074900fb4c5062c0e1b9286f113e7DRC#if defined(__mips__) 5116a61c1e6dc0263148e8e8e1a13da8624cc5a065fDRC if (jsimd_can_h2v2_smooth_downsample()) 5126a61c1e6dc0263148e8e8e1a13da8624cc5a065fDRC downsample->methods[ci] = jsimd_h2v2_smooth_downsample; 5136a61c1e6dc0263148e8e8e1a13da8624cc5a065fDRC else 514a3c3bbc2f43074900fb4c5062c0e1b9286f113e7DRC#endif 5156a61c1e6dc0263148e8e8e1a13da8624cc5a065fDRC downsample->methods[ci] = h2v2_smooth_downsample; 516b775351012af176720429ac21d11682a0b75b4b7DRC downsample->pub.need_context_rows = TRUE; 517b329697ded0b8cdc6d00bcaf39f56c779b9182f6DRC } else 51888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#endif 519b329697ded0b8cdc6d00bcaf39f56c779b9182f6DRC { 520b775351012af176720429ac21d11682a0b75b4b7DRC if (jsimd_can_h2v2_downsample()) 521b775351012af176720429ac21d11682a0b75b4b7DRC downsample->methods[ci] = jsimd_h2v2_downsample; 522b775351012af176720429ac21d11682a0b75b4b7DRC else 523b775351012af176720429ac21d11682a0b75b4b7DRC downsample->methods[ci] = h2v2_downsample; 5243b489c3af780cfd1c9243eb58eb12f76a76491eeDRC } 52588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && 526b775351012af176720429ac21d11682a0b75b4b7DRC (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { 52788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane smoothok = FALSE; 52836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane downsample->methods[ci] = int_downsample; 52988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane } else 53036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); 5312cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane } 5322cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane 53388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#ifdef INPUT_SMOOTHING_SUPPORTED 53488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane if (cinfo->smoothing_factor && !smoothok) 53536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); 53688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#endif 5372cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane} 538