• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * jccolor.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) 2009-2012, 2015, D. R. Commander.
9  * Copyright (C) 2014, MIPS Technologies, Inc., California.
10  * For conditions of distribution and use, see the accompanying README.ijg
11  * file.
12  *
13  * This file contains input colorspace conversion routines.
14  */
15 
16 #define JPEG_INTERNALS
17 #include "jinclude.h"
18 #include "jpeglib.h"
19 #include "jsimd.h"
20 #include "jconfigint.h"
21 
22 
23 /* Private subobject */
24 
25 typedef struct {
26   struct jpeg_color_converter pub; /* public fields */
27 
28   /* Private state for RGB->YCC conversion */
29   JLONG *rgb_ycc_tab;           /* => table for RGB to YCbCr conversion */
30 } my_color_converter;
31 
32 typedef my_color_converter *my_cconvert_ptr;
33 
34 
35 /**************** RGB -> YCbCr 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  *      Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
42  *      Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B  + CENTERJSAMPLE
43  *      Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B  + CENTERJSAMPLE
44  * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
45  * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
46  * rather than CENTERJSAMPLE, for Cb and Cr.  This gave equal positive and
47  * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
48  * were not represented exactly.  Now we sacrifice exact representation of
49  * maximum red and maximum blue in order to get exact grayscales.
50  *
51  * To avoid floating-point arithmetic, we represent the fractional constants
52  * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
53  * the products by 2^16, with appropriate rounding, to get the correct answer.
54  *
55  * For even more speed, we avoid doing any multiplications in the inner loop
56  * by precalculating the constants times R,G,B for all possible values.
57  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
58  * for 12-bit samples it is still acceptable.  It's not very reasonable for
59  * 16-bit samples, but if you want lossless storage you shouldn't be changing
60  * colorspace anyway.
61  * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
62  * in the tables to save adding them separately in the inner loop.
63  */
64 
65 #define SCALEBITS       16      /* speediest right-shift on some machines */
66 #define CBCR_OFFSET     ((JLONG)CENTERJSAMPLE << SCALEBITS)
67 #define ONE_HALF        ((JLONG)1 << (SCALEBITS - 1))
68 #define FIX(x)          ((JLONG)((x) * (1L << SCALEBITS) + 0.5))
69 
70 /* We allocate one big table and divide it up into eight parts, instead of
71  * doing eight alloc_small requests.  This lets us use a single table base
72  * address, which can be held in a register in the inner loops on many
73  * machines (more than can hold all eight addresses, anyway).
74  */
75 
76 #define R_Y_OFF         0                       /* offset to R => Y section */
77 #define G_Y_OFF         (1 * (MAXJSAMPLE + 1))  /* offset to G => Y section */
78 #define B_Y_OFF         (2 * (MAXJSAMPLE + 1))  /* etc. */
79 #define R_CB_OFF        (3 * (MAXJSAMPLE + 1))
80 #define G_CB_OFF        (4 * (MAXJSAMPLE + 1))
81 #define B_CB_OFF        (5 * (MAXJSAMPLE + 1))
82 #define R_CR_OFF        B_CB_OFF                /* B=>Cb, R=>Cr are the same */
83 #define G_CR_OFF        (6 * (MAXJSAMPLE + 1))
84 #define B_CR_OFF        (7 * (MAXJSAMPLE + 1))
85 #define TABLE_SIZE      (8 * (MAXJSAMPLE + 1))
86 
87 
88 /* Include inline routines for colorspace extensions */
89 
90 #include "jccolext.c"
91 #undef RGB_RED
92 #undef RGB_GREEN
93 #undef RGB_BLUE
94 #undef RGB_PIXELSIZE
95 
96 #define RGB_RED  EXT_RGB_RED
97 #define RGB_GREEN  EXT_RGB_GREEN
98 #define RGB_BLUE  EXT_RGB_BLUE
99 #define RGB_PIXELSIZE  EXT_RGB_PIXELSIZE
100 #define rgb_ycc_convert_internal  extrgb_ycc_convert_internal
101 #define rgb_gray_convert_internal  extrgb_gray_convert_internal
102 #define rgb_rgb_convert_internal  extrgb_rgb_convert_internal
103 #include "jccolext.c"
104 #undef RGB_RED
105 #undef RGB_GREEN
106 #undef RGB_BLUE
107 #undef RGB_PIXELSIZE
108 #undef rgb_ycc_convert_internal
109 #undef rgb_gray_convert_internal
110 #undef rgb_rgb_convert_internal
111 
112 #define RGB_RED  EXT_RGBX_RED
113 #define RGB_GREEN  EXT_RGBX_GREEN
114 #define RGB_BLUE  EXT_RGBX_BLUE
115 #define RGB_PIXELSIZE  EXT_RGBX_PIXELSIZE
116 #define rgb_ycc_convert_internal  extrgbx_ycc_convert_internal
117 #define rgb_gray_convert_internal  extrgbx_gray_convert_internal
118 #define rgb_rgb_convert_internal  extrgbx_rgb_convert_internal
119 #include "jccolext.c"
120 #undef RGB_RED
121 #undef RGB_GREEN
122 #undef RGB_BLUE
123 #undef RGB_PIXELSIZE
124 #undef rgb_ycc_convert_internal
125 #undef rgb_gray_convert_internal
126 #undef rgb_rgb_convert_internal
127 
128 #define RGB_RED  EXT_BGR_RED
129 #define RGB_GREEN  EXT_BGR_GREEN
130 #define RGB_BLUE  EXT_BGR_BLUE
131 #define RGB_PIXELSIZE  EXT_BGR_PIXELSIZE
132 #define rgb_ycc_convert_internal  extbgr_ycc_convert_internal
133 #define rgb_gray_convert_internal  extbgr_gray_convert_internal
134 #define rgb_rgb_convert_internal  extbgr_rgb_convert_internal
135 #include "jccolext.c"
136 #undef RGB_RED
137 #undef RGB_GREEN
138 #undef RGB_BLUE
139 #undef RGB_PIXELSIZE
140 #undef rgb_ycc_convert_internal
141 #undef rgb_gray_convert_internal
142 #undef rgb_rgb_convert_internal
143 
144 #define RGB_RED  EXT_BGRX_RED
145 #define RGB_GREEN  EXT_BGRX_GREEN
146 #define RGB_BLUE  EXT_BGRX_BLUE
147 #define RGB_PIXELSIZE  EXT_BGRX_PIXELSIZE
148 #define rgb_ycc_convert_internal  extbgrx_ycc_convert_internal
149 #define rgb_gray_convert_internal  extbgrx_gray_convert_internal
150 #define rgb_rgb_convert_internal  extbgrx_rgb_convert_internal
151 #include "jccolext.c"
152 #undef RGB_RED
153 #undef RGB_GREEN
154 #undef RGB_BLUE
155 #undef RGB_PIXELSIZE
156 #undef rgb_ycc_convert_internal
157 #undef rgb_gray_convert_internal
158 #undef rgb_rgb_convert_internal
159 
160 #define RGB_RED  EXT_XBGR_RED
161 #define RGB_GREEN  EXT_XBGR_GREEN
162 #define RGB_BLUE  EXT_XBGR_BLUE
163 #define RGB_PIXELSIZE  EXT_XBGR_PIXELSIZE
164 #define rgb_ycc_convert_internal  extxbgr_ycc_convert_internal
165 #define rgb_gray_convert_internal  extxbgr_gray_convert_internal
166 #define rgb_rgb_convert_internal  extxbgr_rgb_convert_internal
167 #include "jccolext.c"
168 #undef RGB_RED
169 #undef RGB_GREEN
170 #undef RGB_BLUE
171 #undef RGB_PIXELSIZE
172 #undef rgb_ycc_convert_internal
173 #undef rgb_gray_convert_internal
174 #undef rgb_rgb_convert_internal
175 
176 #define RGB_RED  EXT_XRGB_RED
177 #define RGB_GREEN  EXT_XRGB_GREEN
178 #define RGB_BLUE  EXT_XRGB_BLUE
179 #define RGB_PIXELSIZE  EXT_XRGB_PIXELSIZE
180 #define rgb_ycc_convert_internal  extxrgb_ycc_convert_internal
181 #define rgb_gray_convert_internal  extxrgb_gray_convert_internal
182 #define rgb_rgb_convert_internal  extxrgb_rgb_convert_internal
183 #include "jccolext.c"
184 #undef RGB_RED
185 #undef RGB_GREEN
186 #undef RGB_BLUE
187 #undef RGB_PIXELSIZE
188 #undef rgb_ycc_convert_internal
189 #undef rgb_gray_convert_internal
190 #undef rgb_rgb_convert_internal
191 
192 
193 /*
194  * Initialize for RGB->YCC colorspace conversion.
195  */
196 
197 METHODDEF(void)
rgb_ycc_start(j_compress_ptr cinfo)198 rgb_ycc_start(j_compress_ptr cinfo)
199 {
200   my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
201   JLONG *rgb_ycc_tab;
202   JLONG i;
203 
204   /* Allocate and fill in the conversion tables. */
205   cconvert->rgb_ycc_tab = rgb_ycc_tab = (JLONG *)
206     (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
207                                 (TABLE_SIZE * sizeof(JLONG)));
208 
209   for (i = 0; i <= MAXJSAMPLE; i++) {
210     rgb_ycc_tab[i + R_Y_OFF] = FIX(0.29900) * i;
211     rgb_ycc_tab[i + G_Y_OFF] = FIX(0.58700) * i;
212     rgb_ycc_tab[i + B_Y_OFF] = FIX(0.11400) * i   + ONE_HALF;
213     rgb_ycc_tab[i + R_CB_OFF] = (-FIX(0.16874)) * i;
214     rgb_ycc_tab[i + G_CB_OFF] = (-FIX(0.33126)) * i;
215     /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
216      * This ensures that the maximum output will round to MAXJSAMPLE
217      * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
218      */
219     rgb_ycc_tab[i + B_CB_OFF] = FIX(0.50000) * i  + CBCR_OFFSET + ONE_HALF - 1;
220 /*  B=>Cb and R=>Cr tables are the same
221     rgb_ycc_tab[i + R_CR_OFF] = FIX(0.50000) * i  + CBCR_OFFSET + ONE_HALF - 1;
222 */
223     rgb_ycc_tab[i + G_CR_OFF] = (-FIX(0.41869)) * i;
224     rgb_ycc_tab[i + B_CR_OFF] = (-FIX(0.08131)) * i;
225   }
226 }
227 
228 
229 /*
230  * Convert some rows of samples to the JPEG colorspace.
231  */
232 
233 METHODDEF(void)
rgb_ycc_convert(j_compress_ptr cinfo,JSAMPARRAY input_buf,JSAMPIMAGE output_buf,JDIMENSION output_row,int num_rows)234 rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
235                 JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
236 {
237   switch (cinfo->in_color_space) {
238   case JCS_EXT_RGB:
239     extrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
240                                 num_rows);
241     break;
242   case JCS_EXT_RGBX:
243   case JCS_EXT_RGBA:
244     extrgbx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
245                                  num_rows);
246     break;
247   case JCS_EXT_BGR:
248     extbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
249                                 num_rows);
250     break;
251   case JCS_EXT_BGRX:
252   case JCS_EXT_BGRA:
253     extbgrx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
254                                  num_rows);
255     break;
256   case JCS_EXT_XBGR:
257   case JCS_EXT_ABGR:
258     extxbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
259                                  num_rows);
260     break;
261   case JCS_EXT_XRGB:
262   case JCS_EXT_ARGB:
263     extxrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
264                                  num_rows);
265     break;
266   default:
267     rgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
268                              num_rows);
269     break;
270   }
271 }
272 
273 
274 /**************** Cases other than RGB -> YCbCr **************/
275 
276 
277 /*
278  * Convert some rows of samples to the JPEG colorspace.
279  */
280 
281 METHODDEF(void)
rgb_gray_convert(j_compress_ptr cinfo,JSAMPARRAY input_buf,JSAMPIMAGE output_buf,JDIMENSION output_row,int num_rows)282 rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
283                  JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
284 {
285   switch (cinfo->in_color_space) {
286   case JCS_EXT_RGB:
287     extrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
288                                  num_rows);
289     break;
290   case JCS_EXT_RGBX:
291   case JCS_EXT_RGBA:
292     extrgbx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
293                                   num_rows);
294     break;
295   case JCS_EXT_BGR:
296     extbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
297                                  num_rows);
298     break;
299   case JCS_EXT_BGRX:
300   case JCS_EXT_BGRA:
301     extbgrx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
302                                   num_rows);
303     break;
304   case JCS_EXT_XBGR:
305   case JCS_EXT_ABGR:
306     extxbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
307                                   num_rows);
308     break;
309   case JCS_EXT_XRGB:
310   case JCS_EXT_ARGB:
311     extxrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
312                                   num_rows);
313     break;
314   default:
315     rgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
316                               num_rows);
317     break;
318   }
319 }
320 
321 
322 /*
323  * Extended RGB to plain RGB conversion
324  */
325 
326 METHODDEF(void)
rgb_rgb_convert(j_compress_ptr cinfo,JSAMPARRAY input_buf,JSAMPIMAGE output_buf,JDIMENSION output_row,int num_rows)327 rgb_rgb_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
328                 JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
329 {
330   switch (cinfo->in_color_space) {
331   case JCS_EXT_RGB:
332     extrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
333                                 num_rows);
334     break;
335   case JCS_EXT_RGBX:
336   case JCS_EXT_RGBA:
337     extrgbx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
338                                  num_rows);
339     break;
340   case JCS_EXT_BGR:
341     extbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
342                                 num_rows);
343     break;
344   case JCS_EXT_BGRX:
345   case JCS_EXT_BGRA:
346     extbgrx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
347                                  num_rows);
348     break;
349   case JCS_EXT_XBGR:
350   case JCS_EXT_ABGR:
351     extxbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
352                                  num_rows);
353     break;
354   case JCS_EXT_XRGB:
355   case JCS_EXT_ARGB:
356     extxrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
357                                  num_rows);
358     break;
359   default:
360     rgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
361                              num_rows);
362     break;
363   }
364 }
365 
366 
367 /*
368  * Convert some rows of samples to the JPEG colorspace.
369  * This version handles Adobe-style CMYK->YCCK conversion,
370  * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
371  * conversion as above, while passing K (black) unchanged.
372  * We assume rgb_ycc_start has been called.
373  */
374 
375 METHODDEF(void)
cmyk_ycck_convert(j_compress_ptr cinfo,JSAMPARRAY input_buf,JSAMPIMAGE output_buf,JDIMENSION output_row,int num_rows)376 cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
377                   JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
378 {
379   my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
380   register int r, g, b;
381   register JLONG *ctab = cconvert->rgb_ycc_tab;
382   register JSAMPROW inptr;
383   register JSAMPROW outptr0, outptr1, outptr2, outptr3;
384   register JDIMENSION col;
385   JDIMENSION num_cols = cinfo->image_width;
386 
387   while (--num_rows >= 0) {
388     inptr = *input_buf++;
389     outptr0 = output_buf[0][output_row];
390     outptr1 = output_buf[1][output_row];
391     outptr2 = output_buf[2][output_row];
392     outptr3 = output_buf[3][output_row];
393     output_row++;
394     for (col = 0; col < num_cols; col++) {
395       r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
396       g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
397       b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
398       /* K passes through as-is */
399       outptr3[col] = inptr[3];  /* don't need GETJSAMPLE here */
400       inptr += 4;
401       /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
402        * must be too; we do not need an explicit range-limiting operation.
403        * Hence the value being shifted is never negative, and we don't
404        * need the general RIGHT_SHIFT macro.
405        */
406       /* Y */
407       outptr0[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
408                                 ctab[b + B_Y_OFF]) >> SCALEBITS);
409       /* Cb */
410       outptr1[col] = (JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] +
411                                 ctab[b + B_CB_OFF]) >> SCALEBITS);
412       /* Cr */
413       outptr2[col] = (JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] +
414                                 ctab[b + B_CR_OFF]) >> SCALEBITS);
415     }
416   }
417 }
418 
419 
420 /*
421  * Convert some rows of samples to the JPEG colorspace.
422  * This version handles grayscale output with no conversion.
423  * The source can be either plain grayscale or YCbCr (since Y == gray).
424  */
425 
426 METHODDEF(void)
grayscale_convert(j_compress_ptr cinfo,JSAMPARRAY input_buf,JSAMPIMAGE output_buf,JDIMENSION output_row,int num_rows)427 grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
428                   JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
429 {
430   register JSAMPROW inptr;
431   register JSAMPROW outptr;
432   register JDIMENSION col;
433   JDIMENSION num_cols = cinfo->image_width;
434   int instride = cinfo->input_components;
435 
436   while (--num_rows >= 0) {
437     inptr = *input_buf++;
438     outptr = output_buf[0][output_row];
439     output_row++;
440     for (col = 0; col < num_cols; col++) {
441       outptr[col] = inptr[0];   /* don't need GETJSAMPLE() here */
442       inptr += instride;
443     }
444   }
445 }
446 
447 
448 /*
449  * Convert some rows of samples to the JPEG colorspace.
450  * This version handles multi-component colorspaces without conversion.
451  * We assume input_components == num_components.
452  */
453 
454 METHODDEF(void)
null_convert(j_compress_ptr cinfo,JSAMPARRAY input_buf,JSAMPIMAGE output_buf,JDIMENSION output_row,int num_rows)455 null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
456              JDIMENSION output_row, int num_rows)
457 {
458   register JSAMPROW inptr;
459   register JSAMPROW outptr, outptr0, outptr1, outptr2, outptr3;
460   register JDIMENSION col;
461   register int ci;
462   int nc = cinfo->num_components;
463   JDIMENSION num_cols = cinfo->image_width;
464 
465   if (nc == 3) {
466     while (--num_rows >= 0) {
467       inptr = *input_buf++;
468       outptr0 = output_buf[0][output_row];
469       outptr1 = output_buf[1][output_row];
470       outptr2 = output_buf[2][output_row];
471       output_row++;
472       for (col = 0; col < num_cols; col++) {
473         outptr0[col] = *inptr++;
474         outptr1[col] = *inptr++;
475         outptr2[col] = *inptr++;
476       }
477     }
478   } else if (nc == 4) {
479     while (--num_rows >= 0) {
480       inptr = *input_buf++;
481       outptr0 = output_buf[0][output_row];
482       outptr1 = output_buf[1][output_row];
483       outptr2 = output_buf[2][output_row];
484       outptr3 = output_buf[3][output_row];
485       output_row++;
486       for (col = 0; col < num_cols; col++) {
487         outptr0[col] = *inptr++;
488         outptr1[col] = *inptr++;
489         outptr2[col] = *inptr++;
490         outptr3[col] = *inptr++;
491       }
492     }
493   } else {
494     while (--num_rows >= 0) {
495       /* It seems fastest to make a separate pass for each component. */
496       for (ci = 0; ci < nc; ci++) {
497         inptr = *input_buf;
498         outptr = output_buf[ci][output_row];
499         for (col = 0; col < num_cols; col++) {
500           outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
501           inptr += nc;
502         }
503       }
504       input_buf++;
505       output_row++;
506     }
507   }
508 }
509 
510 
511 /*
512  * Empty method for start_pass.
513  */
514 
515 METHODDEF(void)
null_method(j_compress_ptr cinfo)516 null_method(j_compress_ptr cinfo)
517 {
518   /* no work needed */
519 }
520 
521 
522 /*
523  * Module initialization routine for input colorspace conversion.
524  */
525 
526 GLOBAL(void)
jinit_color_converter(j_compress_ptr cinfo)527 jinit_color_converter(j_compress_ptr cinfo)
528 {
529   my_cconvert_ptr cconvert;
530 
531   cconvert = (my_cconvert_ptr)
532     (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
533                                 sizeof(my_color_converter));
534   cinfo->cconvert = (struct jpeg_color_converter *)cconvert;
535   /* set start_pass to null method until we find out differently */
536   cconvert->pub.start_pass = null_method;
537 
538   /* Make sure input_components agrees with in_color_space */
539   switch (cinfo->in_color_space) {
540   case JCS_GRAYSCALE:
541     if (cinfo->input_components != 1)
542       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
543     break;
544 
545   case JCS_RGB:
546   case JCS_EXT_RGB:
547   case JCS_EXT_RGBX:
548   case JCS_EXT_BGR:
549   case JCS_EXT_BGRX:
550   case JCS_EXT_XBGR:
551   case JCS_EXT_XRGB:
552   case JCS_EXT_RGBA:
553   case JCS_EXT_BGRA:
554   case JCS_EXT_ABGR:
555   case JCS_EXT_ARGB:
556     if (cinfo->input_components != rgb_pixelsize[cinfo->in_color_space])
557       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
558     break;
559 
560   case JCS_YCbCr:
561     if (cinfo->input_components != 3)
562       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
563     break;
564 
565   case JCS_CMYK:
566   case JCS_YCCK:
567     if (cinfo->input_components != 4)
568       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
569     break;
570 
571   default:                      /* JCS_UNKNOWN can be anything */
572     if (cinfo->input_components < 1)
573       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
574     break;
575   }
576 
577   /* Check num_components, set conversion method based on requested space */
578   switch (cinfo->jpeg_color_space) {
579   case JCS_GRAYSCALE:
580     if (cinfo->num_components != 1)
581       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
582     if (cinfo->in_color_space == JCS_GRAYSCALE)
583       cconvert->pub.color_convert = grayscale_convert;
584     else if (cinfo->in_color_space == JCS_RGB ||
585              cinfo->in_color_space == JCS_EXT_RGB ||
586              cinfo->in_color_space == JCS_EXT_RGBX ||
587              cinfo->in_color_space == JCS_EXT_BGR ||
588              cinfo->in_color_space == JCS_EXT_BGRX ||
589              cinfo->in_color_space == JCS_EXT_XBGR ||
590              cinfo->in_color_space == JCS_EXT_XRGB ||
591              cinfo->in_color_space == JCS_EXT_RGBA ||
592              cinfo->in_color_space == JCS_EXT_BGRA ||
593              cinfo->in_color_space == JCS_EXT_ABGR ||
594              cinfo->in_color_space == JCS_EXT_ARGB) {
595       if (jsimd_can_rgb_gray())
596         cconvert->pub.color_convert = jsimd_rgb_gray_convert;
597       else {
598         cconvert->pub.start_pass = rgb_ycc_start;
599         cconvert->pub.color_convert = rgb_gray_convert;
600       }
601     } else if (cinfo->in_color_space == JCS_YCbCr)
602       cconvert->pub.color_convert = grayscale_convert;
603     else
604       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
605     break;
606 
607   case JCS_RGB:
608     if (cinfo->num_components != 3)
609       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
610     if (rgb_red[cinfo->in_color_space] == 0 &&
611         rgb_green[cinfo->in_color_space] == 1 &&
612         rgb_blue[cinfo->in_color_space] == 2 &&
613         rgb_pixelsize[cinfo->in_color_space] == 3) {
614 #if defined(__mips__)
615       if (jsimd_c_can_null_convert())
616         cconvert->pub.color_convert = jsimd_c_null_convert;
617       else
618 #endif
619         cconvert->pub.color_convert = null_convert;
620     } else if (cinfo->in_color_space == JCS_RGB ||
621                cinfo->in_color_space == JCS_EXT_RGB ||
622                cinfo->in_color_space == JCS_EXT_RGBX ||
623                cinfo->in_color_space == JCS_EXT_BGR ||
624                cinfo->in_color_space == JCS_EXT_BGRX ||
625                cinfo->in_color_space == JCS_EXT_XBGR ||
626                cinfo->in_color_space == JCS_EXT_XRGB ||
627                cinfo->in_color_space == JCS_EXT_RGBA ||
628                cinfo->in_color_space == JCS_EXT_BGRA ||
629                cinfo->in_color_space == JCS_EXT_ABGR ||
630                cinfo->in_color_space == JCS_EXT_ARGB)
631       cconvert->pub.color_convert = rgb_rgb_convert;
632     else
633       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
634     break;
635 
636   case JCS_YCbCr:
637     if (cinfo->num_components != 3)
638       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
639     if (cinfo->in_color_space == JCS_RGB ||
640         cinfo->in_color_space == JCS_EXT_RGB ||
641         cinfo->in_color_space == JCS_EXT_RGBX ||
642         cinfo->in_color_space == JCS_EXT_BGR ||
643         cinfo->in_color_space == JCS_EXT_BGRX ||
644         cinfo->in_color_space == JCS_EXT_XBGR ||
645         cinfo->in_color_space == JCS_EXT_XRGB ||
646         cinfo->in_color_space == JCS_EXT_RGBA ||
647         cinfo->in_color_space == JCS_EXT_BGRA ||
648         cinfo->in_color_space == JCS_EXT_ABGR ||
649         cinfo->in_color_space == JCS_EXT_ARGB) {
650       if (jsimd_can_rgb_ycc())
651         cconvert->pub.color_convert = jsimd_rgb_ycc_convert;
652       else {
653         cconvert->pub.start_pass = rgb_ycc_start;
654         cconvert->pub.color_convert = rgb_ycc_convert;
655       }
656     } else if (cinfo->in_color_space == JCS_YCbCr) {
657 #if defined(__mips__)
658       if (jsimd_c_can_null_convert())
659         cconvert->pub.color_convert = jsimd_c_null_convert;
660       else
661 #endif
662         cconvert->pub.color_convert = null_convert;
663     } else
664       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
665     break;
666 
667   case JCS_CMYK:
668     if (cinfo->num_components != 4)
669       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
670     if (cinfo->in_color_space == JCS_CMYK) {
671 #if defined(__mips__)
672       if (jsimd_c_can_null_convert())
673         cconvert->pub.color_convert = jsimd_c_null_convert;
674       else
675 #endif
676         cconvert->pub.color_convert = null_convert;
677     } else
678       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
679     break;
680 
681   case JCS_YCCK:
682     if (cinfo->num_components != 4)
683       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
684     if (cinfo->in_color_space == JCS_CMYK) {
685       cconvert->pub.start_pass = rgb_ycc_start;
686       cconvert->pub.color_convert = cmyk_ycck_convert;
687     } else if (cinfo->in_color_space == JCS_YCCK) {
688 #if defined(__mips__)
689       if (jsimd_c_can_null_convert())
690         cconvert->pub.color_convert = jsimd_c_null_convert;
691       else
692 #endif
693         cconvert->pub.color_convert = null_convert;
694     } else
695       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
696     break;
697 
698   default:                      /* allow null conversion of JCS_UNKNOWN */
699     if (cinfo->jpeg_color_space != cinfo->in_color_space ||
700         cinfo->num_components != cinfo->input_components)
701       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
702 #if defined(__mips__)
703     if (jsimd_c_can_null_convert())
704       cconvert->pub.color_convert = jsimd_c_null_convert;
705     else
706 #endif
707       cconvert->pub.color_convert = null_convert;
708     break;
709   }
710 }
711