• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * jdsample.c
3  *
4  * This file was part of the Independent JPEG Group's software:
5  * Copyright (C) 1991-1996, Thomas G. Lane.
6  * libjpeg-turbo Modifications:
7  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
8  * Copyright (C) 2010, 2015-2016, D. R. Commander.
9  * Copyright (C) 2014, MIPS Technologies, Inc., California.
10  * Copyright (C) 2015, Google, Inc.
11  * For conditions of distribution and use, see the accompanying README.ijg
12  * file.
13  *
14  * This file contains upsampling routines.
15  *
16  * Upsampling input data is counted in "row groups".  A row group
17  * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
18  * sample rows of each component.  Upsampling will normally produce
19  * max_v_samp_factor pixel rows from each row group (but this could vary
20  * if the upsampler is applying a scale factor of its own).
21  *
22  * An excellent reference for image resampling is
23  *   Digital Image Warping, George Wolberg, 1990.
24  *   Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
25  */
26 
27 #include "jinclude.h"
28 #include "jdsample.h"
29 #include "jsimd.h"
30 #include "jpegcomp.h"
31 
32 
33 
34 /*
35  * Initialize for an upsampling pass.
36  */
37 
38 METHODDEF(void)
start_pass_upsample(j_decompress_ptr cinfo)39 start_pass_upsample(j_decompress_ptr cinfo)
40 {
41   my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
42 
43   /* Mark the conversion buffer empty */
44   upsample->next_row_out = cinfo->max_v_samp_factor;
45   /* Initialize total-height counter for detecting bottom of image */
46   upsample->rows_to_go = cinfo->output_height;
47 }
48 
49 
50 /*
51  * Control routine to do upsampling (and color conversion).
52  *
53  * In this version we upsample each component independently.
54  * We upsample one row group into the conversion buffer, then apply
55  * color conversion a row at a time.
56  */
57 
58 METHODDEF(void)
sep_upsample(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION * in_row_group_ctr,JDIMENSION in_row_groups_avail,JSAMPARRAY output_buf,JDIMENSION * out_row_ctr,JDIMENSION out_rows_avail)59 sep_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
60              JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
61              JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
62              JDIMENSION out_rows_avail)
63 {
64   my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
65   int ci;
66   jpeg_component_info *compptr;
67   JDIMENSION num_rows;
68 
69   /* Fill the conversion buffer, if it's empty */
70   if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
71     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
72          ci++, compptr++) {
73       /* Invoke per-component upsample method.  Notice we pass a POINTER
74        * to color_buf[ci], so that fullsize_upsample can change it.
75        */
76       (*upsample->methods[ci]) (cinfo, compptr,
77         input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
78         upsample->color_buf + ci);
79     }
80     upsample->next_row_out = 0;
81   }
82 
83   /* Color-convert and emit rows */
84 
85   /* How many we have in the buffer: */
86   num_rows = (JDIMENSION)(cinfo->max_v_samp_factor - upsample->next_row_out);
87   /* Not more than the distance to the end of the image.  Need this test
88    * in case the image height is not a multiple of max_v_samp_factor:
89    */
90   if (num_rows > upsample->rows_to_go)
91     num_rows = upsample->rows_to_go;
92   /* And not more than what the client can accept: */
93   out_rows_avail -= *out_row_ctr;
94   if (num_rows > out_rows_avail)
95     num_rows = out_rows_avail;
96 
97   (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
98                                      (JDIMENSION)upsample->next_row_out,
99                                      output_buf + *out_row_ctr, (int)num_rows);
100 
101   /* Adjust counts */
102   *out_row_ctr += num_rows;
103   upsample->rows_to_go -= num_rows;
104   upsample->next_row_out += num_rows;
105   /* When the buffer is emptied, declare this input row group consumed */
106   if (upsample->next_row_out >= cinfo->max_v_samp_factor)
107     (*in_row_group_ctr)++;
108 }
109 
110 
111 /*
112  * These are the routines invoked by sep_upsample to upsample pixel values
113  * of a single component.  One row group is processed per call.
114  */
115 
116 
117 /*
118  * For full-size components, we just make color_buf[ci] point at the
119  * input buffer, and thus avoid copying any data.  Note that this is
120  * safe only because sep_upsample doesn't declare the input row group
121  * "consumed" until we are done color converting and emitting it.
122  */
123 
124 METHODDEF(void)
fullsize_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)125 fullsize_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
126                   JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
127 {
128   *output_data_ptr = input_data;
129 }
130 
131 
132 /*
133  * This is a no-op version used for "uninteresting" components.
134  * These components will not be referenced by color conversion.
135  */
136 
137 METHODDEF(void)
noop_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)138 noop_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
139               JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
140 {
141   *output_data_ptr = NULL;      /* safety check */
142 }
143 
144 
145 /*
146  * This version handles any integral sampling ratios.
147  * This is not used for typical JPEG files, so it need not be fast.
148  * Nor, for that matter, is it particularly accurate: the algorithm is
149  * simple replication of the input pixel onto the corresponding output
150  * pixels.  The hi-falutin sampling literature refers to this as a
151  * "box filter".  A box filter tends to introduce visible artifacts,
152  * so if you are actually going to use 3:1 or 4:1 sampling ratios
153  * you would be well advised to improve this code.
154  */
155 
156 METHODDEF(void)
int_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)157 int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
158              JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
159 {
160   my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
161   JSAMPARRAY output_data = *output_data_ptr;
162   register JSAMPROW inptr, outptr;
163   register JSAMPLE invalue;
164   register int h;
165   JSAMPROW outend;
166   int h_expand, v_expand;
167   int inrow, outrow;
168 
169   h_expand = upsample->h_expand[compptr->component_index];
170   v_expand = upsample->v_expand[compptr->component_index];
171 
172   inrow = outrow = 0;
173   while (outrow < cinfo->max_v_samp_factor) {
174     /* Generate one output row with proper horizontal expansion */
175     inptr = input_data[inrow];
176     outptr = output_data[outrow];
177     outend = outptr + cinfo->output_width;
178     while (outptr < outend) {
179       invalue = *inptr++;       /* don't need GETJSAMPLE() here */
180       for (h = h_expand; h > 0; h--) {
181         *outptr++ = invalue;
182       }
183     }
184     /* Generate any additional output rows by duplicating the first one */
185     if (v_expand > 1) {
186       jcopy_sample_rows(output_data, outrow, output_data, outrow + 1,
187                         v_expand - 1, cinfo->output_width);
188     }
189     inrow++;
190     outrow += v_expand;
191   }
192 }
193 
194 
195 /*
196  * Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
197  * It's still a box filter.
198  */
199 
200 METHODDEF(void)
h2v1_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)201 h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
202               JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
203 {
204   JSAMPARRAY output_data = *output_data_ptr;
205   register JSAMPROW inptr, outptr;
206   register JSAMPLE invalue;
207   JSAMPROW outend;
208   int inrow;
209 
210   for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
211     inptr = input_data[inrow];
212     outptr = output_data[inrow];
213     outend = outptr + cinfo->output_width;
214     while (outptr < outend) {
215       invalue = *inptr++;       /* don't need GETJSAMPLE() here */
216       *outptr++ = invalue;
217       *outptr++ = invalue;
218     }
219   }
220 }
221 
222 
223 /*
224  * Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
225  * It's still a box filter.
226  */
227 
228 METHODDEF(void)
h2v2_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)229 h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
230               JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
231 {
232   JSAMPARRAY output_data = *output_data_ptr;
233   register JSAMPROW inptr, outptr;
234   register JSAMPLE invalue;
235   JSAMPROW outend;
236   int inrow, outrow;
237 
238   inrow = outrow = 0;
239   while (outrow < cinfo->max_v_samp_factor) {
240     inptr = input_data[inrow];
241     outptr = output_data[outrow];
242     outend = outptr + cinfo->output_width;
243     while (outptr < outend) {
244       invalue = *inptr++;       /* don't need GETJSAMPLE() here */
245       *outptr++ = invalue;
246       *outptr++ = invalue;
247     }
248     jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, 1,
249                       cinfo->output_width);
250     inrow++;
251     outrow += 2;
252   }
253 }
254 
255 
256 /*
257  * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
258  *
259  * The upsampling algorithm is linear interpolation between pixel centers,
260  * also known as a "triangle filter".  This is a good compromise between
261  * speed and visual quality.  The centers of the output pixels are 1/4 and 3/4
262  * of the way between input pixel centers.
263  *
264  * A note about the "bias" calculations: when rounding fractional values to
265  * integer, we do not want to always round 0.5 up to the next integer.
266  * If we did that, we'd introduce a noticeable bias towards larger values.
267  * Instead, this code is arranged so that 0.5 will be rounded up or down at
268  * alternate pixel locations (a simple ordered dither pattern).
269  */
270 
271 METHODDEF(void)
h2v1_fancy_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)272 h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
273                     JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
274 {
275   JSAMPARRAY output_data = *output_data_ptr;
276   register JSAMPROW inptr, outptr;
277   register int invalue;
278   register JDIMENSION colctr;
279   int inrow;
280 
281   for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
282     inptr = input_data[inrow];
283     outptr = output_data[inrow];
284     /* Special case for first column */
285     invalue = GETJSAMPLE(*inptr++);
286     *outptr++ = (JSAMPLE)invalue;
287     *outptr++ = (JSAMPLE)((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
288 
289     for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
290       /* General case: 3/4 * nearer pixel + 1/4 * further pixel */
291       invalue = GETJSAMPLE(*inptr++) * 3;
292       *outptr++ = (JSAMPLE)((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
293       *outptr++ = (JSAMPLE)((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
294     }
295 
296     /* Special case for last column */
297     invalue = GETJSAMPLE(*inptr);
298     *outptr++ = (JSAMPLE)((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
299     *outptr++ = (JSAMPLE)invalue;
300   }
301 }
302 
303 
304 /*
305  * Fancy processing for 1:1 horizontal and 2:1 vertical (4:4:0 subsampling).
306  *
307  * This is a less common case, but it can be encountered when losslessly
308  * rotating/transposing a JPEG file that uses 4:2:2 chroma subsampling.
309  */
310 
311 METHODDEF(void)
h1v2_fancy_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)312 h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
313                     JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
314 {
315   JSAMPARRAY output_data = *output_data_ptr;
316   JSAMPROW inptr0, inptr1, outptr;
317 #if BITS_IN_JSAMPLE == 8
318   int thiscolsum;
319 #else
320   JLONG thiscolsum;
321 #endif
322   JDIMENSION colctr;
323   int inrow, outrow, v;
324 
325   inrow = outrow = 0;
326   while (outrow < cinfo->max_v_samp_factor) {
327     for (v = 0; v < 2; v++) {
328       /* inptr0 points to nearest input row, inptr1 points to next nearest */
329       inptr0 = input_data[inrow];
330       if (v == 0)               /* next nearest is row above */
331         inptr1 = input_data[inrow - 1];
332       else                      /* next nearest is row below */
333         inptr1 = input_data[inrow + 1];
334       outptr = output_data[outrow++];
335 
336       for (colctr = 0; colctr < compptr->downsampled_width; colctr++) {
337         thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
338         *outptr++ = (JSAMPLE)((thiscolsum + 1) >> 2);
339       }
340     }
341     inrow++;
342   }
343 }
344 
345 
346 /*
347  * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
348  * Again a triangle filter; see comments for h2v1 case, above.
349  *
350  * It is OK for us to reference the adjacent input rows because we demanded
351  * context from the main buffer controller (see initialization code).
352  */
353 
354 METHODDEF(void)
h2v2_fancy_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)355 h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
356                     JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
357 {
358   JSAMPARRAY output_data = *output_data_ptr;
359   register JSAMPROW inptr0, inptr1, outptr;
360 #if BITS_IN_JSAMPLE == 8
361   register int thiscolsum, lastcolsum, nextcolsum;
362 #else
363   register JLONG thiscolsum, lastcolsum, nextcolsum;
364 #endif
365   register JDIMENSION colctr;
366   int inrow, outrow, v;
367 
368   inrow = outrow = 0;
369   while (outrow < cinfo->max_v_samp_factor) {
370     for (v = 0; v < 2; v++) {
371       /* inptr0 points to nearest input row, inptr1 points to next nearest */
372       inptr0 = input_data[inrow];
373       if (v == 0)               /* next nearest is row above */
374         inptr1 = input_data[inrow - 1];
375       else                      /* next nearest is row below */
376         inptr1 = input_data[inrow + 1];
377       outptr = output_data[outrow++];
378 
379       /* Special case for first column */
380       thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
381       nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
382       *outptr++ = (JSAMPLE)((thiscolsum * 4 + 8) >> 4);
383       *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4);
384       lastcolsum = thiscolsum;  thiscolsum = nextcolsum;
385 
386       for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
387         /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
388         /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
389         nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
390         *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4);
391         *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4);
392         lastcolsum = thiscolsum;  thiscolsum = nextcolsum;
393       }
394 
395       /* Special case for last column */
396       *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4);
397       *outptr++ = (JSAMPLE)((thiscolsum * 4 + 7) >> 4);
398     }
399     inrow++;
400   }
401 }
402 
403 
404 /*
405  * Module initialization routine for upsampling.
406  */
407 
408 GLOBAL(void)
jinit_upsampler(j_decompress_ptr cinfo)409 jinit_upsampler(j_decompress_ptr cinfo)
410 {
411   my_upsample_ptr upsample;
412   int ci;
413   jpeg_component_info *compptr;
414   boolean need_buffer, do_fancy;
415   int h_in_group, v_in_group, h_out_group, v_out_group;
416 
417   if (!cinfo->master->jinit_upsampler_no_alloc) {
418     upsample = (my_upsample_ptr)
419       (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
420                                   sizeof(my_upsampler));
421     cinfo->upsample = (struct jpeg_upsampler *)upsample;
422     upsample->pub.start_pass = start_pass_upsample;
423     upsample->pub.upsample = sep_upsample;
424     upsample->pub.need_context_rows = FALSE; /* until we find out differently */
425   } else
426     upsample = (my_upsample_ptr)cinfo->upsample;
427 
428   if (cinfo->CCIR601_sampling)  /* this isn't supported */
429     ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
430 
431   /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
432    * so don't ask for it.
433    */
434   do_fancy = cinfo->do_fancy_upsampling && cinfo->_min_DCT_scaled_size > 1;
435 
436   /* Verify we can handle the sampling factors, select per-component methods,
437    * and create storage as needed.
438    */
439   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
440        ci++, compptr++) {
441     /* Compute size of an "input group" after IDCT scaling.  This many samples
442      * are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
443      */
444     h_in_group = (compptr->h_samp_factor * compptr->_DCT_scaled_size) /
445                  cinfo->_min_DCT_scaled_size;
446     v_in_group = (compptr->v_samp_factor * compptr->_DCT_scaled_size) /
447                  cinfo->_min_DCT_scaled_size;
448     h_out_group = cinfo->max_h_samp_factor;
449     v_out_group = cinfo->max_v_samp_factor;
450     upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
451     need_buffer = TRUE;
452     if (!compptr->component_needed) {
453       /* Don't bother to upsample an uninteresting component. */
454       upsample->methods[ci] = noop_upsample;
455       need_buffer = FALSE;
456     } else if (h_in_group == h_out_group && v_in_group == v_out_group) {
457       /* Fullsize components can be processed without any work. */
458       upsample->methods[ci] = fullsize_upsample;
459       need_buffer = FALSE;
460     } else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) {
461       /* Special cases for 2h1v upsampling */
462       if (do_fancy && compptr->downsampled_width > 2) {
463         if (jsimd_can_h2v1_fancy_upsample())
464           upsample->methods[ci] = jsimd_h2v1_fancy_upsample;
465         else
466           upsample->methods[ci] = h2v1_fancy_upsample;
467       } else {
468         if (jsimd_can_h2v1_upsample())
469           upsample->methods[ci] = jsimd_h2v1_upsample;
470         else
471           upsample->methods[ci] = h2v1_upsample;
472       }
473     } else if (h_in_group == h_out_group &&
474                v_in_group * 2 == v_out_group && do_fancy) {
475       /* Non-fancy upsampling is handled by the generic method */
476       upsample->methods[ci] = h1v2_fancy_upsample;
477       upsample->pub.need_context_rows = TRUE;
478     } else if (h_in_group * 2 == h_out_group &&
479                v_in_group * 2 == v_out_group) {
480       /* Special cases for 2h2v upsampling */
481       if (do_fancy && compptr->downsampled_width > 2) {
482         if (jsimd_can_h2v2_fancy_upsample())
483           upsample->methods[ci] = jsimd_h2v2_fancy_upsample;
484         else
485           upsample->methods[ci] = h2v2_fancy_upsample;
486         upsample->pub.need_context_rows = TRUE;
487       } else {
488         if (jsimd_can_h2v2_upsample())
489           upsample->methods[ci] = jsimd_h2v2_upsample;
490         else
491           upsample->methods[ci] = h2v2_upsample;
492       }
493     } else if ((h_out_group % h_in_group) == 0 &&
494                (v_out_group % v_in_group) == 0) {
495       /* Generic integral-factors upsampling method */
496 #if defined(__mips__)
497       if (jsimd_can_int_upsample())
498         upsample->methods[ci] = jsimd_int_upsample;
499       else
500 #endif
501         upsample->methods[ci] = int_upsample;
502       upsample->h_expand[ci] = (UINT8)(h_out_group / h_in_group);
503       upsample->v_expand[ci] = (UINT8)(v_out_group / v_in_group);
504     } else
505       ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
506     if (need_buffer && !cinfo->master->jinit_upsampler_no_alloc) {
507       upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
508         ((j_common_ptr)cinfo, JPOOL_IMAGE,
509          (JDIMENSION)jround_up((long)cinfo->output_width,
510                                (long)cinfo->max_h_samp_factor),
511          (JDIMENSION)cinfo->max_v_samp_factor);
512     }
513   }
514 }
515