xref: /plan9/sys/src/cmd/gs/jpeg/jdmaster.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier  * jdmaster.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 master control logic for the JPEG decompressor.
97dd7cddfSDavid du Colombier  * These routines are concerned with selecting the modules to be executed
107dd7cddfSDavid du Colombier  * and with determining the number of passes and the work to be done in each
117dd7cddfSDavid du Colombier  * pass.
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_decomp_master pub; /* public fields */
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier   int pass_number;		/* # of passes completed */
257dd7cddfSDavid du Colombier 
267dd7cddfSDavid du Colombier   boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
277dd7cddfSDavid du Colombier 
287dd7cddfSDavid du Colombier   /* Saved references to initialized quantizer modules,
297dd7cddfSDavid du Colombier    * in case we need to switch modes.
307dd7cddfSDavid du Colombier    */
317dd7cddfSDavid du Colombier   struct jpeg_color_quantizer * quantizer_1pass;
327dd7cddfSDavid du Colombier   struct jpeg_color_quantizer * quantizer_2pass;
337dd7cddfSDavid du Colombier } my_decomp_master;
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier typedef my_decomp_master * my_master_ptr;
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier /*
397dd7cddfSDavid du Colombier  * Determine whether merged upsample/color conversion should be used.
407dd7cddfSDavid du Colombier  * CRUCIAL: this must match the actual capabilities of jdmerge.c!
417dd7cddfSDavid du Colombier  */
427dd7cddfSDavid du Colombier 
437dd7cddfSDavid du Colombier LOCAL(boolean)
use_merged_upsample(j_decompress_ptr cinfo)447dd7cddfSDavid du Colombier use_merged_upsample (j_decompress_ptr cinfo)
457dd7cddfSDavid du Colombier {
467dd7cddfSDavid du Colombier #ifdef UPSAMPLE_MERGING_SUPPORTED
477dd7cddfSDavid du Colombier   /* Merging is the equivalent of plain box-filter upsampling */
487dd7cddfSDavid du Colombier   if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling)
497dd7cddfSDavid du Colombier     return FALSE;
507dd7cddfSDavid du Colombier   /* jdmerge.c only supports YCC=>RGB color conversion */
517dd7cddfSDavid du Colombier   if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
527dd7cddfSDavid du Colombier       cinfo->out_color_space != JCS_RGB ||
537dd7cddfSDavid du Colombier       cinfo->out_color_components != RGB_PIXELSIZE)
547dd7cddfSDavid du Colombier     return FALSE;
557dd7cddfSDavid du Colombier   /* and it only handles 2h1v or 2h2v sampling ratios */
567dd7cddfSDavid du Colombier   if (cinfo->comp_info[0].h_samp_factor != 2 ||
577dd7cddfSDavid du Colombier       cinfo->comp_info[1].h_samp_factor != 1 ||
587dd7cddfSDavid du Colombier       cinfo->comp_info[2].h_samp_factor != 1 ||
597dd7cddfSDavid du Colombier       cinfo->comp_info[0].v_samp_factor >  2 ||
607dd7cddfSDavid du Colombier       cinfo->comp_info[1].v_samp_factor != 1 ||
617dd7cddfSDavid du Colombier       cinfo->comp_info[2].v_samp_factor != 1)
627dd7cddfSDavid du Colombier     return FALSE;
637dd7cddfSDavid du Colombier   /* furthermore, it doesn't work if we've scaled the IDCTs differently */
647dd7cddfSDavid du Colombier   if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
657dd7cddfSDavid du Colombier       cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
667dd7cddfSDavid du Colombier       cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size)
677dd7cddfSDavid du Colombier     return FALSE;
687dd7cddfSDavid du Colombier   /* ??? also need to test for upsample-time rescaling, when & if supported */
697dd7cddfSDavid du Colombier   return TRUE;			/* by golly, it'll work... */
707dd7cddfSDavid du Colombier #else
717dd7cddfSDavid du Colombier   return FALSE;
727dd7cddfSDavid du Colombier #endif
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier /*
777dd7cddfSDavid du Colombier  * Compute output image dimensions and related values.
787dd7cddfSDavid du Colombier  * NOTE: this is exported for possible use by application.
797dd7cddfSDavid du Colombier  * Hence it mustn't do anything that can't be done twice.
807dd7cddfSDavid du Colombier  * Also note that it may be called before the master module is initialized!
817dd7cddfSDavid du Colombier  */
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier GLOBAL(void)
jpeg_calc_output_dimensions(j_decompress_ptr cinfo)847dd7cddfSDavid du Colombier jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
857dd7cddfSDavid du Colombier /* Do computations that are needed before master selection phase */
867dd7cddfSDavid du Colombier {
87*593dc095SDavid du Colombier #ifdef IDCT_SCALING_SUPPORTED
887dd7cddfSDavid du Colombier   int ci;
897dd7cddfSDavid du Colombier   jpeg_component_info *compptr;
90*593dc095SDavid du Colombier #endif
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier   /* Prevent application from calling me at wrong times */
937dd7cddfSDavid du Colombier   if (cinfo->global_state != DSTATE_READY)
947dd7cddfSDavid du Colombier     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
957dd7cddfSDavid du Colombier 
967dd7cddfSDavid du Colombier #ifdef IDCT_SCALING_SUPPORTED
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier   /* Compute actual output image dimensions and DCT scaling choices. */
997dd7cddfSDavid du Colombier   if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
1007dd7cddfSDavid du Colombier     /* Provide 1/8 scaling */
1017dd7cddfSDavid du Colombier     cinfo->output_width = (JDIMENSION)
1027dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_width, 8L);
1037dd7cddfSDavid du Colombier     cinfo->output_height = (JDIMENSION)
1047dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_height, 8L);
1057dd7cddfSDavid du Colombier     cinfo->min_DCT_scaled_size = 1;
1067dd7cddfSDavid du Colombier   } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
1077dd7cddfSDavid du Colombier     /* Provide 1/4 scaling */
1087dd7cddfSDavid du Colombier     cinfo->output_width = (JDIMENSION)
1097dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_width, 4L);
1107dd7cddfSDavid du Colombier     cinfo->output_height = (JDIMENSION)
1117dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_height, 4L);
1127dd7cddfSDavid du Colombier     cinfo->min_DCT_scaled_size = 2;
1137dd7cddfSDavid du Colombier   } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
1147dd7cddfSDavid du Colombier     /* Provide 1/2 scaling */
1157dd7cddfSDavid du Colombier     cinfo->output_width = (JDIMENSION)
1167dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_width, 2L);
1177dd7cddfSDavid du Colombier     cinfo->output_height = (JDIMENSION)
1187dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_height, 2L);
1197dd7cddfSDavid du Colombier     cinfo->min_DCT_scaled_size = 4;
1207dd7cddfSDavid du Colombier   } else {
1217dd7cddfSDavid du Colombier     /* Provide 1/1 scaling */
1227dd7cddfSDavid du Colombier     cinfo->output_width = cinfo->image_width;
1237dd7cddfSDavid du Colombier     cinfo->output_height = cinfo->image_height;
1247dd7cddfSDavid du Colombier     cinfo->min_DCT_scaled_size = DCTSIZE;
1257dd7cddfSDavid du Colombier   }
1267dd7cddfSDavid du Colombier   /* In selecting the actual DCT scaling for each component, we try to
1277dd7cddfSDavid du Colombier    * scale up the chroma components via IDCT scaling rather than upsampling.
1287dd7cddfSDavid du Colombier    * This saves time if the upsampler gets to use 1:1 scaling.
1297dd7cddfSDavid du Colombier    * Note this code assumes that the supported DCT scalings are powers of 2.
1307dd7cddfSDavid du Colombier    */
1317dd7cddfSDavid du Colombier   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
1327dd7cddfSDavid du Colombier        ci++, compptr++) {
1337dd7cddfSDavid du Colombier     int ssize = cinfo->min_DCT_scaled_size;
1347dd7cddfSDavid du Colombier     while (ssize < DCTSIZE &&
1357dd7cddfSDavid du Colombier 	   (compptr->h_samp_factor * ssize * 2 <=
1367dd7cddfSDavid du Colombier 	    cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) &&
1377dd7cddfSDavid du Colombier 	   (compptr->v_samp_factor * ssize * 2 <=
1387dd7cddfSDavid du Colombier 	    cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) {
1397dd7cddfSDavid du Colombier       ssize = ssize * 2;
1407dd7cddfSDavid du Colombier     }
1417dd7cddfSDavid du Colombier     compptr->DCT_scaled_size = ssize;
1427dd7cddfSDavid du Colombier   }
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier   /* Recompute downsampled dimensions of components;
1457dd7cddfSDavid du Colombier    * application needs to know these if using raw downsampled data.
1467dd7cddfSDavid du Colombier    */
1477dd7cddfSDavid du Colombier   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
1487dd7cddfSDavid du Colombier        ci++, compptr++) {
1497dd7cddfSDavid du Colombier     /* Size in samples, after IDCT scaling */
1507dd7cddfSDavid du Colombier     compptr->downsampled_width = (JDIMENSION)
1517dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_width *
1527dd7cddfSDavid du Colombier 		    (long) (compptr->h_samp_factor * compptr->DCT_scaled_size),
1537dd7cddfSDavid du Colombier 		    (long) (cinfo->max_h_samp_factor * DCTSIZE));
1547dd7cddfSDavid du Colombier     compptr->downsampled_height = (JDIMENSION)
1557dd7cddfSDavid du Colombier       jdiv_round_up((long) cinfo->image_height *
1567dd7cddfSDavid du Colombier 		    (long) (compptr->v_samp_factor * compptr->DCT_scaled_size),
1577dd7cddfSDavid du Colombier 		    (long) (cinfo->max_v_samp_factor * DCTSIZE));
1587dd7cddfSDavid du Colombier   }
1597dd7cddfSDavid du Colombier 
1607dd7cddfSDavid du Colombier #else /* !IDCT_SCALING_SUPPORTED */
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier   /* Hardwire it to "no scaling" */
1637dd7cddfSDavid du Colombier   cinfo->output_width = cinfo->image_width;
1647dd7cddfSDavid du Colombier   cinfo->output_height = cinfo->image_height;
1657dd7cddfSDavid du Colombier   /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE,
1667dd7cddfSDavid du Colombier    * and has computed unscaled downsampled_width and downsampled_height.
1677dd7cddfSDavid du Colombier    */
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier #endif /* IDCT_SCALING_SUPPORTED */
1707dd7cddfSDavid du Colombier 
1717dd7cddfSDavid du Colombier   /* Report number of components in selected colorspace. */
1727dd7cddfSDavid du Colombier   /* Probably this should be in the color conversion module... */
1737dd7cddfSDavid du Colombier   switch (cinfo->out_color_space) {
1747dd7cddfSDavid du Colombier   case JCS_GRAYSCALE:
1757dd7cddfSDavid du Colombier     cinfo->out_color_components = 1;
1767dd7cddfSDavid du Colombier     break;
1777dd7cddfSDavid du Colombier   case JCS_RGB:
1787dd7cddfSDavid du Colombier #if RGB_PIXELSIZE != 3
1797dd7cddfSDavid du Colombier     cinfo->out_color_components = RGB_PIXELSIZE;
1807dd7cddfSDavid du Colombier     break;
1817dd7cddfSDavid du Colombier #endif /* else share code with YCbCr */
1827dd7cddfSDavid du Colombier   case JCS_YCbCr:
1837dd7cddfSDavid du Colombier     cinfo->out_color_components = 3;
1847dd7cddfSDavid du Colombier     break;
1857dd7cddfSDavid du Colombier   case JCS_CMYK:
1867dd7cddfSDavid du Colombier   case JCS_YCCK:
1877dd7cddfSDavid du Colombier     cinfo->out_color_components = 4;
1887dd7cddfSDavid du Colombier     break;
1897dd7cddfSDavid du Colombier   default:			/* else must be same colorspace as in file */
1907dd7cddfSDavid du Colombier     cinfo->out_color_components = cinfo->num_components;
1917dd7cddfSDavid du Colombier     break;
1927dd7cddfSDavid du Colombier   }
1937dd7cddfSDavid du Colombier   cinfo->output_components = (cinfo->quantize_colors ? 1 :
1947dd7cddfSDavid du Colombier 			      cinfo->out_color_components);
1957dd7cddfSDavid du Colombier 
1967dd7cddfSDavid du Colombier   /* See if upsampler will want to emit more than one row at a time */
1977dd7cddfSDavid du Colombier   if (use_merged_upsample(cinfo))
1987dd7cddfSDavid du Colombier     cinfo->rec_outbuf_height = cinfo->max_v_samp_factor;
1997dd7cddfSDavid du Colombier   else
2007dd7cddfSDavid du Colombier     cinfo->rec_outbuf_height = 1;
2017dd7cddfSDavid du Colombier }
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier /*
2057dd7cddfSDavid du Colombier  * Several decompression processes need to range-limit values to the range
2067dd7cddfSDavid du Colombier  * 0..MAXJSAMPLE; the input value may fall somewhat outside this range
2077dd7cddfSDavid du Colombier  * due to noise introduced by quantization, roundoff error, etc.  These
2087dd7cddfSDavid du Colombier  * processes are inner loops and need to be as fast as possible.  On most
2097dd7cddfSDavid du Colombier  * machines, particularly CPUs with pipelines or instruction prefetch,
2107dd7cddfSDavid du Colombier  * a (subscript-check-less) C table lookup
2117dd7cddfSDavid du Colombier  *		x = sample_range_limit[x];
2127dd7cddfSDavid du Colombier  * is faster than explicit tests
2137dd7cddfSDavid du Colombier  *		if (x < 0)  x = 0;
2147dd7cddfSDavid du Colombier  *		else if (x > MAXJSAMPLE)  x = MAXJSAMPLE;
2157dd7cddfSDavid du Colombier  * These processes all use a common table prepared by the routine below.
2167dd7cddfSDavid du Colombier  *
2177dd7cddfSDavid du Colombier  * For most steps we can mathematically guarantee that the initial value
2187dd7cddfSDavid du Colombier  * of x is within MAXJSAMPLE+1 of the legal range, so a table running from
2197dd7cddfSDavid du Colombier  * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient.  But for the initial
2207dd7cddfSDavid du Colombier  * limiting step (just after the IDCT), a wildly out-of-range value is
2217dd7cddfSDavid du Colombier  * possible if the input data is corrupt.  To avoid any chance of indexing
2227dd7cddfSDavid du Colombier  * off the end of memory and getting a bad-pointer trap, we perform the
2237dd7cddfSDavid du Colombier  * post-IDCT limiting thus:
2247dd7cddfSDavid du Colombier  *		x = range_limit[x & MASK];
2257dd7cddfSDavid du Colombier  * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
2267dd7cddfSDavid du Colombier  * samples.  Under normal circumstances this is more than enough range and
2277dd7cddfSDavid du Colombier  * a correct output will be generated; with bogus input data the mask will
2287dd7cddfSDavid du Colombier  * cause wraparound, and we will safely generate a bogus-but-in-range output.
2297dd7cddfSDavid du Colombier  * For the post-IDCT step, we want to convert the data from signed to unsigned
2307dd7cddfSDavid du Colombier  * representation by adding CENTERJSAMPLE at the same time that we limit it.
2317dd7cddfSDavid du Colombier  * So the post-IDCT limiting table ends up looking like this:
2327dd7cddfSDavid du Colombier  *   CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
2337dd7cddfSDavid du Colombier  *   MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
2347dd7cddfSDavid du Colombier  *   0          (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
2357dd7cddfSDavid du Colombier  *   0,1,...,CENTERJSAMPLE-1
2367dd7cddfSDavid du Colombier  * Negative inputs select values from the upper half of the table after
2377dd7cddfSDavid du Colombier  * masking.
2387dd7cddfSDavid du Colombier  *
2397dd7cddfSDavid du Colombier  * We can save some space by overlapping the start of the post-IDCT table
2407dd7cddfSDavid du Colombier  * with the simpler range limiting table.  The post-IDCT table begins at
2417dd7cddfSDavid du Colombier  * sample_range_limit + CENTERJSAMPLE.
2427dd7cddfSDavid du Colombier  *
2437dd7cddfSDavid du Colombier  * Note that the table is allocated in near data space on PCs; it's small
2447dd7cddfSDavid du Colombier  * enough and used often enough to justify this.
2457dd7cddfSDavid du Colombier  */
2467dd7cddfSDavid du Colombier 
2477dd7cddfSDavid du Colombier LOCAL(void)
prepare_range_limit_table(j_decompress_ptr cinfo)2487dd7cddfSDavid du Colombier prepare_range_limit_table (j_decompress_ptr cinfo)
2497dd7cddfSDavid du Colombier /* Allocate and fill in the sample_range_limit table */
2507dd7cddfSDavid du Colombier {
2517dd7cddfSDavid du Colombier   JSAMPLE * table;
2527dd7cddfSDavid du Colombier   int i;
2537dd7cddfSDavid du Colombier 
2547dd7cddfSDavid du Colombier   table = (JSAMPLE *)
2557dd7cddfSDavid du Colombier     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
2567dd7cddfSDavid du Colombier 		(5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
2577dd7cddfSDavid du Colombier   table += (MAXJSAMPLE+1);	/* allow negative subscripts of simple table */
2587dd7cddfSDavid du Colombier   cinfo->sample_range_limit = table;
2597dd7cddfSDavid du Colombier   /* First segment of "simple" table: limit[x] = 0 for x < 0 */
2607dd7cddfSDavid du Colombier   MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
2617dd7cddfSDavid du Colombier   /* Main part of "simple" table: limit[x] = x */
2627dd7cddfSDavid du Colombier   for (i = 0; i <= MAXJSAMPLE; i++)
2637dd7cddfSDavid du Colombier     table[i] = (JSAMPLE) i;
2647dd7cddfSDavid du Colombier   table += CENTERJSAMPLE;	/* Point to where post-IDCT table starts */
2657dd7cddfSDavid du Colombier   /* End of simple table, rest of first half of post-IDCT table */
2667dd7cddfSDavid du Colombier   for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
2677dd7cddfSDavid du Colombier     table[i] = MAXJSAMPLE;
2687dd7cddfSDavid du Colombier   /* Second half of post-IDCT table */
2697dd7cddfSDavid du Colombier   MEMZERO(table + (2 * (MAXJSAMPLE+1)),
2707dd7cddfSDavid du Colombier 	  (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
2717dd7cddfSDavid du Colombier   MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
2727dd7cddfSDavid du Colombier 	  cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
2737dd7cddfSDavid du Colombier }
2747dd7cddfSDavid du Colombier 
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier /*
2777dd7cddfSDavid du Colombier  * Master selection of decompression modules.
2787dd7cddfSDavid du Colombier  * This is done once at jpeg_start_decompress time.  We determine
2797dd7cddfSDavid du Colombier  * which modules will be used and give them appropriate initialization calls.
2807dd7cddfSDavid du Colombier  * We also initialize the decompressor input side to begin consuming data.
2817dd7cddfSDavid du Colombier  *
2827dd7cddfSDavid du Colombier  * Since jpeg_read_header has finished, we know what is in the SOF
2837dd7cddfSDavid du Colombier  * and (first) SOS markers.  We also have all the application parameter
2847dd7cddfSDavid du Colombier  * settings.
2857dd7cddfSDavid du Colombier  */
2867dd7cddfSDavid du Colombier 
2877dd7cddfSDavid du Colombier LOCAL(void)
master_selection(j_decompress_ptr cinfo)2887dd7cddfSDavid du Colombier master_selection (j_decompress_ptr cinfo)
2897dd7cddfSDavid du Colombier {
2907dd7cddfSDavid du Colombier   my_master_ptr master = (my_master_ptr) cinfo->master;
2917dd7cddfSDavid du Colombier   boolean use_c_buffer;
2927dd7cddfSDavid du Colombier   long samplesperrow;
2937dd7cddfSDavid du Colombier   JDIMENSION jd_samplesperrow;
2947dd7cddfSDavid du Colombier 
2957dd7cddfSDavid du Colombier   /* Initialize dimensions and other stuff */
2967dd7cddfSDavid du Colombier   jpeg_calc_output_dimensions(cinfo);
2977dd7cddfSDavid du Colombier   prepare_range_limit_table(cinfo);
2987dd7cddfSDavid du Colombier 
2997dd7cddfSDavid du Colombier   /* Width of an output scanline must be representable as JDIMENSION. */
3007dd7cddfSDavid du Colombier   samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
3017dd7cddfSDavid du Colombier   jd_samplesperrow = (JDIMENSION) samplesperrow;
3027dd7cddfSDavid du Colombier   if ((long) jd_samplesperrow != samplesperrow)
3037dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
3047dd7cddfSDavid du Colombier 
3057dd7cddfSDavid du Colombier   /* Initialize my private state */
3067dd7cddfSDavid du Colombier   master->pass_number = 0;
3077dd7cddfSDavid du Colombier   master->using_merged_upsample = use_merged_upsample(cinfo);
3087dd7cddfSDavid du Colombier 
3097dd7cddfSDavid du Colombier   /* Color quantizer selection */
3107dd7cddfSDavid du Colombier   master->quantizer_1pass = NULL;
3117dd7cddfSDavid du Colombier   master->quantizer_2pass = NULL;
3127dd7cddfSDavid du Colombier   /* No mode changes if not using buffered-image mode. */
3137dd7cddfSDavid du Colombier   if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
3147dd7cddfSDavid du Colombier     cinfo->enable_1pass_quant = FALSE;
3157dd7cddfSDavid du Colombier     cinfo->enable_external_quant = FALSE;
3167dd7cddfSDavid du Colombier     cinfo->enable_2pass_quant = FALSE;
3177dd7cddfSDavid du Colombier   }
3187dd7cddfSDavid du Colombier   if (cinfo->quantize_colors) {
3197dd7cddfSDavid du Colombier     if (cinfo->raw_data_out)
3207dd7cddfSDavid du Colombier       ERREXIT(cinfo, JERR_NOTIMPL);
3217dd7cddfSDavid du Colombier     /* 2-pass quantizer only works in 3-component color space. */
3227dd7cddfSDavid du Colombier     if (cinfo->out_color_components != 3) {
3237dd7cddfSDavid du Colombier       cinfo->enable_1pass_quant = TRUE;
3247dd7cddfSDavid du Colombier       cinfo->enable_external_quant = FALSE;
3257dd7cddfSDavid du Colombier       cinfo->enable_2pass_quant = FALSE;
3267dd7cddfSDavid du Colombier       cinfo->colormap = NULL;
3277dd7cddfSDavid du Colombier     } else if (cinfo->colormap != NULL) {
3287dd7cddfSDavid du Colombier       cinfo->enable_external_quant = TRUE;
3297dd7cddfSDavid du Colombier     } else if (cinfo->two_pass_quantize) {
3307dd7cddfSDavid du Colombier       cinfo->enable_2pass_quant = TRUE;
3317dd7cddfSDavid du Colombier     } else {
3327dd7cddfSDavid du Colombier       cinfo->enable_1pass_quant = TRUE;
3337dd7cddfSDavid du Colombier     }
3347dd7cddfSDavid du Colombier 
3357dd7cddfSDavid du Colombier     if (cinfo->enable_1pass_quant) {
3367dd7cddfSDavid du Colombier #ifdef QUANT_1PASS_SUPPORTED
3377dd7cddfSDavid du Colombier       jinit_1pass_quantizer(cinfo);
3387dd7cddfSDavid du Colombier       master->quantizer_1pass = cinfo->cquantize;
3397dd7cddfSDavid du Colombier #else
3407dd7cddfSDavid du Colombier       ERREXIT(cinfo, JERR_NOT_COMPILED);
3417dd7cddfSDavid du Colombier #endif
3427dd7cddfSDavid du Colombier     }
3437dd7cddfSDavid du Colombier 
3447dd7cddfSDavid du Colombier     /* We use the 2-pass code to map to external colormaps. */
3457dd7cddfSDavid du Colombier     if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) {
3467dd7cddfSDavid du Colombier #ifdef QUANT_2PASS_SUPPORTED
3477dd7cddfSDavid du Colombier       jinit_2pass_quantizer(cinfo);
3487dd7cddfSDavid du Colombier       master->quantizer_2pass = cinfo->cquantize;
3497dd7cddfSDavid du Colombier #else
3507dd7cddfSDavid du Colombier       ERREXIT(cinfo, JERR_NOT_COMPILED);
3517dd7cddfSDavid du Colombier #endif
3527dd7cddfSDavid du Colombier     }
3537dd7cddfSDavid du Colombier     /* If both quantizers are initialized, the 2-pass one is left active;
3547dd7cddfSDavid du Colombier      * this is necessary for starting with quantization to an external map.
3557dd7cddfSDavid du Colombier      */
3567dd7cddfSDavid du Colombier   }
3577dd7cddfSDavid du Colombier 
3587dd7cddfSDavid du Colombier   /* Post-processing: in particular, color conversion first */
3597dd7cddfSDavid du Colombier   if (! cinfo->raw_data_out) {
3607dd7cddfSDavid du Colombier     if (master->using_merged_upsample) {
3617dd7cddfSDavid du Colombier #ifdef UPSAMPLE_MERGING_SUPPORTED
3627dd7cddfSDavid du Colombier       jinit_merged_upsampler(cinfo); /* does color conversion too */
3637dd7cddfSDavid du Colombier #else
3647dd7cddfSDavid du Colombier       ERREXIT(cinfo, JERR_NOT_COMPILED);
3657dd7cddfSDavid du Colombier #endif
3667dd7cddfSDavid du Colombier     } else {
3677dd7cddfSDavid du Colombier       jinit_color_deconverter(cinfo);
3687dd7cddfSDavid du Colombier       jinit_upsampler(cinfo);
3697dd7cddfSDavid du Colombier     }
3707dd7cddfSDavid du Colombier     jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
3717dd7cddfSDavid du Colombier   }
3727dd7cddfSDavid du Colombier   /* Inverse DCT */
3737dd7cddfSDavid du Colombier   jinit_inverse_dct(cinfo);
3747dd7cddfSDavid du Colombier   /* Entropy decoding: either Huffman or arithmetic coding. */
3757dd7cddfSDavid du Colombier   if (cinfo->arith_code) {
3767dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
3777dd7cddfSDavid du Colombier   } else {
3787dd7cddfSDavid du Colombier     if (cinfo->progressive_mode) {
3797dd7cddfSDavid du Colombier #ifdef D_PROGRESSIVE_SUPPORTED
3807dd7cddfSDavid du Colombier       jinit_phuff_decoder(cinfo);
3817dd7cddfSDavid du Colombier #else
3827dd7cddfSDavid du Colombier       ERREXIT(cinfo, JERR_NOT_COMPILED);
3837dd7cddfSDavid du Colombier #endif
3847dd7cddfSDavid du Colombier     } else
3857dd7cddfSDavid du Colombier       jinit_huff_decoder(cinfo);
3867dd7cddfSDavid du Colombier   }
3877dd7cddfSDavid du Colombier 
3887dd7cddfSDavid du Colombier   /* Initialize principal buffer controllers. */
3897dd7cddfSDavid du Colombier   use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
3907dd7cddfSDavid du Colombier   jinit_d_coef_controller(cinfo, use_c_buffer);
3917dd7cddfSDavid du Colombier 
3927dd7cddfSDavid du Colombier   if (! cinfo->raw_data_out)
3937dd7cddfSDavid du Colombier     jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
3947dd7cddfSDavid du Colombier 
3957dd7cddfSDavid du Colombier   /* We can now tell the memory manager to allocate virtual arrays. */
3967dd7cddfSDavid du Colombier   (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
3977dd7cddfSDavid du Colombier 
3987dd7cddfSDavid du Colombier   /* Initialize input side of decompressor to consume first scan. */
3997dd7cddfSDavid du Colombier   (*cinfo->inputctl->start_input_pass) (cinfo);
4007dd7cddfSDavid du Colombier 
4017dd7cddfSDavid du Colombier #ifdef D_MULTISCAN_FILES_SUPPORTED
4027dd7cddfSDavid du Colombier   /* If jpeg_start_decompress will read the whole file, initialize
4037dd7cddfSDavid du Colombier    * progress monitoring appropriately.  The input step is counted
4047dd7cddfSDavid du Colombier    * as one pass.
4057dd7cddfSDavid du Colombier    */
4067dd7cddfSDavid du Colombier   if (cinfo->progress != NULL && ! cinfo->buffered_image &&
4077dd7cddfSDavid du Colombier       cinfo->inputctl->has_multiple_scans) {
4087dd7cddfSDavid du Colombier     int nscans;
4097dd7cddfSDavid du Colombier     /* Estimate number of scans to set pass_limit. */
4107dd7cddfSDavid du Colombier     if (cinfo->progressive_mode) {
4117dd7cddfSDavid du Colombier       /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
4127dd7cddfSDavid du Colombier       nscans = 2 + 3 * cinfo->num_components;
4137dd7cddfSDavid du Colombier     } else {
4147dd7cddfSDavid du Colombier       /* For a nonprogressive multiscan file, estimate 1 scan per component. */
4157dd7cddfSDavid du Colombier       nscans = cinfo->num_components;
4167dd7cddfSDavid du Colombier     }
4177dd7cddfSDavid du Colombier     cinfo->progress->pass_counter = 0L;
4187dd7cddfSDavid du Colombier     cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
4197dd7cddfSDavid du Colombier     cinfo->progress->completed_passes = 0;
4207dd7cddfSDavid du Colombier     cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
4217dd7cddfSDavid du Colombier     /* Count the input pass as done */
4227dd7cddfSDavid du Colombier     master->pass_number++;
4237dd7cddfSDavid du Colombier   }
4247dd7cddfSDavid du Colombier #endif /* D_MULTISCAN_FILES_SUPPORTED */
4257dd7cddfSDavid du Colombier }
4267dd7cddfSDavid du Colombier 
4277dd7cddfSDavid du Colombier 
4287dd7cddfSDavid du Colombier /*
4297dd7cddfSDavid du Colombier  * Per-pass setup.
4307dd7cddfSDavid du Colombier  * This is called at the beginning of each output pass.  We determine which
4317dd7cddfSDavid du Colombier  * modules will be active during this pass and give them appropriate
4327dd7cddfSDavid du Colombier  * start_pass calls.  We also set is_dummy_pass to indicate whether this
4337dd7cddfSDavid du Colombier  * is a "real" output pass or a dummy pass for color quantization.
434*593dc095SDavid du Colombier  * (In the latter case, jdapistd.c will crank the pass to completion.)
4357dd7cddfSDavid du Colombier  */
4367dd7cddfSDavid du Colombier 
4377dd7cddfSDavid du Colombier METHODDEF(void)
prepare_for_output_pass(j_decompress_ptr cinfo)4387dd7cddfSDavid du Colombier prepare_for_output_pass (j_decompress_ptr cinfo)
4397dd7cddfSDavid du Colombier {
4407dd7cddfSDavid du Colombier   my_master_ptr master = (my_master_ptr) cinfo->master;
4417dd7cddfSDavid du Colombier 
4427dd7cddfSDavid du Colombier   if (master->pub.is_dummy_pass) {
4437dd7cddfSDavid du Colombier #ifdef QUANT_2PASS_SUPPORTED
4447dd7cddfSDavid du Colombier     /* Final pass of 2-pass quantization */
4457dd7cddfSDavid du Colombier     master->pub.is_dummy_pass = FALSE;
4467dd7cddfSDavid du Colombier     (*cinfo->cquantize->start_pass) (cinfo, FALSE);
4477dd7cddfSDavid du Colombier     (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST);
4487dd7cddfSDavid du Colombier     (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST);
4497dd7cddfSDavid du Colombier #else
4507dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_NOT_COMPILED);
4517dd7cddfSDavid du Colombier #endif /* QUANT_2PASS_SUPPORTED */
4527dd7cddfSDavid du Colombier   } else {
4537dd7cddfSDavid du Colombier     if (cinfo->quantize_colors && cinfo->colormap == NULL) {
4547dd7cddfSDavid du Colombier       /* Select new quantization method */
4557dd7cddfSDavid du Colombier       if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) {
4567dd7cddfSDavid du Colombier 	cinfo->cquantize = master->quantizer_2pass;
4577dd7cddfSDavid du Colombier 	master->pub.is_dummy_pass = TRUE;
4587dd7cddfSDavid du Colombier       } else if (cinfo->enable_1pass_quant) {
4597dd7cddfSDavid du Colombier 	cinfo->cquantize = master->quantizer_1pass;
4607dd7cddfSDavid du Colombier       } else {
4617dd7cddfSDavid du Colombier 	ERREXIT(cinfo, JERR_MODE_CHANGE);
4627dd7cddfSDavid du Colombier       }
4637dd7cddfSDavid du Colombier     }
4647dd7cddfSDavid du Colombier     (*cinfo->idct->start_pass) (cinfo);
4657dd7cddfSDavid du Colombier     (*cinfo->coef->start_output_pass) (cinfo);
4667dd7cddfSDavid du Colombier     if (! cinfo->raw_data_out) {
4677dd7cddfSDavid du Colombier       if (! master->using_merged_upsample)
4687dd7cddfSDavid du Colombier 	(*cinfo->cconvert->start_pass) (cinfo);
4697dd7cddfSDavid du Colombier       (*cinfo->upsample->start_pass) (cinfo);
4707dd7cddfSDavid du Colombier       if (cinfo->quantize_colors)
4717dd7cddfSDavid du Colombier 	(*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass);
4727dd7cddfSDavid du Colombier       (*cinfo->post->start_pass) (cinfo,
4737dd7cddfSDavid du Colombier 	    (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
4747dd7cddfSDavid du Colombier       (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
4757dd7cddfSDavid du Colombier     }
4767dd7cddfSDavid du Colombier   }
4777dd7cddfSDavid du Colombier 
4787dd7cddfSDavid du Colombier   /* Set up progress monitor's pass info if present */
4797dd7cddfSDavid du Colombier   if (cinfo->progress != NULL) {
4807dd7cddfSDavid du Colombier     cinfo->progress->completed_passes = master->pass_number;
4817dd7cddfSDavid du Colombier     cinfo->progress->total_passes = master->pass_number +
4827dd7cddfSDavid du Colombier 				    (master->pub.is_dummy_pass ? 2 : 1);
4837dd7cddfSDavid du Colombier     /* In buffered-image mode, we assume one more output pass if EOI not
4847dd7cddfSDavid du Colombier      * yet reached, but no more passes if EOI has been reached.
4857dd7cddfSDavid du Colombier      */
4867dd7cddfSDavid du Colombier     if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
4877dd7cddfSDavid du Colombier       cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
4887dd7cddfSDavid du Colombier     }
4897dd7cddfSDavid du Colombier   }
4907dd7cddfSDavid du Colombier }
4917dd7cddfSDavid du Colombier 
4927dd7cddfSDavid du Colombier 
4937dd7cddfSDavid du Colombier /*
4947dd7cddfSDavid du Colombier  * Finish up at end of an output pass.
4957dd7cddfSDavid du Colombier  */
4967dd7cddfSDavid du Colombier 
4977dd7cddfSDavid du Colombier METHODDEF(void)
finish_output_pass(j_decompress_ptr cinfo)4987dd7cddfSDavid du Colombier finish_output_pass (j_decompress_ptr cinfo)
4997dd7cddfSDavid du Colombier {
5007dd7cddfSDavid du Colombier   my_master_ptr master = (my_master_ptr) cinfo->master;
5017dd7cddfSDavid du Colombier 
5027dd7cddfSDavid du Colombier   if (cinfo->quantize_colors)
5037dd7cddfSDavid du Colombier     (*cinfo->cquantize->finish_pass) (cinfo);
5047dd7cddfSDavid du Colombier   master->pass_number++;
5057dd7cddfSDavid du Colombier }
5067dd7cddfSDavid du Colombier 
5077dd7cddfSDavid du Colombier 
5087dd7cddfSDavid du Colombier #ifdef D_MULTISCAN_FILES_SUPPORTED
5097dd7cddfSDavid du Colombier 
5107dd7cddfSDavid du Colombier /*
5117dd7cddfSDavid du Colombier  * Switch to a new external colormap between output passes.
5127dd7cddfSDavid du Colombier  */
5137dd7cddfSDavid du Colombier 
5147dd7cddfSDavid du Colombier GLOBAL(void)
jpeg_new_colormap(j_decompress_ptr cinfo)5157dd7cddfSDavid du Colombier jpeg_new_colormap (j_decompress_ptr cinfo)
5167dd7cddfSDavid du Colombier {
5177dd7cddfSDavid du Colombier   my_master_ptr master = (my_master_ptr) cinfo->master;
5187dd7cddfSDavid du Colombier 
5197dd7cddfSDavid du Colombier   /* Prevent application from calling me at wrong times */
5207dd7cddfSDavid du Colombier   if (cinfo->global_state != DSTATE_BUFIMAGE)
5217dd7cddfSDavid du Colombier     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
5227dd7cddfSDavid du Colombier 
5237dd7cddfSDavid du Colombier   if (cinfo->quantize_colors && cinfo->enable_external_quant &&
5247dd7cddfSDavid du Colombier       cinfo->colormap != NULL) {
5257dd7cddfSDavid du Colombier     /* Select 2-pass quantizer for external colormap use */
5267dd7cddfSDavid du Colombier     cinfo->cquantize = master->quantizer_2pass;
5277dd7cddfSDavid du Colombier     /* Notify quantizer of colormap change */
5287dd7cddfSDavid du Colombier     (*cinfo->cquantize->new_color_map) (cinfo);
5297dd7cddfSDavid du Colombier     master->pub.is_dummy_pass = FALSE; /* just in case */
5307dd7cddfSDavid du Colombier   } else
5317dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_MODE_CHANGE);
5327dd7cddfSDavid du Colombier }
5337dd7cddfSDavid du Colombier 
5347dd7cddfSDavid du Colombier #endif /* D_MULTISCAN_FILES_SUPPORTED */
5357dd7cddfSDavid du Colombier 
5367dd7cddfSDavid du Colombier 
5377dd7cddfSDavid du Colombier /*
5387dd7cddfSDavid du Colombier  * Initialize master decompression control and select active modules.
5397dd7cddfSDavid du Colombier  * This is performed at the start of jpeg_start_decompress.
5407dd7cddfSDavid du Colombier  */
5417dd7cddfSDavid du Colombier 
5427dd7cddfSDavid du Colombier GLOBAL(void)
jinit_master_decompress(j_decompress_ptr cinfo)5437dd7cddfSDavid du Colombier jinit_master_decompress (j_decompress_ptr cinfo)
5447dd7cddfSDavid du Colombier {
5457dd7cddfSDavid du Colombier   my_master_ptr master;
5467dd7cddfSDavid du Colombier 
5477dd7cddfSDavid du Colombier   master = (my_master_ptr)
5487dd7cddfSDavid du Colombier       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
5497dd7cddfSDavid du Colombier 				  SIZEOF(my_decomp_master));
5507dd7cddfSDavid du Colombier   cinfo->master = (struct jpeg_decomp_master *) master;
5517dd7cddfSDavid du Colombier   master->pub.prepare_for_output_pass = prepare_for_output_pass;
5527dd7cddfSDavid du Colombier   master->pub.finish_output_pass = finish_output_pass;
5537dd7cddfSDavid du Colombier 
5547dd7cddfSDavid du Colombier   master->pub.is_dummy_pass = FALSE;
5557dd7cddfSDavid du Colombier 
5567dd7cddfSDavid du Colombier   master_selection(cinfo);
5577dd7cddfSDavid du Colombier }
558