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 * Copyright (C) 2019-2020, Arm Limited.
12 * For conditions of distribution and use, see the accompanying README.ijg
15 * This file contains upsampling routines.
17 * Upsampling input data is counted in "row groups". A row group
18 * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
19 * sample rows of each component. Upsampling will normally produce
20 * max_v_samp_factor pixel rows from each row group (but this could vary
21 * if the upsampler is applying a scale factor of its own).
23 * An excellent reference for image resampling is
24 * Digital Image Warping, George Wolberg, 1990.
25 * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
36 * Initialize for an upsampling pass.
40 start_pass_upsample(j_decompress_ptr cinfo
)
42 my_upsample_ptr upsample
= (my_upsample_ptr
)cinfo
->upsample
;
44 /* Mark the conversion buffer empty */
45 upsample
->next_row_out
= cinfo
->max_v_samp_factor
;
46 /* Initialize total-height counter for detecting bottom of image */
47 upsample
->rows_to_go
= cinfo
->output_height
;
52 * Control routine to do upsampling (and color conversion).
54 * In this version we upsample each component independently.
55 * We upsample one row group into the conversion buffer, then apply
56 * color conversion a row at a time.
60 sep_upsample(j_decompress_ptr cinfo
, JSAMPIMAGE input_buf
,
61 JDIMENSION
*in_row_group_ctr
, JDIMENSION in_row_groups_avail
,
62 JSAMPARRAY output_buf
, JDIMENSION
*out_row_ctr
,
63 JDIMENSION out_rows_avail
)
65 my_upsample_ptr upsample
= (my_upsample_ptr
)cinfo
->upsample
;
67 jpeg_component_info
*compptr
;
70 /* Fill the conversion buffer, if it's empty */
71 if (upsample
->next_row_out
>= cinfo
->max_v_samp_factor
) {
72 for (ci
= 0, compptr
= cinfo
->comp_info
; ci
< cinfo
->num_components
;
74 /* Invoke per-component upsample method. Notice we pass a POINTER
75 * to color_buf[ci], so that fullsize_upsample can change it.
77 (*upsample
->methods
[ci
]) (cinfo
, compptr
,
78 input_buf
[ci
] + (*in_row_group_ctr
* upsample
->rowgroup_height
[ci
]),
79 upsample
->color_buf
+ ci
);
81 upsample
->next_row_out
= 0;
84 /* Color-convert and emit rows */
86 /* How many we have in the buffer: */
87 num_rows
= (JDIMENSION
)(cinfo
->max_v_samp_factor
- upsample
->next_row_out
);
88 /* Not more than the distance to the end of the image. Need this test
89 * in case the image height is not a multiple of max_v_samp_factor:
91 if (num_rows
> upsample
->rows_to_go
)
92 num_rows
= upsample
->rows_to_go
;
93 /* And not more than what the client can accept: */
94 out_rows_avail
-= *out_row_ctr
;
95 if (num_rows
> out_rows_avail
)
96 num_rows
= out_rows_avail
;
98 (*cinfo
->cconvert
->color_convert
) (cinfo
, upsample
->color_buf
,
99 (JDIMENSION
)upsample
->next_row_out
,
100 output_buf
+ *out_row_ctr
, (int)num_rows
);
103 *out_row_ctr
+= num_rows
;
104 upsample
->rows_to_go
-= num_rows
;
105 upsample
->next_row_out
+= num_rows
;
106 /* When the buffer is emptied, declare this input row group consumed */
107 if (upsample
->next_row_out
>= cinfo
->max_v_samp_factor
)
108 (*in_row_group_ctr
)++;
113 * These are the routines invoked by sep_upsample to upsample pixel values
114 * of a single component. One row group is processed per call.
119 * For full-size components, we just make color_buf[ci] point at the
120 * input buffer, and thus avoid copying any data. Note that this is
121 * safe only because sep_upsample doesn't declare the input row group
122 * "consumed" until we are done color converting and emitting it.
126 fullsize_upsample(j_decompress_ptr cinfo
, jpeg_component_info
*compptr
,
127 JSAMPARRAY input_data
, JSAMPARRAY
*output_data_ptr
)
129 *output_data_ptr
= input_data
;
134 * This is a no-op version used for "uninteresting" components.
135 * These components will not be referenced by color conversion.
139 noop_upsample(j_decompress_ptr cinfo
, jpeg_component_info
*compptr
,
140 JSAMPARRAY input_data
, JSAMPARRAY
*output_data_ptr
)
142 *output_data_ptr
= NULL
; /* safety check */
147 * This version handles any integral sampling ratios.
148 * This is not used for typical JPEG files, so it need not be fast.
149 * Nor, for that matter, is it particularly accurate: the algorithm is
150 * simple replication of the input pixel onto the corresponding output
151 * pixels. The hi-falutin sampling literature refers to this as a
152 * "box filter". A box filter tends to introduce visible artifacts,
153 * so if you are actually going to use 3:1 or 4:1 sampling ratios
154 * you would be well advised to improve this code.
158 int_upsample(j_decompress_ptr cinfo
, jpeg_component_info
*compptr
,
159 JSAMPARRAY input_data
, JSAMPARRAY
*output_data_ptr
)
161 my_upsample_ptr upsample
= (my_upsample_ptr
)cinfo
->upsample
;
162 JSAMPARRAY output_data
= *output_data_ptr
;
163 register JSAMPROW inptr
, outptr
;
164 register JSAMPLE invalue
;
167 int h_expand
, v_expand
;
170 h_expand
= upsample
->h_expand
[compptr
->component_index
];
171 v_expand
= upsample
->v_expand
[compptr
->component_index
];
174 while (outrow
< cinfo
->max_v_samp_factor
) {
175 /* Generate one output row with proper horizontal expansion */
176 inptr
= input_data
[inrow
];
177 outptr
= output_data
[outrow
];
178 outend
= outptr
+ cinfo
->output_width
;
179 while (outptr
< outend
) {
181 for (h
= h_expand
; h
> 0; h
--) {
185 /* Generate any additional output rows by duplicating the first one */
187 jcopy_sample_rows(output_data
, outrow
, output_data
, outrow
+ 1,
188 v_expand
- 1, cinfo
->output_width
);
197 * Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
198 * It's still a box filter.
202 h2v1_upsample(j_decompress_ptr cinfo
, jpeg_component_info
*compptr
,
203 JSAMPARRAY input_data
, JSAMPARRAY
*output_data_ptr
)
205 JSAMPARRAY output_data
= *output_data_ptr
;
206 register JSAMPROW inptr
, outptr
;
207 register JSAMPLE invalue
;
211 for (inrow
= 0; inrow
< cinfo
->max_v_samp_factor
; inrow
++) {
212 inptr
= input_data
[inrow
];
213 outptr
= output_data
[inrow
];
214 outend
= outptr
+ cinfo
->output_width
;
215 while (outptr
< outend
) {
225 * Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
226 * It's still a box filter.
230 h2v2_upsample(j_decompress_ptr cinfo
, jpeg_component_info
*compptr
,
231 JSAMPARRAY input_data
, JSAMPARRAY
*output_data_ptr
)
233 JSAMPARRAY output_data
= *output_data_ptr
;
234 register JSAMPROW inptr
, outptr
;
235 register JSAMPLE invalue
;
240 while (outrow
< cinfo
->max_v_samp_factor
) {
241 inptr
= input_data
[inrow
];
242 outptr
= output_data
[outrow
];
243 outend
= outptr
+ cinfo
->output_width
;
244 while (outptr
< outend
) {
249 jcopy_sample_rows(output_data
, outrow
, output_data
, outrow
+ 1, 1,
250 cinfo
->output_width
);
258 * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
260 * The upsampling algorithm is linear interpolation between pixel centers,
261 * also known as a "triangle filter". This is a good compromise between
262 * speed and visual quality. The centers of the output pixels are 1/4 and 3/4
263 * of the way between input pixel centers.
265 * A note about the "bias" calculations: when rounding fractional values to
266 * integer, we do not want to always round 0.5 up to the next integer.
267 * If we did that, we'd introduce a noticeable bias towards larger values.
268 * Instead, this code is arranged so that 0.5 will be rounded up or down at
269 * alternate pixel locations (a simple ordered dither pattern).
273 h2v1_fancy_upsample(j_decompress_ptr cinfo
, jpeg_component_info
*compptr
,
274 JSAMPARRAY input_data
, JSAMPARRAY
*output_data_ptr
)
276 JSAMPARRAY output_data
= *output_data_ptr
;
277 register JSAMPROW inptr
, outptr
;
278 register int invalue
;
279 register JDIMENSION colctr
;
282 for (inrow
= 0; inrow
< cinfo
->max_v_samp_factor
; inrow
++) {
283 inptr
= input_data
[inrow
];
284 outptr
= output_data
[inrow
];
285 /* Special case for first column */
287 *outptr
++ = (JSAMPLE
)invalue
;
288 *outptr
++ = (JSAMPLE
)((invalue
* 3 + inptr
[0] + 2) >> 2);
290 for (colctr
= compptr
->downsampled_width
- 2; colctr
> 0; colctr
--) {
291 /* General case: 3/4 * nearer pixel + 1/4 * further pixel */
292 invalue
= (*inptr
++) * 3;
293 *outptr
++ = (JSAMPLE
)((invalue
+ inptr
[-2] + 1) >> 2);
294 *outptr
++ = (JSAMPLE
)((invalue
+ inptr
[0] + 2) >> 2);
297 /* Special case for last column */
299 *outptr
++ = (JSAMPLE
)((invalue
* 3 + inptr
[-1] + 1) >> 2);
300 *outptr
++ = (JSAMPLE
)invalue
;
306 * Fancy processing for 1:1 horizontal and 2:1 vertical (4:4:0 subsampling).
308 * This is a less common case, but it can be encountered when losslessly
309 * rotating/transposing a JPEG file that uses 4:2:2 chroma subsampling.
313 h1v2_fancy_upsample(j_decompress_ptr cinfo
, jpeg_component_info
*compptr
,
314 JSAMPARRAY input_data
, JSAMPARRAY
*output_data_ptr
)
316 JSAMPARRAY output_data
= *output_data_ptr
;
317 JSAMPROW inptr0
, inptr1
, outptr
;
318 #if BITS_IN_JSAMPLE == 8
319 int thiscolsum
, bias
;
321 JLONG thiscolsum
, bias
;
324 int inrow
, outrow
, v
;
327 while (outrow
< cinfo
->max_v_samp_factor
) {
328 for (v
= 0; v
< 2; v
++) {
329 /* inptr0 points to nearest input row, inptr1 points to next nearest */
330 inptr0
= input_data
[inrow
];
331 if (v
== 0) { /* next nearest is row above */
332 inptr1
= input_data
[inrow
- 1];
334 } else { /* next nearest is row below */
335 inptr1
= input_data
[inrow
+ 1];
338 outptr
= output_data
[outrow
++];
340 for (colctr
= 0; colctr
< compptr
->downsampled_width
; colctr
++) {
341 thiscolsum
= (*inptr0
++) * 3 + (*inptr1
++);
342 *outptr
++ = (JSAMPLE
)((thiscolsum
+ bias
) >> 2);
351 * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
352 * Again a triangle filter; see comments for h2v1 case, above.
354 * It is OK for us to reference the adjacent input rows because we demanded
355 * context from the main buffer controller (see initialization code).
359 h2v2_fancy_upsample(j_decompress_ptr cinfo
, jpeg_component_info
*compptr
,
360 JSAMPARRAY input_data
, JSAMPARRAY
*output_data_ptr
)
362 JSAMPARRAY output_data
= *output_data_ptr
;
363 register JSAMPROW inptr0
, inptr1
, outptr
;
364 #if BITS_IN_JSAMPLE == 8
365 register int thiscolsum
, lastcolsum
, nextcolsum
;
367 register JLONG thiscolsum
, lastcolsum
, nextcolsum
;
369 register JDIMENSION colctr
;
370 int inrow
, outrow
, v
;
373 while (outrow
< cinfo
->max_v_samp_factor
) {
374 for (v
= 0; v
< 2; v
++) {
375 /* inptr0 points to nearest input row, inptr1 points to next nearest */
376 inptr0
= input_data
[inrow
];
377 if (v
== 0) /* next nearest is row above */
378 inptr1
= input_data
[inrow
- 1];
379 else /* next nearest is row below */
380 inptr1
= input_data
[inrow
+ 1];
381 outptr
= output_data
[outrow
++];
383 /* Special case for first column */
384 thiscolsum
= (*inptr0
++) * 3 + (*inptr1
++);
385 nextcolsum
= (*inptr0
++) * 3 + (*inptr1
++);
386 *outptr
++ = (JSAMPLE
)((thiscolsum
* 4 + 8) >> 4);
387 *outptr
++ = (JSAMPLE
)((thiscolsum
* 3 + nextcolsum
+ 7) >> 4);
388 lastcolsum
= thiscolsum
; thiscolsum
= nextcolsum
;
390 for (colctr
= compptr
->downsampled_width
- 2; colctr
> 0; colctr
--) {
391 /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
392 /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
393 nextcolsum
= (*inptr0
++) * 3 + (*inptr1
++);
394 *outptr
++ = (JSAMPLE
)((thiscolsum
* 3 + lastcolsum
+ 8) >> 4);
395 *outptr
++ = (JSAMPLE
)((thiscolsum
* 3 + nextcolsum
+ 7) >> 4);
396 lastcolsum
= thiscolsum
; thiscolsum
= nextcolsum
;
399 /* Special case for last column */
400 *outptr
++ = (JSAMPLE
)((thiscolsum
* 3 + lastcolsum
+ 8) >> 4);
401 *outptr
++ = (JSAMPLE
)((thiscolsum
* 4 + 7) >> 4);
409 * Module initialization routine for upsampling.
413 jinit_upsampler(j_decompress_ptr cinfo
)
415 my_upsample_ptr upsample
;
417 jpeg_component_info
*compptr
;
418 boolean need_buffer
, do_fancy
;
419 int h_in_group
, v_in_group
, h_out_group
, v_out_group
;
421 if (!cinfo
->master
->jinit_upsampler_no_alloc
) {
422 upsample
= (my_upsample_ptr
)
423 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
)cinfo
, JPOOL_IMAGE
,
424 sizeof(my_upsampler
));
425 cinfo
->upsample
= (struct jpeg_upsampler
*)upsample
;
426 upsample
->pub
.start_pass
= start_pass_upsample
;
427 upsample
->pub
.upsample
= sep_upsample
;
428 upsample
->pub
.need_context_rows
= FALSE
; /* until we find out differently */
430 upsample
= (my_upsample_ptr
)cinfo
->upsample
;
432 if (cinfo
->CCIR601_sampling
) /* this isn't supported */
433 ERREXIT(cinfo
, JERR_CCIR601_NOTIMPL
);
435 /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
436 * so don't ask for it.
438 do_fancy
= cinfo
->do_fancy_upsampling
&& cinfo
->_min_DCT_scaled_size
> 1;
440 /* Verify we can handle the sampling factors, select per-component methods,
441 * and create storage as needed.
443 for (ci
= 0, compptr
= cinfo
->comp_info
; ci
< cinfo
->num_components
;
445 /* Compute size of an "input group" after IDCT scaling. This many samples
446 * are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
448 h_in_group
= (compptr
->h_samp_factor
* compptr
->_DCT_scaled_size
) /
449 cinfo
->_min_DCT_scaled_size
;
450 v_in_group
= (compptr
->v_samp_factor
* compptr
->_DCT_scaled_size
) /
451 cinfo
->_min_DCT_scaled_size
;
452 h_out_group
= cinfo
->max_h_samp_factor
;
453 v_out_group
= cinfo
->max_v_samp_factor
;
454 upsample
->rowgroup_height
[ci
] = v_in_group
; /* save for use later */
456 if (!compptr
->component_needed
) {
457 /* Don't bother to upsample an uninteresting component. */
458 upsample
->methods
[ci
] = noop_upsample
;
460 } else if (h_in_group
== h_out_group
&& v_in_group
== v_out_group
) {
461 /* Fullsize components can be processed without any work. */
462 upsample
->methods
[ci
] = fullsize_upsample
;
464 } else if (h_in_group
* 2 == h_out_group
&& v_in_group
== v_out_group
) {
465 /* Special cases for 2h1v upsampling */
466 if (do_fancy
&& compptr
->downsampled_width
> 2) {
467 if (jsimd_can_h2v1_fancy_upsample())
468 upsample
->methods
[ci
] = jsimd_h2v1_fancy_upsample
;
470 upsample
->methods
[ci
] = h2v1_fancy_upsample
;
472 if (jsimd_can_h2v1_upsample())
473 upsample
->methods
[ci
] = jsimd_h2v1_upsample
;
475 upsample
->methods
[ci
] = h2v1_upsample
;
477 } else if (h_in_group
== h_out_group
&&
478 v_in_group
* 2 == v_out_group
&& do_fancy
) {
479 /* Non-fancy upsampling is handled by the generic method */
480 #if defined(__arm__) || defined(__aarch64__) || \
481 defined(_M_ARM) || defined(_M_ARM64)
482 if (jsimd_can_h1v2_fancy_upsample())
483 upsample
->methods
[ci
] = jsimd_h1v2_fancy_upsample
;
486 upsample
->methods
[ci
] = h1v2_fancy_upsample
;
487 upsample
->pub
.need_context_rows
= TRUE
;
488 } else if (h_in_group
* 2 == h_out_group
&&
489 v_in_group
* 2 == v_out_group
) {
490 /* Special cases for 2h2v upsampling */
491 if (do_fancy
&& compptr
->downsampled_width
> 2) {
492 if (jsimd_can_h2v2_fancy_upsample())
493 upsample
->methods
[ci
] = jsimd_h2v2_fancy_upsample
;
495 upsample
->methods
[ci
] = h2v2_fancy_upsample
;
496 upsample
->pub
.need_context_rows
= TRUE
;
498 if (jsimd_can_h2v2_upsample())
499 upsample
->methods
[ci
] = jsimd_h2v2_upsample
;
501 upsample
->methods
[ci
] = h2v2_upsample
;
503 } else if ((h_out_group
% h_in_group
) == 0 &&
504 (v_out_group
% v_in_group
) == 0) {
505 /* Generic integral-factors upsampling method */
506 #if defined(__mips__)
507 if (jsimd_can_int_upsample())
508 upsample
->methods
[ci
] = jsimd_int_upsample
;
511 upsample
->methods
[ci
] = int_upsample
;
512 upsample
->h_expand
[ci
] = (UINT8
)(h_out_group
/ h_in_group
);
513 upsample
->v_expand
[ci
] = (UINT8
)(v_out_group
/ v_in_group
);
515 ERREXIT(cinfo
, JERR_FRACT_SAMPLE_NOTIMPL
);
516 if (need_buffer
&& !cinfo
->master
->jinit_upsampler_no_alloc
) {
517 upsample
->color_buf
[ci
] = (*cinfo
->mem
->alloc_sarray
)
518 ((j_common_ptr
)cinfo
, JPOOL_IMAGE
,
519 (JDIMENSION
)jround_up((long)cinfo
->output_width
,
520 (long)cinfo
->max_h_samp_factor
),
521 (JDIMENSION
)cinfo
->max_v_samp_factor
);