1 : /*
2 : * jdcolor.c
3 : *
4 : * Copyright (C) 1991-1997, 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 output colorspace conversion routines.
11 : */
12 :
13 : #define JPEG_INTERNALS
14 : #include "jinclude.h"
15 : #include "jpeglib.h"
16 : #include "jsimd.h"
17 : #include "config.h"
18 :
19 :
20 : /* Private subobject */
21 :
22 : typedef struct {
23 : struct jpeg_color_deconverter pub; /* public fields */
24 :
25 : /* Private state for YCC->RGB conversion */
26 : int * Cr_r_tab; /* => table for Cr to R conversion */
27 : int * Cb_b_tab; /* => table for Cb to B conversion */
28 : INT32 * Cr_g_tab; /* => table for Cr to G conversion */
29 : INT32 * Cb_g_tab; /* => table for Cb to G conversion */
30 : } my_color_deconverter;
31 :
32 : typedef my_color_deconverter * my_cconvert_ptr;
33 :
34 :
35 : /**************** YCbCr -> RGB conversion: most common case **************/
36 :
37 : /*
38 : * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
39 : * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
40 : * The conversion equations to be implemented are therefore
41 : * R = Y + 1.40200 * Cr
42 : * G = Y - 0.34414 * Cb - 0.71414 * Cr
43 : * B = Y + 1.77200 * Cb
44 : * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
45 : * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
46 : *
47 : * To avoid floating-point arithmetic, we represent the fractional constants
48 : * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
49 : * the products by 2^16, with appropriate rounding, to get the correct answer.
50 : * Notice that Y, being an integral input, does not contribute any fraction
51 : * so it need not participate in the rounding.
52 : *
53 : * For even more speed, we avoid doing any multiplications in the inner loop
54 : * by precalculating the constants times Cb and Cr for all possible values.
55 : * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
56 : * for 12-bit samples it is still acceptable. It's not very reasonable for
57 : * 16-bit samples, but if you want lossless storage you shouldn't be changing
58 : * colorspace anyway.
59 : * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
60 : * values for the G calculation are left scaled up, since we must add them
61 : * together before rounding.
62 : */
63 :
64 : #define SCALEBITS 16 /* speediest right-shift on some machines */
65 : #define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
66 : #define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
67 :
68 :
69 : /* Include inline routines for colorspace extensions */
70 :
71 : #include "jdcolext.c"
72 : #undef RGB_RED
73 : #undef RGB_GREEN
74 : #undef RGB_BLUE
75 : #undef RGB_PIXELSIZE
76 :
77 : #define RGB_RED EXT_RGB_RED
78 : #define RGB_GREEN EXT_RGB_GREEN
79 : #define RGB_BLUE EXT_RGB_BLUE
80 : #define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
81 : #define ycc_rgb_convert_internal ycc_extrgb_convert_internal
82 : #define gray_rgb_convert_internal gray_extrgb_convert_internal
83 : #include "jdcolext.c"
84 : #undef RGB_RED
85 : #undef RGB_GREEN
86 : #undef RGB_BLUE
87 : #undef RGB_PIXELSIZE
88 : #undef ycc_rgb_convert_internal
89 : #undef gray_rgb_convert_internal
90 :
91 : #define RGB_RED EXT_RGBX_RED
92 : #define RGB_GREEN EXT_RGBX_GREEN
93 : #define RGB_BLUE EXT_RGBX_BLUE
94 : #define RGB_ALPHA 3
95 : #define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
96 : #define ycc_rgb_convert_internal ycc_extrgbx_convert_internal
97 : #define gray_rgb_convert_internal gray_extrgbx_convert_internal
98 : #include "jdcolext.c"
99 : #undef RGB_RED
100 : #undef RGB_GREEN
101 : #undef RGB_BLUE
102 : #undef RGB_ALPHA
103 : #undef RGB_PIXELSIZE
104 : #undef ycc_rgb_convert_internal
105 : #undef gray_rgb_convert_internal
106 :
107 : #define RGB_RED EXT_BGR_RED
108 : #define RGB_GREEN EXT_BGR_GREEN
109 : #define RGB_BLUE EXT_BGR_BLUE
110 : #define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
111 : #define ycc_rgb_convert_internal ycc_extbgr_convert_internal
112 : #define gray_rgb_convert_internal gray_extbgr_convert_internal
113 : #include "jdcolext.c"
114 : #undef RGB_RED
115 : #undef RGB_GREEN
116 : #undef RGB_BLUE
117 : #undef RGB_PIXELSIZE
118 : #undef ycc_rgb_convert_internal
119 : #undef gray_rgb_convert_internal
120 :
121 : #define RGB_RED EXT_BGRX_RED
122 : #define RGB_GREEN EXT_BGRX_GREEN
123 : #define RGB_BLUE EXT_BGRX_BLUE
124 : #define RGB_ALPHA 3
125 : #define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
126 : #define ycc_rgb_convert_internal ycc_extbgrx_convert_internal
127 : #define gray_rgb_convert_internal gray_extbgrx_convert_internal
128 : #include "jdcolext.c"
129 : #undef RGB_RED
130 : #undef RGB_GREEN
131 : #undef RGB_BLUE
132 : #undef RGB_ALPHA
133 : #undef RGB_PIXELSIZE
134 : #undef ycc_rgb_convert_internal
135 : #undef gray_rgb_convert_internal
136 :
137 : #define RGB_RED EXT_XBGR_RED
138 : #define RGB_GREEN EXT_XBGR_GREEN
139 : #define RGB_BLUE EXT_XBGR_BLUE
140 : #define RGB_ALPHA 0
141 : #define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
142 : #define ycc_rgb_convert_internal ycc_extxbgr_convert_internal
143 : #define gray_rgb_convert_internal gray_extxbgr_convert_internal
144 : #include "jdcolext.c"
145 : #undef RGB_RED
146 : #undef RGB_GREEN
147 : #undef RGB_BLUE
148 : #undef RGB_ALPHA
149 : #undef RGB_PIXELSIZE
150 : #undef ycc_rgb_convert_internal
151 : #undef gray_rgb_convert_internal
152 :
153 : #define RGB_RED EXT_XRGB_RED
154 : #define RGB_GREEN EXT_XRGB_GREEN
155 : #define RGB_BLUE EXT_XRGB_BLUE
156 : #define RGB_ALPHA 0
157 : #define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
158 : #define ycc_rgb_convert_internal ycc_extxrgb_convert_internal
159 : #define gray_rgb_convert_internal gray_extxrgb_convert_internal
160 : #include "jdcolext.c"
161 : #undef RGB_RED
162 : #undef RGB_GREEN
163 : #undef RGB_BLUE
164 : #undef RGB_ALPHA
165 : #undef RGB_PIXELSIZE
166 : #undef ycc_rgb_convert_internal
167 : #undef gray_rgb_convert_internal
168 :
169 :
170 : /*
171 : * Initialize tables for YCC->RGB colorspace conversion.
172 : */
173 :
174 : LOCAL(void)
175 0 : build_ycc_rgb_table (j_decompress_ptr cinfo)
176 : {
177 0 : my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
178 : int i;
179 : INT32 x;
180 : SHIFT_TEMPS
181 :
182 0 : cconvert->Cr_r_tab = (int *)
183 0 : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
184 : (MAXJSAMPLE+1) * SIZEOF(int));
185 0 : cconvert->Cb_b_tab = (int *)
186 0 : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
187 : (MAXJSAMPLE+1) * SIZEOF(int));
188 0 : cconvert->Cr_g_tab = (INT32 *)
189 0 : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
190 : (MAXJSAMPLE+1) * SIZEOF(INT32));
191 0 : cconvert->Cb_g_tab = (INT32 *)
192 0 : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
193 : (MAXJSAMPLE+1) * SIZEOF(INT32));
194 :
195 0 : for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
196 : /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
197 : /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
198 : /* Cr=>R value is nearest int to 1.40200 * x */
199 0 : cconvert->Cr_r_tab[i] = (int)
200 0 : RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
201 : /* Cb=>B value is nearest int to 1.77200 * x */
202 0 : cconvert->Cb_b_tab[i] = (int)
203 0 : RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
204 : /* Cr=>G value is scaled-up -0.71414 * x */
205 0 : cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
206 : /* Cb=>G value is scaled-up -0.34414 * x */
207 : /* We also add in ONE_HALF so that need not do it in inner loop */
208 0 : cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
209 : }
210 0 : }
211 :
212 :
213 : /*
214 : * Convert some rows of samples to the output colorspace.
215 : */
216 :
217 : METHODDEF(void)
218 0 : ycc_rgb_convert (j_decompress_ptr cinfo,
219 : JSAMPIMAGE input_buf, JDIMENSION input_row,
220 : JSAMPARRAY output_buf, int num_rows)
221 : {
222 0 : switch (cinfo->out_color_space) {
223 : case JCS_EXT_RGB:
224 : ycc_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
225 : num_rows);
226 0 : break;
227 : case JCS_EXT_RGBX:
228 : case JCS_EXT_RGBA:
229 : ycc_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
230 : num_rows);
231 0 : break;
232 : case JCS_EXT_BGR:
233 : ycc_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
234 : num_rows);
235 0 : break;
236 : case JCS_EXT_BGRX:
237 : case JCS_EXT_BGRA:
238 : ycc_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
239 : num_rows);
240 0 : break;
241 : case JCS_EXT_XBGR:
242 : case JCS_EXT_ABGR:
243 : ycc_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
244 : num_rows);
245 0 : break;
246 : case JCS_EXT_XRGB:
247 : case JCS_EXT_ARGB:
248 : ycc_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
249 : num_rows);
250 0 : break;
251 : default:
252 : ycc_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
253 : num_rows);
254 0 : break;
255 : }
256 0 : }
257 :
258 :
259 : /**************** Cases other than YCbCr -> RGB **************/
260 :
261 :
262 : /*
263 : * Color conversion for no colorspace change: just copy the data,
264 : * converting from separate-planes to interleaved representation.
265 : */
266 :
267 : METHODDEF(void)
268 0 : null_convert (j_decompress_ptr cinfo,
269 : JSAMPIMAGE input_buf, JDIMENSION input_row,
270 : JSAMPARRAY output_buf, int num_rows)
271 : {
272 : register JSAMPROW inptr, outptr;
273 : register JDIMENSION count;
274 0 : register int num_components = cinfo->num_components;
275 0 : JDIMENSION num_cols = cinfo->output_width;
276 : int ci;
277 :
278 0 : while (--num_rows >= 0) {
279 0 : for (ci = 0; ci < num_components; ci++) {
280 0 : inptr = input_buf[ci][input_row];
281 0 : outptr = output_buf[0] + ci;
282 0 : for (count = num_cols; count > 0; count--) {
283 0 : *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */
284 0 : outptr += num_components;
285 : }
286 : }
287 0 : input_row++;
288 0 : output_buf++;
289 : }
290 0 : }
291 :
292 :
293 : /*
294 : * Color conversion for grayscale: just copy the data.
295 : * This also works for YCbCr -> grayscale conversion, in which
296 : * we just copy the Y (luminance) component and ignore chrominance.
297 : */
298 :
299 : METHODDEF(void)
300 0 : grayscale_convert (j_decompress_ptr cinfo,
301 : JSAMPIMAGE input_buf, JDIMENSION input_row,
302 : JSAMPARRAY output_buf, int num_rows)
303 : {
304 0 : jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
305 : num_rows, cinfo->output_width);
306 0 : }
307 :
308 :
309 : /*
310 : * Convert grayscale to RGB
311 : */
312 :
313 : METHODDEF(void)
314 0 : gray_rgb_convert (j_decompress_ptr cinfo,
315 : JSAMPIMAGE input_buf, JDIMENSION input_row,
316 : JSAMPARRAY output_buf, int num_rows)
317 : {
318 0 : switch (cinfo->out_color_space) {
319 : case JCS_EXT_RGB:
320 : gray_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
321 : num_rows);
322 0 : break;
323 : case JCS_EXT_RGBX:
324 : case JCS_EXT_RGBA:
325 : gray_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
326 : num_rows);
327 0 : break;
328 : case JCS_EXT_BGR:
329 : gray_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
330 : num_rows);
331 0 : break;
332 : case JCS_EXT_BGRX:
333 : case JCS_EXT_BGRA:
334 : gray_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
335 : num_rows);
336 0 : break;
337 : case JCS_EXT_XBGR:
338 : case JCS_EXT_ABGR:
339 : gray_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
340 : num_rows);
341 0 : break;
342 : case JCS_EXT_XRGB:
343 : case JCS_EXT_ARGB:
344 : gray_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
345 : num_rows);
346 0 : break;
347 : default:
348 : gray_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
349 : num_rows);
350 0 : break;
351 : }
352 0 : }
353 :
354 :
355 : /*
356 : * Adobe-style YCCK->CMYK conversion.
357 : * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
358 : * conversion as above, while passing K (black) unchanged.
359 : * We assume build_ycc_rgb_table has been called.
360 : */
361 :
362 : METHODDEF(void)
363 0 : ycck_cmyk_convert (j_decompress_ptr cinfo,
364 : JSAMPIMAGE input_buf, JDIMENSION input_row,
365 : JSAMPARRAY output_buf, int num_rows)
366 : {
367 0 : my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
368 : register int y, cb, cr;
369 : register JSAMPROW outptr;
370 : register JSAMPROW inptr0, inptr1, inptr2, inptr3;
371 : register JDIMENSION col;
372 0 : JDIMENSION num_cols = cinfo->output_width;
373 : /* copy these pointers into registers if possible */
374 0 : register JSAMPLE * range_limit = cinfo->sample_range_limit;
375 0 : register int * Crrtab = cconvert->Cr_r_tab;
376 0 : register int * Cbbtab = cconvert->Cb_b_tab;
377 0 : register INT32 * Crgtab = cconvert->Cr_g_tab;
378 0 : register INT32 * Cbgtab = cconvert->Cb_g_tab;
379 : SHIFT_TEMPS
380 :
381 0 : while (--num_rows >= 0) {
382 0 : inptr0 = input_buf[0][input_row];
383 0 : inptr1 = input_buf[1][input_row];
384 0 : inptr2 = input_buf[2][input_row];
385 0 : inptr3 = input_buf[3][input_row];
386 0 : input_row++;
387 0 : outptr = *output_buf++;
388 0 : for (col = 0; col < num_cols; col++) {
389 0 : y = GETJSAMPLE(inptr0[col]);
390 0 : cb = GETJSAMPLE(inptr1[col]);
391 0 : cr = GETJSAMPLE(inptr2[col]);
392 : /* Range-limiting is essential due to noise introduced by DCT losses. */
393 0 : outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
394 0 : outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
395 0 : ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
396 : SCALEBITS)))];
397 0 : outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
398 : /* K passes through unchanged */
399 0 : outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
400 0 : outptr += 4;
401 : }
402 : }
403 0 : }
404 :
405 :
406 : /*
407 : * Empty method for start_pass.
408 : */
409 :
410 : METHODDEF(void)
411 5 : start_pass_dcolor (j_decompress_ptr cinfo)
412 : {
413 : /* no work needed */
414 5 : }
415 :
416 :
417 : /*
418 : * Module initialization routine for output colorspace conversion.
419 : */
420 :
421 : GLOBAL(void)
422 5 : jinit_color_deconverter (j_decompress_ptr cinfo)
423 : {
424 : my_cconvert_ptr cconvert;
425 : int ci;
426 :
427 5 : cconvert = (my_cconvert_ptr)
428 5 : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
429 : SIZEOF(my_color_deconverter));
430 5 : cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
431 5 : cconvert->pub.start_pass = start_pass_dcolor;
432 :
433 : /* Make sure num_components agrees with jpeg_color_space */
434 5 : switch (cinfo->jpeg_color_space) {
435 : case JCS_GRAYSCALE:
436 0 : if (cinfo->num_components != 1)
437 0 : ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
438 0 : break;
439 :
440 : case JCS_RGB:
441 : case JCS_YCbCr:
442 5 : if (cinfo->num_components != 3)
443 0 : ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
444 5 : break;
445 :
446 : case JCS_CMYK:
447 : case JCS_YCCK:
448 0 : if (cinfo->num_components != 4)
449 0 : ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
450 0 : break;
451 :
452 : default: /* JCS_UNKNOWN can be anything */
453 0 : if (cinfo->num_components < 1)
454 0 : ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
455 0 : break;
456 : }
457 :
458 : /* Set out_color_components and conversion method based on requested space.
459 : * Also clear the component_needed flags for any unused components,
460 : * so that earlier pipeline stages can avoid useless computation.
461 : */
462 :
463 5 : switch (cinfo->out_color_space) {
464 : case JCS_GRAYSCALE:
465 0 : cinfo->out_color_components = 1;
466 0 : if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
467 0 : cinfo->jpeg_color_space == JCS_YCbCr) {
468 0 : cconvert->pub.color_convert = grayscale_convert;
469 : /* For color->grayscale conversion, only the Y (0) component is needed */
470 0 : for (ci = 1; ci < cinfo->num_components; ci++)
471 0 : cinfo->comp_info[ci].component_needed = FALSE;
472 : } else
473 0 : ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
474 0 : break;
475 :
476 : case JCS_RGB:
477 : case JCS_EXT_RGB:
478 : case JCS_EXT_RGBX:
479 : case JCS_EXT_BGR:
480 : case JCS_EXT_BGRX:
481 : case JCS_EXT_XBGR:
482 : case JCS_EXT_XRGB:
483 : case JCS_EXT_RGBA:
484 : case JCS_EXT_BGRA:
485 : case JCS_EXT_ABGR:
486 : case JCS_EXT_ARGB:
487 5 : cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space];
488 5 : if (cinfo->jpeg_color_space == JCS_YCbCr) {
489 5 : if (jsimd_can_ycc_rgb())
490 5 : cconvert->pub.color_convert = jsimd_ycc_rgb_convert;
491 : else {
492 0 : cconvert->pub.color_convert = ycc_rgb_convert;
493 0 : build_ycc_rgb_table(cinfo);
494 : }
495 0 : } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
496 0 : cconvert->pub.color_convert = gray_rgb_convert;
497 0 : } else if (cinfo->jpeg_color_space == cinfo->out_color_space &&
498 0 : rgb_pixelsize[cinfo->out_color_space] == 3) {
499 0 : cconvert->pub.color_convert = null_convert;
500 : } else
501 0 : ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
502 5 : break;
503 :
504 : case JCS_CMYK:
505 0 : cinfo->out_color_components = 4;
506 0 : if (cinfo->jpeg_color_space == JCS_YCCK) {
507 0 : cconvert->pub.color_convert = ycck_cmyk_convert;
508 0 : build_ycc_rgb_table(cinfo);
509 0 : } else if (cinfo->jpeg_color_space == JCS_CMYK) {
510 0 : cconvert->pub.color_convert = null_convert;
511 : } else
512 0 : ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
513 0 : break;
514 :
515 : default:
516 : /* Permit null conversion to same output space */
517 0 : if (cinfo->out_color_space == cinfo->jpeg_color_space) {
518 0 : cinfo->out_color_components = cinfo->num_components;
519 0 : cconvert->pub.color_convert = null_convert;
520 : } else /* unsupported non-null conversion */
521 0 : ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
522 0 : break;
523 : }
524 :
525 5 : if (cinfo->quantize_colors)
526 0 : cinfo->output_components = 1; /* single colormapped output component */
527 : else
528 5 : cinfo->output_components = cinfo->out_color_components;
529 5 : }
|