Path: blob/master/3rdparty/libjpeg-turbo/src/jcsample.c
16337 views
/*1* jcsample.c2*3* This file was part of the Independent JPEG Group's software:4* Copyright (C) 1991-1996, Thomas G. Lane.5* libjpeg-turbo Modifications:6* Copyright 2009 Pierre Ossman <[email protected]> for Cendio AB7* Copyright (C) 2014, MIPS Technologies, Inc., California.8* Copyright (C) 2015, D. R. Commander.9* For conditions of distribution and use, see the accompanying README.ijg10* file.11*12* This file contains downsampling routines.13*14* Downsampling input data is counted in "row groups". A row group15* is defined to be max_v_samp_factor pixel rows of each component,16* from which the downsampler produces v_samp_factor sample rows.17* A single row group is processed in each call to the downsampler module.18*19* The downsampler is responsible for edge-expansion of its output data20* to fill an integral number of DCT blocks horizontally. The source buffer21* may be modified if it is helpful for this purpose (the source buffer is22* allocated wide enough to correspond to the desired output width).23* The caller (the prep controller) is responsible for vertical padding.24*25* The downsampler may request "context rows" by setting need_context_rows26* during startup. In this case, the input arrays will contain at least27* one row group's worth of pixels above and below the passed-in data;28* the caller will create dummy rows at image top and bottom by replicating29* the first or last real pixel row.30*31* An excellent reference for image resampling is32* Digital Image Warping, George Wolberg, 1990.33* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.34*35* The downsampling algorithm used here is a simple average of the source36* pixels covered by the output pixel. The hi-falutin sampling literature37* refers to this as a "box filter". In general the characteristics of a box38* filter are not very good, but for the specific cases we normally use (1:139* and 2:1 ratios) the box is equivalent to a "triangle filter" which is not40* nearly so bad. If you intend to use other sampling ratios, you'd be well41* advised to improve this code.42*43* A simple input-smoothing capability is provided. This is mainly intended44* for cleaning up color-dithered GIF input files (if you find it inadequate,45* we suggest using an external filtering program such as pnmconvol). When46* enabled, each input pixel P is replaced by a weighted sum of itself and its47* eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF,48* where SF = (smoothing_factor / 1024).49* Currently, smoothing is only supported for 2h2v sampling factors.50*/5152#define JPEG_INTERNALS53#include "jinclude.h"54#include "jpeglib.h"55#include "jsimd.h"565758/* Pointer to routine to downsample a single component */59typedef void (*downsample1_ptr) (j_compress_ptr cinfo,60jpeg_component_info *compptr,61JSAMPARRAY input_data,62JSAMPARRAY output_data);6364/* Private subobject */6566typedef struct {67struct jpeg_downsampler pub; /* public fields */6869/* Downsampling method pointers, one per component */70downsample1_ptr methods[MAX_COMPONENTS];71} my_downsampler;7273typedef my_downsampler *my_downsample_ptr;747576/*77* Initialize for a downsampling pass.78*/7980METHODDEF(void)81start_pass_downsample (j_compress_ptr cinfo)82{83/* no work for now */84}858687/*88* Expand a component horizontally from width input_cols to width output_cols,89* by duplicating the rightmost samples.90*/9192LOCAL(void)93expand_right_edge (JSAMPARRAY image_data, int num_rows,94JDIMENSION input_cols, JDIMENSION output_cols)95{96register JSAMPROW ptr;97register JSAMPLE pixval;98register int count;99int row;100int numcols = (int) (output_cols - input_cols);101102if (numcols > 0) {103for (row = 0; row < num_rows; row++) {104ptr = image_data[row] + input_cols;105pixval = ptr[-1]; /* don't need GETJSAMPLE() here */106for (count = numcols; count > 0; count--)107*ptr++ = pixval;108}109}110}111112113/*114* Do downsampling for a whole row group (all components).115*116* In this version we simply downsample each component independently.117*/118119METHODDEF(void)120sep_downsample (j_compress_ptr cinfo,121JSAMPIMAGE input_buf, JDIMENSION in_row_index,122JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)123{124my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;125int ci;126jpeg_component_info *compptr;127JSAMPARRAY in_ptr, out_ptr;128129for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;130ci++, compptr++) {131in_ptr = input_buf[ci] + in_row_index;132out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);133(*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);134}135}136137138/*139* Downsample pixel values of a single component.140* One row group is processed per call.141* This version handles arbitrary integral sampling ratios, without smoothing.142* Note that this version is not actually used for customary sampling ratios.143*/144145METHODDEF(void)146int_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,147JSAMPARRAY input_data, JSAMPARRAY output_data)148{149int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;150JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */151JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;152JSAMPROW inptr, outptr;153JLONG outvalue;154155h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;156v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;157numpix = h_expand * v_expand;158numpix2 = numpix/2;159160/* Expand input data enough to let all the output samples be generated161* by the standard loop. Special-casing padded output would be more162* efficient.163*/164expand_right_edge(input_data, cinfo->max_v_samp_factor,165cinfo->image_width, output_cols * h_expand);166167inrow = 0;168for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {169outptr = output_data[outrow];170for (outcol = 0, outcol_h = 0; outcol < output_cols;171outcol++, outcol_h += h_expand) {172outvalue = 0;173for (v = 0; v < v_expand; v++) {174inptr = input_data[inrow+v] + outcol_h;175for (h = 0; h < h_expand; h++) {176outvalue += (JLONG) GETJSAMPLE(*inptr++);177}178}179*outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);180}181inrow += v_expand;182}183}184185186/*187* Downsample pixel values of a single component.188* This version handles the special case of a full-size component,189* without smoothing.190*/191192METHODDEF(void)193fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,194JSAMPARRAY input_data, JSAMPARRAY output_data)195{196/* Copy the data */197jcopy_sample_rows(input_data, 0, output_data, 0,198cinfo->max_v_samp_factor, cinfo->image_width);199/* Edge-expand */200expand_right_edge(output_data, cinfo->max_v_samp_factor,201cinfo->image_width, compptr->width_in_blocks * DCTSIZE);202}203204205/*206* Downsample pixel values of a single component.207* This version handles the common case of 2:1 horizontal and 1:1 vertical,208* without smoothing.209*210* A note about the "bias" calculations: when rounding fractional values to211* integer, we do not want to always round 0.5 up to the next integer.212* If we did that, we'd introduce a noticeable bias towards larger values.213* Instead, this code is arranged so that 0.5 will be rounded up or down at214* alternate pixel locations (a simple ordered dither pattern).215*/216217METHODDEF(void)218h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,219JSAMPARRAY input_data, JSAMPARRAY output_data)220{221int outrow;222JDIMENSION outcol;223JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;224register JSAMPROW inptr, outptr;225register int bias;226227/* Expand input data enough to let all the output samples be generated228* by the standard loop. Special-casing padded output would be more229* efficient.230*/231expand_right_edge(input_data, cinfo->max_v_samp_factor,232cinfo->image_width, output_cols * 2);233234for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {235outptr = output_data[outrow];236inptr = input_data[outrow];237bias = 0; /* bias = 0,1,0,1,... for successive samples */238for (outcol = 0; outcol < output_cols; outcol++) {239*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])240+ bias) >> 1);241bias ^= 1; /* 0=>1, 1=>0 */242inptr += 2;243}244}245}246247248/*249* Downsample pixel values of a single component.250* This version handles the standard case of 2:1 horizontal and 2:1 vertical,251* without smoothing.252*/253254METHODDEF(void)255h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,256JSAMPARRAY input_data, JSAMPARRAY output_data)257{258int inrow, outrow;259JDIMENSION outcol;260JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;261register JSAMPROW inptr0, inptr1, outptr;262register int bias;263264/* Expand input data enough to let all the output samples be generated265* by the standard loop. Special-casing padded output would be more266* efficient.267*/268expand_right_edge(input_data, cinfo->max_v_samp_factor,269cinfo->image_width, output_cols * 2);270271inrow = 0;272for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {273outptr = output_data[outrow];274inptr0 = input_data[inrow];275inptr1 = input_data[inrow+1];276bias = 1; /* bias = 1,2,1,2,... for successive samples */277for (outcol = 0; outcol < output_cols; outcol++) {278*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +279GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])280+ bias) >> 2);281bias ^= 3; /* 1=>2, 2=>1 */282inptr0 += 2; inptr1 += 2;283}284inrow += 2;285}286}287288289#ifdef INPUT_SMOOTHING_SUPPORTED290291/*292* Downsample pixel values of a single component.293* This version handles the standard case of 2:1 horizontal and 2:1 vertical,294* with smoothing. One row of context is required.295*/296297METHODDEF(void)298h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,299JSAMPARRAY input_data, JSAMPARRAY output_data)300{301int inrow, outrow;302JDIMENSION colctr;303JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;304register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;305JLONG membersum, neighsum, memberscale, neighscale;306307/* Expand input data enough to let all the output samples be generated308* by the standard loop. Special-casing padded output would be more309* efficient.310*/311expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,312cinfo->image_width, output_cols * 2);313314/* We don't bother to form the individual "smoothed" input pixel values;315* we can directly compute the output which is the average of the four316* smoothed values. Each of the four member pixels contributes a fraction317* (1-8*SF) to its own smoothed image and a fraction SF to each of the three318* other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final319* output. The four corner-adjacent neighbor pixels contribute a fraction320* SF to just one smoothed pixel, or SF/4 to the final output; while the321* eight edge-adjacent neighbors contribute SF to each of two smoothed322* pixels, or SF/2 overall. In order to use integer arithmetic, these323* factors are scaled by 2^16 = 65536.324* Also recall that SF = smoothing_factor / 1024.325*/326327memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */328neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */329330inrow = 0;331for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {332outptr = output_data[outrow];333inptr0 = input_data[inrow];334inptr1 = input_data[inrow+1];335above_ptr = input_data[inrow-1];336below_ptr = input_data[inrow+2];337338/* Special case for first column: pretend column -1 is same as column 0 */339membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +340GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);341neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +342GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +343GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +344GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);345neighsum += neighsum;346neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +347GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);348membersum = membersum * memberscale + neighsum * neighscale;349*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);350inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;351352for (colctr = output_cols - 2; colctr > 0; colctr--) {353/* sum of pixels directly mapped to this output element */354membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +355GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);356/* sum of edge-neighbor pixels */357neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +358GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +359GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +360GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);361/* The edge-neighbors count twice as much as corner-neighbors */362neighsum += neighsum;363/* Add in the corner-neighbors */364neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +365GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);366/* form final output scaled up by 2^16 */367membersum = membersum * memberscale + neighsum * neighscale;368/* round, descale and output it */369*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);370inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;371}372373/* Special case for last column */374membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +375GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);376neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +377GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +378GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +379GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);380neighsum += neighsum;381neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +382GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);383membersum = membersum * memberscale + neighsum * neighscale;384*outptr = (JSAMPLE) ((membersum + 32768) >> 16);385386inrow += 2;387}388}389390391/*392* Downsample pixel values of a single component.393* This version handles the special case of a full-size component,394* with smoothing. One row of context is required.395*/396397METHODDEF(void)398fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,399JSAMPARRAY input_data, JSAMPARRAY output_data)400{401int outrow;402JDIMENSION colctr;403JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;404register JSAMPROW inptr, above_ptr, below_ptr, outptr;405JLONG membersum, neighsum, memberscale, neighscale;406int colsum, lastcolsum, nextcolsum;407408/* Expand input data enough to let all the output samples be generated409* by the standard loop. Special-casing padded output would be more410* efficient.411*/412expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,413cinfo->image_width, output_cols);414415/* Each of the eight neighbor pixels contributes a fraction SF to the416* smoothed pixel, while the main pixel contributes (1-8*SF). In order417* to use integer arithmetic, these factors are multiplied by 2^16 = 65536.418* Also recall that SF = smoothing_factor / 1024.419*/420421memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */422neighscale = cinfo->smoothing_factor * 64; /* scaled SF */423424for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {425outptr = output_data[outrow];426inptr = input_data[outrow];427above_ptr = input_data[outrow-1];428below_ptr = input_data[outrow+1];429430/* Special case for first column */431colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +432GETJSAMPLE(*inptr);433membersum = GETJSAMPLE(*inptr++);434nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +435GETJSAMPLE(*inptr);436neighsum = colsum + (colsum - membersum) + nextcolsum;437membersum = membersum * memberscale + neighsum * neighscale;438*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);439lastcolsum = colsum; colsum = nextcolsum;440441for (colctr = output_cols - 2; colctr > 0; colctr--) {442membersum = GETJSAMPLE(*inptr++);443above_ptr++; below_ptr++;444nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +445GETJSAMPLE(*inptr);446neighsum = lastcolsum + (colsum - membersum) + nextcolsum;447membersum = membersum * memberscale + neighsum * neighscale;448*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);449lastcolsum = colsum; colsum = nextcolsum;450}451452/* Special case for last column */453membersum = GETJSAMPLE(*inptr);454neighsum = lastcolsum + (colsum - membersum) + colsum;455membersum = membersum * memberscale + neighsum * neighscale;456*outptr = (JSAMPLE) ((membersum + 32768) >> 16);457458}459}460461#endif /* INPUT_SMOOTHING_SUPPORTED */462463464/*465* Module initialization routine for downsampling.466* Note that we must select a routine for each component.467*/468469GLOBAL(void)470jinit_downsampler (j_compress_ptr cinfo)471{472my_downsample_ptr downsample;473int ci;474jpeg_component_info *compptr;475boolean smoothok = TRUE;476477downsample = (my_downsample_ptr)478(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,479sizeof(my_downsampler));480cinfo->downsample = (struct jpeg_downsampler *) downsample;481downsample->pub.start_pass = start_pass_downsample;482downsample->pub.downsample = sep_downsample;483downsample->pub.need_context_rows = FALSE;484485if (cinfo->CCIR601_sampling)486ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);487488/* Verify we can handle the sampling factors, and set up method pointers */489for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;490ci++, compptr++) {491if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&492compptr->v_samp_factor == cinfo->max_v_samp_factor) {493#ifdef INPUT_SMOOTHING_SUPPORTED494if (cinfo->smoothing_factor) {495downsample->methods[ci] = fullsize_smooth_downsample;496downsample->pub.need_context_rows = TRUE;497} else498#endif499downsample->methods[ci] = fullsize_downsample;500} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&501compptr->v_samp_factor == cinfo->max_v_samp_factor) {502smoothok = FALSE;503if (jsimd_can_h2v1_downsample())504downsample->methods[ci] = jsimd_h2v1_downsample;505else506downsample->methods[ci] = h2v1_downsample;507} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&508compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {509#ifdef INPUT_SMOOTHING_SUPPORTED510if (cinfo->smoothing_factor) {511#if defined(__mips__)512if (jsimd_can_h2v2_smooth_downsample())513downsample->methods[ci] = jsimd_h2v2_smooth_downsample;514else515#endif516downsample->methods[ci] = h2v2_smooth_downsample;517downsample->pub.need_context_rows = TRUE;518} else519#endif520{521if (jsimd_can_h2v2_downsample())522downsample->methods[ci] = jsimd_h2v2_downsample;523else524downsample->methods[ci] = h2v2_downsample;525}526} else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&527(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {528smoothok = FALSE;529downsample->methods[ci] = int_downsample;530} else531ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);532}533534#ifdef INPUT_SMOOTHING_SUPPORTED535if (cinfo->smoothing_factor && !smoothok)536TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);537#endif538}539540541