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