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