Path: blob/master/src/java.desktop/share/native/libjavajpeg/jcsample.c
41149 views
/*1* reserved comment block2* DO NOT REMOVE OR ALTER!3*/4/*5* jcsample.c6*7* Copyright (C) 1991-1996, Thomas G. Lane.8* This file is part of the Independent JPEG Group's software.9* For conditions of distribution and use, see the accompanying README file.10*11* This file contains downsampling routines.12*13* Downsampling input data is counted in "row groups". A row group14* is defined to be max_v_samp_factor pixel rows of each component,15* from which the downsampler produces v_samp_factor sample rows.16* A single row group is processed in each call to the downsampler module.17*18* The downsampler is responsible for edge-expansion of its output data19* to fill an integral number of DCT blocks horizontally. The source buffer20* may be modified if it is helpful for this purpose (the source buffer is21* allocated wide enough to correspond to the desired output width).22* The caller (the prep controller) is responsible for vertical padding.23*24* The downsampler may request "context rows" by setting need_context_rows25* during startup. In this case, the input arrays will contain at least26* one row group's worth of pixels above and below the passed-in data;27* the caller will create dummy rows at image top and bottom by replicating28* the first or last real pixel row.29*30* An excellent reference for image resampling is31* Digital Image Warping, George Wolberg, 1990.32* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.33*34* The downsampling algorithm used here is a simple average of the source35* pixels covered by the output pixel. The hi-falutin sampling literature36* refers to this as a "box filter". In general the characteristics of a box37* filter are not very good, but for the specific cases we normally use (1:138* and 2:1 ratios) the box is equivalent to a "triangle filter" which is not39* nearly so bad. If you intend to use other sampling ratios, you'd be well40* advised to improve this code.41*42* A simple input-smoothing capability is provided. This is mainly intended43* for cleaning up color-dithered GIF input files (if you find it inadequate,44* we suggest using an external filtering program such as pnmconvol). When45* enabled, each input pixel P is replaced by a weighted sum of itself and its46* eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF,47* where SF = (smoothing_factor / 1024).48* Currently, smoothing is only supported for 2h2v sampling factors.49*/5051#define JPEG_INTERNALS52#include "jinclude.h"53#include "jpeglib.h"545556/* Pointer to routine to downsample a single component */57typedef JMETHOD(void, downsample1_ptr,58(j_compress_ptr cinfo, jpeg_component_info * compptr,59JSAMPARRAY input_data, JSAMPARRAY output_data));6061/* Private subobject */6263typedef struct {64struct jpeg_downsampler pub; /* public fields */6566/* Downsampling method pointers, one per component */67downsample1_ptr methods[MAX_COMPONENTS];68} my_downsampler;6970typedef my_downsampler * my_downsample_ptr;717273/*74* Initialize for a downsampling pass.75*/7677METHODDEF(void)78start_pass_downsample (j_compress_ptr cinfo)79{80/* no work for now */81}828384/*85* Expand a component horizontally from width input_cols to width output_cols,86* by duplicating the rightmost samples.87*/8889LOCAL(void)90expand_right_edge (JSAMPARRAY image_data, int num_rows,91JDIMENSION input_cols, JDIMENSION output_cols)92{93register JSAMPROW ptr;94register JSAMPLE pixval;95register int count;96int row;97int numcols = (int) (output_cols - input_cols);9899if (numcols > 0) {100for (row = 0; row < num_rows; row++) {101ptr = image_data[row] + input_cols;102pixval = ptr[-1]; /* don't need GETJSAMPLE() here */103for (count = numcols; count > 0; count--)104*ptr++ = pixval;105}106}107}108109110/*111* Do downsampling for a whole row group (all components).112*113* In this version we simply downsample each component independently.114*/115116METHODDEF(void)117sep_downsample (j_compress_ptr cinfo,118JSAMPIMAGE input_buf, JDIMENSION in_row_index,119JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)120{121my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;122int ci;123jpeg_component_info * compptr;124JSAMPARRAY in_ptr, out_ptr;125126for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;127ci++, compptr++) {128in_ptr = input_buf[ci] + in_row_index;129out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);130(*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);131}132}133134135/*136* Downsample pixel values of a single component.137* One row group is processed per call.138* This version handles arbitrary integral sampling ratios, without smoothing.139* Note that this version is not actually used for customary sampling ratios.140*/141142METHODDEF(void)143int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,144JSAMPARRAY input_data, JSAMPARRAY output_data)145{146int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;147JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */148JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;149JSAMPROW inptr, outptr;150INT32 outvalue;151152h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;153v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;154numpix = h_expand * v_expand;155numpix2 = numpix/2;156157/* Expand input data enough to let all the output samples be generated158* by the standard loop. Special-casing padded output would be more159* efficient.160*/161expand_right_edge(input_data, cinfo->max_v_samp_factor,162cinfo->image_width, output_cols * h_expand);163164inrow = 0;165for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {166outptr = output_data[outrow];167for (outcol = 0, outcol_h = 0; outcol < output_cols;168outcol++, outcol_h += h_expand) {169outvalue = 0;170for (v = 0; v < v_expand; v++) {171inptr = input_data[inrow+v] + outcol_h;172for (h = 0; h < h_expand; h++) {173outvalue += (INT32) GETJSAMPLE(*inptr++);174}175}176*outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);177}178inrow += v_expand;179}180}181182183/*184* Downsample pixel values of a single component.185* This version handles the special case of a full-size component,186* without smoothing.187*/188189METHODDEF(void)190fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,191JSAMPARRAY input_data, JSAMPARRAY output_data)192{193/* Copy the data */194jcopy_sample_rows(input_data, 0, output_data, 0,195cinfo->max_v_samp_factor, cinfo->image_width);196/* Edge-expand */197expand_right_edge(output_data, cinfo->max_v_samp_factor,198cinfo->image_width, compptr->width_in_blocks * DCTSIZE);199}200201202/*203* Downsample pixel values of a single component.204* This version handles the common case of 2:1 horizontal and 1:1 vertical,205* without smoothing.206*207* A note about the "bias" calculations: when rounding fractional values to208* integer, we do not want to always round 0.5 up to the next integer.209* If we did that, we'd introduce a noticeable bias towards larger values.210* Instead, this code is arranged so that 0.5 will be rounded up or down at211* alternate pixel locations (a simple ordered dither pattern).212*/213214METHODDEF(void)215h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,216JSAMPARRAY input_data, JSAMPARRAY output_data)217{218int outrow;219JDIMENSION outcol;220JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;221register JSAMPROW inptr, outptr;222register int bias;223224/* Expand input data enough to let all the output samples be generated225* by the standard loop. Special-casing padded output would be more226* efficient.227*/228expand_right_edge(input_data, cinfo->max_v_samp_factor,229cinfo->image_width, output_cols * 2);230231for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {232outptr = output_data[outrow];233inptr = input_data[outrow];234bias = 0; /* bias = 0,1,0,1,... for successive samples */235for (outcol = 0; outcol < output_cols; outcol++) {236*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])237+ bias) >> 1);238bias ^= 1; /* 0=>1, 1=>0 */239inptr += 2;240}241}242}243244245/*246* Downsample pixel values of a single component.247* This version handles the standard case of 2:1 horizontal and 2:1 vertical,248* without smoothing.249*/250251METHODDEF(void)252h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,253JSAMPARRAY input_data, JSAMPARRAY output_data)254{255int inrow, outrow;256JDIMENSION outcol;257JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;258register JSAMPROW inptr0, inptr1, outptr;259register int bias;260261/* Expand input data enough to let all the output samples be generated262* by the standard loop. Special-casing padded output would be more263* efficient.264*/265expand_right_edge(input_data, cinfo->max_v_samp_factor,266cinfo->image_width, output_cols * 2);267268inrow = 0;269for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {270outptr = output_data[outrow];271inptr0 = input_data[inrow];272inptr1 = input_data[inrow+1];273bias = 1; /* bias = 1,2,1,2,... for successive samples */274for (outcol = 0; outcol < output_cols; outcol++) {275*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +276GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])277+ bias) >> 2);278bias ^= 3; /* 1=>2, 2=>1 */279inptr0 += 2; inptr1 += 2;280}281inrow += 2;282}283}284285286#ifdef INPUT_SMOOTHING_SUPPORTED287288/*289* Downsample pixel values of a single component.290* This version handles the standard case of 2:1 horizontal and 2:1 vertical,291* with smoothing. One row of context is required.292*/293294METHODDEF(void)295h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,296JSAMPARRAY input_data, JSAMPARRAY output_data)297{298int inrow, outrow;299JDIMENSION colctr;300JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;301register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;302INT32 membersum, neighsum, memberscale, neighscale;303304/* Expand input data enough to let all the output samples be generated305* by the standard loop. Special-casing padded output would be more306* efficient.307*/308expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,309cinfo->image_width, output_cols * 2);310311/* We don't bother to form the individual "smoothed" input pixel values;312* we can directly compute the output which is the average of the four313* smoothed values. Each of the four member pixels contributes a fraction314* (1-8*SF) to its own smoothed image and a fraction SF to each of the three315* other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final316* output. The four corner-adjacent neighbor pixels contribute a fraction317* SF to just one smoothed pixel, or SF/4 to the final output; while the318* eight edge-adjacent neighbors contribute SF to each of two smoothed319* pixels, or SF/2 overall. In order to use integer arithmetic, these320* factors are scaled by 2^16 = 65536.321* Also recall that SF = smoothing_factor / 1024.322*/323324memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */325neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */326327inrow = 0;328for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {329outptr = output_data[outrow];330inptr0 = input_data[inrow];331inptr1 = input_data[inrow+1];332above_ptr = input_data[inrow-1];333below_ptr = input_data[inrow+2];334335/* Special case for first column: pretend column -1 is same as column 0 */336membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +337GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);338neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +339GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +340GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +341GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);342neighsum += neighsum;343neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +344GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);345membersum = membersum * memberscale + neighsum * neighscale;346*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);347inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;348349for (colctr = output_cols - 2; colctr > 0; colctr--) {350/* sum of pixels directly mapped to this output element */351membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +352GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);353/* sum of edge-neighbor pixels */354neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +355GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +356GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +357GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);358/* The edge-neighbors count twice as much as corner-neighbors */359neighsum += neighsum;360/* Add in the corner-neighbors */361neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +362GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);363/* form final output scaled up by 2^16 */364membersum = membersum * memberscale + neighsum * neighscale;365/* round, descale and output it */366*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);367inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;368}369370/* Special case for last column */371membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +372GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);373neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +374GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +375GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +376GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);377neighsum += neighsum;378neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +379GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);380membersum = membersum * memberscale + neighsum * neighscale;381*outptr = (JSAMPLE) ((membersum + 32768) >> 16);382383inrow += 2;384}385}386387388/*389* Downsample pixel values of a single component.390* This version handles the special case of a full-size component,391* with smoothing. One row of context is required.392*/393394METHODDEF(void)395fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,396JSAMPARRAY input_data, JSAMPARRAY output_data)397{398int outrow;399JDIMENSION colctr;400JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;401register JSAMPROW inptr, above_ptr, below_ptr, outptr;402INT32 membersum, neighsum, memberscale, neighscale;403int colsum, lastcolsum, nextcolsum;404405/* Expand input data enough to let all the output samples be generated406* by the standard loop. Special-casing padded output would be more407* efficient.408*/409expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,410cinfo->image_width, output_cols);411412/* Each of the eight neighbor pixels contributes a fraction SF to the413* smoothed pixel, while the main pixel contributes (1-8*SF). In order414* to use integer arithmetic, these factors are multiplied by 2^16 = 65536.415* Also recall that SF = smoothing_factor / 1024.416*/417418memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */419neighscale = cinfo->smoothing_factor * 64; /* scaled SF */420421for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {422outptr = output_data[outrow];423inptr = input_data[outrow];424above_ptr = input_data[outrow-1];425below_ptr = input_data[outrow+1];426427/* Special case for first column */428colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +429GETJSAMPLE(*inptr);430membersum = GETJSAMPLE(*inptr++);431nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +432GETJSAMPLE(*inptr);433neighsum = colsum + (colsum - membersum) + nextcolsum;434membersum = membersum * memberscale + neighsum * neighscale;435*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);436lastcolsum = colsum; colsum = nextcolsum;437438for (colctr = output_cols - 2; colctr > 0; colctr--) {439membersum = GETJSAMPLE(*inptr++);440above_ptr++; below_ptr++;441nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +442GETJSAMPLE(*inptr);443neighsum = lastcolsum + (colsum - membersum) + nextcolsum;444membersum = membersum * memberscale + neighsum * neighscale;445*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);446lastcolsum = colsum; colsum = nextcolsum;447}448449/* Special case for last column */450membersum = GETJSAMPLE(*inptr);451neighsum = lastcolsum + (colsum - membersum) + colsum;452membersum = membersum * memberscale + neighsum * neighscale;453*outptr = (JSAMPLE) ((membersum + 32768) >> 16);454455}456}457458#endif /* INPUT_SMOOTHING_SUPPORTED */459460461/*462* Module initialization routine for downsampling.463* Note that we must select a routine for each component.464*/465466GLOBAL(void)467jinit_downsampler (j_compress_ptr cinfo)468{469my_downsample_ptr downsample;470int ci;471jpeg_component_info * compptr;472boolean smoothok = TRUE;473474downsample = (my_downsample_ptr)475(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,476SIZEOF(my_downsampler));477cinfo->downsample = (struct jpeg_downsampler *) downsample;478downsample->pub.start_pass = start_pass_downsample;479downsample->pub.downsample = sep_downsample;480downsample->pub.need_context_rows = FALSE;481482if (cinfo->CCIR601_sampling)483ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);484485/* Verify we can handle the sampling factors, and set up method pointers */486for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;487ci++, compptr++) {488if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&489compptr->v_samp_factor == cinfo->max_v_samp_factor) {490#ifdef INPUT_SMOOTHING_SUPPORTED491if (cinfo->smoothing_factor) {492downsample->methods[ci] = fullsize_smooth_downsample;493downsample->pub.need_context_rows = TRUE;494} else495#endif496downsample->methods[ci] = fullsize_downsample;497} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&498compptr->v_samp_factor == cinfo->max_v_samp_factor) {499smoothok = FALSE;500downsample->methods[ci] = h2v1_downsample;501} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&502compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {503#ifdef INPUT_SMOOTHING_SUPPORTED504if (cinfo->smoothing_factor) {505downsample->methods[ci] = h2v2_smooth_downsample;506downsample->pub.need_context_rows = TRUE;507} else508#endif509downsample->methods[ci] = h2v2_downsample;510} else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&511(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {512smoothok = FALSE;513downsample->methods[ci] = int_downsample;514} else515ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);516}517518#ifdef INPUT_SMOOTHING_SUPPORTED519if (cinfo->smoothing_factor && !smoothok)520TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);521#endif522}523524525