Home | History | Annotate | Download | only in libjpeg-turbo
      1 /*
      2  * jdcolor.c
      3  *
      4  * This file was part of the Independent JPEG Group's software:
      5  * Copyright (C) 1991-1997, Thomas G. Lane.
      6  * Modified 2011 by Guido Vollbeding.
      7  * libjpeg-turbo Modifications:
      8  * Copyright 2009 Pierre Ossman <ossman (at) cendio.se> for Cendio AB
      9  * Copyright (C) 2009, 2011-2012, 2014-2015, D. R. Commander.
     10  * Copyright (C) 2013, Linaro Limited.
     11  * For conditions of distribution and use, see the accompanying README.ijg
     12  * file.
     13  *
     14  * This file contains output colorspace conversion routines.
     15  */
     16 
     17 #define JPEG_INTERNALS
     18 #include "jinclude.h"
     19 #include "jpeglib.h"
     20 #include "jsimd.h"
     21 #include "jconfigint.h"
     22 
     23 
     24 /* Private subobject */
     25 
     26 typedef struct {
     27   struct jpeg_color_deconverter pub; /* public fields */
     28 
     29   /* Private state for YCC->RGB conversion */
     30   int *Cr_r_tab;                /* => table for Cr to R conversion */
     31   int *Cb_b_tab;                /* => table for Cb to B conversion */
     32   JLONG *Cr_g_tab;              /* => table for Cr to G conversion */
     33   JLONG *Cb_g_tab;              /* => table for Cb to G conversion */
     34 
     35   /* Private state for RGB->Y conversion */
     36   JLONG *rgb_y_tab;             /* => table for RGB to Y conversion */
     37 } my_color_deconverter;
     38 
     39 typedef my_color_deconverter *my_cconvert_ptr;
     40 
     41 
     42 /**************** YCbCr -> RGB conversion: most common case **************/
     43 /****************   RGB -> Y   conversion: less common case **************/
     44 
     45 /*
     46  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
     47  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
     48  * The conversion equations to be implemented are therefore
     49  *
     50  *      R = Y                + 1.40200 * Cr
     51  *      G = Y - 0.34414 * Cb - 0.71414 * Cr
     52  *      B = Y + 1.77200 * Cb
     53  *
     54  *      Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
     55  *
     56  * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
     57  * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
     58  *
     59  * To avoid floating-point arithmetic, we represent the fractional constants
     60  * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
     61  * the products by 2^16, with appropriate rounding, to get the correct answer.
     62  * Notice that Y, being an integral input, does not contribute any fraction
     63  * so it need not participate in the rounding.
     64  *
     65  * For even more speed, we avoid doing any multiplications in the inner loop
     66  * by precalculating the constants times Cb and Cr for all possible values.
     67  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
     68  * for 12-bit samples it is still acceptable.  It's not very reasonable for
     69  * 16-bit samples, but if you want lossless storage you shouldn't be changing
     70  * colorspace anyway.
     71  * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
     72  * values for the G calculation are left scaled up, since we must add them
     73  * together before rounding.
     74  */
     75 
     76 #define SCALEBITS       16      /* speediest right-shift on some machines */
     77 #define ONE_HALF        ((JLONG) 1 << (SCALEBITS-1))
     78 #define FIX(x)          ((JLONG) ((x) * (1L<<SCALEBITS) + 0.5))
     79 
     80 /* We allocate one big table for RGB->Y conversion and divide it up into
     81  * three parts, instead of doing three alloc_small requests.  This lets us
     82  * use a single table base address, which can be held in a register in the
     83  * inner loops on many machines (more than can hold all three addresses,
     84  * anyway).
     85  */
     86 
     87 #define R_Y_OFF         0                       /* offset to R => Y section */
     88 #define G_Y_OFF         (1*(MAXJSAMPLE+1))      /* offset to G => Y section */
     89 #define B_Y_OFF         (2*(MAXJSAMPLE+1))      /* etc. */
     90 #define TABLE_SIZE      (3*(MAXJSAMPLE+1))
     91 
     92 
     93 /* Include inline routines for colorspace extensions */
     94 
     95 #include "jdcolext.c"
     96 #undef RGB_RED
     97 #undef RGB_GREEN
     98 #undef RGB_BLUE
     99 #undef RGB_PIXELSIZE
    100 
    101 #define RGB_RED EXT_RGB_RED
    102 #define RGB_GREEN EXT_RGB_GREEN
    103 #define RGB_BLUE EXT_RGB_BLUE
    104 #define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
    105 #define ycc_rgb_convert_internal ycc_extrgb_convert_internal
    106 #define gray_rgb_convert_internal gray_extrgb_convert_internal
    107 #define rgb_rgb_convert_internal rgb_extrgb_convert_internal
    108 #include "jdcolext.c"
    109 #undef RGB_RED
    110 #undef RGB_GREEN
    111 #undef RGB_BLUE
    112 #undef RGB_PIXELSIZE
    113 #undef ycc_rgb_convert_internal
    114 #undef gray_rgb_convert_internal
    115 #undef rgb_rgb_convert_internal
    116 
    117 #define RGB_RED EXT_RGBX_RED
    118 #define RGB_GREEN EXT_RGBX_GREEN
    119 #define RGB_BLUE EXT_RGBX_BLUE
    120 #define RGB_ALPHA 3
    121 #define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
    122 #define ycc_rgb_convert_internal ycc_extrgbx_convert_internal
    123 #define gray_rgb_convert_internal gray_extrgbx_convert_internal
    124 #define rgb_rgb_convert_internal rgb_extrgbx_convert_internal
    125 #include "jdcolext.c"
    126 #undef RGB_RED
    127 #undef RGB_GREEN
    128 #undef RGB_BLUE
    129 #undef RGB_ALPHA
    130 #undef RGB_PIXELSIZE
    131 #undef ycc_rgb_convert_internal
    132 #undef gray_rgb_convert_internal
    133 #undef rgb_rgb_convert_internal
    134 
    135 #define RGB_RED EXT_BGR_RED
    136 #define RGB_GREEN EXT_BGR_GREEN
    137 #define RGB_BLUE EXT_BGR_BLUE
    138 #define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
    139 #define ycc_rgb_convert_internal ycc_extbgr_convert_internal
    140 #define gray_rgb_convert_internal gray_extbgr_convert_internal
    141 #define rgb_rgb_convert_internal rgb_extbgr_convert_internal
    142 #include "jdcolext.c"
    143 #undef RGB_RED
    144 #undef RGB_GREEN
    145 #undef RGB_BLUE
    146 #undef RGB_PIXELSIZE
    147 #undef ycc_rgb_convert_internal
    148 #undef gray_rgb_convert_internal
    149 #undef rgb_rgb_convert_internal
    150 
    151 #define RGB_RED EXT_BGRX_RED
    152 #define RGB_GREEN EXT_BGRX_GREEN
    153 #define RGB_BLUE EXT_BGRX_BLUE
    154 #define RGB_ALPHA 3
    155 #define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
    156 #define ycc_rgb_convert_internal ycc_extbgrx_convert_internal
    157 #define gray_rgb_convert_internal gray_extbgrx_convert_internal
    158 #define rgb_rgb_convert_internal rgb_extbgrx_convert_internal
    159 #include "jdcolext.c"
    160 #undef RGB_RED
    161 #undef RGB_GREEN
    162 #undef RGB_BLUE
    163 #undef RGB_ALPHA
    164 #undef RGB_PIXELSIZE
    165 #undef ycc_rgb_convert_internal
    166 #undef gray_rgb_convert_internal
    167 #undef rgb_rgb_convert_internal
    168 
    169 #define RGB_RED EXT_XBGR_RED
    170 #define RGB_GREEN EXT_XBGR_GREEN
    171 #define RGB_BLUE EXT_XBGR_BLUE
    172 #define RGB_ALPHA 0
    173 #define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
    174 #define ycc_rgb_convert_internal ycc_extxbgr_convert_internal
    175 #define gray_rgb_convert_internal gray_extxbgr_convert_internal
    176 #define rgb_rgb_convert_internal rgb_extxbgr_convert_internal
    177 #include "jdcolext.c"
    178 #undef RGB_RED
    179 #undef RGB_GREEN
    180 #undef RGB_BLUE
    181 #undef RGB_ALPHA
    182 #undef RGB_PIXELSIZE
    183 #undef ycc_rgb_convert_internal
    184 #undef gray_rgb_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_ALPHA 0
    191 #define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
    192 #define ycc_rgb_convert_internal ycc_extxrgb_convert_internal
    193 #define gray_rgb_convert_internal gray_extxrgb_convert_internal
    194 #define rgb_rgb_convert_internal rgb_extxrgb_convert_internal
    195 #include "jdcolext.c"
    196 #undef RGB_RED
    197 #undef RGB_GREEN
    198 #undef RGB_BLUE
    199 #undef RGB_ALPHA
    200 #undef RGB_PIXELSIZE
    201 #undef ycc_rgb_convert_internal
    202 #undef gray_rgb_convert_internal
    203 #undef rgb_rgb_convert_internal
    204 
    205 
    206 /*
    207  * Initialize tables for YCC->RGB colorspace conversion.
    208  */
    209 
    210 LOCAL(void)
    211 build_ycc_rgb_table (j_decompress_ptr cinfo)
    212 {
    213   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    214   int i;
    215   JLONG x;
    216   SHIFT_TEMPS
    217 
    218   cconvert->Cr_r_tab = (int *)
    219     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    220                                 (MAXJSAMPLE+1) * sizeof(int));
    221   cconvert->Cb_b_tab = (int *)
    222     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    223                                 (MAXJSAMPLE+1) * sizeof(int));
    224   cconvert->Cr_g_tab = (JLONG *)
    225     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    226                                 (MAXJSAMPLE+1) * sizeof(JLONG));
    227   cconvert->Cb_g_tab = (JLONG *)
    228     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    229                                 (MAXJSAMPLE+1) * sizeof(JLONG));
    230 
    231   for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
    232     /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
    233     /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
    234     /* Cr=>R value is nearest int to 1.40200 * x */
    235     cconvert->Cr_r_tab[i] = (int)
    236                     RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
    237     /* Cb=>B value is nearest int to 1.77200 * x */
    238     cconvert->Cb_b_tab[i] = (int)
    239                     RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
    240     /* Cr=>G value is scaled-up -0.71414 * x */
    241     cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
    242     /* Cb=>G value is scaled-up -0.34414 * x */
    243     /* We also add in ONE_HALF so that need not do it in inner loop */
    244     cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
    245   }
    246 }
    247 
    248 
    249 /*
    250  * Convert some rows of samples to the output colorspace.
    251  */
    252 
    253 METHODDEF(void)
    254 ycc_rgb_convert (j_decompress_ptr cinfo,
    255                  JSAMPIMAGE input_buf, JDIMENSION input_row,
    256                  JSAMPARRAY output_buf, int num_rows)
    257 {
    258   switch (cinfo->out_color_space) {
    259     case JCS_EXT_RGB:
    260       ycc_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
    261                                   num_rows);
    262       break;
    263     case JCS_EXT_RGBX:
    264     case JCS_EXT_RGBA:
    265       ycc_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
    266                                    num_rows);
    267       break;
    268     case JCS_EXT_BGR:
    269       ycc_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
    270                                   num_rows);
    271       break;
    272     case JCS_EXT_BGRX:
    273     case JCS_EXT_BGRA:
    274       ycc_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
    275                                    num_rows);
    276       break;
    277     case JCS_EXT_XBGR:
    278     case JCS_EXT_ABGR:
    279       ycc_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
    280                                    num_rows);
    281       break;
    282     case JCS_EXT_XRGB:
    283     case JCS_EXT_ARGB:
    284       ycc_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
    285                                    num_rows);
    286       break;
    287     default:
    288       ycc_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
    289                                num_rows);
    290       break;
    291   }
    292 }
    293 
    294 
    295 /**************** Cases other than YCbCr -> RGB **************/
    296 
    297 
    298 /*
    299  * Initialize for RGB->grayscale colorspace conversion.
    300  */
    301 
    302 LOCAL(void)
    303 build_rgb_y_table (j_decompress_ptr cinfo)
    304 {
    305   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    306   JLONG *rgb_y_tab;
    307   JLONG i;
    308 
    309   /* Allocate and fill in the conversion tables. */
    310   cconvert->rgb_y_tab = rgb_y_tab = (JLONG *)
    311     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    312                                 (TABLE_SIZE * sizeof(JLONG)));
    313 
    314   for (i = 0; i <= MAXJSAMPLE; i++) {
    315     rgb_y_tab[i+R_Y_OFF] = FIX(0.29900) * i;
    316     rgb_y_tab[i+G_Y_OFF] = FIX(0.58700) * i;
    317     rgb_y_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
    318   }
    319 }
    320 
    321 
    322 /*
    323  * Convert RGB to grayscale.
    324  */
    325 
    326 METHODDEF(void)
    327 rgb_gray_convert (j_decompress_ptr cinfo,
    328                   JSAMPIMAGE input_buf, JDIMENSION input_row,
    329                   JSAMPARRAY output_buf, int num_rows)
    330 {
    331   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    332   register int r, g, b;
    333   register JLONG *ctab = cconvert->rgb_y_tab;
    334   register JSAMPROW outptr;
    335   register JSAMPROW inptr0, inptr1, inptr2;
    336   register JDIMENSION col;
    337   JDIMENSION num_cols = cinfo->output_width;
    338 
    339   while (--num_rows >= 0) {
    340     inptr0 = input_buf[0][input_row];
    341     inptr1 = input_buf[1][input_row];
    342     inptr2 = input_buf[2][input_row];
    343     input_row++;
    344     outptr = *output_buf++;
    345     for (col = 0; col < num_cols; col++) {
    346       r = GETJSAMPLE(inptr0[col]);
    347       g = GETJSAMPLE(inptr1[col]);
    348       b = GETJSAMPLE(inptr2[col]);
    349       /* Y */
    350       outptr[col] = (JSAMPLE)
    351                 ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
    352                  >> SCALEBITS);
    353     }
    354   }
    355 }
    356 
    357 
    358 /*
    359  * Color conversion for no colorspace change: just copy the data,
    360  * converting from separate-planes to interleaved representation.
    361  */
    362 
    363 METHODDEF(void)
    364 null_convert (j_decompress_ptr cinfo,
    365               JSAMPIMAGE input_buf, JDIMENSION input_row,
    366               JSAMPARRAY output_buf, int num_rows)
    367 {
    368   register JSAMPROW inptr, inptr0, inptr1, inptr2, inptr3, outptr;
    369   register JDIMENSION col;
    370   register int num_components = cinfo->num_components;
    371   JDIMENSION num_cols = cinfo->output_width;
    372   int ci;
    373 
    374   if (num_components == 3) {
    375     while (--num_rows >= 0) {
    376       inptr0 = input_buf[0][input_row];
    377       inptr1 = input_buf[1][input_row];
    378       inptr2 = input_buf[2][input_row];
    379       input_row++;
    380       outptr = *output_buf++;
    381       for (col = 0; col < num_cols; col++) {
    382         *outptr++ = inptr0[col];
    383         *outptr++ = inptr1[col];
    384         *outptr++ = inptr2[col];
    385       }
    386     }
    387   } else if (num_components == 4) {
    388     while (--num_rows >= 0) {
    389       inptr0 = input_buf[0][input_row];
    390       inptr1 = input_buf[1][input_row];
    391       inptr2 = input_buf[2][input_row];
    392       inptr3 = input_buf[3][input_row];
    393       input_row++;
    394       outptr = *output_buf++;
    395       for (col = 0; col < num_cols; col++) {
    396         *outptr++ = inptr0[col];
    397         *outptr++ = inptr1[col];
    398         *outptr++ = inptr2[col];
    399         *outptr++ = inptr3[col];
    400       }
    401     }
    402   } else {
    403     while (--num_rows >= 0) {
    404       for (ci = 0; ci < num_components; ci++) {
    405         inptr = input_buf[ci][input_row];
    406         outptr = *output_buf;
    407         for (col = 0; col < num_cols; col++) {
    408           outptr[ci] = inptr[col];
    409           outptr += num_components;
    410         }
    411       }
    412       output_buf++;
    413       input_row++;
    414     }
    415   }
    416 }
    417 
    418 
    419 /*
    420  * Color conversion for grayscale: just copy the data.
    421  * This also works for YCbCr -> grayscale conversion, in which
    422  * we just copy the Y (luminance) component and ignore chrominance.
    423  */
    424 
    425 METHODDEF(void)
    426 grayscale_convert (j_decompress_ptr cinfo,
    427                    JSAMPIMAGE input_buf, JDIMENSION input_row,
    428                    JSAMPARRAY output_buf, int num_rows)
    429 {
    430   jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
    431                     num_rows, cinfo->output_width);
    432 }
    433 
    434 
    435 /*
    436  * Convert grayscale to RGB
    437  */
    438 
    439 METHODDEF(void)
    440 gray_rgb_convert (j_decompress_ptr cinfo,
    441                   JSAMPIMAGE input_buf, JDIMENSION input_row,
    442                   JSAMPARRAY output_buf, int num_rows)
    443 {
    444   switch (cinfo->out_color_space) {
    445     case JCS_EXT_RGB:
    446       gray_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
    447                                    num_rows);
    448       break;
    449     case JCS_EXT_RGBX:
    450     case JCS_EXT_RGBA:
    451       gray_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
    452                                     num_rows);
    453       break;
    454     case JCS_EXT_BGR:
    455       gray_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
    456                                    num_rows);
    457       break;
    458     case JCS_EXT_BGRX:
    459     case JCS_EXT_BGRA:
    460       gray_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
    461                                     num_rows);
    462       break;
    463     case JCS_EXT_XBGR:
    464     case JCS_EXT_ABGR:
    465       gray_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
    466                                     num_rows);
    467       break;
    468     case JCS_EXT_XRGB:
    469     case JCS_EXT_ARGB:
    470       gray_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
    471                                     num_rows);
    472       break;
    473     default:
    474       gray_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
    475                                 num_rows);
    476       break;
    477   }
    478 }
    479 
    480 
    481 /*
    482  * Convert plain RGB to extended RGB
    483  */
    484 
    485 METHODDEF(void)
    486 rgb_rgb_convert (j_decompress_ptr cinfo,
    487                   JSAMPIMAGE input_buf, JDIMENSION input_row,
    488                   JSAMPARRAY output_buf, int num_rows)
    489 {
    490   switch (cinfo->out_color_space) {
    491     case JCS_EXT_RGB:
    492       rgb_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
    493                                   num_rows);
    494       break;
    495     case JCS_EXT_RGBX:
    496     case JCS_EXT_RGBA:
    497       rgb_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
    498                                    num_rows);
    499       break;
    500     case JCS_EXT_BGR:
    501       rgb_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
    502                                   num_rows);
    503       break;
    504     case JCS_EXT_BGRX:
    505     case JCS_EXT_BGRA:
    506       rgb_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
    507                                    num_rows);
    508       break;
    509     case JCS_EXT_XBGR:
    510     case JCS_EXT_ABGR:
    511       rgb_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
    512                                    num_rows);
    513       break;
    514     case JCS_EXT_XRGB:
    515     case JCS_EXT_ARGB:
    516       rgb_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
    517                                    num_rows);
    518       break;
    519     default:
    520       rgb_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
    521                                num_rows);
    522       break;
    523   }
    524 }
    525 
    526 
    527 /*
    528  * Adobe-style YCCK->CMYK conversion.
    529  * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
    530  * conversion as above, while passing K (black) unchanged.
    531  * We assume build_ycc_rgb_table has been called.
    532  */
    533 
    534 METHODDEF(void)
    535 ycck_cmyk_convert (j_decompress_ptr cinfo,
    536                    JSAMPIMAGE input_buf, JDIMENSION input_row,
    537                    JSAMPARRAY output_buf, int num_rows)
    538 {
    539   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    540   register int y, cb, cr;
    541   register JSAMPROW outptr;
    542   register JSAMPROW inptr0, inptr1, inptr2, inptr3;
    543   register JDIMENSION col;
    544   JDIMENSION num_cols = cinfo->output_width;
    545   /* copy these pointers into registers if possible */
    546   register JSAMPLE *range_limit = cinfo->sample_range_limit;
    547   register int *Crrtab = cconvert->Cr_r_tab;
    548   register int *Cbbtab = cconvert->Cb_b_tab;
    549   register JLONG *Crgtab = cconvert->Cr_g_tab;
    550   register JLONG *Cbgtab = cconvert->Cb_g_tab;
    551   SHIFT_TEMPS
    552 
    553   while (--num_rows >= 0) {
    554     inptr0 = input_buf[0][input_row];
    555     inptr1 = input_buf[1][input_row];
    556     inptr2 = input_buf[2][input_row];
    557     inptr3 = input_buf[3][input_row];
    558     input_row++;
    559     outptr = *output_buf++;
    560     for (col = 0; col < num_cols; col++) {
    561       y  = GETJSAMPLE(inptr0[col]);
    562       cb = GETJSAMPLE(inptr1[col]);
    563       cr = GETJSAMPLE(inptr2[col]);
    564       /* Range-limiting is essential due to noise introduced by DCT losses. */
    565       outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])];   /* red */
    566       outptr[1] = range_limit[MAXJSAMPLE - (y +                 /* green */
    567                               ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
    568                                                  SCALEBITS)))];
    569       outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])];   /* blue */
    570       /* K passes through unchanged */
    571       outptr[3] = inptr3[col];  /* don't need GETJSAMPLE here */
    572       outptr += 4;
    573     }
    574   }
    575 }
    576 
    577 
    578 /*
    579  * RGB565 conversion
    580  */
    581 
    582 #define PACK_SHORT_565_LE(r, g, b)   ((((r) << 8) & 0xF800) |  \
    583                                       (((g) << 3) & 0x7E0) | ((b) >> 3))
    584 #define PACK_SHORT_565_BE(r, g, b)   (((r) & 0xF8) | ((g) >> 5) |  \
    585                                       (((g) << 11) & 0xE000) |  \
    586                                       (((b) << 5) & 0x1F00))
    587 
    588 #define PACK_TWO_PIXELS_LE(l, r)     ((r << 16) | l)
    589 #define PACK_TWO_PIXELS_BE(l, r)     ((l << 16) | r)
    590 
    591 #define PACK_NEED_ALIGNMENT(ptr)     (((size_t)(ptr)) & 3)
    592 
    593 #define WRITE_TWO_ALIGNED_PIXELS(addr, pixels)  ((*(int *)(addr)) = pixels)
    594 
    595 #define DITHER_565_R(r, dither)  ((r) + ((dither) & 0xFF))
    596 #define DITHER_565_G(g, dither)  ((g) + (((dither) & 0xFF) >> 1))
    597 #define DITHER_565_B(b, dither)  ((b) + ((dither) & 0xFF))
    598 
    599 
    600 /* Declarations for ordered dithering
    601  *
    602  * We use a 4x4 ordered dither array packed into 32 bits.  This array is
    603  * sufficent for dithering RGB888 to RGB565.
    604  */
    605 
    606 #define DITHER_MASK       0x3
    607 #define DITHER_ROTATE(x)  ((((x) & 0xFF) << 24) | (((x) >> 8) & 0x00FFFFFF))
    608 static const JLONG dither_matrix[4] = {
    609   0x0008020A,
    610   0x0C040E06,
    611   0x030B0109,
    612   0x0F070D05
    613 };
    614 
    615 
    616 static INLINE boolean is_big_endian(void)
    617 {
    618   int test_value = 1;
    619   if (*(char *)&test_value != 1)
    620     return TRUE;
    621   return FALSE;
    622 }
    623 
    624 
    625 /* Include inline routines for RGB565 conversion */
    626 
    627 #define PACK_SHORT_565 PACK_SHORT_565_LE
    628 #define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE
    629 #define ycc_rgb565_convert_internal ycc_rgb565_convert_le
    630 #define ycc_rgb565D_convert_internal ycc_rgb565D_convert_le
    631 #define rgb_rgb565_convert_internal rgb_rgb565_convert_le
    632 #define rgb_rgb565D_convert_internal rgb_rgb565D_convert_le
    633 #define gray_rgb565_convert_internal gray_rgb565_convert_le
    634 #define gray_rgb565D_convert_internal gray_rgb565D_convert_le
    635 #include "jdcol565.c"
    636 #undef PACK_SHORT_565
    637 #undef PACK_TWO_PIXELS
    638 #undef ycc_rgb565_convert_internal
    639 #undef ycc_rgb565D_convert_internal
    640 #undef rgb_rgb565_convert_internal
    641 #undef rgb_rgb565D_convert_internal
    642 #undef gray_rgb565_convert_internal
    643 #undef gray_rgb565D_convert_internal
    644 
    645 #define PACK_SHORT_565 PACK_SHORT_565_BE
    646 #define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE
    647 #define ycc_rgb565_convert_internal ycc_rgb565_convert_be
    648 #define ycc_rgb565D_convert_internal ycc_rgb565D_convert_be
    649 #define rgb_rgb565_convert_internal rgb_rgb565_convert_be
    650 #define rgb_rgb565D_convert_internal rgb_rgb565D_convert_be
    651 #define gray_rgb565_convert_internal gray_rgb565_convert_be
    652 #define gray_rgb565D_convert_internal gray_rgb565D_convert_be
    653 #include "jdcol565.c"
    654 #undef PACK_SHORT_565
    655 #undef PACK_TWO_PIXELS
    656 #undef ycc_rgb565_convert_internal
    657 #undef ycc_rgb565D_convert_internal
    658 #undef rgb_rgb565_convert_internal
    659 #undef rgb_rgb565D_convert_internal
    660 #undef gray_rgb565_convert_internal
    661 #undef gray_rgb565D_convert_internal
    662 
    663 
    664 METHODDEF(void)
    665 ycc_rgb565_convert (j_decompress_ptr cinfo,
    666                     JSAMPIMAGE input_buf, JDIMENSION input_row,
    667                     JSAMPARRAY output_buf, int num_rows)
    668 {
    669   if (is_big_endian())
    670     ycc_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
    671   else
    672     ycc_rgb565_convert_le(cinfo, input_buf, input_row, output_buf, num_rows);
    673 }
    674 
    675 
    676 METHODDEF(void)
    677 ycc_rgb565D_convert (j_decompress_ptr cinfo,
    678                      JSAMPIMAGE input_buf, JDIMENSION input_row,
    679                      JSAMPARRAY output_buf, int num_rows)
    680 {
    681   if (is_big_endian())
    682     ycc_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
    683   else
    684     ycc_rgb565D_convert_le(cinfo, input_buf, input_row, output_buf, num_rows);
    685 }
    686 
    687 
    688 METHODDEF(void)
    689 rgb_rgb565_convert (j_decompress_ptr cinfo,
    690                     JSAMPIMAGE input_buf, JDIMENSION input_row,
    691                     JSAMPARRAY output_buf, int num_rows)
    692 {
    693   if (is_big_endian())
    694     rgb_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
    695   else
    696     rgb_rgb565_convert_le(cinfo, input_buf, input_row, output_buf, num_rows);
    697 }
    698 
    699 
    700 METHODDEF(void)
    701 rgb_rgb565D_convert (j_decompress_ptr cinfo,
    702                      JSAMPIMAGE input_buf, JDIMENSION input_row,
    703                      JSAMPARRAY output_buf, int num_rows)
    704 {
    705   if (is_big_endian())
    706     rgb_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
    707   else
    708     rgb_rgb565D_convert_le(cinfo, input_buf, input_row, output_buf, num_rows);
    709 }
    710 
    711 
    712 METHODDEF(void)
    713 gray_rgb565_convert (j_decompress_ptr cinfo,
    714                      JSAMPIMAGE input_buf, JDIMENSION input_row,
    715                      JSAMPARRAY output_buf, int num_rows)
    716 {
    717   if (is_big_endian())
    718     gray_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
    719   else
    720     gray_rgb565_convert_le(cinfo, input_buf, input_row, output_buf, num_rows);
    721 }
    722 
    723 
    724 METHODDEF(void)
    725 gray_rgb565D_convert (j_decompress_ptr cinfo,
    726                       JSAMPIMAGE input_buf, JDIMENSION input_row,
    727                       JSAMPARRAY output_buf, int num_rows)
    728 {
    729   if (is_big_endian())
    730     gray_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
    731   else
    732     gray_rgb565D_convert_le(cinfo, input_buf, input_row, output_buf, num_rows);
    733 }
    734 
    735 
    736 /*
    737  * Empty method for start_pass.
    738  */
    739 
    740 METHODDEF(void)
    741 start_pass_dcolor (j_decompress_ptr cinfo)
    742 {
    743   /* no work needed */
    744 }
    745 
    746 
    747 /*
    748  * Module initialization routine for output colorspace conversion.
    749  */
    750 
    751 GLOBAL(void)
    752 jinit_color_deconverter (j_decompress_ptr cinfo)
    753 {
    754   my_cconvert_ptr cconvert;
    755   int ci;
    756 
    757   cconvert = (my_cconvert_ptr)
    758     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    759                                 sizeof(my_color_deconverter));
    760   cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
    761   cconvert->pub.start_pass = start_pass_dcolor;
    762 
    763   /* Make sure num_components agrees with jpeg_color_space */
    764   switch (cinfo->jpeg_color_space) {
    765   case JCS_GRAYSCALE:
    766     if (cinfo->num_components != 1)
    767       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    768     break;
    769 
    770   case JCS_RGB:
    771   case JCS_YCbCr:
    772     if (cinfo->num_components != 3)
    773       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    774     break;
    775 
    776   case JCS_CMYK:
    777   case JCS_YCCK:
    778     if (cinfo->num_components != 4)
    779       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    780     break;
    781 
    782   default:                      /* JCS_UNKNOWN can be anything */
    783     if (cinfo->num_components < 1)
    784       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    785     break;
    786   }
    787 
    788   /* Set out_color_components and conversion method based on requested space.
    789    * Also clear the component_needed flags for any unused components,
    790    * so that earlier pipeline stages can avoid useless computation.
    791    */
    792 
    793   switch (cinfo->out_color_space) {
    794   case JCS_GRAYSCALE:
    795     cinfo->out_color_components = 1;
    796     if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
    797         cinfo->jpeg_color_space == JCS_YCbCr) {
    798       cconvert->pub.color_convert = grayscale_convert;
    799       /* For color->grayscale conversion, only the Y (0) component is needed */
    800       for (ci = 1; ci < cinfo->num_components; ci++)
    801         cinfo->comp_info[ci].component_needed = FALSE;
    802     } else if (cinfo->jpeg_color_space == JCS_RGB) {
    803       cconvert->pub.color_convert = rgb_gray_convert;
    804       build_rgb_y_table(cinfo);
    805     } else
    806       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    807     break;
    808 
    809   case JCS_RGB:
    810   case JCS_EXT_RGB:
    811   case JCS_EXT_RGBX:
    812   case JCS_EXT_BGR:
    813   case JCS_EXT_BGRX:
    814   case JCS_EXT_XBGR:
    815   case JCS_EXT_XRGB:
    816   case JCS_EXT_RGBA:
    817   case JCS_EXT_BGRA:
    818   case JCS_EXT_ABGR:
    819   case JCS_EXT_ARGB:
    820     cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space];
    821     if (cinfo->jpeg_color_space == JCS_YCbCr) {
    822       if (jsimd_can_ycc_rgb())
    823         cconvert->pub.color_convert = jsimd_ycc_rgb_convert;
    824       else {
    825         cconvert->pub.color_convert = ycc_rgb_convert;
    826         build_ycc_rgb_table(cinfo);
    827       }
    828     } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
    829       cconvert->pub.color_convert = gray_rgb_convert;
    830     } else if (cinfo->jpeg_color_space == JCS_RGB) {
    831       if (rgb_red[cinfo->out_color_space] == 0 &&
    832           rgb_green[cinfo->out_color_space] == 1 &&
    833           rgb_blue[cinfo->out_color_space] == 2 &&
    834           rgb_pixelsize[cinfo->out_color_space] == 3)
    835         cconvert->pub.color_convert = null_convert;
    836       else
    837         cconvert->pub.color_convert = rgb_rgb_convert;
    838     } else
    839       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    840     break;
    841 
    842   case JCS_RGB565:
    843     cinfo->out_color_components = 3;
    844     if (cinfo->dither_mode == JDITHER_NONE) {
    845       if (cinfo->jpeg_color_space == JCS_YCbCr) {
    846          if (jsimd_can_ycc_rgb565())
    847            cconvert->pub.color_convert = jsimd_ycc_rgb565_convert;
    848          else {
    849            cconvert->pub.color_convert = ycc_rgb565_convert;
    850            build_ycc_rgb_table(cinfo);
    851         }
    852       } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
    853         cconvert->pub.color_convert = gray_rgb565_convert;
    854       } else if (cinfo->jpeg_color_space == JCS_RGB) {
    855         cconvert->pub.color_convert = rgb_rgb565_convert;
    856       } else
    857         ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    858     } else {
    859       /* only ordered dithering is supported */
    860       if (cinfo->jpeg_color_space == JCS_YCbCr) {
    861         cconvert->pub.color_convert = ycc_rgb565D_convert;
    862         build_ycc_rgb_table(cinfo);
    863       } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
    864         cconvert->pub.color_convert = gray_rgb565D_convert;
    865       } else if (cinfo->jpeg_color_space == JCS_RGB) {
    866         cconvert->pub.color_convert = rgb_rgb565D_convert;
    867       } else
    868         ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    869     }
    870     break;
    871 
    872   case JCS_CMYK:
    873     cinfo->out_color_components = 4;
    874     if (cinfo->jpeg_color_space == JCS_YCCK) {
    875       cconvert->pub.color_convert = ycck_cmyk_convert;
    876       build_ycc_rgb_table(cinfo);
    877     } else if (cinfo->jpeg_color_space == JCS_CMYK) {
    878       cconvert->pub.color_convert = null_convert;
    879     } else
    880       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    881     break;
    882 
    883   default:
    884     /* Permit null conversion to same output space */
    885     if (cinfo->out_color_space == cinfo->jpeg_color_space) {
    886       cinfo->out_color_components = cinfo->num_components;
    887       cconvert->pub.color_convert = null_convert;
    888     } else                      /* unsupported non-null conversion */
    889       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    890     break;
    891   }
    892 
    893   if (cinfo->quantize_colors)
    894     cinfo->output_components = 1; /* single colormapped output component */
    895   else
    896     cinfo->output_components = cinfo->out_color_components;
    897 }
    898