xref: /plan9/sys/src/cmd/gs/jpeg/jdinput.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier  * jdinput.c
37dd7cddfSDavid du Colombier  *
4*593dc095SDavid du Colombier  * Copyright (C) 1991-1997, Thomas G. Lane.
57dd7cddfSDavid du Colombier  * This file is part of the Independent JPEG Group's software.
67dd7cddfSDavid du Colombier  * For conditions of distribution and use, see the accompanying README file.
77dd7cddfSDavid du Colombier  *
87dd7cddfSDavid du Colombier  * This file contains input control logic for the JPEG decompressor.
97dd7cddfSDavid du Colombier  * These routines are concerned with controlling the decompressor's input
107dd7cddfSDavid du Colombier  * processing (marker reading and coefficient decoding).  The actual input
117dd7cddfSDavid du Colombier  * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c.
127dd7cddfSDavid du Colombier  */
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier #define JPEG_INTERNALS
157dd7cddfSDavid du Colombier #include "jinclude.h"
167dd7cddfSDavid du Colombier #include "jpeglib.h"
177dd7cddfSDavid du Colombier 
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier /* Private state */
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier typedef struct {
227dd7cddfSDavid du Colombier   struct jpeg_input_controller pub; /* public fields */
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier   boolean inheaders;		/* TRUE until first SOS is reached */
257dd7cddfSDavid du Colombier } my_input_controller;
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier typedef my_input_controller * my_inputctl_ptr;
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier 
307dd7cddfSDavid du Colombier /* Forward declarations */
317dd7cddfSDavid du Colombier METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo));
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier /*
357dd7cddfSDavid du Colombier  * Routines to calculate various quantities related to the size of the image.
367dd7cddfSDavid du Colombier  */
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier LOCAL(void)
initial_setup(j_decompress_ptr cinfo)397dd7cddfSDavid du Colombier initial_setup (j_decompress_ptr cinfo)
407dd7cddfSDavid du Colombier /* Called once, when first SOS marker is reached */
417dd7cddfSDavid du Colombier {
427dd7cddfSDavid du Colombier   int ci;
437dd7cddfSDavid du Colombier   jpeg_component_info *compptr;
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier   /* Make sure image isn't bigger than I can handle */
467dd7cddfSDavid du Colombier   if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
477dd7cddfSDavid du Colombier       (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
487dd7cddfSDavid du Colombier     ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier   /* For now, precision must match compiled-in value... */
517dd7cddfSDavid du Colombier   if (cinfo->data_precision != BITS_IN_JSAMPLE)
527dd7cddfSDavid du Colombier     ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier   /* Check that number of components won't exceed internal array sizes */
557dd7cddfSDavid du Colombier   if (cinfo->num_components > MAX_COMPONENTS)
567dd7cddfSDavid du Colombier     ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
577dd7cddfSDavid du Colombier 	     MAX_COMPONENTS);
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier   /* Compute maximum sampling factors; check factor validity */
607dd7cddfSDavid du Colombier   cinfo->max_h_samp_factor = 1;
617dd7cddfSDavid du Colombier   cinfo->max_v_samp_factor = 1;
627dd7cddfSDavid du Colombier   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
637dd7cddfSDavid du Colombier        ci++, compptr++) {
647dd7cddfSDavid du Colombier     if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
657dd7cddfSDavid du Colombier 	compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
667dd7cddfSDavid du Colombier       ERREXIT(cinfo, JERR_BAD_SAMPLING);
677dd7cddfSDavid du Colombier     cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
687dd7cddfSDavid du Colombier 				   compptr->h_samp_factor);
697dd7cddfSDavid du Colombier     cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
707dd7cddfSDavid du Colombier 				   compptr->v_samp_factor);
717dd7cddfSDavid du Colombier   }
727dd7cddfSDavid du Colombier 
737dd7cddfSDavid du Colombier   /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
747dd7cddfSDavid du Colombier    * In the full decompressor, this will be overridden by jdmaster.c;
757dd7cddfSDavid du Colombier    * but in the transcoder, jdmaster.c is not used, so we must do it here.
767dd7cddfSDavid du Colombier    */
777dd7cddfSDavid du Colombier   cinfo->min_DCT_scaled_size = DCTSIZE;
787dd7cddfSDavid du Colombier 
797dd7cddfSDavid du Colombier   /* Compute dimensions of components */
807dd7cddfSDavid du Colombier   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
817dd7cddfSDavid du Colombier        ci++, compptr++) {
827dd7cddfSDavid du Colombier     compptr->DCT_scaled_size = DCTSIZE;
837dd7cddfSDavid du Colombier     /* Size in DCT blocks */
847dd7cddfSDavid du Colombier     compptr->width_in_blocks = (JDIMENSION)
857dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
867dd7cddfSDavid du Colombier 		    (long) (cinfo->max_h_samp_factor * DCTSIZE));
877dd7cddfSDavid du Colombier     compptr->height_in_blocks = (JDIMENSION)
887dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
897dd7cddfSDavid du Colombier 		    (long) (cinfo->max_v_samp_factor * DCTSIZE));
907dd7cddfSDavid du Colombier     /* downsampled_width and downsampled_height will also be overridden by
917dd7cddfSDavid du Colombier      * jdmaster.c if we are doing full decompression.  The transcoder library
927dd7cddfSDavid du Colombier      * doesn't use these values, but the calling application might.
937dd7cddfSDavid du Colombier      */
947dd7cddfSDavid du Colombier     /* Size in samples */
957dd7cddfSDavid du Colombier     compptr->downsampled_width = (JDIMENSION)
967dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
977dd7cddfSDavid du Colombier 		    (long) cinfo->max_h_samp_factor);
987dd7cddfSDavid du Colombier     compptr->downsampled_height = (JDIMENSION)
997dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
1007dd7cddfSDavid du Colombier 		    (long) cinfo->max_v_samp_factor);
1017dd7cddfSDavid du Colombier     /* Mark component needed, until color conversion says otherwise */
1027dd7cddfSDavid du Colombier     compptr->component_needed = TRUE;
1037dd7cddfSDavid du Colombier     /* Mark no quantization table yet saved for component */
1047dd7cddfSDavid du Colombier     compptr->quant_table = NULL;
1057dd7cddfSDavid du Colombier   }
1067dd7cddfSDavid du Colombier 
1077dd7cddfSDavid du Colombier   /* Compute number of fully interleaved MCU rows. */
1087dd7cddfSDavid du Colombier   cinfo->total_iMCU_rows = (JDIMENSION)
1097dd7cddfSDavid du Colombier     jdiv_round_up((long) cinfo->image_height,
1107dd7cddfSDavid du Colombier 		  (long) (cinfo->max_v_samp_factor*DCTSIZE));
1117dd7cddfSDavid du Colombier 
1127dd7cddfSDavid du Colombier   /* Decide whether file contains multiple scans */
1137dd7cddfSDavid du Colombier   if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
1147dd7cddfSDavid du Colombier     cinfo->inputctl->has_multiple_scans = TRUE;
1157dd7cddfSDavid du Colombier   else
1167dd7cddfSDavid du Colombier     cinfo->inputctl->has_multiple_scans = FALSE;
1177dd7cddfSDavid du Colombier }
1187dd7cddfSDavid du Colombier 
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier LOCAL(void)
per_scan_setup(j_decompress_ptr cinfo)1217dd7cddfSDavid du Colombier per_scan_setup (j_decompress_ptr cinfo)
1227dd7cddfSDavid du Colombier /* Do computations that are needed before processing a JPEG scan */
1237dd7cddfSDavid du Colombier /* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
1247dd7cddfSDavid du Colombier {
1257dd7cddfSDavid du Colombier   int ci, mcublks, tmp;
1267dd7cddfSDavid du Colombier   jpeg_component_info *compptr;
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier   if (cinfo->comps_in_scan == 1) {
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier     /* Noninterleaved (single-component) scan */
1317dd7cddfSDavid du Colombier     compptr = cinfo->cur_comp_info[0];
1327dd7cddfSDavid du Colombier 
1337dd7cddfSDavid du Colombier     /* Overall image size in MCUs */
1347dd7cddfSDavid du Colombier     cinfo->MCUs_per_row = compptr->width_in_blocks;
1357dd7cddfSDavid du Colombier     cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
1367dd7cddfSDavid du Colombier 
1377dd7cddfSDavid du Colombier     /* For noninterleaved scan, always one block per MCU */
1387dd7cddfSDavid du Colombier     compptr->MCU_width = 1;
1397dd7cddfSDavid du Colombier     compptr->MCU_height = 1;
1407dd7cddfSDavid du Colombier     compptr->MCU_blocks = 1;
1417dd7cddfSDavid du Colombier     compptr->MCU_sample_width = compptr->DCT_scaled_size;
1427dd7cddfSDavid du Colombier     compptr->last_col_width = 1;
1437dd7cddfSDavid du Colombier     /* For noninterleaved scans, it is convenient to define last_row_height
1447dd7cddfSDavid du Colombier      * as the number of block rows present in the last iMCU row.
1457dd7cddfSDavid du Colombier      */
1467dd7cddfSDavid du Colombier     tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
1477dd7cddfSDavid du Colombier     if (tmp == 0) tmp = compptr->v_samp_factor;
1487dd7cddfSDavid du Colombier     compptr->last_row_height = tmp;
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier     /* Prepare array describing MCU composition */
1517dd7cddfSDavid du Colombier     cinfo->blocks_in_MCU = 1;
1527dd7cddfSDavid du Colombier     cinfo->MCU_membership[0] = 0;
1537dd7cddfSDavid du Colombier 
1547dd7cddfSDavid du Colombier   } else {
1557dd7cddfSDavid du Colombier 
1567dd7cddfSDavid du Colombier     /* Interleaved (multi-component) scan */
1577dd7cddfSDavid du Colombier     if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
1587dd7cddfSDavid du Colombier       ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
1597dd7cddfSDavid du Colombier 	       MAX_COMPS_IN_SCAN);
1607dd7cddfSDavid du Colombier 
1617dd7cddfSDavid du Colombier     /* Overall image size in MCUs */
1627dd7cddfSDavid du Colombier     cinfo->MCUs_per_row = (JDIMENSION)
1637dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_width,
1647dd7cddfSDavid du Colombier 		    (long) (cinfo->max_h_samp_factor*DCTSIZE));
1657dd7cddfSDavid du Colombier     cinfo->MCU_rows_in_scan = (JDIMENSION)
1667dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_height,
1677dd7cddfSDavid du Colombier 		    (long) (cinfo->max_v_samp_factor*DCTSIZE));
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier     cinfo->blocks_in_MCU = 0;
1707dd7cddfSDavid du Colombier 
1717dd7cddfSDavid du Colombier     for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
1727dd7cddfSDavid du Colombier       compptr = cinfo->cur_comp_info[ci];
1737dd7cddfSDavid du Colombier       /* Sampling factors give # of blocks of component in each MCU */
1747dd7cddfSDavid du Colombier       compptr->MCU_width = compptr->h_samp_factor;
1757dd7cddfSDavid du Colombier       compptr->MCU_height = compptr->v_samp_factor;
1767dd7cddfSDavid du Colombier       compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
1777dd7cddfSDavid du Colombier       compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size;
1787dd7cddfSDavid du Colombier       /* Figure number of non-dummy blocks in last MCU column & row */
1797dd7cddfSDavid du Colombier       tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
1807dd7cddfSDavid du Colombier       if (tmp == 0) tmp = compptr->MCU_width;
1817dd7cddfSDavid du Colombier       compptr->last_col_width = tmp;
1827dd7cddfSDavid du Colombier       tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
1837dd7cddfSDavid du Colombier       if (tmp == 0) tmp = compptr->MCU_height;
1847dd7cddfSDavid du Colombier       compptr->last_row_height = tmp;
1857dd7cddfSDavid du Colombier       /* Prepare array describing MCU composition */
1867dd7cddfSDavid du Colombier       mcublks = compptr->MCU_blocks;
1877dd7cddfSDavid du Colombier       if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU)
1887dd7cddfSDavid du Colombier 	ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
1897dd7cddfSDavid du Colombier       while (mcublks-- > 0) {
1907dd7cddfSDavid du Colombier 	cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
1917dd7cddfSDavid du Colombier       }
1927dd7cddfSDavid du Colombier     }
1937dd7cddfSDavid du Colombier 
1947dd7cddfSDavid du Colombier   }
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier 
1977dd7cddfSDavid du Colombier 
1987dd7cddfSDavid du Colombier /*
1997dd7cddfSDavid du Colombier  * Save away a copy of the Q-table referenced by each component present
2007dd7cddfSDavid du Colombier  * in the current scan, unless already saved during a prior scan.
2017dd7cddfSDavid du Colombier  *
2027dd7cddfSDavid du Colombier  * In a multiple-scan JPEG file, the encoder could assign different components
2037dd7cddfSDavid du Colombier  * the same Q-table slot number, but change table definitions between scans
2047dd7cddfSDavid du Colombier  * so that each component uses a different Q-table.  (The IJG encoder is not
2057dd7cddfSDavid du Colombier  * currently capable of doing this, but other encoders might.)  Since we want
2067dd7cddfSDavid du Colombier  * to be able to dequantize all the components at the end of the file, this
2077dd7cddfSDavid du Colombier  * means that we have to save away the table actually used for each component.
2087dd7cddfSDavid du Colombier  * We do this by copying the table at the start of the first scan containing
2097dd7cddfSDavid du Colombier  * the component.
2107dd7cddfSDavid du Colombier  * The JPEG spec prohibits the encoder from changing the contents of a Q-table
2117dd7cddfSDavid du Colombier  * slot between scans of a component using that slot.  If the encoder does so
2127dd7cddfSDavid du Colombier  * anyway, this decoder will simply use the Q-table values that were current
2137dd7cddfSDavid du Colombier  * at the start of the first scan for the component.
2147dd7cddfSDavid du Colombier  *
2157dd7cddfSDavid du Colombier  * The decompressor output side looks only at the saved quant tables,
2167dd7cddfSDavid du Colombier  * not at the current Q-table slots.
2177dd7cddfSDavid du Colombier  */
2187dd7cddfSDavid du Colombier 
2197dd7cddfSDavid du Colombier LOCAL(void)
latch_quant_tables(j_decompress_ptr cinfo)2207dd7cddfSDavid du Colombier latch_quant_tables (j_decompress_ptr cinfo)
2217dd7cddfSDavid du Colombier {
2227dd7cddfSDavid du Colombier   int ci, qtblno;
2237dd7cddfSDavid du Colombier   jpeg_component_info *compptr;
2247dd7cddfSDavid du Colombier   JQUANT_TBL * qtbl;
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
2277dd7cddfSDavid du Colombier     compptr = cinfo->cur_comp_info[ci];
2287dd7cddfSDavid du Colombier     /* No work if we already saved Q-table for this component */
2297dd7cddfSDavid du Colombier     if (compptr->quant_table != NULL)
2307dd7cddfSDavid du Colombier       continue;
2317dd7cddfSDavid du Colombier     /* Make sure specified quantization table is present */
2327dd7cddfSDavid du Colombier     qtblno = compptr->quant_tbl_no;
2337dd7cddfSDavid du Colombier     if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
2347dd7cddfSDavid du Colombier 	cinfo->quant_tbl_ptrs[qtblno] == NULL)
2357dd7cddfSDavid du Colombier       ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
2367dd7cddfSDavid du Colombier     /* OK, save away the quantization table */
2377dd7cddfSDavid du Colombier     qtbl = (JQUANT_TBL *)
2387dd7cddfSDavid du Colombier       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
2397dd7cddfSDavid du Colombier 				  SIZEOF(JQUANT_TBL));
2407dd7cddfSDavid du Colombier     MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
2417dd7cddfSDavid du Colombier     compptr->quant_table = qtbl;
2427dd7cddfSDavid du Colombier   }
2437dd7cddfSDavid du Colombier }
2447dd7cddfSDavid du Colombier 
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier /*
2477dd7cddfSDavid du Colombier  * Initialize the input modules to read a scan of compressed data.
2487dd7cddfSDavid du Colombier  * The first call to this is done by jdmaster.c after initializing
2497dd7cddfSDavid du Colombier  * the entire decompressor (during jpeg_start_decompress).
2507dd7cddfSDavid du Colombier  * Subsequent calls come from consume_markers, below.
2517dd7cddfSDavid du Colombier  */
2527dd7cddfSDavid du Colombier 
2537dd7cddfSDavid du Colombier METHODDEF(void)
start_input_pass(j_decompress_ptr cinfo)2547dd7cddfSDavid du Colombier start_input_pass (j_decompress_ptr cinfo)
2557dd7cddfSDavid du Colombier {
2567dd7cddfSDavid du Colombier   per_scan_setup(cinfo);
2577dd7cddfSDavid du Colombier   latch_quant_tables(cinfo);
2587dd7cddfSDavid du Colombier   (*cinfo->entropy->start_pass) (cinfo);
2597dd7cddfSDavid du Colombier   (*cinfo->coef->start_input_pass) (cinfo);
2607dd7cddfSDavid du Colombier   cinfo->inputctl->consume_input = cinfo->coef->consume_data;
2617dd7cddfSDavid du Colombier }
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier 
2647dd7cddfSDavid du Colombier /*
2657dd7cddfSDavid du Colombier  * Finish up after inputting a compressed-data scan.
2667dd7cddfSDavid du Colombier  * This is called by the coefficient controller after it's read all
2677dd7cddfSDavid du Colombier  * the expected data of the scan.
2687dd7cddfSDavid du Colombier  */
2697dd7cddfSDavid du Colombier 
2707dd7cddfSDavid du Colombier METHODDEF(void)
finish_input_pass(j_decompress_ptr cinfo)2717dd7cddfSDavid du Colombier finish_input_pass (j_decompress_ptr cinfo)
2727dd7cddfSDavid du Colombier {
2737dd7cddfSDavid du Colombier   cinfo->inputctl->consume_input = consume_markers;
2747dd7cddfSDavid du Colombier }
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier 
2777dd7cddfSDavid du Colombier /*
2787dd7cddfSDavid du Colombier  * Read JPEG markers before, between, or after compressed-data scans.
2797dd7cddfSDavid du Colombier  * Change state as necessary when a new scan is reached.
2807dd7cddfSDavid du Colombier  * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
2817dd7cddfSDavid du Colombier  *
2827dd7cddfSDavid du Colombier  * The consume_input method pointer points either here or to the
2837dd7cddfSDavid du Colombier  * coefficient controller's consume_data routine, depending on whether
2847dd7cddfSDavid du Colombier  * we are reading a compressed data segment or inter-segment markers.
2857dd7cddfSDavid du Colombier  */
2867dd7cddfSDavid du Colombier 
2877dd7cddfSDavid du Colombier METHODDEF(int)
consume_markers(j_decompress_ptr cinfo)2887dd7cddfSDavid du Colombier consume_markers (j_decompress_ptr cinfo)
2897dd7cddfSDavid du Colombier {
2907dd7cddfSDavid du Colombier   my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
2917dd7cddfSDavid du Colombier   int val;
2927dd7cddfSDavid du Colombier 
2937dd7cddfSDavid du Colombier   if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
2947dd7cddfSDavid du Colombier     return JPEG_REACHED_EOI;
2957dd7cddfSDavid du Colombier 
2967dd7cddfSDavid du Colombier   val = (*cinfo->marker->read_markers) (cinfo);
2977dd7cddfSDavid du Colombier 
2987dd7cddfSDavid du Colombier   switch (val) {
2997dd7cddfSDavid du Colombier   case JPEG_REACHED_SOS:	/* Found SOS */
3007dd7cddfSDavid du Colombier     if (inputctl->inheaders) {	/* 1st SOS */
3017dd7cddfSDavid du Colombier       initial_setup(cinfo);
3027dd7cddfSDavid du Colombier       inputctl->inheaders = FALSE;
3037dd7cddfSDavid du Colombier       /* Note: start_input_pass must be called by jdmaster.c
304*593dc095SDavid du Colombier        * before any more input can be consumed.  jdapimin.c is
3057dd7cddfSDavid du Colombier        * responsible for enforcing this sequencing.
3067dd7cddfSDavid du Colombier        */
3077dd7cddfSDavid du Colombier     } else {			/* 2nd or later SOS marker */
3087dd7cddfSDavid du Colombier       if (! inputctl->pub.has_multiple_scans)
3097dd7cddfSDavid du Colombier 	ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
3107dd7cddfSDavid du Colombier       start_input_pass(cinfo);
3117dd7cddfSDavid du Colombier     }
3127dd7cddfSDavid du Colombier     break;
3137dd7cddfSDavid du Colombier   case JPEG_REACHED_EOI:	/* Found EOI */
3147dd7cddfSDavid du Colombier     inputctl->pub.eoi_reached = TRUE;
3157dd7cddfSDavid du Colombier     if (inputctl->inheaders) {	/* Tables-only datastream, apparently */
3167dd7cddfSDavid du Colombier       if (cinfo->marker->saw_SOF)
3177dd7cddfSDavid du Colombier 	ERREXIT(cinfo, JERR_SOF_NO_SOS);
3187dd7cddfSDavid du Colombier     } else {
3197dd7cddfSDavid du Colombier       /* Prevent infinite loop in coef ctlr's decompress_data routine
3207dd7cddfSDavid du Colombier        * if user set output_scan_number larger than number of scans.
3217dd7cddfSDavid du Colombier        */
3227dd7cddfSDavid du Colombier       if (cinfo->output_scan_number > cinfo->input_scan_number)
3237dd7cddfSDavid du Colombier 	cinfo->output_scan_number = cinfo->input_scan_number;
3247dd7cddfSDavid du Colombier     }
3257dd7cddfSDavid du Colombier     break;
3267dd7cddfSDavid du Colombier   case JPEG_SUSPENDED:
3277dd7cddfSDavid du Colombier     break;
3287dd7cddfSDavid du Colombier   }
3297dd7cddfSDavid du Colombier 
3307dd7cddfSDavid du Colombier   return val;
3317dd7cddfSDavid du Colombier }
3327dd7cddfSDavid du Colombier 
3337dd7cddfSDavid du Colombier 
3347dd7cddfSDavid du Colombier /*
3357dd7cddfSDavid du Colombier  * Reset state to begin a fresh datastream.
3367dd7cddfSDavid du Colombier  */
3377dd7cddfSDavid du Colombier 
3387dd7cddfSDavid du Colombier METHODDEF(void)
reset_input_controller(j_decompress_ptr cinfo)3397dd7cddfSDavid du Colombier reset_input_controller (j_decompress_ptr cinfo)
3407dd7cddfSDavid du Colombier {
3417dd7cddfSDavid du Colombier   my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
3427dd7cddfSDavid du Colombier 
3437dd7cddfSDavid du Colombier   inputctl->pub.consume_input = consume_markers;
3447dd7cddfSDavid du Colombier   inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
3457dd7cddfSDavid du Colombier   inputctl->pub.eoi_reached = FALSE;
3467dd7cddfSDavid du Colombier   inputctl->inheaders = TRUE;
3477dd7cddfSDavid du Colombier   /* Reset other modules */
3487dd7cddfSDavid du Colombier   (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
3497dd7cddfSDavid du Colombier   (*cinfo->marker->reset_marker_reader) (cinfo);
3507dd7cddfSDavid du Colombier   /* Reset progression state -- would be cleaner if entropy decoder did this */
3517dd7cddfSDavid du Colombier   cinfo->coef_bits = NULL;
3527dd7cddfSDavid du Colombier }
3537dd7cddfSDavid du Colombier 
3547dd7cddfSDavid du Colombier 
3557dd7cddfSDavid du Colombier /*
3567dd7cddfSDavid du Colombier  * Initialize the input controller module.
3577dd7cddfSDavid du Colombier  * This is called only once, when the decompression object is created.
3587dd7cddfSDavid du Colombier  */
3597dd7cddfSDavid du Colombier 
3607dd7cddfSDavid du Colombier GLOBAL(void)
jinit_input_controller(j_decompress_ptr cinfo)3617dd7cddfSDavid du Colombier jinit_input_controller (j_decompress_ptr cinfo)
3627dd7cddfSDavid du Colombier {
3637dd7cddfSDavid du Colombier   my_inputctl_ptr inputctl;
3647dd7cddfSDavid du Colombier 
3657dd7cddfSDavid du Colombier   /* Create subobject in permanent pool */
3667dd7cddfSDavid du Colombier   inputctl = (my_inputctl_ptr)
3677dd7cddfSDavid du Colombier     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
3687dd7cddfSDavid du Colombier 				SIZEOF(my_input_controller));
3697dd7cddfSDavid du Colombier   cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
3707dd7cddfSDavid du Colombier   /* Initialize method pointers */
3717dd7cddfSDavid du Colombier   inputctl->pub.consume_input = consume_markers;
3727dd7cddfSDavid du Colombier   inputctl->pub.reset_input_controller = reset_input_controller;
3737dd7cddfSDavid du Colombier   inputctl->pub.start_input_pass = start_input_pass;
3747dd7cddfSDavid du Colombier   inputctl->pub.finish_input_pass = finish_input_pass;
3757dd7cddfSDavid du Colombier   /* Initialize state: can't use reset_input_controller since we don't
3767dd7cddfSDavid du Colombier    * want to try to reset other modules yet.
3777dd7cddfSDavid du Colombier    */
3787dd7cddfSDavid du Colombier   inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
3797dd7cddfSDavid du Colombier   inputctl->pub.eoi_reached = FALSE;
3807dd7cddfSDavid du Colombier   inputctl->inheaders = TRUE;
3817dd7cddfSDavid du Colombier }
382