DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

jdmerge.cpp (15532B)


      1 /*
      2  * jdmerge.c
      3  *
      4  * Copyright (C) 1994-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 code for merged upsampling/color conversion.
      9  *
     10  * This file combines functions from jdsample.c and jdcolor.c;
     11  * read those files first to understand what's going on.
     12  *
     13  * When the chroma components are to be upsampled by simple replication
     14  * (ie, box filtering), we can save some work in color conversion by
     15  * calculating all the output pixels corresponding to a pair of chroma
     16  * samples at one time.  In the conversion equations
     17  *	R = Y           + K1 * Cr
     18  *	G = Y + K2 * Cb + K3 * Cr
     19  *	B = Y + K4 * Cb
     20  * only the Y term varies among the group of pixels corresponding to a pair
     21  * of chroma samples, so the rest of the terms can be calculated just once.
     22  * At typical sampling ratios, this eliminates half or three-quarters of the
     23  * multiplications needed for color conversion.
     24  *
     25  * This file currently provides implementations for the following cases:
     26  *	YCbCr => RGB color conversion only.
     27  *	Sampling ratios of 2h1v or 2h2v.
     28  *	No scaling needed at upsample time.
     29  *	Corner-aligned (non-CCIR601) sampling alignment.
     30  * Other special cases could be added, but in most applications these are
     31  * the only common cases.  (For uncommon cases we fall back on the more
     32  * general code in jdsample.c and jdcolor.c.)
     33  */
     34 
     35 #define JPEG_INTERNALS
     36 #include "jinclude.h"
     37 #include "jpeglib.h"
     38 
     39 #ifdef UPSAMPLE_MERGING_SUPPORTED
     40 
     41 
     42 /* Private subobject */
     43 
     44 typedef struct {
     45     struct jpeg_upsampler pub;  /* public fields */
     46 
     47     /* Pointer to routine to do actual upsampling/conversion of one row group */
     48     JMETHOD( void, upmethod, ( j_decompress_ptr cinfo,
     49                                JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
     50                                JSAMPARRAY output_buf ) );
     51 
     52     /* Private state for YCC->RGB conversion */
     53     int *   Cr_r_tab;   /* => table for Cr to R conversion */
     54     int *   Cb_b_tab;   /* => table for Cb to B conversion */
     55     INT32 * Cr_g_tab;   /* => table for Cr to G conversion */
     56     INT32 * Cb_g_tab;   /* => table for Cb to G conversion */
     57 
     58     /* For 2:1 vertical sampling, we produce two output rows at a time.
     59      * We need a "spare" row buffer to hold the second output row if the
     60      * application provides just a one-row buffer; we also use the spare
     61      * to discard the dummy last row if the image height is odd.
     62      */
     63     JSAMPROW spare_row;
     64     boolean  spare_full;    /* T if spare buffer is occupied */
     65 
     66     JDIMENSION out_row_width;/* samples per output row */
     67     JDIMENSION rows_to_go;  /* counts rows remaining in image */
     68 } my_upsampler;
     69 
     70 typedef my_upsampler * my_upsample_ptr;
     71 
     72 #define SCALEBITS   16  /* speediest right-shift on some machines */
     73 #define ONE_HALF    ( (INT32) 1 << ( SCALEBITS - 1 ) )
     74 #define FIX( x )      ( (INT32) ( ( x ) * ( 1L << SCALEBITS ) + 0.5 ) )
     75 
     76 
     77 /*
     78  * Initialize tables for YCC->RGB colorspace conversion.
     79  * This is taken directly from jdcolor.c; see that file for more info.
     80  */
     81 
     82 LOCAL void
     83 build_ycc_rgb_table( j_decompress_ptr cinfo ) {
     84     my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
     85     int i;
     86     INT32 x;
     87     SHIFT_TEMPS
     88 
     89     upsample->Cr_r_tab = (int *)
     90                          ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
     91                                                       ( MAXJSAMPLE + 1 ) * SIZEOF( int ) );
     92     upsample->Cb_b_tab = (int *)
     93                          ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
     94                                                       ( MAXJSAMPLE + 1 ) * SIZEOF( int ) );
     95     upsample->Cr_g_tab = (INT32 *)
     96                          ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
     97                                                       ( MAXJSAMPLE + 1 ) * SIZEOF( INT32 ) );
     98     upsample->Cb_g_tab = (INT32 *)
     99                          ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
    100                                                       ( MAXJSAMPLE + 1 ) * SIZEOF( INT32 ) );
    101 
    102     for ( i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++ ) {
    103         /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
    104         /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
    105         /* Cr=>R value is nearest int to 1.40200 * x */
    106         upsample->Cr_r_tab[i] = (int)
    107                                 RIGHT_SHIFT( FIX( 1.40200 ) * x + ONE_HALF, SCALEBITS );
    108         /* Cb=>B value is nearest int to 1.77200 * x */
    109         upsample->Cb_b_tab[i] = (int)
    110                                 RIGHT_SHIFT( FIX( 1.77200 ) * x + ONE_HALF, SCALEBITS );
    111         /* Cr=>G value is scaled-up -0.71414 * x */
    112         upsample->Cr_g_tab[i] = ( -FIX( 0.71414 ) ) * x;
    113         /* Cb=>G value is scaled-up -0.34414 * x */
    114         /* We also add in ONE_HALF so that need not do it in inner loop */
    115         upsample->Cb_g_tab[i] = ( -FIX( 0.34414 ) ) * x + ONE_HALF;
    116     }
    117 }
    118 
    119 
    120 /*
    121  * Initialize for an upsampling pass.
    122  */
    123 
    124 METHODDEF void
    125 start_pass_merged_upsample( j_decompress_ptr cinfo ) {
    126     my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
    127 
    128     /* Mark the spare buffer empty */
    129     upsample->spare_full = FALSE;
    130     /* Initialize total-height counter for detecting bottom of image */
    131     upsample->rows_to_go = cinfo->output_height;
    132 }
    133 
    134 
    135 /*
    136  * Control routine to do upsampling (and color conversion).
    137  *
    138  * The control routine just handles the row buffering considerations.
    139  */
    140 
    141 METHODDEF void
    142 merged_2v_upsample( j_decompress_ptr cinfo,
    143                     JSAMPIMAGE input_buf, JDIMENSION * in_row_group_ctr,
    144                     JDIMENSION in_row_groups_avail,
    145                     JSAMPARRAY output_buf, JDIMENSION * out_row_ctr,
    146                     JDIMENSION out_rows_avail ) {
    147 /* 2:1 vertical sampling case: may need a spare row. */
    148     my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
    149     JSAMPROW work_ptrs[2];
    150     JDIMENSION num_rows;    /* number of rows returned to caller */
    151 
    152     if ( upsample->spare_full ) {
    153         /* If we have a spare row saved from a previous cycle, just return it. */
    154         jcopy_sample_rows( &upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
    155                            1, upsample->out_row_width );
    156         num_rows = 1;
    157         upsample->spare_full = FALSE;
    158     } else {
    159         /* Figure number of rows to return to caller. */
    160         num_rows = 2;
    161         /* Not more than the distance to the end of the image. */
    162         if ( num_rows > upsample->rows_to_go ) {
    163             num_rows = upsample->rows_to_go;
    164         }
    165         /* And not more than what the client can accept: */
    166         out_rows_avail -= *out_row_ctr;
    167         if ( num_rows > out_rows_avail ) {
    168             num_rows = out_rows_avail;
    169         }
    170         /* Create output pointer array for upsampler. */
    171         work_ptrs[0] = output_buf[*out_row_ctr];
    172         if ( num_rows > 1 ) {
    173             work_ptrs[1] = output_buf[*out_row_ctr + 1];
    174         } else {
    175             work_ptrs[1] = upsample->spare_row;
    176             upsample->spare_full = TRUE;
    177         }
    178         /* Now do the upsampling. */
    179         ( *upsample->upmethod )( cinfo, input_buf, *in_row_group_ctr, work_ptrs );
    180     }
    181 
    182     /* Adjust counts */
    183     *out_row_ctr += num_rows;
    184     upsample->rows_to_go -= num_rows;
    185     /* When the buffer is emptied, declare this input row group consumed */
    186     if ( !upsample->spare_full ) {
    187         ( *in_row_group_ctr )++;
    188     }
    189 }
    190 
    191 
    192 METHODDEF void
    193 merged_1v_upsample( j_decompress_ptr cinfo,
    194                     JSAMPIMAGE input_buf, JDIMENSION * in_row_group_ctr,
    195                     JDIMENSION in_row_groups_avail,
    196                     JSAMPARRAY output_buf, JDIMENSION * out_row_ctr,
    197                     JDIMENSION out_rows_avail ) {
    198 /* 1:1 vertical sampling case: much easier, never need a spare row. */
    199     my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
    200 
    201     /* Just do the upsampling. */
    202     ( *upsample->upmethod )( cinfo, input_buf, *in_row_group_ctr,
    203                              output_buf + *out_row_ctr );
    204     /* Adjust counts */
    205     ( *out_row_ctr )++;
    206     ( *in_row_group_ctr )++;
    207 }
    208 
    209 
    210 /*
    211  * These are the routines invoked by the control routines to do
    212  * the actual upsampling/conversion.  One row group is processed per call.
    213  *
    214  * Note: since we may be writing directly into application-supplied buffers,
    215  * we have to be honest about the output width; we can't assume the buffer
    216  * has been rounded up to an even width.
    217  */
    218 
    219 
    220 /*
    221  * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
    222  */
    223 
    224 METHODDEF void
    225 h2v1_merged_upsample( j_decompress_ptr cinfo,
    226                       JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
    227                       JSAMPARRAY output_buf ) {
    228     my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
    229     register int y, cred, cgreen, cblue;
    230     int cb, cr;
    231     register JSAMPROW outptr;
    232     JSAMPROW inptr0, inptr1, inptr2;
    233     JDIMENSION col;
    234     /* copy these pointers into registers if possible */
    235     register JSAMPLE * range_limit = cinfo->sample_range_limit;
    236     int * Crrtab = upsample->Cr_r_tab;
    237     int * Cbbtab = upsample->Cb_b_tab;
    238     INT32 * Crgtab = upsample->Cr_g_tab;
    239     INT32 * Cbgtab = upsample->Cb_g_tab;
    240     SHIFT_TEMPS
    241 
    242     inptr0 = input_buf[0][in_row_group_ctr];
    243     inptr1 = input_buf[1][in_row_group_ctr];
    244     inptr2 = input_buf[2][in_row_group_ctr];
    245     outptr = output_buf[0];
    246     /* Loop for each pair of output pixels */
    247     for ( col = cinfo->output_width >> 1; col > 0; col-- ) {
    248         /* Do the chroma part of the calculation */
    249         cb = GETJSAMPLE( *inptr1++ );
    250         cr = GETJSAMPLE( *inptr2++ );
    251         cred = Crrtab[cr];
    252         cgreen = (int) RIGHT_SHIFT( Cbgtab[cb] + Crgtab[cr], SCALEBITS );
    253         cblue = Cbbtab[cb];
    254         /* Fetch 2 Y values and emit 2 pixels */
    255         y  = GETJSAMPLE( *inptr0++ );
    256         outptr[RGB_RED] =   range_limit[y + cred];
    257         outptr[RGB_GREEN] = range_limit[y + cgreen];
    258         outptr[RGB_BLUE] =  range_limit[y + cblue];
    259         outptr += RGB_PIXELSIZE;
    260         y  = GETJSAMPLE( *inptr0++ );
    261         outptr[RGB_RED] =   range_limit[y + cred];
    262         outptr[RGB_GREEN] = range_limit[y + cgreen];
    263         outptr[RGB_BLUE] =  range_limit[y + cblue];
    264         outptr += RGB_PIXELSIZE;
    265     }
    266     /* If image width is odd, do the last output column separately */
    267     if ( cinfo->output_width & 1 ) {
    268         cb = GETJSAMPLE( *inptr1 );
    269         cr = GETJSAMPLE( *inptr2 );
    270         cred = Crrtab[cr];
    271         cgreen = (int) RIGHT_SHIFT( Cbgtab[cb] + Crgtab[cr], SCALEBITS );
    272         cblue = Cbbtab[cb];
    273         y  = GETJSAMPLE( *inptr0 );
    274         outptr[RGB_RED] =   range_limit[y + cred];
    275         outptr[RGB_GREEN] = range_limit[y + cgreen];
    276         outptr[RGB_BLUE] =  range_limit[y + cblue];
    277     }
    278 }
    279 
    280 
    281 /*
    282  * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
    283  */
    284 
    285 METHODDEF void
    286 h2v2_merged_upsample( j_decompress_ptr cinfo,
    287                       JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
    288                       JSAMPARRAY output_buf ) {
    289     my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
    290     register int y, cred, cgreen, cblue;
    291     int cb, cr;
    292     register JSAMPROW outptr0, outptr1;
    293     JSAMPROW inptr00, inptr01, inptr1, inptr2;
    294     JDIMENSION col;
    295     /* copy these pointers into registers if possible */
    296     register JSAMPLE * range_limit = cinfo->sample_range_limit;
    297     int * Crrtab = upsample->Cr_r_tab;
    298     int * Cbbtab = upsample->Cb_b_tab;
    299     INT32 * Crgtab = upsample->Cr_g_tab;
    300     INT32 * Cbgtab = upsample->Cb_g_tab;
    301     SHIFT_TEMPS
    302 
    303     inptr00 = input_buf[0][in_row_group_ctr * 2];
    304     inptr01 = input_buf[0][in_row_group_ctr * 2 + 1];
    305     inptr1 = input_buf[1][in_row_group_ctr];
    306     inptr2 = input_buf[2][in_row_group_ctr];
    307     outptr0 = output_buf[0];
    308     outptr1 = output_buf[1];
    309     /* Loop for each group of output pixels */
    310     for ( col = cinfo->output_width >> 1; col > 0; col-- ) {
    311         /* Do the chroma part of the calculation */
    312         cb = GETJSAMPLE( *inptr1++ );
    313         cr = GETJSAMPLE( *inptr2++ );
    314         cred = Crrtab[cr];
    315         cgreen = (int) RIGHT_SHIFT( Cbgtab[cb] + Crgtab[cr], SCALEBITS );
    316         cblue = Cbbtab[cb];
    317         /* Fetch 4 Y values and emit 4 pixels */
    318         y  = GETJSAMPLE( *inptr00++ );
    319         outptr0[RGB_RED] =   range_limit[y + cred];
    320         outptr0[RGB_GREEN] = range_limit[y + cgreen];
    321         outptr0[RGB_BLUE] =  range_limit[y + cblue];
    322         outptr0 += RGB_PIXELSIZE;
    323         y  = GETJSAMPLE( *inptr00++ );
    324         outptr0[RGB_RED] =   range_limit[y + cred];
    325         outptr0[RGB_GREEN] = range_limit[y + cgreen];
    326         outptr0[RGB_BLUE] =  range_limit[y + cblue];
    327         outptr0 += RGB_PIXELSIZE;
    328         y  = GETJSAMPLE( *inptr01++ );
    329         outptr1[RGB_RED] =   range_limit[y + cred];
    330         outptr1[RGB_GREEN] = range_limit[y + cgreen];
    331         outptr1[RGB_BLUE] =  range_limit[y + cblue];
    332         outptr1 += RGB_PIXELSIZE;
    333         y  = GETJSAMPLE( *inptr01++ );
    334         outptr1[RGB_RED] =   range_limit[y + cred];
    335         outptr1[RGB_GREEN] = range_limit[y + cgreen];
    336         outptr1[RGB_BLUE] =  range_limit[y + cblue];
    337         outptr1 += RGB_PIXELSIZE;
    338     }
    339     /* If image width is odd, do the last output column separately */
    340     if ( cinfo->output_width & 1 ) {
    341         cb = GETJSAMPLE( *inptr1 );
    342         cr = GETJSAMPLE( *inptr2 );
    343         cred = Crrtab[cr];
    344         cgreen = (int) RIGHT_SHIFT( Cbgtab[cb] + Crgtab[cr], SCALEBITS );
    345         cblue = Cbbtab[cb];
    346         y  = GETJSAMPLE( *inptr00 );
    347         outptr0[RGB_RED] =   range_limit[y + cred];
    348         outptr0[RGB_GREEN] = range_limit[y + cgreen];
    349         outptr0[RGB_BLUE] =  range_limit[y + cblue];
    350         y  = GETJSAMPLE( *inptr01 );
    351         outptr1[RGB_RED] =   range_limit[y + cred];
    352         outptr1[RGB_GREEN] = range_limit[y + cgreen];
    353         outptr1[RGB_BLUE] =  range_limit[y + cblue];
    354     }
    355 }
    356 
    357 
    358 /*
    359  * Module initialization routine for merged upsampling/color conversion.
    360  *
    361  * NB: this is called under the conditions determined by use_merged_upsample()
    362  * in jdmaster.c.  That routine MUST correspond to the actual capabilities
    363  * of this module; no safety checks are made here.
    364  */
    365 
    366 GLOBAL void
    367 jinit_merged_upsampler( j_decompress_ptr cinfo ) {
    368     my_upsample_ptr upsample;
    369 
    370     upsample = (my_upsample_ptr)
    371                ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
    372                                             SIZEOF( my_upsampler ) );
    373     cinfo->upsample = (struct jpeg_upsampler *) upsample;
    374     upsample->pub.start_pass = start_pass_merged_upsample;
    375     upsample->pub.need_context_rows = FALSE;
    376 
    377     upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
    378 
    379     if ( cinfo->max_v_samp_factor == 2 ) {
    380         upsample->pub.upsample = merged_2v_upsample;
    381         upsample->upmethod = h2v2_merged_upsample;
    382         /* Allocate a spare row buffer */
    383         upsample->spare_row = (JSAMPROW)
    384                               ( *cinfo->mem->alloc_large )( (j_common_ptr) cinfo, JPOOL_IMAGE,
    385                                                            (size_t) ( upsample->out_row_width * SIZEOF( JSAMPLE ) ) );
    386     } else {
    387         upsample->pub.upsample = merged_1v_upsample;
    388         upsample->upmethod = h2v1_merged_upsample;
    389         /* No spare row needed */
    390         upsample->spare_row = NULL;
    391     }
    392 
    393     build_ycc_rgb_table( cinfo );
    394 }
    395 
    396 #endif /* UPSAMPLE_MERGING_SUPPORTED */