source: trunk/third/firefox/jpeg/jcsample.c @ 21695

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