tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

jdcolor.c (29866B)


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