DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

jccolor.cpp (17408B)


      1 /*
      2  * jccolor.c
      3  *
      4  * Copyright (C) 1991-1994, 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 input 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_converter pub;/* public fields */
     20 
     21     /* Private state for RGB->YCC conversion */
     22     INT32 * rgb_ycc_tab;    /* => table for RGB to YCbCr conversion */
     23 } my_color_converter;
     24 
     25 typedef my_color_converter * my_cconvert_ptr;
     26 
     27 
     28 /**************** RGB -> YCbCr conversion: most common case **************/
     29 
     30 /*
     31  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
     32  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
     33  * The conversion equations to be implemented are therefore
     34  *	Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
     35  *	Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B  + CENTERJSAMPLE
     36  *	Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B  + CENTERJSAMPLE
     37  * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
     38  * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
     39  * rather than CENTERJSAMPLE, for Cb and Cr.  This gave equal positive and
     40  * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
     41  * were not represented exactly.  Now we sacrifice exact representation of
     42  * maximum red and maximum blue in order to get exact grayscales.
     43  *
     44  * To avoid floating-point arithmetic, we represent the fractional constants
     45  * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
     46  * the products by 2^16, with appropriate rounding, to get the correct answer.
     47  *
     48  * For even more speed, we avoid doing any multiplications in the inner loop
     49  * by precalculating the constants times R,G,B for all possible values.
     50  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
     51  * for 12-bit samples it is still acceptable.  It's not very reasonable for
     52  * 16-bit samples, but if you want lossless storage you shouldn't be changing
     53  * colorspace anyway.
     54  * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
     55  * in the tables to save adding them separately in the inner loop.
     56  */
     57 
     58 #define SCALEBITS   16  /* speediest right-shift on some machines */
     59 #define CBCR_OFFSET ( (INT32) CENTERJSAMPLE << SCALEBITS )
     60 #define ONE_HALF    ( (INT32) 1 << ( SCALEBITS - 1 ) )
     61 #define FIX( x )      ( (INT32) ( ( x ) * ( 1L << SCALEBITS ) + 0.5 ) )
     62 
     63 /* We allocate one big table and divide it up into eight parts, instead of
     64  * doing eight alloc_small requests.  This lets us use a single table base
     65  * address, which can be held in a register in the inner loops on many
     66  * machines (more than can hold all eight addresses, anyway).
     67  */
     68 
     69 #define R_Y_OFF     0           /* offset to R => Y section */
     70 #define G_Y_OFF     ( 1 * ( MAXJSAMPLE + 1 ) )  /* offset to G => Y section */
     71 #define B_Y_OFF     ( 2 * ( MAXJSAMPLE + 1 ) )  /* etc. */
     72 #define R_CB_OFF    ( 3 * ( MAXJSAMPLE + 1 ) )
     73 #define G_CB_OFF    ( 4 * ( MAXJSAMPLE + 1 ) )
     74 #define B_CB_OFF    ( 5 * ( MAXJSAMPLE + 1 ) )
     75 #define R_CR_OFF    B_CB_OFF        /* B=>Cb, R=>Cr are the same */
     76 #define G_CR_OFF    ( 6 * ( MAXJSAMPLE + 1 ) )
     77 #define B_CR_OFF    ( 7 * ( MAXJSAMPLE + 1 ) )
     78 #define TABLE_SIZE  ( 8 * ( MAXJSAMPLE + 1 ) )
     79 
     80 
     81 /*
     82  * Initialize for RGB->YCC colorspace conversion.
     83  */
     84 
     85 METHODDEF void
     86 rgb_ycc_start( j_compress_ptr cinfo ) {
     87     my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
     88     INT32 * rgb_ycc_tab;
     89     INT32 i;
     90 
     91     /* Allocate and fill in the conversion tables. */
     92     cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
     93                                           ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
     94                                                                        ( TABLE_SIZE * SIZEOF( INT32 ) ) );
     95 
     96     for ( i = 0; i <= MAXJSAMPLE; i++ ) {
     97         rgb_ycc_tab[i + R_Y_OFF] = FIX( 0.29900 ) * i;
     98         rgb_ycc_tab[i + G_Y_OFF] = FIX( 0.58700 ) * i;
     99         rgb_ycc_tab[i + B_Y_OFF] = FIX( 0.11400 ) * i     + ONE_HALF;
    100         rgb_ycc_tab[i + R_CB_OFF] = ( -FIX( 0.16874 ) ) * i;
    101         rgb_ycc_tab[i + G_CB_OFF] = ( -FIX( 0.33126 ) ) * i;
    102         /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
    103          * This ensures that the maximum output will round to MAXJSAMPLE
    104          * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
    105          */
    106         rgb_ycc_tab[i + B_CB_OFF] = FIX( 0.50000 ) * i    + CBCR_OFFSET + ONE_HALF - 1;
    107 /*  B=>Cb and R=>Cr tables are the same
    108     rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1;
    109  */
    110         rgb_ycc_tab[i + G_CR_OFF] = ( -FIX( 0.41869 ) ) * i;
    111         rgb_ycc_tab[i + B_CR_OFF] = ( -FIX( 0.08131 ) ) * i;
    112     }
    113 }
    114 
    115 
    116 /*
    117  * Convert some rows of samples to the JPEG colorspace.
    118  *
    119  * Note that we change from the application's interleaved-pixel format
    120  * to our internal noninterleaved, one-plane-per-component format.
    121  * The input buffer is therefore three times as wide as the output buffer.
    122  *
    123  * A starting row offset is provided only for the output buffer.  The caller
    124  * can easily adjust the passed input_buf value to accommodate any row
    125  * offset required on that side.
    126  */
    127 
    128 METHODDEF void
    129 rgb_ycc_convert( j_compress_ptr cinfo,
    130                  JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    131                  JDIMENSION output_row, int num_rows ) {
    132     my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    133     register int r, g, b;
    134     register INT32 * ctab = cconvert->rgb_ycc_tab;
    135     register JSAMPROW inptr;
    136     register JSAMPROW outptr0, outptr1, outptr2;
    137     register JDIMENSION col;
    138     JDIMENSION num_cols = cinfo->image_width;
    139 
    140     while ( --num_rows >= 0 ) {
    141         inptr = *input_buf++;
    142         outptr0 = output_buf[0][output_row];
    143         outptr1 = output_buf[1][output_row];
    144         outptr2 = output_buf[2][output_row];
    145         output_row++;
    146         for ( col = 0; col < num_cols; col++ ) {
    147             r = GETJSAMPLE( inptr[RGB_RED] );
    148             g = GETJSAMPLE( inptr[RGB_GREEN] );
    149             b = GETJSAMPLE( inptr[RGB_BLUE] );
    150             inptr += RGB_PIXELSIZE;
    151             /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
    152              * must be too; we do not need an explicit range-limiting operation.
    153              * Hence the value being shifted is never negative, and we don't
    154              * need the general RIGHT_SHIFT macro.
    155              */
    156             /* Y */
    157             outptr0[col] = (JSAMPLE)
    158                            ( ( ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + ctab[b + B_Y_OFF] )
    159                             >> SCALEBITS );
    160             /* Cb */
    161             outptr1[col] = (JSAMPLE)
    162                            ( ( ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] + ctab[b + B_CB_OFF] )
    163                             >> SCALEBITS );
    164             /* Cr */
    165             outptr2[col] = (JSAMPLE)
    166                            ( ( ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] + ctab[b + B_CR_OFF] )
    167                             >> SCALEBITS );
    168         }
    169     }
    170 }
    171 
    172 
    173 /**************** Cases other than RGB -> YCbCr **************/
    174 
    175 
    176 /*
    177  * Convert some rows of samples to the JPEG colorspace.
    178  * This version handles RGB->grayscale conversion, which is the same
    179  * as the RGB->Y portion of RGB->YCbCr.
    180  * We assume rgb_ycc_start has been called (we only use the Y tables).
    181  */
    182 
    183 METHODDEF void
    184 rgb_gray_convert( j_compress_ptr cinfo,
    185                   JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    186                   JDIMENSION output_row, int num_rows ) {
    187     my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    188     register int r, g, b;
    189     register INT32 * ctab = cconvert->rgb_ycc_tab;
    190     register JSAMPROW inptr;
    191     register JSAMPROW outptr;
    192     register JDIMENSION col;
    193     JDIMENSION num_cols = cinfo->image_width;
    194 
    195     while ( --num_rows >= 0 ) {
    196         inptr = *input_buf++;
    197         outptr = output_buf[0][output_row];
    198         output_row++;
    199         for ( col = 0; col < num_cols; col++ ) {
    200             r = GETJSAMPLE( inptr[RGB_RED] );
    201             g = GETJSAMPLE( inptr[RGB_GREEN] );
    202             b = GETJSAMPLE( inptr[RGB_BLUE] );
    203             inptr += RGB_PIXELSIZE;
    204             /* Y */
    205             outptr[col] = (JSAMPLE)
    206                           ( ( ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + ctab[b + B_Y_OFF] )
    207                            >> SCALEBITS );
    208         }
    209     }
    210 }
    211 
    212 
    213 /*
    214  * Convert some rows of samples to the JPEG colorspace.
    215  * This version handles Adobe-style CMYK->YCCK conversion,
    216  * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
    217  * conversion as above, while passing K (black) unchanged.
    218  * We assume rgb_ycc_start has been called.
    219  */
    220 
    221 METHODDEF void
    222 cmyk_ycck_convert( j_compress_ptr cinfo,
    223                    JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    224                    JDIMENSION output_row, int num_rows ) {
    225     my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
    226     register int r, g, b;
    227     register INT32 * ctab = cconvert->rgb_ycc_tab;
    228     register JSAMPROW inptr;
    229     register JSAMPROW outptr0, outptr1, outptr2, outptr3;
    230     register JDIMENSION col;
    231     JDIMENSION num_cols = cinfo->image_width;
    232 
    233     while ( --num_rows >= 0 ) {
    234         inptr = *input_buf++;
    235         outptr0 = output_buf[0][output_row];
    236         outptr1 = output_buf[1][output_row];
    237         outptr2 = output_buf[2][output_row];
    238         outptr3 = output_buf[3][output_row];
    239         output_row++;
    240         for ( col = 0; col < num_cols; col++ ) {
    241             r = MAXJSAMPLE - GETJSAMPLE( inptr[0] );
    242             g = MAXJSAMPLE - GETJSAMPLE( inptr[1] );
    243             b = MAXJSAMPLE - GETJSAMPLE( inptr[2] );
    244             /* K passes through as-is */
    245             outptr3[col] = inptr[3];/* don't need GETJSAMPLE here */
    246             inptr += 4;
    247             /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
    248              * must be too; we do not need an explicit range-limiting operation.
    249              * Hence the value being shifted is never negative, and we don't
    250              * need the general RIGHT_SHIFT macro.
    251              */
    252             /* Y */
    253             outptr0[col] = (JSAMPLE)
    254                            ( ( ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + ctab[b + B_Y_OFF] )
    255                             >> SCALEBITS );
    256             /* Cb */
    257             outptr1[col] = (JSAMPLE)
    258                            ( ( ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] + ctab[b + B_CB_OFF] )
    259                             >> SCALEBITS );
    260             /* Cr */
    261             outptr2[col] = (JSAMPLE)
    262                            ( ( ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] + ctab[b + B_CR_OFF] )
    263                             >> SCALEBITS );
    264         }
    265     }
    266 }
    267 
    268 
    269 /*
    270  * Convert some rows of samples to the JPEG colorspace.
    271  * This version handles grayscale output with no conversion.
    272  * The source can be either plain grayscale or YCbCr (since Y == gray).
    273  */
    274 
    275 METHODDEF void
    276 grayscale_convert( j_compress_ptr cinfo,
    277                    JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    278                    JDIMENSION output_row, int num_rows ) {
    279     register JSAMPROW inptr;
    280     register JSAMPROW outptr;
    281     register JDIMENSION col;
    282     JDIMENSION num_cols = cinfo->image_width;
    283     int instride = cinfo->input_components;
    284 
    285     while ( --num_rows >= 0 ) {
    286         inptr = *input_buf++;
    287         outptr = output_buf[0][output_row];
    288         output_row++;
    289         for ( col = 0; col < num_cols; col++ ) {
    290             outptr[col] = inptr[0];/* don't need GETJSAMPLE() here */
    291             inptr += instride;
    292         }
    293     }
    294 }
    295 
    296 
    297 /*
    298  * Convert some rows of samples to the JPEG colorspace.
    299  * This version handles multi-component colorspaces without conversion.
    300  * We assume input_components == num_components.
    301  */
    302 
    303 METHODDEF void
    304 null_convert( j_compress_ptr cinfo,
    305               JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
    306               JDIMENSION output_row, int num_rows ) {
    307     register JSAMPROW inptr;
    308     register JSAMPROW outptr;
    309     register JDIMENSION col;
    310     register int ci;
    311     int nc = cinfo->num_components;
    312     JDIMENSION num_cols = cinfo->image_width;
    313 
    314     while ( --num_rows >= 0 ) {
    315         /* It seems fastest to make a separate pass for each component. */
    316         for ( ci = 0; ci < nc; ci++ ) {
    317             inptr = *input_buf;
    318             outptr = output_buf[ci][output_row];
    319             for ( col = 0; col < num_cols; col++ ) {
    320                 outptr[col] = inptr[ci];/* don't need GETJSAMPLE() here */
    321                 inptr += nc;
    322             }
    323         }
    324         input_buf++;
    325         output_row++;
    326     }
    327 }
    328 
    329 
    330 /*
    331  * Empty method for start_pass.
    332  */
    333 
    334 METHODDEF void
    335 null_method( j_compress_ptr cinfo ) {
    336     /* no work needed */
    337 }
    338 
    339 
    340 /*
    341  * Module initialization routine for input colorspace conversion.
    342  */
    343 
    344 GLOBAL void
    345 jinit_color_converter( j_compress_ptr cinfo ) {
    346     my_cconvert_ptr cconvert;
    347 
    348     cconvert = (my_cconvert_ptr)
    349                ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
    350                                             SIZEOF( my_color_converter ) );
    351     cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
    352     /* set start_pass to null method until we find out differently */
    353     cconvert->pub.start_pass = null_method;
    354 
    355     /* Make sure input_components agrees with in_color_space */
    356     switch ( cinfo->in_color_space ) {
    357         case JCS_GRAYSCALE:
    358             if ( cinfo->input_components != 1 ) {
    359                 ERREXIT( cinfo, JERR_BAD_IN_COLORSPACE );
    360             }
    361             break;
    362 
    363         case JCS_RGB:
    364 #if RGB_PIXELSIZE != 3
    365             if ( cinfo->input_components != RGB_PIXELSIZE ) {
    366                 ERREXIT( cinfo, JERR_BAD_IN_COLORSPACE );
    367             }
    368             break;
    369 #endif /* else share code with YCbCr */
    370 
    371         case JCS_YCbCr:
    372             if ( cinfo->input_components != 3 ) {
    373                 ERREXIT( cinfo, JERR_BAD_IN_COLORSPACE );
    374             }
    375             break;
    376 
    377         case JCS_CMYK:
    378         case JCS_YCCK:
    379             if ( cinfo->input_components != 4 ) {
    380                 ERREXIT( cinfo, JERR_BAD_IN_COLORSPACE );
    381             }
    382             break;
    383 
    384         default:    /* JCS_UNKNOWN can be anything */
    385             if ( cinfo->input_components < 1 ) {
    386                 ERREXIT( cinfo, JERR_BAD_IN_COLORSPACE );
    387             }
    388             break;
    389     }
    390 
    391     /* Check num_components, set conversion method based on requested space */
    392     switch ( cinfo->jpeg_color_space ) {
    393         case JCS_GRAYSCALE:
    394             if ( cinfo->num_components != 1 ) {
    395                 ERREXIT( cinfo, JERR_BAD_J_COLORSPACE );
    396             }
    397             if ( cinfo->in_color_space == JCS_GRAYSCALE ) {
    398                 cconvert->pub.color_convert = grayscale_convert;
    399             } else if ( cinfo->in_color_space == JCS_RGB ) {
    400                 cconvert->pub.start_pass = rgb_ycc_start;
    401                 cconvert->pub.color_convert = rgb_gray_convert;
    402             } else if ( cinfo->in_color_space == JCS_YCbCr ) {
    403                 cconvert->pub.color_convert = grayscale_convert;
    404             } else {
    405                 ERREXIT( cinfo, JERR_CONVERSION_NOTIMPL );
    406             }
    407             break;
    408 
    409         case JCS_RGB:
    410             if ( cinfo->num_components != 3 ) {
    411                 ERREXIT( cinfo, JERR_BAD_J_COLORSPACE );
    412             }
    413             if ( ( cinfo->in_color_space == JCS_RGB ) && ( RGB_PIXELSIZE == 3 ) ) {
    414                 cconvert->pub.color_convert = null_convert;
    415             } else {
    416                 ERREXIT( cinfo, JERR_CONVERSION_NOTIMPL );
    417             }
    418             break;
    419 
    420         case JCS_YCbCr:
    421             if ( cinfo->num_components != 3 ) {
    422                 ERREXIT( cinfo, JERR_BAD_J_COLORSPACE );
    423             }
    424             if ( cinfo->in_color_space == JCS_RGB ) {
    425                 cconvert->pub.start_pass = rgb_ycc_start;
    426                 cconvert->pub.color_convert = rgb_ycc_convert;
    427             } else if ( cinfo->in_color_space == JCS_YCbCr ) {
    428                 cconvert->pub.color_convert = null_convert;
    429             } else {
    430                 ERREXIT( cinfo, JERR_CONVERSION_NOTIMPL );
    431             }
    432             break;
    433 
    434         case JCS_CMYK:
    435             if ( cinfo->num_components != 4 ) {
    436                 ERREXIT( cinfo, JERR_BAD_J_COLORSPACE );
    437             }
    438             if ( cinfo->in_color_space == JCS_CMYK ) {
    439                 cconvert->pub.color_convert = null_convert;
    440             } else {
    441                 ERREXIT( cinfo, JERR_CONVERSION_NOTIMPL );
    442             }
    443             break;
    444 
    445         case JCS_YCCK:
    446             if ( cinfo->num_components != 4 ) {
    447                 ERREXIT( cinfo, JERR_BAD_J_COLORSPACE );
    448             }
    449             if ( cinfo->in_color_space == JCS_CMYK ) {
    450                 cconvert->pub.start_pass = rgb_ycc_start;
    451                 cconvert->pub.color_convert = cmyk_ycck_convert;
    452             } else if ( cinfo->in_color_space == JCS_YCCK ) {
    453                 cconvert->pub.color_convert = null_convert;
    454             } else {
    455                 ERREXIT( cinfo, JERR_CONVERSION_NOTIMPL );
    456             }
    457             break;
    458 
    459         default:    /* allow null conversion of JCS_UNKNOWN */
    460             if ( ( cinfo->jpeg_color_space != cinfo->in_color_space ) ||
    461                 ( cinfo->num_components != cinfo->input_components ) ) {
    462                 ERREXIT( cinfo, JERR_CONVERSION_NOTIMPL );
    463             }
    464             cconvert->pub.color_convert = null_convert;
    465             break;
    466     }
    467 }