Home | History | Annotate | Download | only in jpeg
      1 /*
      2  * jdcolor.c
      3  *
      4  * Copyright (C) 1991-1997, Thomas G. Lane.
      5  * This file is part of the Independent JPEG Group's software.
      6  * For conditions of distribution and use, see the accompanying README file.
      7  *
      8  * This file contains output colorspace conversion routines.
      9  */
     10 
     11 #define JPEG_INTERNALS
     12 #include "jinclude.h"
     13 #include "jpeglib.h"
     14 
     15 
     16 /* Private subobject */
     17 
     18 typedef struct {
     19   struct jpeg_color_deconverter pub; /* public fields */
     20 
     21   /* Private state for YCC->RGB conversion */
     22   int * Cr_r_tab;		/* => table for Cr to R conversion */
     23   int * Cb_b_tab;		/* => table for Cb to B conversion */
     24   INT32 * Cr_g_tab;		/* => table for Cr to G conversion */
     25   INT32 * Cb_g_tab;		/* => table for Cb to G conversion */
     26 } my_color_deconverter;
     27 
     28 typedef my_color_deconverter * my_cconvert_ptr;
     29 
     30 
     31 #ifdef ANDROID_RGB
     32 
     33 /* Declarations for ordered dithering.
     34  *
     35  * We use 4x4 ordered dither array packed into 32 bits. This array is
     36  * sufficent for dithering RGB_888 to RGB_565.
     37  */
     38 
     39 #define DITHER_MASK         0x3
     40 #define DITHER_ROTATE(x)    (((x)<<24) | (((x)>>8)&0x00FFFFFF))
     41 static const INT32 dither_matrix[4] = {
     42   0x0008020A,
     43   0x0C040E06,
     44   0x030B0109,
     45   0x0F070D05
     46 };
     47 
     48 #endif
     49 
     50 
     51 /**************** YCbCr -> RGB conversion: most common case **************/
     52 
     53 /*
     54  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
     55  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
     56  * The conversion equations to be implemented are therefore
     57  *	R = Y                + 1.40200 * Cr
     58  *	G = Y - 0.34414 * Cb - 0.71414 * Cr
     59  *	B = Y + 1.77200 * Cb
     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 JSAMPLEs 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	((INT32) 1 << (SCALEBITS-1))
     82 #define FIX(x)		((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
     83 
     84 
     85 /*
     86  * Initialize tables for YCC->RGB colorspace conversion.
     87  */
     88 
     89 LOCAL(void)
     90 build_ycc_rgb_table (j_decompress_ptr cinfo)
     91 {
     92   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
     93   int i;
     94   INT32 x;
     95   SHIFT_TEMPS
     96 
     97   cconvert->Cr_r_tab = (int *)
     98     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
     99                                 (MAXJSAMPLE+1) * SIZEOF(int));
    100   cconvert->Cb_b_tab = (int *)
    101     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    102                                 (MAXJSAMPLE+1) * SIZEOF(int));
    103   cconvert->Cr_g_tab = (INT32 *)
    104     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    105                                 (MAXJSAMPLE+1) * SIZEOF(INT32));
    106   cconvert->Cb_g_tab = (INT32 *)
    107     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    108                                 (MAXJSAMPLE+1) * SIZEOF(INT32));
    109 
    110   for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
    111     /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
    112     /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
    113     /* Cr=>R value is nearest int to 1.40200 * x */
    114     cconvert->Cr_r_tab[i] = (int)
    115                     RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
    116     /* Cb=>B value is nearest int to 1.77200 * x */
    117     cconvert->Cb_b_tab[i] = (int)
    118                     RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
    119     /* Cr=>G value is scaled-up -0.71414 * x */
    120     cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
    121     /* Cb=>G value is scaled-up -0.34414 * x */
    122     /* We also add in ONE_HALF so that need not do it in inner loop */
    123     cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
    124   }
    125 }
    126 
    127 /*
    128  * Convert some rows of samples to the output colorspace.
    129  *
    130  * Note that we change from noninterleaved, one-plane-per-component format
    131  * to interleaved-pixel format.  The output buffer is therefore three times
    132  * as wide as the input buffer.
    133  * A starting row offset is provided only for the input buffer.  The caller
    134  * can easily adjust the passed output_buf value to accommodate any row
    135  * offset required on that side.
    136  */
    137 
    138 METHODDEF(void)
    139 ycc_rgb_convert (j_decompress_ptr cinfo,
    140 		 JSAMPIMAGE input_buf, JDIMENSION input_row,
    141 		 JSAMPARRAY output_buf, int num_rows)
    142 {
    143   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    144   register int y, cb, cr;
    145   register JSAMPROW outptr;
    146   register JSAMPROW inptr0, inptr1, inptr2;
    147   register JDIMENSION col;
    148   JDIMENSION num_cols = cinfo->output_width;
    149   /* copy these pointers into registers if possible */
    150   register JSAMPLE * range_limit = cinfo->sample_range_limit;
    151   register int * Crrtab = cconvert->Cr_r_tab;
    152   register int * Cbbtab = cconvert->Cb_b_tab;
    153   register INT32 * Crgtab = cconvert->Cr_g_tab;
    154   register INT32 * Cbgtab = cconvert->Cb_g_tab;
    155   SHIFT_TEMPS
    156 
    157   while (--num_rows >= 0) {
    158     inptr0 = input_buf[0][input_row];
    159     inptr1 = input_buf[1][input_row];
    160     inptr2 = input_buf[2][input_row];
    161     input_row++;
    162     outptr = *output_buf++;
    163     for (col = 0; col < num_cols; col++) {
    164       y  = GETJSAMPLE(inptr0[col]);
    165       cb = GETJSAMPLE(inptr1[col]);
    166       cr = GETJSAMPLE(inptr2[col]);
    167       /* Range-limiting is essential due to noise introduced by DCT losses. */
    168       outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
    169       outptr[RGB_GREEN] = range_limit[y +
    170                               ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
    171                                                  SCALEBITS))];
    172       outptr[RGB_BLUE] =  range_limit[y + Cbbtab[cb]];
    173       outptr += RGB_PIXELSIZE;
    174     }
    175   }
    176 }
    177 
    178 #ifdef ANDROID_RGB
    179 METHODDEF(void)
    180 ycc_rgba_8888_convert (j_decompress_ptr cinfo,
    181          JSAMPIMAGE input_buf, JDIMENSION input_row,
    182          JSAMPARRAY output_buf, int num_rows)
    183 {
    184   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    185   register int y, cb, cr;
    186   register JSAMPROW outptr;
    187   register JSAMPROW inptr0, inptr1, inptr2;
    188   register JDIMENSION col;
    189   JDIMENSION num_cols = cinfo->output_width;
    190   /* copy these pointers into registers if possible */
    191   register JSAMPLE * range_limit = cinfo->sample_range_limit;
    192   register int * Crrtab = cconvert->Cr_r_tab;
    193   register int * Cbbtab = cconvert->Cb_b_tab;
    194   register INT32 * Crgtab = cconvert->Cr_g_tab;
    195   register INT32 * Cbgtab = cconvert->Cb_g_tab;
    196   SHIFT_TEMPS
    197 
    198   while (--num_rows >= 0) {
    199     inptr0 = input_buf[0][input_row];
    200     inptr1 = input_buf[1][input_row];
    201     inptr2 = input_buf[2][input_row];
    202     input_row++;
    203     outptr = *output_buf++;
    204     for (col = 0; col < num_cols; col++) {
    205       y  = GETJSAMPLE(inptr0[col]);
    206       cb = GETJSAMPLE(inptr1[col]);
    207       cr = GETJSAMPLE(inptr2[col]);
    208       /* Range-limiting is essential due to noise introduced by DCT losses. */
    209       outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
    210       outptr[RGB_GREEN] = range_limit[y +
    211                               ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
    212                                                  SCALEBITS))];
    213       outptr[RGB_BLUE] =  range_limit[y + Cbbtab[cb]];
    214       outptr[RGB_ALPHA] =  0xFF;
    215       outptr += 4;
    216     }
    217   }
    218 }
    219 
    220 METHODDEF(void)
    221 ycc_rgb_565_convert (j_decompress_ptr cinfo,
    222          JSAMPIMAGE input_buf, JDIMENSION input_row,
    223          JSAMPARRAY output_buf, int num_rows)
    224 {
    225   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    226   register int y, cb, cr;
    227   register JSAMPROW outptr;
    228   register JSAMPROW inptr0, inptr1, inptr2;
    229   register JDIMENSION col;
    230   JDIMENSION num_cols = cinfo->output_width;
    231   /* copy these pointers into registers if possible */
    232   register JSAMPLE * range_limit = cinfo->sample_range_limit;
    233   register int * Crrtab = cconvert->Cr_r_tab;
    234   register int * Cbbtab = cconvert->Cb_b_tab;
    235   register INT32 * Crgtab = cconvert->Cr_g_tab;
    236   register INT32 * Cbgtab = cconvert->Cb_g_tab;
    237   SHIFT_TEMPS
    238 
    239   while (--num_rows >= 0) {
    240     INT32 rgb;
    241     unsigned int r, g, b;
    242     inptr0 = input_buf[0][input_row];
    243     inptr1 = input_buf[1][input_row];
    244     inptr2 = input_buf[2][input_row];
    245     input_row++;
    246     outptr = *output_buf++;
    247 
    248     if (PACK_NEED_ALIGNMENT(outptr)) {
    249         y  = GETJSAMPLE(*inptr0++);
    250         cb = GETJSAMPLE(*inptr1++);
    251         cr = GETJSAMPLE(*inptr2++);
    252         r = range_limit[y + Crrtab[cr]];
    253         g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))];
    254         b = range_limit[y + Cbbtab[cb]];
    255         rgb = PACK_SHORT_565(r,g,b);
    256         *(INT16*)outptr = rgb;
    257         outptr += 2;
    258         num_cols--;
    259     }
    260     for (col = 0; col < (num_cols>>1); col++) {
    261       y  = GETJSAMPLE(*inptr0++);
    262       cb = GETJSAMPLE(*inptr1++);
    263       cr = GETJSAMPLE(*inptr2++);
    264       r = range_limit[y + Crrtab[cr]];
    265       g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))];
    266       b = range_limit[y + Cbbtab[cb]];
    267       rgb = PACK_SHORT_565(r,g,b);
    268 
    269       y  = GETJSAMPLE(*inptr0++);
    270       cb = GETJSAMPLE(*inptr1++);
    271       cr = GETJSAMPLE(*inptr2++);
    272       r = range_limit[y + Crrtab[cr]];
    273       g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))];
    274       b = range_limit[y + Cbbtab[cb]];
    275       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
    276       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    277       outptr += 4;
    278     }
    279     if (num_cols&1) {
    280       y  = GETJSAMPLE(*inptr0);
    281       cb = GETJSAMPLE(*inptr1);
    282       cr = GETJSAMPLE(*inptr2);
    283       r = range_limit[y + Crrtab[cr]];
    284       g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))];
    285       b = range_limit[y + Cbbtab[cb]];
    286       rgb = PACK_SHORT_565(r,g,b);
    287       *(INT16*)outptr = rgb;
    288     }
    289   }
    290 }
    291 
    292 METHODDEF(void)
    293 ycc_rgb_565D_convert (j_decompress_ptr cinfo,
    294          JSAMPIMAGE input_buf, JDIMENSION input_row,
    295          JSAMPARRAY output_buf, int num_rows)
    296 {
    297   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    298   register int y, cb, cr;
    299   register JSAMPROW outptr;
    300   register JSAMPROW inptr0, inptr1, inptr2;
    301   register JDIMENSION col;
    302   JDIMENSION num_cols = cinfo->output_width;
    303   /* copy these pointers into registers if possible */
    304   register JSAMPLE * range_limit = cinfo->sample_range_limit;
    305   register int * Crrtab = cconvert->Cr_r_tab;
    306   register int * Cbbtab = cconvert->Cb_b_tab;
    307   register INT32 * Crgtab = cconvert->Cr_g_tab;
    308   register INT32 * Cbgtab = cconvert->Cb_g_tab;
    309   INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
    310   SHIFT_TEMPS
    311 
    312   while (--num_rows >= 0) {
    313     INT32 rgb;
    314     unsigned int r, g, b;
    315     inptr0 = input_buf[0][input_row];
    316     inptr1 = input_buf[1][input_row];
    317     inptr2 = input_buf[2][input_row];
    318     input_row++;
    319     outptr = *output_buf++;
    320     if (PACK_NEED_ALIGNMENT(outptr)) {
    321         y  = GETJSAMPLE(*inptr0++);
    322         cb = GETJSAMPLE(*inptr1++);
    323         cr = GETJSAMPLE(*inptr2++);
    324         r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
    325         g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)];
    326         b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
    327         rgb = PACK_SHORT_565(r,g,b);
    328         *(INT16*)outptr = rgb;
    329         outptr += 2;
    330         num_cols--;
    331     }
    332     for (col = 0; col < (num_cols>>1); col++) {
    333       y  = GETJSAMPLE(*inptr0++);
    334       cb = GETJSAMPLE(*inptr1++);
    335       cr = GETJSAMPLE(*inptr2++);
    336       r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
    337       g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)];
    338       b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
    339       d0 = DITHER_ROTATE(d0);
    340       rgb = PACK_SHORT_565(r,g,b);
    341       y  = GETJSAMPLE(*inptr0++);
    342       cb = GETJSAMPLE(*inptr1++);
    343       cr = GETJSAMPLE(*inptr2++);
    344       r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
    345       g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)];
    346       b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
    347       d0 = DITHER_ROTATE(d0);
    348       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
    349       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    350       outptr += 4;
    351     }
    352     if (num_cols&1) {
    353       y  = GETJSAMPLE(*inptr0);
    354       cb = GETJSAMPLE(*inptr1);
    355       cr = GETJSAMPLE(*inptr2);
    356       r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
    357       g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)];
    358       b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
    359       rgb = PACK_SHORT_565(r,g,b);
    360       *(INT16*)outptr = rgb;
    361     }
    362   }
    363 }
    364 
    365 #endif
    366 
    367 /**************** Cases other than YCbCr -> RGB(A) **************/
    368 
    369 #ifdef ANDROID_RGB
    370 METHODDEF(void)
    371 rgb_rgba_8888_convert (j_decompress_ptr cinfo,
    372          JSAMPIMAGE input_buf, JDIMENSION input_row,
    373          JSAMPARRAY output_buf, int num_rows)
    374 {
    375   register JSAMPROW outptr;
    376   register JSAMPROW inptr0, inptr1, inptr2;
    377   register JDIMENSION col;
    378   JDIMENSION num_cols = cinfo->output_width;
    379   SHIFT_TEMPS
    380 
    381   while (--num_rows >= 0) {
    382     inptr0 = input_buf[0][input_row];
    383     inptr1 = input_buf[1][input_row];
    384     inptr2 = input_buf[2][input_row];
    385     input_row++;
    386     outptr = *output_buf++;
    387     for (col = 0; col < num_cols; col++) {
    388       *outptr++ = *inptr0++;
    389       *outptr++ = *inptr1++;
    390       *outptr++ = *inptr2++;
    391       *outptr++ = 0xFF;
    392     }
    393   }
    394 }
    395 
    396 METHODDEF(void)
    397 rgb_rgb_565_convert (j_decompress_ptr cinfo,
    398          JSAMPIMAGE input_buf, JDIMENSION input_row,
    399          JSAMPARRAY output_buf, int num_rows)
    400 {
    401   register JSAMPROW outptr;
    402   register JSAMPROW inptr0, inptr1, inptr2;
    403   register JDIMENSION col;
    404   JDIMENSION num_cols = cinfo->output_width;
    405   SHIFT_TEMPS
    406 
    407   while (--num_rows >= 0) {
    408     INT32 rgb;
    409     unsigned int r, g, b;
    410     inptr0 = input_buf[0][input_row];
    411     inptr1 = input_buf[1][input_row];
    412     inptr2 = input_buf[2][input_row];
    413     input_row++;
    414     outptr = *output_buf++;
    415     if (PACK_NEED_ALIGNMENT(outptr)) {
    416         r = GETJSAMPLE(*inptr0++);
    417         g = GETJSAMPLE(*inptr1++);
    418         b = GETJSAMPLE(*inptr2++);
    419         rgb = PACK_SHORT_565(r,g,b);
    420         *(INT16*)outptr = rgb;
    421         outptr += 2;
    422         num_cols--;
    423     }
    424     for (col = 0; col < (num_cols>>1); col++) {
    425       r = GETJSAMPLE(*inptr0++);
    426       g = GETJSAMPLE(*inptr1++);
    427       b = GETJSAMPLE(*inptr2++);
    428       rgb = PACK_SHORT_565(r,g,b);
    429       r = GETJSAMPLE(*inptr0++);
    430       g = GETJSAMPLE(*inptr1++);
    431       b = GETJSAMPLE(*inptr2++);
    432       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
    433       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    434       outptr += 4;
    435     }
    436     if (num_cols&1) {
    437       r = GETJSAMPLE(*inptr0);
    438       g = GETJSAMPLE(*inptr1);
    439       b = GETJSAMPLE(*inptr2);
    440       rgb = PACK_SHORT_565(r,g,b);
    441       *(INT16*)outptr = rgb;
    442     }
    443   }
    444 }
    445 
    446 
    447 METHODDEF(void)
    448 rgb_rgb_565D_convert (j_decompress_ptr cinfo,
    449          JSAMPIMAGE input_buf, JDIMENSION input_row,
    450          JSAMPARRAY output_buf, int num_rows)
    451 {
    452   register JSAMPROW outptr;
    453   register JSAMPROW inptr0, inptr1, inptr2;
    454   register JDIMENSION col;
    455   register JSAMPLE * range_limit = cinfo->sample_range_limit;
    456   JDIMENSION num_cols = cinfo->output_width;
    457   INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
    458   SHIFT_TEMPS
    459 
    460   while (--num_rows >= 0) {
    461     INT32 rgb;
    462     unsigned int r, g, b;
    463     inptr0 = input_buf[0][input_row];
    464     inptr1 = input_buf[1][input_row];
    465     inptr2 = input_buf[2][input_row];
    466     input_row++;
    467     outptr = *output_buf++;
    468     if (PACK_NEED_ALIGNMENT(outptr)) {
    469         r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
    470         g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
    471         b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
    472         rgb = PACK_SHORT_565(r,g,b);
    473         *(INT16*)outptr = rgb;
    474         outptr += 2;
    475         num_cols--;
    476     }
    477     for (col = 0; col < (num_cols>>1); col++) {
    478       r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
    479       g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
    480       b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
    481       d0 = DITHER_ROTATE(d0);
    482       rgb = PACK_SHORT_565(r,g,b);
    483       r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
    484       g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
    485       b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
    486       d0 = DITHER_ROTATE(d0);
    487       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
    488       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    489       outptr += 4;
    490     }
    491     if (num_cols&1) {
    492       r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0), d0)];
    493       g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1), d0)];
    494       b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2), d0)];
    495       rgb = PACK_SHORT_565(r,g,b);
    496       *(INT16*)outptr = rgb;
    497     }
    498   }
    499 }
    500 
    501 #endif
    502 
    503 /*
    504  * Color conversion for no colorspace change: just copy the data,
    505  * converting from separate-planes to interleaved representation.
    506  */
    507 
    508 METHODDEF(void)
    509 null_convert (j_decompress_ptr cinfo,
    510 	      JSAMPIMAGE input_buf, JDIMENSION input_row,
    511 	      JSAMPARRAY output_buf, int num_rows)
    512 {
    513   register JSAMPROW inptr, outptr;
    514   register JDIMENSION count;
    515   register int num_components = cinfo->num_components;
    516   JDIMENSION num_cols = cinfo->output_width;
    517   int ci;
    518 
    519   while (--num_rows >= 0) {
    520     for (ci = 0; ci < num_components; ci++) {
    521       inptr = input_buf[ci][input_row];
    522       outptr = output_buf[0] + ci;
    523       for (count = num_cols; count > 0; count--) {
    524 	*outptr = *inptr++;	/* needn't bother with GETJSAMPLE() here */
    525 	outptr += num_components;
    526       }
    527     }
    528     input_row++;
    529     output_buf++;
    530   }
    531 }
    532 
    533 
    534 /*
    535  * Color conversion for grayscale: just copy the data.
    536  * This also works for YCbCr -> grayscale conversion, in which
    537  * we just copy the Y (luminance) component and ignore chrominance.
    538  */
    539 
    540 METHODDEF(void)
    541 grayscale_convert (j_decompress_ptr cinfo,
    542 		   JSAMPIMAGE input_buf, JDIMENSION input_row,
    543 		   JSAMPARRAY output_buf, int num_rows)
    544 {
    545   jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
    546 		    num_rows, cinfo->output_width);
    547 }
    548 
    549 
    550 /*
    551  * Convert grayscale to RGB: just duplicate the graylevel three times.
    552  * This is provided to support applications that don't want to cope
    553  * with grayscale as a separate case.
    554  */
    555 
    556 METHODDEF(void)
    557 gray_rgb_convert (j_decompress_ptr cinfo,
    558 		  JSAMPIMAGE input_buf, JDIMENSION input_row,
    559 		  JSAMPARRAY output_buf, int num_rows)
    560 {
    561   register JSAMPROW inptr, outptr;
    562   register JDIMENSION col;
    563   JDIMENSION num_cols = cinfo->output_width;
    564 
    565   while (--num_rows >= 0) {
    566     inptr = input_buf[0][input_row++];
    567     outptr = *output_buf++;
    568     for (col = 0; col < num_cols; col++) {
    569       /* We can dispense with GETJSAMPLE() here */
    570       outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
    571       outptr += RGB_PIXELSIZE;
    572     }
    573   }
    574 }
    575 
    576 #ifdef ANDROID_RGB
    577 METHODDEF(void)
    578 gray_rgba_8888_convert (j_decompress_ptr cinfo,
    579           JSAMPIMAGE input_buf, JDIMENSION input_row,
    580           JSAMPARRAY output_buf, int num_rows)
    581 {
    582   register JSAMPROW inptr, outptr;
    583   register JDIMENSION col;
    584   JDIMENSION num_cols = cinfo->output_width;
    585 
    586   while (--num_rows >= 0) {
    587     inptr = input_buf[0][input_row++];
    588     outptr = *output_buf++;
    589     for (col = 0; col < num_cols; col++) {
    590       /* We can dispense with GETJSAMPLE() here */
    591       outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
    592       outptr[RGB_ALPHA] = 0xff;
    593       outptr += 4;
    594     }
    595   }
    596 }
    597 
    598 METHODDEF(void)
    599 gray_rgb_565_convert (j_decompress_ptr cinfo,
    600           JSAMPIMAGE input_buf, JDIMENSION input_row,
    601           JSAMPARRAY output_buf, int num_rows)
    602 {
    603   register JSAMPROW inptr, outptr;
    604   register JDIMENSION col;
    605   JDIMENSION num_cols = cinfo->output_width;
    606 
    607   while (--num_rows >= 0) {
    608     INT32 rgb;
    609     unsigned int g;
    610     inptr = input_buf[0][input_row++];
    611     outptr = *output_buf++;
    612     if (PACK_NEED_ALIGNMENT(outptr)) {
    613         g = *inptr++;
    614         rgb = PACK_SHORT_565(g, g, g);
    615         *(INT16*)outptr = rgb;
    616         outptr += 2;
    617         num_cols--;
    618     }
    619     for (col = 0; col < (num_cols>>1); col++) {
    620       g = *inptr++;
    621       rgb = PACK_SHORT_565(g, g, g);
    622       g = *inptr++;
    623       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g));
    624       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    625       outptr += 4;
    626     }
    627     if (num_cols&1) {
    628       g = *inptr;
    629       rgb = PACK_SHORT_565(g, g, g);
    630       *(INT16*)outptr = rgb;
    631     }
    632   }
    633 }
    634 
    635 METHODDEF(void)
    636 gray_rgb_565D_convert (j_decompress_ptr cinfo,
    637           JSAMPIMAGE input_buf, JDIMENSION input_row,
    638           JSAMPARRAY output_buf, int num_rows)
    639 {
    640   register JSAMPROW inptr, outptr;
    641   register JDIMENSION col;
    642   register JSAMPLE * range_limit = cinfo->sample_range_limit;
    643   JDIMENSION num_cols = cinfo->output_width;
    644   INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
    645 
    646   while (--num_rows >= 0) {
    647     INT32 rgb;
    648     unsigned int g;
    649     inptr = input_buf[0][input_row++];
    650     outptr = *output_buf++;
    651     if (PACK_NEED_ALIGNMENT(outptr)) {
    652         g = *inptr++;
    653         g = range_limit[DITHER_565_R(g, d0)];
    654         rgb = PACK_SHORT_565(g, g, g);
    655         *(INT16*)outptr = rgb;
    656         outptr += 2;
    657         num_cols--;
    658     }
    659     for (col = 0; col < (num_cols>>1); col++) {
    660       g = *inptr++;
    661       g = range_limit[DITHER_565_R(g, d0)];
    662       rgb = PACK_SHORT_565(g, g, g);
    663       d0 = DITHER_ROTATE(d0);
    664       g = *inptr++;
    665       g = range_limit[DITHER_565_R(g, d0)];
    666       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g));
    667       d0 = DITHER_ROTATE(d0);
    668       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    669       outptr += 4;
    670     }
    671     if (num_cols&1) {
    672       g = *inptr;
    673       g = range_limit[DITHER_565_R(g, d0)];
    674       rgb = PACK_SHORT_565(g, g, g);
    675       *(INT16*)outptr = rgb;
    676     }
    677   }
    678 }
    679 #endif
    680 
    681 /*
    682  * Adobe-style YCCK->CMYK conversion.
    683  * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
    684  * conversion as above, while passing K (black) unchanged.
    685  * We assume build_ycc_rgb_table has been called.
    686  */
    687 
    688 METHODDEF(void)
    689 ycck_cmyk_convert (j_decompress_ptr cinfo,
    690 		   JSAMPIMAGE input_buf, JDIMENSION input_row,
    691 		   JSAMPARRAY output_buf, int num_rows)
    692 {
    693   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    694   register int y, cb, cr;
    695   register JSAMPROW outptr;
    696   register JSAMPROW inptr0, inptr1, inptr2, inptr3;
    697   register JDIMENSION col;
    698   JDIMENSION num_cols = cinfo->output_width;
    699   /* copy these pointers into registers if possible */
    700   register JSAMPLE * range_limit = cinfo->sample_range_limit;
    701   register int * Crrtab = cconvert->Cr_r_tab;
    702   register int * Cbbtab = cconvert->Cb_b_tab;
    703   register INT32 * Crgtab = cconvert->Cr_g_tab;
    704   register INT32 * Cbgtab = cconvert->Cb_g_tab;
    705   SHIFT_TEMPS
    706 
    707   while (--num_rows >= 0) {
    708     inptr0 = input_buf[0][input_row];
    709     inptr1 = input_buf[1][input_row];
    710     inptr2 = input_buf[2][input_row];
    711     inptr3 = input_buf[3][input_row];
    712     input_row++;
    713     outptr = *output_buf++;
    714     for (col = 0; col < num_cols; col++) {
    715       y  = GETJSAMPLE(inptr0[col]);
    716       cb = GETJSAMPLE(inptr1[col]);
    717       cr = GETJSAMPLE(inptr2[col]);
    718       /* Range-limiting is essential due to noise introduced by DCT losses. */
    719       outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])];   /* red */
    720       outptr[1] = range_limit[MAXJSAMPLE - (y +                 /* green */
    721                               ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
    722                                                  SCALEBITS)))];
    723       outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])];   /* blue */
    724       /* K passes through unchanged */
    725       outptr[3] = inptr3[col];	/* don't need GETJSAMPLE here */
    726       outptr += 4;
    727     }
    728   }
    729 }
    730 
    731 
    732 /*
    733  * Empty method for start_pass.
    734  */
    735 
    736 METHODDEF(void)
    737 start_pass_dcolor (j_decompress_ptr cinfo)
    738 {
    739   /* no work needed */
    740 }
    741 
    742 
    743 /*
    744  * Module initialization routine for output colorspace conversion.
    745  */
    746 
    747 GLOBAL(void)
    748 jinit_color_deconverter (j_decompress_ptr cinfo)
    749 {
    750   my_cconvert_ptr cconvert;
    751   int ci;
    752 
    753   cconvert = (my_cconvert_ptr)
    754     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    755 				SIZEOF(my_color_deconverter));
    756   cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
    757   cconvert->pub.start_pass = start_pass_dcolor;
    758 
    759   /* Make sure num_components agrees with jpeg_color_space */
    760   switch (cinfo->jpeg_color_space) {
    761   case JCS_GRAYSCALE:
    762     if (cinfo->num_components != 1)
    763       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    764     break;
    765 
    766   case JCS_RGB:
    767   case JCS_YCbCr:
    768     if (cinfo->num_components != 3)
    769       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    770     break;
    771 
    772   case JCS_CMYK:
    773   case JCS_YCCK:
    774     if (cinfo->num_components != 4)
    775       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    776     break;
    777 
    778   default:			/* JCS_UNKNOWN can be anything */
    779     if (cinfo->num_components < 1)
    780       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
    781     break;
    782   }
    783 
    784   /* Set out_color_components and conversion method based on requested space.
    785    * Also clear the component_needed flags for any unused components,
    786    * so that earlier pipeline stages can avoid useless computation.
    787    */
    788 
    789   switch (cinfo->out_color_space) {
    790   case JCS_GRAYSCALE:
    791     cinfo->out_color_components = 1;
    792     if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
    793 	cinfo->jpeg_color_space == JCS_YCbCr) {
    794       cconvert->pub.color_convert = grayscale_convert;
    795       /* For color->grayscale conversion, only the Y (0) component is needed */
    796       for (ci = 1; ci < cinfo->num_components; ci++)
    797 	cinfo->comp_info[ci].component_needed = FALSE;
    798     } else
    799       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    800     break;
    801 
    802   case JCS_RGB:
    803     cinfo->out_color_components = RGB_PIXELSIZE;
    804     if (cinfo->jpeg_color_space == JCS_YCbCr) {
    805       cconvert->pub.color_convert = ycc_rgb_convert;
    806       build_ycc_rgb_table(cinfo);
    807     } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
    808       cconvert->pub.color_convert = gray_rgb_convert;
    809     } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
    810       cconvert->pub.color_convert = null_convert;
    811     } else
    812       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    813     break;
    814 
    815 #ifdef ANDROID_RGB
    816   case JCS_RGBA_8888:
    817     cinfo->out_color_components = 4;
    818     if (cinfo->jpeg_color_space == JCS_YCbCr) {
    819       cconvert->pub.color_convert = ycc_rgba_8888_convert;
    820       build_ycc_rgb_table(cinfo);
    821     } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
    822       cconvert->pub.color_convert = gray_rgba_8888_convert;
    823     } else if (cinfo->jpeg_color_space == JCS_RGB) {
    824       cconvert->pub.color_convert = rgb_rgba_8888_convert;
    825     } else
    826       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    827     break;
    828 
    829   case JCS_RGB_565:
    830     cinfo->out_color_components = RGB_PIXELSIZE;
    831     if (cinfo->dither_mode == JDITHER_NONE) {
    832       if (cinfo->jpeg_color_space == JCS_YCbCr) {
    833         cconvert->pub.color_convert = ycc_rgb_565_convert;
    834         build_ycc_rgb_table(cinfo);
    835       } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
    836         cconvert->pub.color_convert = gray_rgb_565_convert;
    837       } else if (cinfo->jpeg_color_space == JCS_RGB) {
    838         cconvert->pub.color_convert = rgb_rgb_565_convert;
    839       } else
    840         ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    841     } else {
    842       /* only ordered dither is supported */
    843       if (cinfo->jpeg_color_space == JCS_YCbCr) {
    844         cconvert->pub.color_convert = ycc_rgb_565D_convert;
    845         build_ycc_rgb_table(cinfo);
    846       } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
    847         cconvert->pub.color_convert = gray_rgb_565D_convert;
    848       } else if (cinfo->jpeg_color_space == JCS_RGB) {
    849         cconvert->pub.color_convert = rgb_rgb_565D_convert;
    850       } else
    851         ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    852     }
    853     break;
    854 #endif
    855 
    856   case JCS_CMYK:
    857     cinfo->out_color_components = 4;
    858     if (cinfo->jpeg_color_space == JCS_YCCK) {
    859       cconvert->pub.color_convert = ycck_cmyk_convert;
    860       build_ycc_rgb_table(cinfo);
    861     } else if (cinfo->jpeg_color_space == JCS_CMYK) {
    862       cconvert->pub.color_convert = null_convert;
    863     } else
    864       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    865     break;
    866 
    867   default:
    868     /* Permit null conversion to same output space */
    869     if (cinfo->out_color_space == cinfo->jpeg_color_space) {
    870       cinfo->out_color_components = cinfo->num_components;
    871       cconvert->pub.color_convert = null_convert;
    872     } else			/* unsupported non-null conversion */
    873       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
    874     break;
    875   }
    876 
    877   if (cinfo->quantize_colors)
    878     cinfo->output_components = 1; /* single colormapped output component */
    879   else
    880     cinfo->output_components = cinfo->out_color_components;
    881 }
    882