Home | History | Annotate | Download | only in libjpeg-turbo
      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 (at) 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 file.
     11  *
     12  * This file contains input colorspace conversion routines.
     13  */
     14 
     15 #define JPEG_INTERNALS
     16 #include "jinclude.h"
     17 #include "jpeglib.h"
     18 #include "jsimd.h"
     19 #include "jconfigint.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   INT32 * 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     ((INT32) CENTERJSAMPLE << SCALEBITS)
     66 #define ONE_HALF        ((INT32) 1 << (SCALEBITS-1))
     67 #define FIX(x)          ((INT32) ((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 
     87 /* Include inline routines for colorspace extensions */
     88 
     89 #include "jccolext.c"
     90 #undef RGB_RED
     91 #undef RGB_GREEN
     92 #undef RGB_BLUE
     93 #undef RGB_PIXELSIZE
     94 
     95 #define RGB_RED EXT_RGB_RED
     96 #define RGB_GREEN EXT_RGB_GREEN
     97 #define RGB_BLUE EXT_RGB_BLUE
     98 #define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
     99 #define rgb_ycc_convert_internal extrgb_ycc_convert_internal
    100 #define rgb_gray_convert_internal extrgb_gray_convert_internal
    101 #define rgb_rgb_convert_internal extrgb_rgb_convert_internal
    102 #include "jccolext.c"
    103 #undef RGB_RED
    104 #undef RGB_GREEN
    105 #undef RGB_BLUE
    106 #undef RGB_PIXELSIZE
    107 #undef rgb_ycc_convert_internal
    108 #undef rgb_gray_convert_internal
    109 #undef rgb_rgb_convert_internal
    110 
    111 #define RGB_RED EXT_RGBX_RED
    112 #define RGB_GREEN EXT_RGBX_GREEN
    113 #define RGB_BLUE EXT_RGBX_BLUE
    114 #define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
    115 #define rgb_ycc_convert_internal extrgbx_ycc_convert_internal
    116 #define rgb_gray_convert_internal extrgbx_gray_convert_internal
    117 #define rgb_rgb_convert_internal extrgbx_rgb_convert_internal
    118 #include "jccolext.c"
    119 #undef RGB_RED
    120 #undef RGB_GREEN
    121 #undef RGB_BLUE
    122 #undef RGB_PIXELSIZE
    123 #undef rgb_ycc_convert_internal
    124 #undef rgb_gray_convert_internal
    125 #undef rgb_rgb_convert_internal
    126 
    127 #define RGB_RED EXT_BGR_RED
    128 #define RGB_GREEN EXT_BGR_GREEN
    129 #define RGB_BLUE EXT_BGR_BLUE
    130 #define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
    131 #define rgb_ycc_convert_internal extbgr_ycc_convert_internal
    132 #define rgb_gray_convert_internal extbgr_gray_convert_internal
    133 #define rgb_rgb_convert_internal extbgr_rgb_convert_internal
    134 #include "jccolext.c"
    135 #undef RGB_RED
    136 #undef RGB_GREEN
    137 #undef RGB_BLUE
    138 #undef RGB_PIXELSIZE
    139 #undef rgb_ycc_convert_internal
    140 #undef rgb_gray_convert_internal
    141 #undef rgb_rgb_convert_internal
    142 
    143 #define RGB_RED EXT_BGRX_RED
    144 #define RGB_GREEN EXT_BGRX_GREEN
    145 #define RGB_BLUE EXT_BGRX_BLUE
    146 #define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
    147 #define rgb_ycc_convert_internal extbgrx_ycc_convert_internal
    148 #define rgb_gray_convert_internal extbgrx_gray_convert_internal
    149 #define rgb_rgb_convert_internal extbgrx_rgb_convert_internal
    150 #include "jccolext.c"
    151 #undef RGB_RED
    152 #undef RGB_GREEN
    153 #undef RGB_BLUE
    154 #undef RGB_PIXELSIZE
    155 #undef rgb_ycc_convert_internal
    156 #undef rgb_gray_convert_internal
    157 #undef rgb_rgb_convert_internal
    158 
    159 #define RGB_RED EXT_XBGR_RED
    160 #define RGB_GREEN EXT_XBGR_GREEN
    161 #define RGB_BLUE EXT_XBGR_BLUE
    162 #define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
    163 #define rgb_ycc_convert_internal extxbgr_ycc_convert_internal
    164 #define rgb_gray_convert_internal extxbgr_gray_convert_internal
    165 #define rgb_rgb_convert_internal extxbgr_rgb_convert_internal
    166 #include "jccolext.c"
    167 #undef RGB_RED
    168 #undef RGB_GREEN
    169 #undef RGB_BLUE
    170 #undef RGB_PIXELSIZE
    171 #undef rgb_ycc_convert_internal
    172 #undef rgb_gray_convert_internal
    173 #undef rgb_rgb_convert_internal
    174 
    175 #define RGB_RED EXT_XRGB_RED
    176 #define RGB_GREEN EXT_XRGB_GREEN
    177 #define RGB_BLUE EXT_XRGB_BLUE
    178 #define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
    179 #define rgb_ycc_convert_internal extxrgb_ycc_convert_internal
    180 #define rgb_gray_convert_internal extxrgb_gray_convert_internal
    181 #define rgb_rgb_convert_internal extxrgb_rgb_convert_internal
    182 #include "jccolext.c"
    183 #undef RGB_RED
    184 #undef RGB_GREEN
    185 #undef RGB_BLUE
    186 #undef RGB_PIXELSIZE
    187 #undef rgb_ycc_convert_internal
    188 #undef rgb_gray_convert_internal
    189 #undef rgb_rgb_convert_internal
    190 
    191 
    192 /*
    193  * Initialize for RGB->YCC colorspace conversion.
    194  */
    195 
    196 METHODDEF(void)
    197 rgb_ycc_start (j_compress_ptr cinfo)
    198 {
    199   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    200   INT32 * rgb_ycc_tab;
    201   INT32 i;
    202 
    203   /* Allocate and fill in the conversion tables. */
    204   cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
    205     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    206                                 (TABLE_SIZE * sizeof(INT32)));
    207 
    208   for (i = 0; i <= MAXJSAMPLE; i++) {
    209     rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
    210     rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
    211     rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i     + ONE_HALF;
    212     rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
    213     rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
    214     /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
    215      * This ensures that the maximum output will round to MAXJSAMPLE
    216      * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
    217      */
    218     rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1;
    219 /*  B=>Cb and R=>Cr tables are the same
    220     rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1;
    221 */
    222     rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
    223     rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
    224   }
    225 }
    226 
    227 
    228 /*
    229  * Convert some rows of samples to the JPEG colorspace.
    230  */
    231 
    232 METHODDEF(void)
    233 rgb_ycc_convert (j_compress_ptr cinfo,
    234                  JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    235                  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)
    282 rgb_gray_convert (j_compress_ptr cinfo,
    283                   JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    284                   JDIMENSION output_row, int num_rows)
    285 {
    286   switch (cinfo->in_color_space) {
    287     case JCS_EXT_RGB:
    288       extrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
    289                                    num_rows);
    290       break;
    291     case JCS_EXT_RGBX:
    292     case JCS_EXT_RGBA:
    293       extrgbx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
    294                                     num_rows);
    295       break;
    296     case JCS_EXT_BGR:
    297       extbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
    298                                    num_rows);
    299       break;
    300     case JCS_EXT_BGRX:
    301     case JCS_EXT_BGRA:
    302       extbgrx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
    303                                     num_rows);
    304       break;
    305     case JCS_EXT_XBGR:
    306     case JCS_EXT_ABGR:
    307       extxbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
    308                                     num_rows);
    309       break;
    310     case JCS_EXT_XRGB:
    311     case JCS_EXT_ARGB:
    312       extxrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
    313                                     num_rows);
    314       break;
    315     default:
    316       rgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
    317                                 num_rows);
    318       break;
    319   }
    320 }
    321 
    322 
    323 /*
    324  * Extended RGB to plain RGB conversion
    325  */
    326 
    327 METHODDEF(void)
    328 rgb_rgb_convert (j_compress_ptr cinfo,
    329                   JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    330                   JDIMENSION output_row, int num_rows)
    331 {
    332   switch (cinfo->in_color_space) {
    333     case JCS_EXT_RGB:
    334       extrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
    335                                   num_rows);
    336       break;
    337     case JCS_EXT_RGBX:
    338     case JCS_EXT_RGBA:
    339       extrgbx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
    340                                    num_rows);
    341       break;
    342     case JCS_EXT_BGR:
    343       extbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
    344                                   num_rows);
    345       break;
    346     case JCS_EXT_BGRX:
    347     case JCS_EXT_BGRA:
    348       extbgrx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
    349                                    num_rows);
    350       break;
    351     case JCS_EXT_XBGR:
    352     case JCS_EXT_ABGR:
    353       extxbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
    354                                    num_rows);
    355       break;
    356     case JCS_EXT_XRGB:
    357     case JCS_EXT_ARGB:
    358       extxrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
    359                                    num_rows);
    360       break;
    361     default:
    362       rgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
    363                                num_rows);
    364       break;
    365   }
    366 }
    367 
    368 
    369 /*
    370  * Convert some rows of samples to the JPEG colorspace.
    371  * This version handles Adobe-style CMYK->YCCK conversion,
    372  * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
    373  * conversion as above, while passing K (black) unchanged.
    374  * We assume rgb_ycc_start has been called.
    375  */
    376 
    377 METHODDEF(void)
    378 cmyk_ycck_convert (j_compress_ptr cinfo,
    379                    JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    380                    JDIMENSION output_row, int num_rows)
    381 {
    382   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    383   register int r, g, b;
    384   register INT32 * ctab = cconvert->rgb_ycc_tab;
    385   register JSAMPROW inptr;
    386   register JSAMPROW outptr0, outptr1, outptr2, outptr3;
    387   register JDIMENSION col;
    388   JDIMENSION num_cols = cinfo->image_width;
    389 
    390   while (--num_rows >= 0) {
    391     inptr = *input_buf++;
    392     outptr0 = output_buf[0][output_row];
    393     outptr1 = output_buf[1][output_row];
    394     outptr2 = output_buf[2][output_row];
    395     outptr3 = output_buf[3][output_row];
    396     output_row++;
    397     for (col = 0; col < num_cols; col++) {
    398       r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
    399       g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
    400       b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
    401       /* K passes through as-is */
    402       outptr3[col] = inptr[3];  /* don't need GETJSAMPLE here */
    403       inptr += 4;
    404       /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
    405        * must be too; we do not need an explicit range-limiting operation.
    406        * Hence the value being shifted is never negative, and we don't
    407        * need the general RIGHT_SHIFT macro.
    408        */
    409       /* Y */
    410       outptr0[col] = (JSAMPLE)
    411                 ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
    412                  >> SCALEBITS);
    413       /* Cb */
    414       outptr1[col] = (JSAMPLE)
    415                 ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
    416                  >> SCALEBITS);
    417       /* Cr */
    418       outptr2[col] = (JSAMPLE)
    419                 ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
    420                  >> SCALEBITS);
    421     }
    422   }
    423 }
    424 
    425 
    426 /*
    427  * Convert some rows of samples to the JPEG colorspace.
    428  * This version handles grayscale output with no conversion.
    429  * The source can be either plain grayscale or YCbCr (since Y == gray).
    430  */
    431 
    432 METHODDEF(void)
    433 grayscale_convert (j_compress_ptr cinfo,
    434                    JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    435                    JDIMENSION output_row, int num_rows)
    436 {
    437   register JSAMPROW inptr;
    438   register JSAMPROW outptr;
    439   register JDIMENSION col;
    440   JDIMENSION num_cols = cinfo->image_width;
    441   int instride = cinfo->input_components;
    442 
    443   while (--num_rows >= 0) {
    444     inptr = *input_buf++;
    445     outptr = output_buf[0][output_row];
    446     output_row++;
    447     for (col = 0; col < num_cols; col++) {
    448       outptr[col] = inptr[0];   /* don't need GETJSAMPLE() here */
    449       inptr += instride;
    450     }
    451   }
    452 }
    453 
    454 
    455 /*
    456  * Convert some rows of samples to the JPEG colorspace.
    457  * This version handles multi-component colorspaces without conversion.
    458  * We assume input_components == num_components.
    459  */
    460 
    461 METHODDEF(void)
    462 null_convert (j_compress_ptr cinfo,
    463               JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    464               JDIMENSION output_row, int num_rows)
    465 {
    466   register JSAMPROW inptr;
    467   register JSAMPROW outptr, outptr0, outptr1, outptr2, outptr3;
    468   register JDIMENSION col;
    469   register int ci;
    470   int nc = cinfo->num_components;
    471   JDIMENSION num_cols = cinfo->image_width;
    472 
    473   if (nc == 3) {
    474     while (--num_rows >= 0) {
    475       inptr = *input_buf++;
    476       outptr0 = output_buf[0][output_row];
    477       outptr1 = output_buf[1][output_row];
    478       outptr2 = output_buf[2][output_row];
    479       output_row++;
    480       for (col = 0; col < num_cols; col++) {
    481         outptr0[col] = *inptr++;
    482         outptr1[col] = *inptr++;
    483         outptr2[col] = *inptr++;
    484       }
    485     }
    486   } else if (nc == 4) {
    487     while (--num_rows >= 0) {
    488       inptr = *input_buf++;
    489       outptr0 = output_buf[0][output_row];
    490       outptr1 = output_buf[1][output_row];
    491       outptr2 = output_buf[2][output_row];
    492       outptr3 = output_buf[3][output_row];
    493       output_row++;
    494       for (col = 0; col < num_cols; col++) {
    495         outptr0[col] = *inptr++;
    496         outptr1[col] = *inptr++;
    497         outptr2[col] = *inptr++;
    498         outptr3[col] = *inptr++;
    499       }
    500     }
    501   } else {
    502     while (--num_rows >= 0) {
    503       /* It seems fastest to make a separate pass for each component. */
    504       for (ci = 0; ci < nc; ci++) {
    505         inptr = *input_buf;
    506         outptr = output_buf[ci][output_row];
    507         for (col = 0; col < num_cols; col++) {
    508           outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
    509           inptr += nc;
    510         }
    511       }
    512       input_buf++;
    513       output_row++;
    514     }
    515   }
    516 }
    517 
    518 
    519 /*
    520  * Empty method for start_pass.
    521  */
    522 
    523 METHODDEF(void)
    524 null_method (j_compress_ptr cinfo)
    525 {
    526   /* no work needed */
    527 }
    528 
    529 
    530 /*
    531  * Module initialization routine for input colorspace conversion.
    532  */
    533 
    534 GLOBAL(void)
    535 jinit_color_converter (j_compress_ptr cinfo)
    536 {
    537   my_cconvert_ptr cconvert;
    538 
    539   cconvert = (my_cconvert_ptr)
    540     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    541                                 sizeof(my_color_converter));
    542   cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
    543   /* set start_pass to null method until we find out differently */
    544   cconvert->pub.start_pass = null_method;
    545 
    546   /* Make sure input_components agrees with in_color_space */
    547   switch (cinfo->in_color_space) {
    548   case JCS_GRAYSCALE:
    549     if (cinfo->input_components != 1)
    550       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
    551     break;
    552 
    553   case JCS_RGB:
    554   case JCS_EXT_RGB:
    555   case JCS_EXT_RGBX:
    556   case JCS_EXT_BGR:
    557   case JCS_EXT_BGRX:
    558   case JCS_EXT_XBGR:
    559   case JCS_EXT_XRGB:
    560   case JCS_EXT_RGBA:
    561   case JCS_EXT_BGRA:
    562   case JCS_EXT_ABGR:
    563   case JCS_EXT_ARGB:
    564     if (cinfo->input_components != rgb_pixelsize[cinfo->in_color_space])
    565       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
    566     break;
    567 
    568   case JCS_YCbCr:
    569     if (cinfo->input_components != 3)
    570       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
    571     break;
    572 
    573   case JCS_CMYK:
    574   case JCS_YCCK:
    575     if (cinfo->input_components != 4)
    576       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
    577     break;
    578 
    579   default:                      /* JCS_UNKNOWN can be anything */
    580     if (cinfo->input_components < 1)
    581       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
    582     break;
    583   }
    584 
    585   /* Check num_components, set conversion method based on requested space */
    586   switch (cinfo->jpeg_color_space) {
    587   case JCS_GRAYSCALE:
    588     if (cinfo->num_components != 1)
    589       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    590     if (cinfo->in_color_space == JCS_GRAYSCALE)
    591       cconvert->pub.color_convert = grayscale_convert;
    592     else if (cinfo->in_color_space == JCS_RGB ||
    593              cinfo->in_color_space == JCS_EXT_RGB ||
    594              cinfo->in_color_space == JCS_EXT_RGBX ||
    595              cinfo->in_color_space == JCS_EXT_BGR ||
    596              cinfo->in_color_space == JCS_EXT_BGRX ||
    597              cinfo->in_color_space == JCS_EXT_XBGR ||
    598              cinfo->in_color_space == JCS_EXT_XRGB ||
    599              cinfo->in_color_space == JCS_EXT_RGBA ||
    600              cinfo->in_color_space == JCS_EXT_BGRA ||
    601              cinfo->in_color_space == JCS_EXT_ABGR ||
    602              cinfo->in_color_space == JCS_EXT_ARGB) {
    603       if (jsimd_can_rgb_gray())
    604         cconvert->pub.color_convert = jsimd_rgb_gray_convert;
    605       else {
    606         cconvert->pub.start_pass = rgb_ycc_start;
    607         cconvert->pub.color_convert = rgb_gray_convert;
    608       }
    609     } else if (cinfo->in_color_space == JCS_YCbCr)
    610       cconvert->pub.color_convert = grayscale_convert;
    611     else
    612       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    613     break;
    614 
    615   case JCS_RGB:
    616     if (cinfo->num_components != 3)
    617       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    618     if (rgb_red[cinfo->in_color_space] == 0 &&
    619         rgb_green[cinfo->in_color_space] == 1 &&
    620         rgb_blue[cinfo->in_color_space] == 2 &&
    621         rgb_pixelsize[cinfo->in_color_space] == 3) {
    622 #if defined(__mips__)
    623       if (jsimd_c_can_null_convert())
    624         cconvert->pub.color_convert = jsimd_c_null_convert;
    625       else
    626 #endif
    627         cconvert->pub.color_convert = null_convert;
    628     } else if (cinfo->in_color_space == JCS_RGB ||
    629                cinfo->in_color_space == JCS_EXT_RGB ||
    630                cinfo->in_color_space == JCS_EXT_RGBX ||
    631                cinfo->in_color_space == JCS_EXT_BGR ||
    632                cinfo->in_color_space == JCS_EXT_BGRX ||
    633                cinfo->in_color_space == JCS_EXT_XBGR ||
    634                cinfo->in_color_space == JCS_EXT_XRGB ||
    635                cinfo->in_color_space == JCS_EXT_RGBA ||
    636                cinfo->in_color_space == JCS_EXT_BGRA ||
    637                cinfo->in_color_space == JCS_EXT_ABGR ||
    638                cinfo->in_color_space == JCS_EXT_ARGB)
    639       cconvert->pub.color_convert = rgb_rgb_convert;
    640     else
    641       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    642     break;
    643 
    644   case JCS_YCbCr:
    645     if (cinfo->num_components != 3)
    646       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    647     if (cinfo->in_color_space == JCS_RGB ||
    648         cinfo->in_color_space == JCS_EXT_RGB ||
    649         cinfo->in_color_space == JCS_EXT_RGBX ||
    650         cinfo->in_color_space == JCS_EXT_BGR ||
    651         cinfo->in_color_space == JCS_EXT_BGRX ||
    652         cinfo->in_color_space == JCS_EXT_XBGR ||
    653         cinfo->in_color_space == JCS_EXT_XRGB ||
    654         cinfo->in_color_space == JCS_EXT_RGBA ||
    655         cinfo->in_color_space == JCS_EXT_BGRA ||
    656         cinfo->in_color_space == JCS_EXT_ABGR ||
    657         cinfo->in_color_space == JCS_EXT_ARGB) {
    658       if (jsimd_can_rgb_ycc())
    659         cconvert->pub.color_convert = jsimd_rgb_ycc_convert;
    660       else {
    661         cconvert->pub.start_pass = rgb_ycc_start;
    662         cconvert->pub.color_convert = rgb_ycc_convert;
    663       }
    664     } else if (cinfo->in_color_space == JCS_YCbCr) {
    665 #if defined(__mips__)
    666       if (jsimd_c_can_null_convert())
    667         cconvert->pub.color_convert = jsimd_c_null_convert;
    668       else
    669 #endif
    670         cconvert->pub.color_convert = null_convert;
    671     } else
    672       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    673     break;
    674 
    675   case JCS_CMYK:
    676     if (cinfo->num_components != 4)
    677       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    678     if (cinfo->in_color_space == JCS_CMYK) {
    679 #if defined(__mips__)
    680       if (jsimd_c_can_null_convert())
    681         cconvert->pub.color_convert = jsimd_c_null_convert;
    682       else
    683 #endif
    684         cconvert->pub.color_convert = null_convert;
    685     } else
    686       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    687     break;
    688 
    689   case JCS_YCCK:
    690     if (cinfo->num_components != 4)
    691       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    692     if (cinfo->in_color_space == JCS_CMYK) {
    693       cconvert->pub.start_pass = rgb_ycc_start;
    694       cconvert->pub.color_convert = cmyk_ycck_convert;
    695     } else if (cinfo->in_color_space == JCS_YCCK) {
    696 #if defined(__mips__)
    697       if (jsimd_c_can_null_convert())
    698         cconvert->pub.color_convert = jsimd_c_null_convert;
    699       else
    700 #endif
    701         cconvert->pub.color_convert = null_convert;
    702     } else
    703       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    704     break;
    705 
    706   default:                      /* allow null conversion of JCS_UNKNOWN */
    707     if (cinfo->jpeg_color_space != cinfo->in_color_space ||
    708         cinfo->num_components != cinfo->input_components)
    709       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    710 #if defined(__mips__)
    711     if (jsimd_c_can_null_convert())
    712       cconvert->pub.color_convert = jsimd_c_null_convert;
    713     else
    714 #endif
    715       cconvert->pub.color_convert = null_convert;
    716     break;
    717   }
    718 }
    719