DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

jdapistd.cpp (10522B)


      1 /*
      2  * jdapistd.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 application interface code for the decompression half
      9  * of the JPEG library.  These are the "standard" API routines that are
     10  * used in the normal full-decompression case.  They are not used by a
     11  * transcoding-only application.  Note that if an application links in
     12  * jpeg_start_decompress, it will end up linking in the entire decompressor.
     13  * We thus must separate this file from jdapimin.c to avoid linking the
     14  * whole decompression library into a transcoder.
     15  */
     16 
     17 #define JPEG_INTERNALS
     18 #include "jinclude.h"
     19 #include "jpeglib.h"
     20 
     21 
     22 /* Forward declarations */
     23 LOCAL boolean output_pass_setup JPP( (j_decompress_ptr cinfo) );
     24 
     25 
     26 /*
     27  * Decompression initialization.
     28  * jpeg_read_header must be completed before calling this.
     29  *
     30  * If a multipass operating mode was selected, this will do all but the
     31  * last pass, and thus may take a great deal of time.
     32  *
     33  * Returns FALSE if suspended.  The return value need be inspected only if
     34  * a suspending data source is used.
     35  */
     36 
     37 GLOBAL boolean
     38 jpeg_start_decompress( j_decompress_ptr cinfo ) {
     39     if ( cinfo->global_state == DSTATE_READY ) {
     40         /* First call: initialize master control, select active modules */
     41         jinit_master_decompress( cinfo );
     42         if ( cinfo->buffered_image ) {
     43             /* No more work here; expecting jpeg_start_output next */
     44             cinfo->global_state = DSTATE_BUFIMAGE;
     45             return TRUE;
     46         }
     47         cinfo->global_state = DSTATE_PRELOAD;
     48     }
     49     if ( cinfo->global_state == DSTATE_PRELOAD ) {
     50         /* If file has multiple scans, absorb them all into the coef buffer */
     51         if ( cinfo->inputctl->has_multiple_scans ) {
     52 #ifdef D_MULTISCAN_FILES_SUPPORTED
     53             for (;; ) {
     54                 int retcode;
     55                 /* Call progress monitor hook if present */
     56                 if ( cinfo->progress != NULL ) {
     57                     ( *cinfo->progress->progress_monitor )( (j_common_ptr) cinfo );
     58                 }
     59                 /* Absorb some more input */
     60                 retcode = ( *cinfo->inputctl->consume_input )( cinfo );
     61                 if ( retcode == JPEG_SUSPENDED ) {
     62                     return FALSE;
     63                 }
     64                 if ( retcode == JPEG_REACHED_EOI ) {
     65                     break;
     66                 }
     67                 /* Advance progress counter if appropriate */
     68                 if ( ( cinfo->progress != NULL ) &&
     69                     ( ( retcode == JPEG_ROW_COMPLETED ) || ( retcode == JPEG_REACHED_SOS ) ) ) {
     70                     if ( ++cinfo->progress->pass_counter >= cinfo->progress->pass_limit ) {
     71                         /* jdmaster underestimated number of scans; ratchet up one scan */
     72                         cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
     73                     }
     74                 }
     75             }
     76 #else
     77             ERREXIT( cinfo, JERR_NOT_COMPILED );
     78 #endif /* D_MULTISCAN_FILES_SUPPORTED */
     79         }
     80         cinfo->output_scan_number = cinfo->input_scan_number;
     81     } else if ( cinfo->global_state != DSTATE_PRESCAN ) {
     82         ERREXIT1( cinfo, JERR_BAD_STATE, cinfo->global_state );
     83     }
     84     /* Perform any dummy output passes, and set up for the final pass */
     85     return output_pass_setup( cinfo );
     86 }
     87 
     88 
     89 /*
     90  * Set up for an output pass, and perform any dummy pass(es) needed.
     91  * Common subroutine for jpeg_start_decompress and jpeg_start_output.
     92  * Entry: global_state = DSTATE_PRESCAN only if previously suspended.
     93  * Exit: If done, returns TRUE and sets global_state for proper output mode.
     94  *       If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.
     95  */
     96 
     97 LOCAL boolean
     98 output_pass_setup( j_decompress_ptr cinfo ) {
     99     if ( cinfo->global_state != DSTATE_PRESCAN ) {
    100         /* First call: do pass setup */
    101         ( *cinfo->master->prepare_for_output_pass )( cinfo );
    102         cinfo->output_scanline = 0;
    103         cinfo->global_state = DSTATE_PRESCAN;
    104     }
    105     /* Loop over any required dummy passes */
    106     while ( cinfo->master->is_dummy_pass ) {
    107 #ifdef QUANT_2PASS_SUPPORTED
    108         /* Crank through the dummy pass */
    109         while ( cinfo->output_scanline < cinfo->output_height ) {
    110             JDIMENSION last_scanline;
    111             /* Call progress monitor hook if present */
    112             if ( cinfo->progress != NULL ) {
    113                 cinfo->progress->pass_counter = (long) cinfo->output_scanline;
    114                 cinfo->progress->pass_limit = (long) cinfo->output_height;
    115                 ( *cinfo->progress->progress_monitor )( (j_common_ptr) cinfo );
    116             }
    117             /* Process some data */
    118             last_scanline = cinfo->output_scanline;
    119             ( *cinfo->main->process_data )( cinfo, (JSAMPARRAY) NULL,
    120                                             &cinfo->output_scanline, (JDIMENSION) 0 );
    121             if ( cinfo->output_scanline == last_scanline ) {
    122                 return FALSE;
    123             }           /* No progress made, must suspend */
    124         }
    125         /* Finish up dummy pass, and set up for another one */
    126         ( *cinfo->master->finish_output_pass )( cinfo );
    127         ( *cinfo->master->prepare_for_output_pass )( cinfo );
    128         cinfo->output_scanline = 0;
    129 #else
    130         ERREXIT( cinfo, JERR_NOT_COMPILED );
    131 #endif /* QUANT_2PASS_SUPPORTED */
    132     }
    133     /* Ready for application to drive output pass through
    134      * jpeg_read_scanlines or jpeg_read_raw_data.
    135      */
    136     cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
    137     return TRUE;
    138 }
    139 
    140 
    141 /*
    142  * Read some scanlines of data from the JPEG decompressor.
    143  *
    144  * The return value will be the number of lines actually read.
    145  * This may be less than the number requested in several cases,
    146  * including bottom of image, data source suspension, and operating
    147  * modes that emit multiple scanlines at a time.
    148  *
    149  * Note: we warn about excess calls to jpeg_read_scanlines() since
    150  * this likely signals an application programmer error.  However,
    151  * an oversize buffer (max_lines > scanlines remaining) is not an error.
    152  */
    153 
    154 GLOBAL JDIMENSION
    155 jpeg_read_scanlines( j_decompress_ptr cinfo, JSAMPARRAY scanlines,
    156                      JDIMENSION max_lines ) {
    157     JDIMENSION row_ctr;
    158 
    159     if ( cinfo->global_state != DSTATE_SCANNING ) {
    160         ERREXIT1( cinfo, JERR_BAD_STATE, cinfo->global_state );
    161     }
    162     if ( cinfo->output_scanline >= cinfo->output_height ) {
    163         WARNMS( cinfo, JWRN_TOO_MUCH_DATA );
    164         return 0;
    165     }
    166 
    167     /* Call progress monitor hook if present */
    168     if ( cinfo->progress != NULL ) {
    169         cinfo->progress->pass_counter = (long) cinfo->output_scanline;
    170         cinfo->progress->pass_limit = (long) cinfo->output_height;
    171         ( *cinfo->progress->progress_monitor )( (j_common_ptr) cinfo );
    172     }
    173 
    174     /* Process some data */
    175     row_ctr = 0;
    176     ( *cinfo->main->process_data )( cinfo, scanlines, &row_ctr, max_lines );
    177     cinfo->output_scanline += row_ctr;
    178     return row_ctr;
    179 }
    180 
    181 
    182 /*
    183  * Alternate entry point to read raw data.
    184  * Processes exactly one iMCU row per call, unless suspended.
    185  */
    186 
    187 GLOBAL JDIMENSION
    188 jpeg_read_raw_data( j_decompress_ptr cinfo, JSAMPIMAGE data,
    189                     JDIMENSION max_lines ) {
    190     JDIMENSION lines_per_iMCU_row;
    191 
    192     if ( cinfo->global_state != DSTATE_RAW_OK ) {
    193         ERREXIT1( cinfo, JERR_BAD_STATE, cinfo->global_state );
    194     }
    195     if ( cinfo->output_scanline >= cinfo->output_height ) {
    196         WARNMS( cinfo, JWRN_TOO_MUCH_DATA );
    197         return 0;
    198     }
    199 
    200     /* Call progress monitor hook if present */
    201     if ( cinfo->progress != NULL ) {
    202         cinfo->progress->pass_counter = (long) cinfo->output_scanline;
    203         cinfo->progress->pass_limit = (long) cinfo->output_height;
    204         ( *cinfo->progress->progress_monitor )( (j_common_ptr) cinfo );
    205     }
    206 
    207     /* Verify that at least one iMCU row can be returned. */
    208     lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size;
    209     if ( max_lines < lines_per_iMCU_row ) {
    210         ERREXIT( cinfo, JERR_BUFFER_SIZE );
    211     }
    212 
    213     /* Decompress directly into user's buffer. */
    214     if ( !( *cinfo->coef->decompress_data )( cinfo, data ) ) {
    215         return 0;
    216     }                   /* suspension forced, can do nothing more */
    217 
    218     /* OK, we processed one iMCU row. */
    219     cinfo->output_scanline += lines_per_iMCU_row;
    220     return lines_per_iMCU_row;
    221 }
    222 
    223 
    224 /* Additional entry points for buffered-image mode. */
    225 
    226 #ifdef D_MULTISCAN_FILES_SUPPORTED
    227 
    228 /*
    229  * Initialize for an output pass in buffered-image mode.
    230  */
    231 
    232 GLOBAL boolean
    233 jpeg_start_output( j_decompress_ptr cinfo, int scan_number ) {
    234     if ( ( cinfo->global_state != DSTATE_BUFIMAGE ) &&
    235         ( cinfo->global_state != DSTATE_PRESCAN ) ) {
    236         ERREXIT1( cinfo, JERR_BAD_STATE, cinfo->global_state );
    237     }
    238     /* Limit scan number to valid range */
    239     if ( scan_number <= 0 ) {
    240         scan_number = 1;
    241     }
    242     if ( ( cinfo->inputctl->eoi_reached ) &&
    243         ( scan_number > cinfo->input_scan_number ) ) {
    244         scan_number = cinfo->input_scan_number;
    245     }
    246     cinfo->output_scan_number = scan_number;
    247     /* Perform any dummy output passes, and set up for the real pass */
    248     return output_pass_setup( cinfo );
    249 }
    250 
    251 
    252 /*
    253  * Finish up after an output pass in buffered-image mode.
    254  *
    255  * Returns FALSE if suspended.  The return value need be inspected only if
    256  * a suspending data source is used.
    257  */
    258 
    259 GLOBAL boolean
    260 jpeg_finish_output( j_decompress_ptr cinfo ) {
    261     if ( ( ( cinfo->global_state == DSTATE_SCANNING ) ||
    262           ( cinfo->global_state == DSTATE_RAW_OK ) && cinfo->buffered_image ) ) {
    263         /* Terminate this pass. */
    264         /* We do not require the whole pass to have been completed. */
    265         ( *cinfo->master->finish_output_pass )( cinfo );
    266         cinfo->global_state = DSTATE_BUFPOST;
    267     } else if ( cinfo->global_state != DSTATE_BUFPOST ) {
    268         /* BUFPOST = repeat call after a suspension, anything else is error */
    269         ERREXIT1( cinfo, JERR_BAD_STATE, cinfo->global_state );
    270     }
    271     /* Read markers looking for SOS or EOI */
    272     while ( cinfo->input_scan_number <= cinfo->output_scan_number &&
    273             !cinfo->inputctl->eoi_reached ) {
    274         if ( ( *cinfo->inputctl->consume_input )( cinfo ) == JPEG_SUSPENDED ) {
    275             return FALSE;
    276         }               /* Suspend, come back later */
    277     }
    278     cinfo->global_state = DSTATE_BUFIMAGE;
    279     return TRUE;
    280 }
    281 
    282 #endif /* D_MULTISCAN_FILES_SUPPORTED */