Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/vncdll/winvnc/libjpeg/jcsample.c
Views: 11784
/*1* jcsample.c2*3* Copyright (C) 1991-1996, Thomas G. Lane.4* This file is part of the Independent JPEG Group's software.5* For conditions of distribution and use, see the accompanying README file.6*7* This file contains downsampling routines.8*9* Downsampling input data is counted in "row groups". A row group10* is defined to be max_v_samp_factor pixel rows of each component,11* from which the downsampler produces v_samp_factor sample rows.12* A single row group is processed in each call to the downsampler module.13*14* The downsampler is responsible for edge-expansion of its output data15* to fill an integral number of DCT blocks horizontally. The source buffer16* may be modified if it is helpful for this purpose (the source buffer is17* allocated wide enough to correspond to the desired output width).18* The caller (the prep controller) is responsible for vertical padding.19*20* The downsampler may request "context rows" by setting need_context_rows21* during startup. In this case, the input arrays will contain at least22* one row group's worth of pixels above and below the passed-in data;23* the caller will create dummy rows at image top and bottom by replicating24* the first or last real pixel row.25*26* An excellent reference for image resampling is27* Digital Image Warping, George Wolberg, 1990.28* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.29*30* The downsampling algorithm used here is a simple average of the source31* pixels covered by the output pixel. The hi-falutin sampling literature32* refers to this as a "box filter". In general the characteristics of a box33* filter are not very good, but for the specific cases we normally use (1:134* and 2:1 ratios) the box is equivalent to a "triangle filter" which is not35* nearly so bad. If you intend to use other sampling ratios, you'd be well36* advised to improve this code.37*38* A simple input-smoothing capability is provided. This is mainly intended39* for cleaning up color-dithered GIF input files (if you find it inadequate,40* we suggest using an external filtering program such as pnmconvol). When41* enabled, each input pixel P is replaced by a weighted sum of itself and its42* eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF,43* where SF = (smoothing_factor / 1024).44* Currently, smoothing is only supported for 2h2v sampling factors.45*/4647#define JPEG_INTERNALS48#include "jinclude.h"49#include "jpeglib.h"505152/* Pointer to routine to downsample a single component */53typedef JMETHOD(void, downsample1_ptr,54(j_compress_ptr cinfo, jpeg_component_info * compptr,55JSAMPARRAY input_data, JSAMPARRAY output_data));5657/* Private subobject */5859typedef struct {60struct jpeg_downsampler pub; /* public fields */6162/* Downsampling method pointers, one per component */63downsample1_ptr methods[MAX_COMPONENTS];64} my_downsampler;6566typedef my_downsampler * my_downsample_ptr;676869/*70* Initialize for a downsampling pass.71*/7273METHODDEF(void)74start_pass_downsample (j_compress_ptr cinfo)75{76/* no work for now */77}787980/*81* Expand a component horizontally from width input_cols to width output_cols,82* by duplicating the rightmost samples.83*/8485LOCAL(void)86expand_right_edge (JSAMPARRAY image_data, int num_rows,87JDIMENSION input_cols, JDIMENSION output_cols)88{89register JSAMPROW ptr;90register JSAMPLE pixval;91register int count;92int row;93int numcols = (int) (output_cols - input_cols);9495if (numcols > 0) {96for (row = 0; row < num_rows; row++) {97ptr = image_data[row] + input_cols;98pixval = ptr[-1]; /* don't need GETJSAMPLE() here */99for (count = numcols; count > 0; count--)100*ptr++ = pixval;101}102}103}104105106/*107* Do downsampling for a whole row group (all components).108*109* In this version we simply downsample each component independently.110*/111112METHODDEF(void)113sep_downsample (j_compress_ptr cinfo,114JSAMPIMAGE input_buf, JDIMENSION in_row_index,115JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)116{117my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;118int ci;119jpeg_component_info * compptr;120JSAMPARRAY in_ptr, out_ptr;121122for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;123ci++, compptr++) {124in_ptr = input_buf[ci] + in_row_index;125out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);126(*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);127}128}129130131/*132* Downsample pixel values of a single component.133* One row group is processed per call.134* This version handles arbitrary integral sampling ratios, without smoothing.135* Note that this version is not actually used for customary sampling ratios.136*/137138METHODDEF(void)139int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,140JSAMPARRAY input_data, JSAMPARRAY output_data)141{142int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;143JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */144JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;145JSAMPROW inptr, outptr;146INT32 outvalue;147148h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;149v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;150numpix = h_expand * v_expand;151numpix2 = numpix/2;152153/* Expand input data enough to let all the output samples be generated154* by the standard loop. Special-casing padded output would be more155* efficient.156*/157expand_right_edge(input_data, cinfo->max_v_samp_factor,158cinfo->image_width, output_cols * h_expand);159160inrow = 0;161for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {162outptr = output_data[outrow];163for (outcol = 0, outcol_h = 0; outcol < output_cols;164outcol++, outcol_h += h_expand) {165outvalue = 0;166for (v = 0; v < v_expand; v++) {167inptr = input_data[inrow+v] + outcol_h;168for (h = 0; h < h_expand; h++) {169outvalue += (INT32) GETJSAMPLE(*inptr++);170}171}172*outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);173}174inrow += v_expand;175}176}177178179/*180* Downsample pixel values of a single component.181* This version handles the special case of a full-size component,182* without smoothing.183*/184185METHODDEF(void)186fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,187JSAMPARRAY input_data, JSAMPARRAY output_data)188{189/* Copy the data */190jcopy_sample_rows(input_data, 0, output_data, 0,191cinfo->max_v_samp_factor, cinfo->image_width);192/* Edge-expand */193expand_right_edge(output_data, cinfo->max_v_samp_factor,194cinfo->image_width, compptr->width_in_blocks * DCTSIZE);195}196197198/*199* Downsample pixel values of a single component.200* This version handles the common case of 2:1 horizontal and 1:1 vertical,201* without smoothing.202*203* A note about the "bias" calculations: when rounding fractional values to204* integer, we do not want to always round 0.5 up to the next integer.205* If we did that, we'd introduce a noticeable bias towards larger values.206* Instead, this code is arranged so that 0.5 will be rounded up or down at207* alternate pixel locations (a simple ordered dither pattern).208*/209210METHODDEF(void)211h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,212JSAMPARRAY input_data, JSAMPARRAY output_data)213{214int outrow;215JDIMENSION outcol;216JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;217register JSAMPROW inptr, outptr;218register int bias;219220/* Expand input data enough to let all the output samples be generated221* by the standard loop. Special-casing padded output would be more222* efficient.223*/224expand_right_edge(input_data, cinfo->max_v_samp_factor,225cinfo->image_width, output_cols * 2);226227for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {228outptr = output_data[outrow];229inptr = input_data[outrow];230bias = 0; /* bias = 0,1,0,1,... for successive samples */231for (outcol = 0; outcol < output_cols; outcol++) {232*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])233+ bias) >> 1);234bias ^= 1; /* 0=>1, 1=>0 */235inptr += 2;236}237}238}239240241/*242* Downsample pixel values of a single component.243* This version handles the standard case of 2:1 horizontal and 2:1 vertical,244* without smoothing.245*/246247METHODDEF(void)248h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,249JSAMPARRAY input_data, JSAMPARRAY output_data)250{251int inrow, outrow;252JDIMENSION outcol;253JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;254register JSAMPROW inptr0, inptr1, outptr;255register int bias;256257/* Expand input data enough to let all the output samples be generated258* by the standard loop. Special-casing padded output would be more259* efficient.260*/261expand_right_edge(input_data, cinfo->max_v_samp_factor,262cinfo->image_width, output_cols * 2);263264inrow = 0;265for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {266outptr = output_data[outrow];267inptr0 = input_data[inrow];268inptr1 = input_data[inrow+1];269bias = 1; /* bias = 1,2,1,2,... for successive samples */270for (outcol = 0; outcol < output_cols; outcol++) {271*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +272GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])273+ bias) >> 2);274bias ^= 3; /* 1=>2, 2=>1 */275inptr0 += 2; inptr1 += 2;276}277inrow += 2;278}279}280281282#ifdef INPUT_SMOOTHING_SUPPORTED283284/*285* Downsample pixel values of a single component.286* This version handles the standard case of 2:1 horizontal and 2:1 vertical,287* with smoothing. One row of context is required.288*/289290METHODDEF(void)291h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,292JSAMPARRAY input_data, JSAMPARRAY output_data)293{294int inrow, outrow;295JDIMENSION colctr;296JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;297register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;298INT32 membersum, neighsum, memberscale, neighscale;299300/* Expand input data enough to let all the output samples be generated301* by the standard loop. Special-casing padded output would be more302* efficient.303*/304expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,305cinfo->image_width, output_cols * 2);306307/* We don't bother to form the individual "smoothed" input pixel values;308* we can directly compute the output which is the average of the four309* smoothed values. Each of the four member pixels contributes a fraction310* (1-8*SF) to its own smoothed image and a fraction SF to each of the three311* other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final312* output. The four corner-adjacent neighbor pixels contribute a fraction313* SF to just one smoothed pixel, or SF/4 to the final output; while the314* eight edge-adjacent neighbors contribute SF to each of two smoothed315* pixels, or SF/2 overall. In order to use integer arithmetic, these316* factors are scaled by 2^16 = 65536.317* Also recall that SF = smoothing_factor / 1024.318*/319320memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */321neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */322323inrow = 0;324for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {325outptr = output_data[outrow];326inptr0 = input_data[inrow];327inptr1 = input_data[inrow+1];328above_ptr = input_data[inrow-1];329below_ptr = input_data[inrow+2];330331/* Special case for first column: pretend column -1 is same as column 0 */332membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +333GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);334neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +335GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +336GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +337GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);338neighsum += neighsum;339neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +340GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);341membersum = membersum * memberscale + neighsum * neighscale;342*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);343inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;344345for (colctr = output_cols - 2; colctr > 0; colctr--) {346/* sum of pixels directly mapped to this output element */347membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +348GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);349/* sum of edge-neighbor pixels */350neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +351GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +352GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +353GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);354/* The edge-neighbors count twice as much as corner-neighbors */355neighsum += neighsum;356/* Add in the corner-neighbors */357neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +358GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);359/* form final output scaled up by 2^16 */360membersum = membersum * memberscale + neighsum * neighscale;361/* round, descale and output it */362*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);363inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;364}365366/* Special case for last column */367membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +368GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);369neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +370GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +371GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +372GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);373neighsum += neighsum;374neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +375GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);376membersum = membersum * memberscale + neighsum * neighscale;377*outptr = (JSAMPLE) ((membersum + 32768) >> 16);378379inrow += 2;380}381}382383384/*385* Downsample pixel values of a single component.386* This version handles the special case of a full-size component,387* with smoothing. One row of context is required.388*/389390METHODDEF(void)391fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,392JSAMPARRAY input_data, JSAMPARRAY output_data)393{394int outrow;395JDIMENSION colctr;396JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;397register JSAMPROW inptr, above_ptr, below_ptr, outptr;398INT32 membersum, neighsum, memberscale, neighscale;399int colsum, lastcolsum, nextcolsum;400401/* Expand input data enough to let all the output samples be generated402* by the standard loop. Special-casing padded output would be more403* efficient.404*/405expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,406cinfo->image_width, output_cols);407408/* Each of the eight neighbor pixels contributes a fraction SF to the409* smoothed pixel, while the main pixel contributes (1-8*SF). In order410* to use integer arithmetic, these factors are multiplied by 2^16 = 65536.411* Also recall that SF = smoothing_factor / 1024.412*/413414memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */415neighscale = cinfo->smoothing_factor * 64; /* scaled SF */416417for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {418outptr = output_data[outrow];419inptr = input_data[outrow];420above_ptr = input_data[outrow-1];421below_ptr = input_data[outrow+1];422423/* Special case for first column */424colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +425GETJSAMPLE(*inptr);426membersum = GETJSAMPLE(*inptr++);427nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +428GETJSAMPLE(*inptr);429neighsum = colsum + (colsum - membersum) + nextcolsum;430membersum = membersum * memberscale + neighsum * neighscale;431*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);432lastcolsum = colsum; colsum = nextcolsum;433434for (colctr = output_cols - 2; colctr > 0; colctr--) {435membersum = GETJSAMPLE(*inptr++);436above_ptr++; below_ptr++;437nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +438GETJSAMPLE(*inptr);439neighsum = lastcolsum + (colsum - membersum) + nextcolsum;440membersum = membersum * memberscale + neighsum * neighscale;441*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);442lastcolsum = colsum; colsum = nextcolsum;443}444445/* Special case for last column */446membersum = GETJSAMPLE(*inptr);447neighsum = lastcolsum + (colsum - membersum) + colsum;448membersum = membersum * memberscale + neighsum * neighscale;449*outptr = (JSAMPLE) ((membersum + 32768) >> 16);450451}452}453454#endif /* INPUT_SMOOTHING_SUPPORTED */455456457/*458* Module initialization routine for downsampling.459* Note that we must select a routine for each component.460*/461462GLOBAL(void)463jinit_downsampler (j_compress_ptr cinfo)464{465my_downsample_ptr downsample;466int ci;467jpeg_component_info * compptr;468boolean smoothok = TRUE;469470downsample = (my_downsample_ptr)471(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,472SIZEOF(my_downsampler));473cinfo->downsample = (struct jpeg_downsampler *) downsample;474downsample->pub.start_pass = start_pass_downsample;475downsample->pub.downsample = sep_downsample;476downsample->pub.need_context_rows = FALSE;477478if (cinfo->CCIR601_sampling)479ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);480481/* Verify we can handle the sampling factors, and set up method pointers */482for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;483ci++, compptr++) {484if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&485compptr->v_samp_factor == cinfo->max_v_samp_factor) {486#ifdef INPUT_SMOOTHING_SUPPORTED487if (cinfo->smoothing_factor) {488downsample->methods[ci] = fullsize_smooth_downsample;489downsample->pub.need_context_rows = TRUE;490} else491#endif492downsample->methods[ci] = fullsize_downsample;493} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&494compptr->v_samp_factor == cinfo->max_v_samp_factor) {495smoothok = FALSE;496downsample->methods[ci] = h2v1_downsample;497} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&498compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {499#ifdef INPUT_SMOOTHING_SUPPORTED500if (cinfo->smoothing_factor) {501downsample->methods[ci] = h2v2_smooth_downsample;502downsample->pub.need_context_rows = TRUE;503} else504#endif505downsample->methods[ci] = h2v2_downsample;506} else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&507(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {508smoothok = FALSE;509downsample->methods[ci] = int_downsample;510} else511ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);512}513514#ifdef INPUT_SMOOTHING_SUPPORTED515if (cinfo->smoothing_factor && !smoothok)516TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);517#endif518}519520521