DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

jdcolor.cpp (14097B)


      1 /*
      2  * jdcolor.c
      3  *
      4  * Copyright (C) 1991-1995, 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 /**************** YCbCr -> RGB conversion: most common case **************/
     32 
     33 /*
     34  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
     35  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
     36  * The conversion equations to be implemented are therefore
     37  *	R = Y                + 1.40200 * Cr
     38  *	G = Y - 0.34414 * Cb - 0.71414 * Cr
     39  *	B = Y + 1.77200 * Cb
     40  * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
     41  * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
     42  *
     43  * To avoid floating-point arithmetic, we represent the fractional constants
     44  * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
     45  * the products by 2^16, with appropriate rounding, to get the correct answer.
     46  * Notice that Y, being an integral input, does not contribute any fraction
     47  * so it need not participate in the rounding.
     48  *
     49  * For even more speed, we avoid doing any multiplications in the inner loop
     50  * by precalculating the constants times Cb and Cr for all possible values.
     51  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
     52  * for 12-bit samples it is still acceptable.  It's not very reasonable for
     53  * 16-bit samples, but if you want lossless storage you shouldn't be changing
     54  * colorspace anyway.
     55  * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
     56  * values for the G calculation are left scaled up, since we must add them
     57  * together before rounding.
     58  */
     59 
     60 #define SCALEBITS   16  /* speediest right-shift on some machines */
     61 #define ONE_HALF    ( (INT32) 1 << ( SCALEBITS - 1 ) )
     62 #define FIX( x )      ( (INT32) ( ( x ) * ( 1L << SCALEBITS ) + 0.5 ) )
     63 
     64 
     65 /*
     66  * Initialize tables for YCC->RGB colorspace conversion.
     67  */
     68 
     69 LOCAL void
     70 build_ycc_rgb_table( j_decompress_ptr cinfo ) {
     71     my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
     72     int i;
     73     INT32 x;
     74     SHIFT_TEMPS
     75 
     76     cconvert->Cr_r_tab = (int *)
     77                          ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
     78                                                       ( MAXJSAMPLE + 1 ) * SIZEOF( int ) );
     79     cconvert->Cb_b_tab = (int *)
     80                          ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
     81                                                       ( MAXJSAMPLE + 1 ) * SIZEOF( int ) );
     82     cconvert->Cr_g_tab = (INT32 *)
     83                          ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
     84                                                       ( MAXJSAMPLE + 1 ) * SIZEOF( INT32 ) );
     85     cconvert->Cb_g_tab = (INT32 *)
     86                          ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
     87                                                       ( MAXJSAMPLE + 1 ) * SIZEOF( INT32 ) );
     88 
     89     for ( i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++ ) {
     90         /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
     91         /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
     92         /* Cr=>R value is nearest int to 1.40200 * x */
     93         cconvert->Cr_r_tab[i] = (int)
     94                                 RIGHT_SHIFT( FIX( 1.40200 ) * x + ONE_HALF, SCALEBITS );
     95         /* Cb=>B value is nearest int to 1.77200 * x */
     96         cconvert->Cb_b_tab[i] = (int)
     97                                 RIGHT_SHIFT( FIX( 1.77200 ) * x + ONE_HALF, SCALEBITS );
     98         /* Cr=>G value is scaled-up -0.71414 * x */
     99         cconvert->Cr_g_tab[i] = ( -FIX( 0.71414 ) ) * x;
    100         /* Cb=>G value is scaled-up -0.34414 * x */
    101         /* We also add in ONE_HALF so that need not do it in inner loop */
    102         cconvert->Cb_g_tab[i] = ( -FIX( 0.34414 ) ) * x + ONE_HALF;
    103     }
    104 }
    105 
    106 
    107 /*
    108  * Convert some rows of samples to the output colorspace.
    109  *
    110  * Note that we change from noninterleaved, one-plane-per-component format
    111  * to interleaved-pixel format.  The output buffer is therefore three times
    112  * as wide as the input buffer.
    113  * A starting row offset is provided only for the input buffer.  The caller
    114  * can easily adjust the passed output_buf value to accommodate any row
    115  * offset required on that side.
    116  */
    117 
    118 METHODDEF void
    119 ycc_rgb_convert( j_decompress_ptr cinfo,
    120                  JSAMPIMAGE input_buf, JDIMENSION input_row,
    121                  JSAMPARRAY output_buf, int num_rows ) {
    122     my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    123     register int y, cb, cr;
    124     register JSAMPROW outptr;
    125     register JSAMPROW inptr0, inptr1, inptr2;
    126     register JDIMENSION col;
    127     JDIMENSION num_cols = cinfo->output_width;
    128     /* copy these pointers into registers if possible */
    129     register JSAMPLE * range_limit = cinfo->sample_range_limit;
    130     register int * Crrtab = cconvert->Cr_r_tab;
    131     register int * Cbbtab = cconvert->Cb_b_tab;
    132     register INT32 * Crgtab = cconvert->Cr_g_tab;
    133     register INT32 * Cbgtab = cconvert->Cb_g_tab;
    134     SHIFT_TEMPS
    135 
    136     while ( --num_rows >= 0 ) {
    137         inptr0 = input_buf[0][input_row];
    138         inptr1 = input_buf[1][input_row];
    139         inptr2 = input_buf[2][input_row];
    140         input_row++;
    141         outptr = *output_buf++;
    142         for ( col = 0; col < num_cols; col++ ) {
    143             y  = GETJSAMPLE( inptr0[col] );
    144             cb = GETJSAMPLE( inptr1[col] );
    145             cr = GETJSAMPLE( inptr2[col] );
    146             /* Range-limiting is essential due to noise introduced by DCT losses. */
    147             outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
    148             outptr[RGB_GREEN] = range_limit[y +
    149                                             ( (int) RIGHT_SHIFT( Cbgtab[cb] + Crgtab[cr],
    150                                                                  SCALEBITS ) )];
    151             outptr[RGB_BLUE] =  range_limit[y + Cbbtab[cb]];
    152             outptr += RGB_PIXELSIZE;
    153         }
    154     }
    155 }
    156 
    157 
    158 /**************** Cases other than YCbCr -> RGB **************/
    159 
    160 
    161 /*
    162  * Color conversion for no colorspace change: just copy the data,
    163  * converting from separate-planes to interleaved representation.
    164  */
    165 
    166 METHODDEF void
    167 null_convert( j_decompress_ptr cinfo,
    168               JSAMPIMAGE input_buf, JDIMENSION input_row,
    169               JSAMPARRAY output_buf, int num_rows ) {
    170     register JSAMPROW inptr, outptr;
    171     register JDIMENSION count;
    172     register int num_components = cinfo->num_components;
    173     JDIMENSION num_cols = cinfo->output_width;
    174     int ci;
    175 
    176     while ( --num_rows >= 0 ) {
    177         for ( ci = 0; ci < num_components; ci++ ) {
    178             inptr = input_buf[ci][input_row];
    179             outptr = output_buf[0] + ci;
    180             for ( count = num_cols; count > 0; count-- ) {
    181                 *outptr = *inptr++;/* needn't bother with GETJSAMPLE() here */
    182                 outptr += num_components;
    183             }
    184         }
    185         input_row++;
    186         output_buf++;
    187     }
    188 }
    189 
    190 
    191 /*
    192  * Color conversion for grayscale: just copy the data.
    193  * This also works for YCbCr -> grayscale conversion, in which
    194  * we just copy the Y (luminance) component and ignore chrominance.
    195  */
    196 
    197 METHODDEF void
    198 grayscale_convert( j_decompress_ptr cinfo,
    199                    JSAMPIMAGE input_buf, JDIMENSION input_row,
    200                    JSAMPARRAY output_buf, int num_rows ) {
    201     jcopy_sample_rows( input_buf[0], (int) input_row, output_buf, 0,
    202                        num_rows, cinfo->output_width );
    203 }
    204 
    205 
    206 /*
    207  * Adobe-style YCCK->CMYK conversion.
    208  * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
    209  * conversion as above, while passing K (black) unchanged.
    210  * We assume build_ycc_rgb_table has been called.
    211  */
    212 
    213 METHODDEF void
    214 ycck_cmyk_convert( j_decompress_ptr cinfo,
    215                    JSAMPIMAGE input_buf, JDIMENSION input_row,
    216                    JSAMPARRAY output_buf, int num_rows ) {
    217     my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    218     register int y, cb, cr;
    219     register JSAMPROW outptr;
    220     register JSAMPROW inptr0, inptr1, inptr2, inptr3;
    221     register JDIMENSION col;
    222     JDIMENSION num_cols = cinfo->output_width;
    223     /* copy these pointers into registers if possible */
    224     register JSAMPLE * range_limit = cinfo->sample_range_limit;
    225     register int * Crrtab = cconvert->Cr_r_tab;
    226     register int * Cbbtab = cconvert->Cb_b_tab;
    227     register INT32 * Crgtab = cconvert->Cr_g_tab;
    228     register INT32 * Cbgtab = cconvert->Cb_g_tab;
    229     SHIFT_TEMPS
    230 
    231     while ( --num_rows >= 0 ) {
    232         inptr0 = input_buf[0][input_row];
    233         inptr1 = input_buf[1][input_row];
    234         inptr2 = input_buf[2][input_row];
    235         inptr3 = input_buf[3][input_row];
    236         input_row++;
    237         outptr = *output_buf++;
    238         for ( col = 0; col < num_cols; col++ ) {
    239             y  = GETJSAMPLE( inptr0[col] );
    240             cb = GETJSAMPLE( inptr1[col] );
    241             cr = GETJSAMPLE( inptr2[col] );
    242             /* Range-limiting is essential due to noise introduced by DCT losses. */
    243             outptr[0] = range_limit[MAXJSAMPLE - ( y + Crrtab[cr] )];/* red */
    244             outptr[1] = range_limit[MAXJSAMPLE - ( y +  /* green */
    245                                                   ( (int) RIGHT_SHIFT( Cbgtab[cb] + Crgtab[cr],
    246                                                                        SCALEBITS ) ) )];
    247             outptr[2] = range_limit[MAXJSAMPLE - ( y + Cbbtab[cb] )];/* blue */
    248             /* K passes through unchanged */
    249             outptr[3] = inptr3[col];/* don't need GETJSAMPLE here */
    250             outptr += 4;
    251         }
    252     }
    253 }
    254 
    255 
    256 /*
    257  * Empty method for start_pass.
    258  */
    259 
    260 METHODDEF void
    261 start_pass_dcolor( j_decompress_ptr cinfo ) {
    262     /* no work needed */
    263 }
    264 
    265 
    266 /*
    267  * Module initialization routine for output colorspace conversion.
    268  */
    269 
    270 GLOBAL void
    271 jinit_color_deconverter( j_decompress_ptr cinfo ) {
    272     my_cconvert_ptr cconvert;
    273     int ci;
    274 
    275     cconvert = (my_cconvert_ptr)
    276                ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
    277                                             SIZEOF( my_color_deconverter ) );
    278     cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
    279     cconvert->pub.start_pass = start_pass_dcolor;
    280 
    281     /* Make sure num_components agrees with jpeg_color_space */
    282     switch ( cinfo->jpeg_color_space ) {
    283         case JCS_GRAYSCALE:
    284             if ( cinfo->num_components != 1 ) {
    285                 ERREXIT( cinfo, JERR_BAD_J_COLORSPACE );
    286             }
    287             break;
    288 
    289         case JCS_RGB:
    290         case JCS_YCbCr:
    291             if ( cinfo->num_components != 3 ) {
    292                 ERREXIT( cinfo, JERR_BAD_J_COLORSPACE );
    293             }
    294             break;
    295 
    296         case JCS_CMYK:
    297         case JCS_YCCK:
    298             if ( cinfo->num_components != 4 ) {
    299                 ERREXIT( cinfo, JERR_BAD_J_COLORSPACE );
    300             }
    301             break;
    302 
    303         default:    /* JCS_UNKNOWN can be anything */
    304             if ( cinfo->num_components < 1 ) {
    305                 ERREXIT( cinfo, JERR_BAD_J_COLORSPACE );
    306             }
    307             break;
    308     }
    309 
    310     /* Set out_color_components and conversion method based on requested space.
    311      * Also clear the component_needed flags for any unused components,
    312      * so that earlier pipeline stages can avoid useless computation.
    313      */
    314 
    315     switch ( cinfo->out_color_space ) {
    316         case JCS_GRAYSCALE:
    317             cinfo->out_color_components = 1;
    318             if ( ( cinfo->jpeg_color_space == JCS_GRAYSCALE ) ||
    319                 ( cinfo->jpeg_color_space == JCS_YCbCr ) ) {
    320                 cconvert->pub.color_convert = grayscale_convert;
    321                 /* For color->grayscale conversion, only the Y (0) component is needed */
    322                 for ( ci = 1; ci < cinfo->num_components; ci++ ) {
    323                     cinfo->comp_info[ci].component_needed = FALSE;
    324                 }
    325             } else {
    326                 ERREXIT( cinfo, JERR_CONVERSION_NOTIMPL );
    327             }
    328             break;
    329 
    330         case JCS_RGB:
    331             cinfo->out_color_components = RGB_PIXELSIZE;
    332             if ( cinfo->jpeg_color_space == JCS_YCbCr ) {
    333                 cconvert->pub.color_convert = ycc_rgb_convert;
    334                 build_ycc_rgb_table( cinfo );
    335             } else if ( cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3 ) {
    336                 cconvert->pub.color_convert = null_convert;
    337             } else {
    338                 ERREXIT( cinfo, JERR_CONVERSION_NOTIMPL );
    339             }
    340             break;
    341 
    342         case JCS_CMYK:
    343             cinfo->out_color_components = 4;
    344             if ( cinfo->jpeg_color_space == JCS_YCCK ) {
    345                 cconvert->pub.color_convert = ycck_cmyk_convert;
    346                 build_ycc_rgb_table( cinfo );
    347             } else if ( cinfo->jpeg_color_space == JCS_CMYK ) {
    348                 cconvert->pub.color_convert = null_convert;
    349             } else {
    350                 ERREXIT( cinfo, JERR_CONVERSION_NOTIMPL );
    351             }
    352             break;
    353 
    354         default:
    355             /* Permit null conversion to same output space */
    356             if ( cinfo->out_color_space == cinfo->jpeg_color_space ) {
    357                 cinfo->out_color_components = cinfo->num_components;
    358                 cconvert->pub.color_convert = null_convert;
    359             } else {/* unsupported non-null conversion */
    360                 ERREXIT( cinfo, JERR_CONVERSION_NOTIMPL );
    361             }
    362             break;
    363     }
    364 
    365     if ( cinfo->quantize_colors ) {
    366         cinfo->output_components = 1;
    367     }                             /* single colormapped output component */
    368     else {
    369         cinfo->output_components = cinfo->out_color_components;
    370     }
    371 }