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