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