DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

jcmainct.cpp (11012B)


      1 /*
      2  * jcmainct.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 the main buffer controller for compression.
      9  * The main buffer lies between the pre-processor and the JPEG
     10  * compressor proper; it holds downsampled data in the JPEG colorspace.
     11  */
     12 
     13 #define JPEG_INTERNALS
     14 #include "jinclude.h"
     15 #include "jpeglib.h"
     16 
     17 
     18 /* Note: currently, there is no operating mode in which a full-image buffer
     19  * is needed at this step.  If there were, that mode could not be used with
     20  * "raw data" input, since this module is bypassed in that case.  However,
     21  * we've left the code here for possible use in special applications.
     22  */
     23 #undef FULL_MAIN_BUFFER_SUPPORTED
     24 
     25 
     26 /* Private buffer controller object */
     27 
     28 typedef struct {
     29     struct jpeg_c_main_controller pub;/* public fields */
     30 
     31     JDIMENSION cur_iMCU_row;/* number of current iMCU row */
     32     JDIMENSION rowgroup_ctr;/* counts row groups received in iMCU row */
     33     boolean    suspended;   /* remember if we suspended output */
     34     J_BUF_MODE pass_mode;   /* current operating mode */
     35 
     36     /* If using just a strip buffer, this points to the entire set of buffers
     37      * (we allocate one for each component).  In the full-image case, this
     38      * points to the currently accessible strips of the virtual arrays.
     39      */
     40     JSAMPARRAY buffer[MAX_COMPONENTS];
     41 
     42 #ifdef FULL_MAIN_BUFFER_SUPPORTED
     43     /* If using full-image storage, this array holds pointers to virtual-array
     44      * control blocks for each component.  Unused if not full-image storage.
     45      */
     46     jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
     47 #endif
     48 } my_main_controller;
     49 
     50 typedef my_main_controller * my_main_ptr;
     51 
     52 
     53 /* Forward declarations */
     54 METHODDEF void process_data_simple_main
     55 JPP( ( j_compress_ptr cinfo, JSAMPARRAY input_buf,
     56        JDIMENSION * in_row_ctr, JDIMENSION in_rows_avail ) );
     57 #ifdef FULL_MAIN_BUFFER_SUPPORTED
     58 METHODDEF void process_data_buffer_main
     59 JPP( ( j_compress_ptr cinfo, JSAMPARRAY input_buf,
     60        JDIMENSION * in_row_ctr, JDIMENSION in_rows_avail ) );
     61 #endif
     62 
     63 
     64 /*
     65  * Initialize for a processing pass.
     66  */
     67 
     68 METHODDEF void
     69 start_pass_main( j_compress_ptr cinfo, J_BUF_MODE pass_mode ) {
     70     my_main_ptr main = (my_main_ptr) cinfo->main;
     71 
     72     /* Do nothing in raw-data mode. */
     73     if ( cinfo->raw_data_in ) {
     74         return;
     75     }
     76 
     77     main->cur_iMCU_row = 0; /* initialize counters */
     78     main->rowgroup_ctr = 0;
     79     main->suspended = FALSE;
     80     main->pass_mode = pass_mode;/* save mode for use by process_data */
     81 
     82     switch ( pass_mode ) {
     83         case JBUF_PASS_THRU:
     84 #ifdef FULL_MAIN_BUFFER_SUPPORTED
     85             if ( main->whole_image[0] != NULL ) {
     86                 ERREXIT( cinfo, JERR_BAD_BUFFER_MODE );
     87             }
     88 #endif
     89             main->pub.process_data = process_data_simple_main;
     90             break;
     91 #ifdef FULL_MAIN_BUFFER_SUPPORTED
     92         case JBUF_SAVE_SOURCE:
     93         case JBUF_CRANK_DEST:
     94         case JBUF_SAVE_AND_PASS:
     95             if ( main->whole_image[0] == NULL ) {
     96                 ERREXIT( cinfo, JERR_BAD_BUFFER_MODE );
     97             }
     98             main->pub.process_data = process_data_buffer_main;
     99             break;
    100 #endif
    101         default:
    102             ERREXIT( cinfo, JERR_BAD_BUFFER_MODE );
    103             break;
    104     }
    105 }
    106 
    107 
    108 /*
    109  * Process some data.
    110  * This routine handles the simple pass-through mode,
    111  * where we have only a strip buffer.
    112  */
    113 
    114 METHODDEF void
    115 process_data_simple_main( j_compress_ptr cinfo,
    116                           JSAMPARRAY input_buf, JDIMENSION * in_row_ctr,
    117                           JDIMENSION in_rows_avail ) {
    118     my_main_ptr main = (my_main_ptr) cinfo->main;
    119 
    120     while ( main->cur_iMCU_row < cinfo->total_iMCU_rows ) {
    121         /* Read input data if we haven't filled the main buffer yet */
    122         if ( main->rowgroup_ctr < DCTSIZE ) {
    123             ( *cinfo->prep->pre_process_data )( cinfo,
    124                                                 input_buf, in_row_ctr, in_rows_avail,
    125                                                 main->buffer, &main->rowgroup_ctr,
    126                                                 (JDIMENSION) DCTSIZE );
    127         }
    128 
    129         /* If we don't have a full iMCU row buffered, return to application for
    130          * more data.  Note that preprocessor will always pad to fill the iMCU row
    131          * at the bottom of the image.
    132          */
    133         if ( main->rowgroup_ctr != DCTSIZE ) {
    134             return;
    135         }
    136 
    137         /* Send the completed row to the compressor */
    138         if ( !( *cinfo->coef->compress_data )( cinfo, main->buffer ) ) {
    139             /* If compressor did not consume the whole row, then we must need to
    140              * suspend processing and return to the application.  In this situation
    141              * we pretend we didn't yet consume the last input row; otherwise, if
    142              * it happened to be the last row of the image, the application would
    143              * think we were done.
    144              */
    145             if ( !main->suspended ) {
    146                 ( *in_row_ctr )--;
    147                 main->suspended = TRUE;
    148             }
    149             return;
    150         }
    151         /* We did finish the row.  Undo our little suspension hack if a previous
    152          * call suspended; then mark the main buffer empty.
    153          */
    154         if ( main->suspended ) {
    155             ( *in_row_ctr )++;
    156             main->suspended = FALSE;
    157         }
    158         main->rowgroup_ctr = 0;
    159         main->cur_iMCU_row++;
    160     }
    161 }
    162 
    163 
    164 #ifdef FULL_MAIN_BUFFER_SUPPORTED
    165 
    166 /*
    167  * Process some data.
    168  * This routine handles all of the modes that use a full-size buffer.
    169  */
    170 
    171 METHODDEF void
    172 process_data_buffer_main( j_compress_ptr cinfo,
    173                           JSAMPARRAY input_buf, JDIMENSION * in_row_ctr,
    174                           JDIMENSION in_rows_avail ) {
    175     my_main_ptr main = (my_main_ptr) cinfo->main;
    176     int ci;
    177     jpeg_component_info * compptr;
    178     boolean writing = ( main->pass_mode != JBUF_CRANK_DEST );
    179 
    180     while ( main->cur_iMCU_row < cinfo->total_iMCU_rows ) {
    181         /* Realign the virtual buffers if at the start of an iMCU row. */
    182         if ( main->rowgroup_ctr == 0 ) {
    183             for ( ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
    184                   ci++, compptr++ ) {
    185                 main->buffer[ci] = ( *cinfo->mem->access_virt_sarray )
    186                                    ( (j_common_ptr) cinfo, main->whole_image[ci],
    187                                     main->cur_iMCU_row * ( compptr->v_samp_factor * DCTSIZE ),
    188                                     (JDIMENSION) ( compptr->v_samp_factor * DCTSIZE ), writing );
    189             }
    190             /* In a read pass, pretend we just read some source data. */
    191             if ( !writing ) {
    192                 *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE;
    193                 main->rowgroup_ctr = DCTSIZE;
    194             }
    195         }
    196 
    197         /* If a write pass, read input data until the current iMCU row is full. */
    198         /* Note: preprocessor will pad if necessary to fill the last iMCU row. */
    199         if ( writing ) {
    200             ( *cinfo->prep->pre_process_data )( cinfo,
    201                                                 input_buf, in_row_ctr, in_rows_avail,
    202                                                 main->buffer, &main->rowgroup_ctr,
    203                                                 (JDIMENSION) DCTSIZE );
    204             /* Return to application if we need more data to fill the iMCU row. */
    205             if ( main->rowgroup_ctr < DCTSIZE ) {
    206                 return;
    207             }
    208         }
    209 
    210         /* Emit data, unless this is a sink-only pass. */
    211         if ( main->pass_mode != JBUF_SAVE_SOURCE ) {
    212             if ( !( *cinfo->coef->compress_data )( cinfo, main->buffer ) ) {
    213                 /* If compressor did not consume the whole row, then we must need to
    214                  * suspend processing and return to the application.  In this situation
    215                  * we pretend we didn't yet consume the last input row; otherwise, if
    216                  * it happened to be the last row of the image, the application would
    217                  * think we were done.
    218                  */
    219                 if ( !main->suspended ) {
    220                     ( *in_row_ctr )--;
    221                     main->suspended = TRUE;
    222                 }
    223                 return;
    224             }
    225             /* We did finish the row.  Undo our little suspension hack if a previous
    226              * call suspended; then mark the main buffer empty.
    227              */
    228             if ( main->suspended ) {
    229                 ( *in_row_ctr )++;
    230                 main->suspended = FALSE;
    231             }
    232         }
    233 
    234         /* If get here, we are done with this iMCU row.  Mark buffer empty. */
    235         main->rowgroup_ctr = 0;
    236         main->cur_iMCU_row++;
    237     }
    238 }
    239 
    240 #endif /* FULL_MAIN_BUFFER_SUPPORTED */
    241 
    242 
    243 /*
    244  * Initialize main buffer controller.
    245  */
    246 
    247 GLOBAL void
    248 jinit_c_main_controller( j_compress_ptr cinfo, boolean need_full_buffer ) {
    249     my_main_ptr main;
    250     int ci;
    251     jpeg_component_info * compptr;
    252 
    253     main = (my_main_ptr)
    254            ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_IMAGE,
    255                                         SIZEOF( my_main_controller ) );
    256     cinfo->main = (struct jpeg_c_main_controller *) main;
    257     main->pub.start_pass = start_pass_main;
    258 
    259     /* We don't need to create a buffer in raw-data mode. */
    260     if ( cinfo->raw_data_in ) {
    261         return;
    262     }
    263 
    264     /* Create the buffer.  It holds downsampled data, so each component
    265      * may be of a different size.
    266      */
    267     if ( need_full_buffer ) {
    268 #ifdef FULL_MAIN_BUFFER_SUPPORTED
    269         /* Allocate a full-image virtual array for each component */
    270         /* Note we pad the bottom to a multiple of the iMCU height */
    271         for ( ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
    272               ci++, compptr++ ) {
    273             main->whole_image[ci] = ( *cinfo->mem->request_virt_sarray )
    274                                     ( (j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
    275                                      compptr->width_in_blocks * DCTSIZE,
    276                                      (JDIMENSION) jround_up( (long) compptr->height_in_blocks,
    277                                                             (long) compptr->v_samp_factor ) * DCTSIZE,
    278                                      (JDIMENSION) ( compptr->v_samp_factor * DCTSIZE ) );
    279         }
    280 #else
    281         ERREXIT( cinfo, JERR_BAD_BUFFER_MODE );
    282 #endif
    283     } else {
    284 #ifdef FULL_MAIN_BUFFER_SUPPORTED
    285         main->whole_image[0] = NULL;/* flag for no virtual arrays */
    286 #endif
    287         /* Allocate a strip buffer for each component */
    288         for ( ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
    289               ci++, compptr++ ) {
    290             main->buffer[ci] = ( *cinfo->mem->alloc_sarray )
    291                                ( (j_common_ptr) cinfo, JPOOL_IMAGE,
    292                                 compptr->width_in_blocks * DCTSIZE,
    293                                 (JDIMENSION) ( compptr->v_samp_factor * DCTSIZE ) );
    294         }
    295     }
    296 }