Home | History | Annotate | Download | only in libjpeg-turbo
      1 /*
      2  * jdcol565.c
      3  *
      4  * This file was part of the Independent JPEG Group's software:
      5  * Copyright (C) 1991-1997, Thomas G. Lane.
      6  * Modifications:
      7  * Copyright (C) 2013, Linaro Limited.
      8  * Copyright (C) 2014-2015, D. R. Commander.
      9  * For conditions of distribution and use, see the accompanying README.ijg
     10  * file.
     11  *
     12  * This file contains output colorspace conversion routines.
     13  */
     14 
     15 /* This file is included by jdcolor.c */
     16 
     17 
     18 INLINE
     19 LOCAL(void)
     20 ycc_rgb565_convert_internal (j_decompress_ptr cinfo,
     21                              JSAMPIMAGE input_buf, JDIMENSION input_row,
     22                              JSAMPARRAY output_buf, int num_rows)
     23 {
     24   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
     25   register int y, cb, cr;
     26   register JSAMPROW outptr;
     27   register JSAMPROW inptr0, inptr1, inptr2;
     28   register JDIMENSION col;
     29   JDIMENSION num_cols = cinfo->output_width;
     30   /* copy these pointers into registers if possible */
     31   register JSAMPLE * range_limit = cinfo->sample_range_limit;
     32   register int * Crrtab = cconvert->Cr_r_tab;
     33   register int * Cbbtab = cconvert->Cb_b_tab;
     34   register JLONG * Crgtab = cconvert->Cr_g_tab;
     35   register JLONG * Cbgtab = cconvert->Cb_g_tab;
     36   SHIFT_TEMPS
     37 
     38   while (--num_rows >= 0) {
     39     JLONG rgb;
     40     unsigned int r, g, b;
     41     inptr0 = input_buf[0][input_row];
     42     inptr1 = input_buf[1][input_row];
     43     inptr2 = input_buf[2][input_row];
     44     input_row++;
     45     outptr = *output_buf++;
     46 
     47     if (PACK_NEED_ALIGNMENT(outptr)) {
     48       y  = GETJSAMPLE(*inptr0++);
     49       cb = GETJSAMPLE(*inptr1++);
     50       cr = GETJSAMPLE(*inptr2++);
     51       r = range_limit[y + Crrtab[cr]];
     52       g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
     53                                             SCALEBITS))];
     54       b = range_limit[y + Cbbtab[cb]];
     55       rgb = PACK_SHORT_565(r, g, b);
     56       *(INT16*)outptr = (INT16)rgb;
     57       outptr += 2;
     58       num_cols--;
     59     }
     60     for (col = 0; col < (num_cols >> 1); col++) {
     61       y  = GETJSAMPLE(*inptr0++);
     62       cb = GETJSAMPLE(*inptr1++);
     63       cr = GETJSAMPLE(*inptr2++);
     64       r = range_limit[y + Crrtab[cr]];
     65       g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
     66                                             SCALEBITS))];
     67       b = range_limit[y + Cbbtab[cb]];
     68       rgb = PACK_SHORT_565(r, g, b);
     69 
     70       y  = GETJSAMPLE(*inptr0++);
     71       cb = GETJSAMPLE(*inptr1++);
     72       cr = GETJSAMPLE(*inptr2++);
     73       r = range_limit[y + Crrtab[cr]];
     74       g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
     75                                             SCALEBITS))];
     76       b = range_limit[y + Cbbtab[cb]];
     77       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
     78 
     79       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
     80       outptr += 4;
     81     }
     82     if (num_cols & 1) {
     83       y  = GETJSAMPLE(*inptr0);
     84       cb = GETJSAMPLE(*inptr1);
     85       cr = GETJSAMPLE(*inptr2);
     86       r = range_limit[y + Crrtab[cr]];
     87       g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
     88                                             SCALEBITS))];
     89       b = range_limit[y + Cbbtab[cb]];
     90       rgb = PACK_SHORT_565(r, g, b);
     91       *(INT16*)outptr = (INT16)rgb;
     92     }
     93   }
     94 }
     95 
     96 
     97 INLINE
     98 LOCAL(void)
     99 ycc_rgb565D_convert_internal (j_decompress_ptr cinfo,
    100                               JSAMPIMAGE input_buf, JDIMENSION input_row,
    101                               JSAMPARRAY output_buf, int num_rows)
    102 {
    103   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    104   register int y, cb, cr;
    105   register JSAMPROW outptr;
    106   register JSAMPROW inptr0, inptr1, inptr2;
    107   register JDIMENSION col;
    108   JDIMENSION num_cols = cinfo->output_width;
    109   /* copy these pointers into registers if possible */
    110   register JSAMPLE * range_limit = cinfo->sample_range_limit;
    111   register int * Crrtab = cconvert->Cr_r_tab;
    112   register int * Cbbtab = cconvert->Cb_b_tab;
    113   register JLONG * Crgtab = cconvert->Cr_g_tab;
    114   register JLONG * Cbgtab = cconvert->Cb_g_tab;
    115   JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
    116   SHIFT_TEMPS
    117 
    118   while (--num_rows >= 0) {
    119     JLONG rgb;
    120     unsigned int r, g, b;
    121 
    122     inptr0 = input_buf[0][input_row];
    123     inptr1 = input_buf[1][input_row];
    124     inptr2 = input_buf[2][input_row];
    125     input_row++;
    126     outptr = *output_buf++;
    127     if (PACK_NEED_ALIGNMENT(outptr)) {
    128       y  = GETJSAMPLE(*inptr0++);
    129       cb = GETJSAMPLE(*inptr1++);
    130       cr = GETJSAMPLE(*inptr2++);
    131       r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
    132       g = range_limit[DITHER_565_G(y +
    133                                    ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
    134                                                      SCALEBITS)), d0)];
    135       b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
    136       rgb = PACK_SHORT_565(r, g, b);
    137       *(INT16*)outptr = (INT16)rgb;
    138       outptr += 2;
    139       num_cols--;
    140     }
    141     for (col = 0; col < (num_cols >> 1); col++) {
    142       y  = GETJSAMPLE(*inptr0++);
    143       cb = GETJSAMPLE(*inptr1++);
    144       cr = GETJSAMPLE(*inptr2++);
    145       r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
    146       g = range_limit[DITHER_565_G(y +
    147                                    ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
    148                                                      SCALEBITS)), d0)];
    149       b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
    150       d0 = DITHER_ROTATE(d0);
    151       rgb = PACK_SHORT_565(r, g, b);
    152 
    153       y  = GETJSAMPLE(*inptr0++);
    154       cb = GETJSAMPLE(*inptr1++);
    155       cr = GETJSAMPLE(*inptr2++);
    156       r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
    157       g = range_limit[DITHER_565_G(y +
    158                                    ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
    159                                                      SCALEBITS)), d0)];
    160       b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
    161       d0 = DITHER_ROTATE(d0);
    162       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
    163 
    164       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    165       outptr += 4;
    166     }
    167     if (num_cols & 1) {
    168       y  = GETJSAMPLE(*inptr0);
    169       cb = GETJSAMPLE(*inptr1);
    170       cr = GETJSAMPLE(*inptr2);
    171       r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
    172       g = range_limit[DITHER_565_G(y +
    173                                    ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
    174                                                      SCALEBITS)), d0)];
    175       b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
    176       rgb = PACK_SHORT_565(r, g, b);
    177       *(INT16*)outptr = (INT16)rgb;
    178     }
    179   }
    180 }
    181 
    182 
    183 INLINE
    184 LOCAL(void)
    185 rgb_rgb565_convert_internal (j_decompress_ptr cinfo,
    186                              JSAMPIMAGE input_buf, JDIMENSION input_row,
    187                              JSAMPARRAY output_buf, int num_rows)
    188 {
    189   register JSAMPROW outptr;
    190   register JSAMPROW inptr0, inptr1, inptr2;
    191   register JDIMENSION col;
    192   JDIMENSION num_cols = cinfo->output_width;
    193   SHIFT_TEMPS
    194 
    195   while (--num_rows >= 0) {
    196     JLONG rgb;
    197     unsigned int r, g, b;
    198 
    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     if (PACK_NEED_ALIGNMENT(outptr)) {
    205       r = GETJSAMPLE(*inptr0++);
    206       g = GETJSAMPLE(*inptr1++);
    207       b = GETJSAMPLE(*inptr2++);
    208       rgb = PACK_SHORT_565(r, g, b);
    209       *(INT16*)outptr = (INT16)rgb;
    210       outptr += 2;
    211       num_cols--;
    212     }
    213     for (col = 0; col < (num_cols >> 1); col++) {
    214       r = GETJSAMPLE(*inptr0++);
    215       g = GETJSAMPLE(*inptr1++);
    216       b = GETJSAMPLE(*inptr2++);
    217       rgb = PACK_SHORT_565(r, g, b);
    218 
    219       r = GETJSAMPLE(*inptr0++);
    220       g = GETJSAMPLE(*inptr1++);
    221       b = GETJSAMPLE(*inptr2++);
    222       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
    223 
    224       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    225       outptr += 4;
    226     }
    227     if (num_cols & 1) {
    228       r = GETJSAMPLE(*inptr0);
    229       g = GETJSAMPLE(*inptr1);
    230       b = GETJSAMPLE(*inptr2);
    231       rgb = PACK_SHORT_565(r, g, b);
    232       *(INT16*)outptr = (INT16)rgb;
    233     }
    234   }
    235 }
    236 
    237 
    238 INLINE
    239 LOCAL(void)
    240 rgb_rgb565D_convert_internal (j_decompress_ptr cinfo,
    241                               JSAMPIMAGE input_buf, JDIMENSION input_row,
    242                               JSAMPARRAY output_buf, int num_rows)
    243 {
    244   register JSAMPROW outptr;
    245   register JSAMPROW inptr0, inptr1, inptr2;
    246   register JDIMENSION col;
    247   register JSAMPLE * range_limit = cinfo->sample_range_limit;
    248   JDIMENSION num_cols = cinfo->output_width;
    249   JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
    250   SHIFT_TEMPS
    251 
    252   while (--num_rows >= 0) {
    253     JLONG rgb;
    254     unsigned int r, g, b;
    255 
    256     inptr0 = input_buf[0][input_row];
    257     inptr1 = input_buf[1][input_row];
    258     inptr2 = input_buf[2][input_row];
    259     input_row++;
    260     outptr = *output_buf++;
    261     if (PACK_NEED_ALIGNMENT(outptr)) {
    262       r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
    263       g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
    264       b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
    265       rgb = PACK_SHORT_565(r, g, b);
    266       *(INT16*)outptr = (INT16)rgb;
    267       outptr += 2;
    268       num_cols--;
    269     }
    270     for (col = 0; col < (num_cols >> 1); col++) {
    271       r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
    272       g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
    273       b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
    274       d0 = DITHER_ROTATE(d0);
    275       rgb = PACK_SHORT_565(r, g, b);
    276 
    277       r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
    278       g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
    279       b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
    280       d0 = DITHER_ROTATE(d0);
    281       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
    282 
    283       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    284       outptr += 4;
    285     }
    286     if (num_cols & 1) {
    287       r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0), d0)];
    288       g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1), d0)];
    289       b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2), d0)];
    290       rgb = PACK_SHORT_565(r, g, b);
    291       *(INT16*)outptr = (INT16)rgb;
    292     }
    293   }
    294 }
    295 
    296 
    297 INLINE
    298 LOCAL(void)
    299 gray_rgb565_convert_internal (j_decompress_ptr cinfo,
    300                               JSAMPIMAGE input_buf, JDIMENSION input_row,
    301                               JSAMPARRAY output_buf, int num_rows)
    302 {
    303   register JSAMPROW inptr, outptr;
    304   register JDIMENSION col;
    305   JDIMENSION num_cols = cinfo->output_width;
    306 
    307   while (--num_rows >= 0) {
    308     JLONG rgb;
    309     unsigned int g;
    310 
    311     inptr = input_buf[0][input_row++];
    312     outptr = *output_buf++;
    313     if (PACK_NEED_ALIGNMENT(outptr)) {
    314       g = *inptr++;
    315       rgb = PACK_SHORT_565(g, g, g);
    316       *(INT16*)outptr = (INT16)rgb;
    317       outptr += 2;
    318       num_cols--;
    319     }
    320     for (col = 0; col < (num_cols >> 1); col++) {
    321       g = *inptr++;
    322       rgb = PACK_SHORT_565(g, g, g);
    323       g = *inptr++;
    324       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g));
    325       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    326       outptr += 4;
    327     }
    328     if (num_cols & 1) {
    329       g = *inptr;
    330       rgb = PACK_SHORT_565(g, g, g);
    331       *(INT16*)outptr = (INT16)rgb;
    332     }
    333   }
    334 }
    335 
    336 
    337 INLINE
    338 LOCAL(void)
    339 gray_rgb565D_convert_internal (j_decompress_ptr cinfo,
    340                                JSAMPIMAGE input_buf, JDIMENSION input_row,
    341                                JSAMPARRAY output_buf, int num_rows)
    342 {
    343   register JSAMPROW inptr, outptr;
    344   register JDIMENSION col;
    345   register JSAMPLE * range_limit = cinfo->sample_range_limit;
    346   JDIMENSION num_cols = cinfo->output_width;
    347   JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
    348 
    349   while (--num_rows >= 0) {
    350     JLONG rgb;
    351     unsigned int g;
    352 
    353     inptr = input_buf[0][input_row++];
    354     outptr = *output_buf++;
    355     if (PACK_NEED_ALIGNMENT(outptr)) {
    356       g = *inptr++;
    357       g = range_limit[DITHER_565_R(g, d0)];
    358       rgb = PACK_SHORT_565(g, g, g);
    359       *(INT16*)outptr = (INT16)rgb;
    360       outptr += 2;
    361       num_cols--;
    362     }
    363     for (col = 0; col < (num_cols >> 1); col++) {
    364       g = *inptr++;
    365       g = range_limit[DITHER_565_R(g, d0)];
    366       rgb = PACK_SHORT_565(g, g, g);
    367       d0 = DITHER_ROTATE(d0);
    368 
    369       g = *inptr++;
    370       g = range_limit[DITHER_565_R(g, d0)];
    371       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g));
    372       d0 = DITHER_ROTATE(d0);
    373 
    374       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
    375       outptr += 4;
    376     }
    377     if (num_cols & 1) {
    378       g = *inptr;
    379       g = range_limit[DITHER_565_R(g, d0)];
    380       rgb = PACK_SHORT_565(g, g, g);
    381       *(INT16*)outptr = (INT16)rgb;
    382     }
    383   }
    384 }
    385