1 : /*
2 : * jdmerge.c
3 : *
4 : * Copyright (C) 1994-1996, Thomas G. Lane.
5 : * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 : * Copyright (C) 2009, 2011, 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 code for merged upsampling/color conversion.
11 : *
12 : * This file combines functions from jdsample.c and jdcolor.c;
13 : * read those files first to understand what's going on.
14 : *
15 : * When the chroma components are to be upsampled by simple replication
16 : * (ie, box filtering), we can save some work in color conversion by
17 : * calculating all the output pixels corresponding to a pair of chroma
18 : * samples at one time. In the conversion equations
19 : * R = Y + K1 * Cr
20 : * G = Y + K2 * Cb + K3 * Cr
21 : * B = Y + K4 * Cb
22 : * only the Y term varies among the group of pixels corresponding to a pair
23 : * of chroma samples, so the rest of the terms can be calculated just once.
24 : * At typical sampling ratios, this eliminates half or three-quarters of the
25 : * multiplications needed for color conversion.
26 : *
27 : * This file currently provides implementations for the following cases:
28 : * YCbCr => RGB color conversion only.
29 : * Sampling ratios of 2h1v or 2h2v.
30 : * No scaling needed at upsample time.
31 : * Corner-aligned (non-CCIR601) sampling alignment.
32 : * Other special cases could be added, but in most applications these are
33 : * the only common cases. (For uncommon cases we fall back on the more
34 : * general code in jdsample.c and jdcolor.c.)
35 : */
36 :
37 : #define JPEG_INTERNALS
38 : #include "jinclude.h"
39 : #include "jpeglib.h"
40 : #include "jsimd.h"
41 : #include "config.h"
42 :
43 : #ifdef UPSAMPLE_MERGING_SUPPORTED
44 :
45 :
46 : /* Private subobject */
47 :
48 : typedef struct {
49 : struct jpeg_upsampler pub; /* public fields */
50 :
51 : /* Pointer to routine to do actual upsampling/conversion of one row group */
52 : JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
53 : JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
54 : JSAMPARRAY output_buf));
55 :
56 : /* Private state for YCC->RGB conversion */
57 : int * Cr_r_tab; /* => table for Cr to R conversion */
58 : int * Cb_b_tab; /* => table for Cb to B conversion */
59 : INT32 * Cr_g_tab; /* => table for Cr to G conversion */
60 : INT32 * Cb_g_tab; /* => table for Cb to G conversion */
61 :
62 : /* For 2:1 vertical sampling, we produce two output rows at a time.
63 : * We need a "spare" row buffer to hold the second output row if the
64 : * application provides just a one-row buffer; we also use the spare
65 : * to discard the dummy last row if the image height is odd.
66 : */
67 : JSAMPROW spare_row;
68 : boolean spare_full; /* T if spare buffer is occupied */
69 :
70 : JDIMENSION out_row_width; /* samples per output row */
71 : JDIMENSION rows_to_go; /* counts rows remaining in image */
72 : } my_upsampler;
73 :
74 : typedef my_upsampler * my_upsample_ptr;
75 :
76 : #define SCALEBITS 16 /* speediest right-shift on some machines */
77 : #define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
78 : #define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
79 :
80 :
81 : /* Include inline routines for colorspace extensions */
82 :
83 : #include "jdmrgext.c"
84 : #undef RGB_RED
85 : #undef RGB_GREEN
86 : #undef RGB_BLUE
87 : #undef RGB_PIXELSIZE
88 :
89 : #define RGB_RED EXT_RGB_RED
90 : #define RGB_GREEN EXT_RGB_GREEN
91 : #define RGB_BLUE EXT_RGB_BLUE
92 : #define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
93 : #define h2v1_merged_upsample_internal extrgb_h2v1_merged_upsample_internal
94 : #define h2v2_merged_upsample_internal extrgb_h2v2_merged_upsample_internal
95 : #include "jdmrgext.c"
96 : #undef RGB_RED
97 : #undef RGB_GREEN
98 : #undef RGB_BLUE
99 : #undef RGB_PIXELSIZE
100 : #undef h2v1_merged_upsample_internal
101 : #undef h2v2_merged_upsample_internal
102 :
103 : #define RGB_RED EXT_RGBX_RED
104 : #define RGB_GREEN EXT_RGBX_GREEN
105 : #define RGB_BLUE EXT_RGBX_BLUE
106 : #define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
107 : #define h2v1_merged_upsample_internal extrgbx_h2v1_merged_upsample_internal
108 : #define h2v2_merged_upsample_internal extrgbx_h2v2_merged_upsample_internal
109 : #include "jdmrgext.c"
110 : #undef RGB_RED
111 : #undef RGB_GREEN
112 : #undef RGB_BLUE
113 : #undef RGB_PIXELSIZE
114 : #undef h2v1_merged_upsample_internal
115 : #undef h2v2_merged_upsample_internal
116 :
117 : #define RGB_RED EXT_BGR_RED
118 : #define RGB_GREEN EXT_BGR_GREEN
119 : #define RGB_BLUE EXT_BGR_BLUE
120 : #define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
121 : #define h2v1_merged_upsample_internal extbgr_h2v1_merged_upsample_internal
122 : #define h2v2_merged_upsample_internal extbgr_h2v2_merged_upsample_internal
123 : #include "jdmrgext.c"
124 : #undef RGB_RED
125 : #undef RGB_GREEN
126 : #undef RGB_BLUE
127 : #undef RGB_PIXELSIZE
128 : #undef h2v1_merged_upsample_internal
129 : #undef h2v2_merged_upsample_internal
130 :
131 : #define RGB_RED EXT_BGRX_RED
132 : #define RGB_GREEN EXT_BGRX_GREEN
133 : #define RGB_BLUE EXT_BGRX_BLUE
134 : #define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
135 : #define h2v1_merged_upsample_internal extbgrx_h2v1_merged_upsample_internal
136 : #define h2v2_merged_upsample_internal extbgrx_h2v2_merged_upsample_internal
137 : #include "jdmrgext.c"
138 : #undef RGB_RED
139 : #undef RGB_GREEN
140 : #undef RGB_BLUE
141 : #undef RGB_PIXELSIZE
142 : #undef h2v1_merged_upsample_internal
143 : #undef h2v2_merged_upsample_internal
144 :
145 : #define RGB_RED EXT_XBGR_RED
146 : #define RGB_GREEN EXT_XBGR_GREEN
147 : #define RGB_BLUE EXT_XBGR_BLUE
148 : #define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
149 : #define h2v1_merged_upsample_internal extxbgr_h2v1_merged_upsample_internal
150 : #define h2v2_merged_upsample_internal extxbgr_h2v2_merged_upsample_internal
151 : #include "jdmrgext.c"
152 : #undef RGB_RED
153 : #undef RGB_GREEN
154 : #undef RGB_BLUE
155 : #undef RGB_PIXELSIZE
156 : #undef h2v1_merged_upsample_internal
157 : #undef h2v2_merged_upsample_internal
158 :
159 : #define RGB_RED EXT_XRGB_RED
160 : #define RGB_GREEN EXT_XRGB_GREEN
161 : #define RGB_BLUE EXT_XRGB_BLUE
162 : #define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
163 : #define h2v1_merged_upsample_internal extxrgb_h2v1_merged_upsample_internal
164 : #define h2v2_merged_upsample_internal extxrgb_h2v2_merged_upsample_internal
165 : #include "jdmrgext.c"
166 : #undef RGB_RED
167 : #undef RGB_GREEN
168 : #undef RGB_BLUE
169 : #undef RGB_PIXELSIZE
170 : #undef h2v1_merged_upsample_internal
171 : #undef h2v2_merged_upsample_internal
172 :
173 :
174 : /*
175 : * Initialize tables for YCC->RGB colorspace conversion.
176 : * This is taken directly from jdcolor.c; see that file for more info.
177 : */
178 :
179 : LOCAL(void)
180 0 : build_ycc_rgb_table (j_decompress_ptr cinfo)
181 : {
182 0 : my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
183 : int i;
184 : INT32 x;
185 : SHIFT_TEMPS
186 :
187 0 : upsample->Cr_r_tab = (int *)
188 0 : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
189 : (MAXJSAMPLE+1) * SIZEOF(int));
190 0 : upsample->Cb_b_tab = (int *)
191 0 : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
192 : (MAXJSAMPLE+1) * SIZEOF(int));
193 0 : upsample->Cr_g_tab = (INT32 *)
194 0 : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
195 : (MAXJSAMPLE+1) * SIZEOF(INT32));
196 0 : upsample->Cb_g_tab = (INT32 *)
197 0 : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
198 : (MAXJSAMPLE+1) * SIZEOF(INT32));
199 :
200 0 : for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
201 : /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
202 : /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
203 : /* Cr=>R value is nearest int to 1.40200 * x */
204 0 : upsample->Cr_r_tab[i] = (int)
205 0 : RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
206 : /* Cb=>B value is nearest int to 1.77200 * x */
207 0 : upsample->Cb_b_tab[i] = (int)
208 0 : RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
209 : /* Cr=>G value is scaled-up -0.71414 * x */
210 0 : upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
211 : /* Cb=>G value is scaled-up -0.34414 * x */
212 : /* We also add in ONE_HALF so that need not do it in inner loop */
213 0 : upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
214 : }
215 0 : }
216 :
217 :
218 : /*
219 : * Initialize for an upsampling pass.
220 : */
221 :
222 : METHODDEF(void)
223 0 : start_pass_merged_upsample (j_decompress_ptr cinfo)
224 : {
225 0 : my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
226 :
227 : /* Mark the spare buffer empty */
228 0 : upsample->spare_full = FALSE;
229 : /* Initialize total-height counter for detecting bottom of image */
230 0 : upsample->rows_to_go = cinfo->output_height;
231 0 : }
232 :
233 :
234 : /*
235 : * Control routine to do upsampling (and color conversion).
236 : *
237 : * The control routine just handles the row buffering considerations.
238 : */
239 :
240 : METHODDEF(void)
241 0 : merged_2v_upsample (j_decompress_ptr cinfo,
242 : JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
243 : JDIMENSION in_row_groups_avail,
244 : JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
245 : JDIMENSION out_rows_avail)
246 : /* 2:1 vertical sampling case: may need a spare row. */
247 : {
248 0 : my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
249 : JSAMPROW work_ptrs[2];
250 : JDIMENSION num_rows; /* number of rows returned to caller */
251 :
252 0 : if (upsample->spare_full) {
253 : /* If we have a spare row saved from a previous cycle, just return it. */
254 0 : jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
255 : 1, upsample->out_row_width);
256 0 : num_rows = 1;
257 0 : upsample->spare_full = FALSE;
258 : } else {
259 : /* Figure number of rows to return to caller. */
260 0 : num_rows = 2;
261 : /* Not more than the distance to the end of the image. */
262 0 : if (num_rows > upsample->rows_to_go)
263 0 : num_rows = upsample->rows_to_go;
264 : /* And not more than what the client can accept: */
265 0 : out_rows_avail -= *out_row_ctr;
266 0 : if (num_rows > out_rows_avail)
267 0 : num_rows = out_rows_avail;
268 : /* Create output pointer array for upsampler. */
269 0 : work_ptrs[0] = output_buf[*out_row_ctr];
270 0 : if (num_rows > 1) {
271 0 : work_ptrs[1] = output_buf[*out_row_ctr + 1];
272 : } else {
273 0 : work_ptrs[1] = upsample->spare_row;
274 0 : upsample->spare_full = TRUE;
275 : }
276 : /* Now do the upsampling. */
277 0 : (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
278 : }
279 :
280 : /* Adjust counts */
281 0 : *out_row_ctr += num_rows;
282 0 : upsample->rows_to_go -= num_rows;
283 : /* When the buffer is emptied, declare this input row group consumed */
284 0 : if (! upsample->spare_full)
285 0 : (*in_row_group_ctr)++;
286 0 : }
287 :
288 :
289 : METHODDEF(void)
290 0 : merged_1v_upsample (j_decompress_ptr cinfo,
291 : JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
292 : JDIMENSION in_row_groups_avail,
293 : JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
294 : JDIMENSION out_rows_avail)
295 : /* 1:1 vertical sampling case: much easier, never need a spare row. */
296 : {
297 0 : my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
298 :
299 : /* Just do the upsampling. */
300 0 : (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
301 0 : output_buf + *out_row_ctr);
302 : /* Adjust counts */
303 0 : (*out_row_ctr)++;
304 0 : (*in_row_group_ctr)++;
305 0 : }
306 :
307 :
308 : /*
309 : * These are the routines invoked by the control routines to do
310 : * the actual upsampling/conversion. One row group is processed per call.
311 : *
312 : * Note: since we may be writing directly into application-supplied buffers,
313 : * we have to be honest about the output width; we can't assume the buffer
314 : * has been rounded up to an even width.
315 : */
316 :
317 :
318 : /*
319 : * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
320 : */
321 :
322 : METHODDEF(void)
323 0 : h2v1_merged_upsample (j_decompress_ptr cinfo,
324 : JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
325 : JSAMPARRAY output_buf)
326 : {
327 0 : switch (cinfo->out_color_space) {
328 : case JCS_EXT_RGB:
329 : extrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
330 : output_buf);
331 0 : break;
332 : case JCS_EXT_RGBX:
333 : case JCS_EXT_RGBA:
334 : extrgbx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
335 : output_buf);
336 0 : break;
337 : case JCS_EXT_BGR:
338 : extbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
339 : output_buf);
340 0 : break;
341 : case JCS_EXT_BGRX:
342 : case JCS_EXT_BGRA:
343 : extbgrx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
344 : output_buf);
345 0 : break;
346 : case JCS_EXT_XBGR:
347 : case JCS_EXT_ABGR:
348 : extxbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
349 : output_buf);
350 0 : break;
351 : case JCS_EXT_XRGB:
352 : case JCS_EXT_ARGB:
353 : extxrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
354 : output_buf);
355 0 : break;
356 : default:
357 : h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
358 : output_buf);
359 0 : break;
360 : }
361 0 : }
362 :
363 :
364 : /*
365 : * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
366 : */
367 :
368 : METHODDEF(void)
369 0 : h2v2_merged_upsample (j_decompress_ptr cinfo,
370 : JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
371 : JSAMPARRAY output_buf)
372 : {
373 0 : switch (cinfo->out_color_space) {
374 : case JCS_EXT_RGB:
375 : extrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
376 : output_buf);
377 0 : break;
378 : case JCS_EXT_RGBX:
379 : case JCS_EXT_RGBA:
380 : extrgbx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
381 : output_buf);
382 0 : break;
383 : case JCS_EXT_BGR:
384 : extbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
385 : output_buf);
386 0 : break;
387 : case JCS_EXT_BGRX:
388 : case JCS_EXT_BGRA:
389 : extbgrx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
390 : output_buf);
391 0 : break;
392 : case JCS_EXT_XBGR:
393 : case JCS_EXT_ABGR:
394 : extxbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
395 : output_buf);
396 0 : break;
397 : case JCS_EXT_XRGB:
398 : case JCS_EXT_ARGB:
399 : extxrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
400 : output_buf);
401 0 : break;
402 : default:
403 : h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
404 : output_buf);
405 0 : break;
406 : }
407 0 : }
408 :
409 :
410 : /*
411 : * Module initialization routine for merged upsampling/color conversion.
412 : *
413 : * NB: this is called under the conditions determined by use_merged_upsample()
414 : * in jdmaster.c. That routine MUST correspond to the actual capabilities
415 : * of this module; no safety checks are made here.
416 : */
417 :
418 : GLOBAL(void)
419 0 : jinit_merged_upsampler (j_decompress_ptr cinfo)
420 : {
421 : my_upsample_ptr upsample;
422 :
423 0 : upsample = (my_upsample_ptr)
424 0 : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
425 : SIZEOF(my_upsampler));
426 0 : cinfo->upsample = (struct jpeg_upsampler *) upsample;
427 0 : upsample->pub.start_pass = start_pass_merged_upsample;
428 0 : upsample->pub.need_context_rows = FALSE;
429 :
430 0 : upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
431 :
432 0 : if (cinfo->max_v_samp_factor == 2) {
433 0 : upsample->pub.upsample = merged_2v_upsample;
434 0 : if (jsimd_can_h2v2_merged_upsample())
435 0 : upsample->upmethod = jsimd_h2v2_merged_upsample;
436 : else
437 0 : upsample->upmethod = h2v2_merged_upsample;
438 : /* Allocate a spare row buffer */
439 0 : upsample->spare_row = (JSAMPROW)
440 0 : (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
441 : (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
442 : } else {
443 0 : upsample->pub.upsample = merged_1v_upsample;
444 0 : if (jsimd_can_h2v1_merged_upsample())
445 0 : upsample->upmethod = jsimd_h2v1_merged_upsample;
446 : else
447 0 : upsample->upmethod = h2v1_merged_upsample;
448 : /* No spare row needed */
449 0 : upsample->spare_row = NULL;
450 : }
451 :
452 0 : build_ycc_rgb_table(cinfo);
453 0 : }
454 :
455 : #endif /* UPSAMPLE_MERGING_SUPPORTED */
|