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