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