home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / compresn / jpegv3sr / jcpipe.c < prev    next >
C/C++ Source or Header  |  1992-03-02  |  26KB  |  721 lines

  1. /*
  2.  * jcpipe.c
  3.  *
  4.  * Copyright (C) 1991, 1992, 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 compression pipeline controllers.
  9.  * These routines are invoked via the c_pipeline_controller method.
  10.  *
  11.  * There are four basic pipeline controllers, one for each combination of:
  12.  *    single-scan JPEG file (single component or fully interleaved)
  13.  *  vs. multiple-scan JPEG file (noninterleaved or partially interleaved).
  14.  *
  15.  *    optimization of entropy encoding parameters
  16.  *  vs. usage of default encoding parameters.
  17.  *
  18.  * Note that these conditions determine the needs for "big" arrays:
  19.  * multiple scans imply a big array for splitting the color components;
  20.  * entropy encoding optimization needs a big array for the MCU data.
  21.  *
  22.  * All but the simplest controller (single-scan, no optimization) can be
  23.  * compiled out through configuration options, if you need to make a minimal
  24.  * implementation.
  25.  */
  26.  
  27. #include "jinclude.h"
  28.  
  29.  
  30. /*
  31.  * About the data structures:
  32.  *
  33.  * The processing chunk size for subsampling is referred to in this file as
  34.  * a "row group": a row group is defined as Vk (v_samp_factor) sample rows of
  35.  * any component after subsampling, or Vmax (max_v_samp_factor) unsubsampled
  36.  * rows.  In an interleaved scan each MCU row contains exactly DCTSIZE row
  37.  * groups of each component in the scan.  In a noninterleaved scan an MCU row
  38.  * is one row of blocks, which might not be an integral number of row groups;
  39.  * for convenience we use a buffer of the same size as in interleaved scans,
  40.  * and process Vk MCU rows in each burst of subsampling.
  41.  * To provide context for the subsampling step, we have to retain the last
  42.  * two row groups of the previous MCU row while reading in the next MCU row
  43.  * (or set of Vk MCU rows).  To do this without copying data about, we create
  44.  * a rather strange data structure.  Exactly DCTSIZE+2 row groups of samples
  45.  * are allocated, but we create two different sets of pointers to this array.
  46.  * The second set swaps the last two pairs of row groups.  By working
  47.  * alternately with the two sets of pointers, we can access the data in the
  48.  * desired order.
  49.  */
  50.  
  51.  
  52.  
  53. /*
  54.  * Utility routines: common code for pipeline controllers
  55.  */
  56.  
  57. LOCAL void
  58. interleaved_scan_setup (compress_info_ptr cinfo)
  59. /* Compute all derived info for an interleaved (multi-component) scan */
  60. /* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */
  61. {
  62.   short ci, mcublks;
  63.   jpeg_component_info *compptr;
  64.  
  65.   if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
  66.     ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  67.  
  68.   cinfo->MCUs_per_row = (cinfo->image_width
  69.              + cinfo->max_h_samp_factor*DCTSIZE - 1)
  70.             / (cinfo->max_h_samp_factor*DCTSIZE);
  71.  
  72.   cinfo->MCU_rows_in_scan = (cinfo->image_height
  73.                  + cinfo->max_v_samp_factor*DCTSIZE - 1)
  74.                 / (cinfo->max_v_samp_factor*DCTSIZE);
  75.   
  76.   cinfo->blocks_in_MCU = 0;
  77.  
  78.   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
  79.     compptr = cinfo->cur_comp_info[ci];
  80.     /* for interleaved scan, sampling factors give # of blocks per component */
  81.     compptr->MCU_width = compptr->h_samp_factor;
  82.     compptr->MCU_height = compptr->v_samp_factor;
  83.     compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
  84.     /* compute physical dimensions of component */
  85.     compptr->subsampled_width = jround_up(compptr->true_comp_width,
  86.                       (long) (compptr->MCU_width*DCTSIZE));
  87.     compptr->subsampled_height = jround_up(compptr->true_comp_height,
  88.                        (long) (compptr->MCU_height*DCTSIZE));
  89.     /* Sanity check */
  90.     if (compptr->subsampled_width !=
  91.     (cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
  92.       ERREXIT(cinfo->emethods, "I'm confused about the image width");
  93.     /* Prepare array describing MCU composition */
  94.     mcublks = compptr->MCU_blocks;
  95.     if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
  96.       ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan");
  97.     while (mcublks-- > 0) {
  98.       cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
  99.     }
  100.   }
  101.  
  102.   (*cinfo->methods->c_per_scan_method_selection) (cinfo);
  103. }
  104.  
  105.  
  106. LOCAL void
  107. noninterleaved_scan_setup (compress_info_ptr cinfo)
  108. /* Compute all derived info for a noninterleaved (single-component) scan */
  109. /* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */
  110. {
  111.   jpeg_component_info *compptr = cinfo->cur_comp_info[0];
  112.  
  113.   /* for noninterleaved scan, always one block per MCU */
  114.   compptr->MCU_width = 1;
  115.   compptr->MCU_height = 1;
  116.   compptr->MCU_blocks = 1;
  117.   /* compute physical dimensions of component */
  118.   compptr->subsampled_width = jround_up(compptr->true_comp_width,
  119.                     (long) DCTSIZE);
  120.   compptr->subsampled_height = jround_up(compptr->true_comp_height,
  121.                      (long) DCTSIZE);
  122.  
  123.   cinfo->MCUs_per_row = compptr->subsampled_width / DCTSIZE;
  124.   cinfo->MCU_rows_in_scan = compptr->subsampled_height / DCTSIZE;
  125.  
  126.   /* Prepare array describing MCU composition */
  127.   cinfo->blocks_in_MCU = 1;
  128.   cinfo->MCU_membership[0] = 0;
  129.  
  130.   (*cinfo->methods->c_per_scan_method_selection) (cinfo);
  131. }
  132.  
  133.  
  134.  
  135. LOCAL void
  136. alloc_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2],
  137.                long fullsize_width)
  138. /* Create a pre-subsampling data buffer having the desired structure */
  139. /* (see comments at head of file) */
  140. {
  141.   short ci, vs, i;
  142.  
  143.   vs = cinfo->max_v_samp_factor; /* row group height */
  144.  
  145.   /* Get top-level space for array pointers */
  146.   fullsize_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  147.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  148.   fullsize_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  149.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  150.  
  151.   for (ci = 0; ci < cinfo->num_components; ci++) {
  152.     /* Allocate the real storage */
  153.     fullsize_data[0][ci] = (*cinfo->emethods->alloc_small_sarray)
  154.                 (fullsize_width,
  155.                 (long) (vs * (DCTSIZE+2)));
  156.     /* Create space for the scrambled-order pointers */
  157.     fullsize_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small)
  158.                 (vs * (DCTSIZE+2) * SIZEOF(JSAMPROW));
  159.     /* Duplicate the first DCTSIZE-2 row groups */
  160.     for (i = 0; i < vs * (DCTSIZE-2); i++) {
  161.       fullsize_data[1][ci][i] = fullsize_data[0][ci][i];
  162.     }
  163.     /* Copy the last four row groups in swapped order */
  164.     for (i = 0; i < vs * 2; i++) {
  165.       fullsize_data[1][ci][vs*DCTSIZE + i] = fullsize_data[0][ci][vs*(DCTSIZE-2) + i];
  166.       fullsize_data[1][ci][vs*(DCTSIZE-2) + i] = fullsize_data[0][ci][vs*DCTSIZE + i];
  167.     }
  168.   }
  169. }
  170.  
  171.  
  172. #if 0                /* this routine not currently needed */
  173.  
  174. LOCAL void
  175. free_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2])
  176. /* Release a sampling buffer created by alloc_sampling_buffer */
  177. {
  178.   short ci;
  179.  
  180.   for (ci = 0; ci < cinfo->num_components; ci++) {
  181.     /* Free the real storage */
  182.     (*cinfo->emethods->free_small_sarray) (fullsize_data[0][ci]);
  183.     /* Free the scrambled-order pointers */
  184.     (*cinfo->emethods->free_small) ((void *) fullsize_data[1][ci]);
  185.   }
  186.  
  187.   /* Free the top-level space */
  188.   (*cinfo->emethods->free_small) ((void *) fullsize_data[0]);
  189.   (*cinfo->emethods->free_small) ((void *) fullsize_data[1]);
  190. }
  191.  
  192. #endif
  193.  
  194.  
  195. LOCAL void
  196. subsample (compress_info_ptr cinfo,
  197.        JSAMPIMAGE fullsize_data, JSAMPIMAGE subsampled_data,
  198.        long fullsize_width,
  199.        short above, short current, short below, short out)
  200. /* Do subsampling of a single row group (of each component). */
  201. /* above, current, below are indexes of row groups in fullsize_data;      */
  202. /* out is the index of the target row group in subsampled_data.           */
  203. /* Special case: above, below can be -1 to indicate top, bottom of image. */
  204. {
  205.   jpeg_component_info *compptr;
  206.   JSAMPARRAY above_ptr, below_ptr;
  207.   JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for subsample expansion at top/bottom */
  208.   short ci, vs, i;
  209.  
  210.   vs = cinfo->max_v_samp_factor; /* row group height */
  211.  
  212.   for (ci = 0; ci < cinfo->num_components; ci++) {
  213.     compptr = & cinfo->comp_info[ci];
  214.  
  215.     if (above >= 0)
  216.       above_ptr = fullsize_data[ci] + above * vs;
  217.     else {
  218.       /* Top of image: make a dummy above-context with copies of 1st row */
  219.       /* We assume current=0 in this case */
  220.       for (i = 0; i < vs; i++)
  221.     dummy[i] = fullsize_data[ci][0];
  222.       above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
  223.     }
  224.  
  225.     if (below >= 0)
  226.       below_ptr = fullsize_data[ci] + below * vs;
  227.     else {
  228.       /* Bot of image: make a dummy below-context with copies of last row */
  229.       for (i = 0; i < vs; i++)
  230.     dummy[i] = fullsize_data[ci][(current+1)*vs-1];
  231.       below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
  232.     }
  233.  
  234.     (*cinfo->methods->subsample[ci])
  235.         (cinfo, (int) ci,
  236.          fullsize_width, (int) vs,
  237.          compptr->subsampled_width, (int) compptr->v_samp_factor,
  238.          above_ptr,
  239.          fullsize_data[ci] + current * vs,
  240.          below_ptr,
  241.          subsampled_data[ci] + out * compptr->v_samp_factor);
  242.   }
  243. }
  244.  
  245.  
  246. /* These vars are initialized by the pipeline controller for use by
  247.  * MCU_output_catcher.
  248.  * To avoid a lot of row-pointer overhead, we cram as many MCUs into each
  249.  * row of whole_scan_MCUs as we can get without exceeding 64KB per row.
  250.  */
  251.  
  252. #define MAX_WHOLE_ROW_BLOCKS    ((int) (65500 / SIZEOF(JBLOCK))) /* max blocks/row */
  253.  
  254. static big_barray_ptr whole_scan_MCUs; /* Big array for saving the MCUs */
  255. static int MCUs_in_big_row;    /* # of MCUs in each row of whole_scan_MCUs */
  256. static long next_whole_row;    /* next row to access in whole_scan_MCUs */
  257. static int next_MCU_index;    /* next MCU in current row */
  258.  
  259.  
  260. METHODDEF void
  261. MCU_output_catcher (compress_info_ptr cinfo, JBLOCK *MCU_data)
  262. /* Output method for siphoning off extract_MCUs output into a big array */
  263. {
  264.   static JBLOCKARRAY rowptr;
  265.  
  266.   if (next_MCU_index >= MCUs_in_big_row) {
  267.     rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
  268.                             next_whole_row, TRUE);
  269.     next_whole_row++;
  270.     next_MCU_index = 0;
  271.   }
  272.  
  273.   /*
  274.    * note that on 80x86, the cast applied to MCU_data implies
  275.    * near to far pointer conversion.
  276.    */
  277.   jcopy_block_row((JBLOCKROW) MCU_data,
  278.           rowptr[0] + next_MCU_index * cinfo->blocks_in_MCU,
  279.           (long) cinfo->blocks_in_MCU);
  280.   next_MCU_index++;
  281. }
  282.  
  283.  
  284. METHODDEF void
  285. dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
  286. /* Dump the MCUs saved in whole_scan_MCUs to the output method. */
  287. /* The method may be either the entropy encoder or some routine supplied */
  288. /* by the entropy optimizer. */
  289. {
  290.   /* On an 80x86 machine, the entropy encoder expects the passed data block
  291.    * to be in NEAR memory (for performance reasons), so we have to copy it
  292.    * back from the big array to a local array.  On less brain-damaged CPUs
  293.    * we needn't do that.
  294.    */
  295. #ifdef NEED_FAR_POINTERS
  296.   JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
  297. #endif
  298.   long mcurow, mcuindex, next_row;
  299.   int next_index;
  300.   JBLOCKARRAY rowptr = NULL;    /* init only to suppress compiler complaint */
  301.  
  302.   next_row = 0;
  303.   next_index = MCUs_in_big_row;
  304.  
  305.   for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) {
  306.     (*cinfo->methods->progress_monitor) (cinfo, mcurow,
  307.                      cinfo->MCU_rows_in_scan);
  308.     for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
  309.       if (next_index >= MCUs_in_big_row) {
  310.     rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
  311.                             next_row, FALSE);
  312.     next_row++;
  313.     next_index = 0;
  314.       }
  315. #ifdef NEED_FAR_POINTERS
  316.       jcopy_block_row(rowptr[0] + next_index * cinfo->blocks_in_MCU,
  317.               (JBLOCKROW) MCU_data, /* casts near to far pointer! */
  318.               (long) cinfo->blocks_in_MCU);
  319.       (*output_method) (cinfo, MCU_data);
  320. #else
  321.       (*output_method) (cinfo, rowptr[0] + next_index * cinfo->blocks_in_MCU);
  322. #endif
  323.       next_index++;
  324.     }
  325.   }
  326.  
  327.   cinfo->completed_passes++;
  328. }
  329.  
  330.  
  331.  
  332. /*
  333.  * Compression pipeline controller used for single-scan files
  334.  * with no optimization of entropy parameters.
  335.  */
  336.  
  337. METHODDEF void
  338. single_ccontroller (compress_info_ptr cinfo)
  339. {
  340.   int rows_in_mem;        /* # of sample rows in full-size buffers */
  341.   long fullsize_width;        /* # of samples per row in full-size buffers */
  342.   long cur_pixel_row;        /* counts # of pixel rows processed */
  343.   long mcu_rows_output;        /* # of MCU rows actually emitted */
  344.   int mcu_rows_per_loop;    /* # of MCU rows processed per outer loop */
  345.   /* Work buffer for pre-subsampling data (see comments at head of file) */
  346.   JSAMPIMAGE fullsize_data[2];
  347.   /* Work buffer for subsampled data */
  348.   JSAMPIMAGE subsampled_data;
  349.   int rows_this_time;
  350.   short ci, whichss, i;
  351.  
  352.   /* Prepare for single scan containing all components */
  353.   if (cinfo->num_components > MAX_COMPS_IN_SCAN)
  354.     ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  355.   cinfo->comps_in_scan = cinfo->num_components;
  356.   for (ci = 0; ci < cinfo->num_components; ci++) {
  357.     cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
  358.   }
  359.   if (cinfo->comps_in_scan == 1) {
  360.     noninterleaved_scan_setup(cinfo);
  361.     /* Vk block rows constitute the same number of MCU rows */
  362.     mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
  363.   } else {
  364.     interleaved_scan_setup(cinfo);
  365.     /* in an interleaved scan, one MCU row contains Vk block rows */
  366.     mcu_rows_per_loop = 1;
  367.   }
  368.   cinfo->total_passes++;
  369.  
  370.   /* Compute dimensions of full-size pixel buffers */
  371.   /* Note these are the same whether interleaved or not. */
  372.   rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
  373.   fullsize_width = jround_up(cinfo->image_width,
  374.                  (long) (cinfo->max_h_samp_factor * DCTSIZE));
  375.  
  376.   /* Allocate working memory: */
  377.   /* fullsize_data is sample data before subsampling */
  378.   alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
  379.   /* subsampled_data is sample data after subsampling */
  380.   subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  381.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  382.   for (ci = 0; ci < cinfo->num_components; ci++) {
  383.     subsampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
  384.             (cinfo->comp_info[ci].subsampled_width,
  385.              (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
  386.   }
  387.  
  388.   /* Tell the memory manager to instantiate big arrays.
  389.    * We don't need any big arrays in this controller,
  390.    * but some other module (like the input file reader) may need one.
  391.    */
  392.   (*cinfo->emethods->alloc_big_arrays)
  393.     ((long) 0,                /* no more small sarrays */
  394.      (long) 0,                /* no more small barrays */
  395.      (long) 0);                /* no more "medium" objects */
  396.  
  397.   /* Initialize output file & do per-scan object init */
  398.  
  399.   (*cinfo->methods->write_scan_header) (cinfo);
  400.   cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
  401.   (*cinfo->methods->entropy_encoder_init) (cinfo);
  402.   (*cinfo->methods->subsample_init) (cinfo);
  403.   (*cinfo->methods->extract_init) (cinfo);
  404.  
  405.   /* Loop over input image: rows_in_mem pixel rows are processed per loop */
  406.  
  407.   mcu_rows_output = 0;
  408.   whichss = 1;            /* arrange to start with fullsize_data[0] */
  409.  
  410.   for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
  411.        cur_pixel_row += rows_in_mem) {
  412.     (*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row,
  413.                      cinfo->image_height);
  414.  
  415.     whichss ^= 1;        /* switch to other fullsize_data buffer */
  416.     
  417.     /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
  418.     /* Then we have exactly DCTSIZE row groups for subsampling. */   
  419.     rows_this_time = (int) MIN((long) rows_in_mem,
  420.                    cinfo->image_height - cur_pixel_row);
  421.  
  422.     (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
  423.                     fullsize_data[whichss]);
  424.     (*cinfo->methods->edge_expand) (cinfo,
  425.                     cinfo->image_width, rows_this_time,
  426.                     fullsize_width, rows_in_mem,
  427.                     fullsize_data[whichss]);
  428.     
  429.     /* Subsample the data (all components) */
  430.     /* First time through is a special case */
  431.     
  432.     if (cur_pixel_row) {
  433.       /* Subsample last row group of previous set */
  434.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  435.         (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
  436.         (short) (DCTSIZE-1));
  437.       /* and dump the previous set's subsampled data */
  438.       (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
  439.                        mcu_rows_per_loop,
  440.                        cinfo->methods->entropy_encode);
  441.       mcu_rows_output += mcu_rows_per_loop;
  442.       /* Subsample first row group of this set */
  443.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  444.         (short) (DCTSIZE+1), (short) 0, (short) 1,
  445.         (short) 0);
  446.     } else {
  447.       /* Subsample first row group with dummy above-context */
  448.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  449.         (short) (-1), (short) 0, (short) 1,
  450.         (short) 0);
  451.     }
  452.     /* Subsample second through next-to-last row groups of this set */
  453.     for (i = 1; i <= DCTSIZE-2; i++) {
  454.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  455.         (short) (i-1), (short) i, (short) (i+1),
  456.         (short) i);
  457.     }
  458.   } /* end of outer loop */
  459.   
  460.   /* Subsample the last row group with dummy below-context */
  461.   /* Note whichss points to last buffer side used */
  462.   subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  463.         (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
  464.         (short) (DCTSIZE-1));
  465.   /* Dump the remaining data (may be less than full height if uninterleaved) */
  466.   (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
  467.         (int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
  468.         cinfo->methods->entropy_encode);
  469.  
  470.   /* Finish output file */
  471.   (*cinfo->methods->extract_term) (cinfo);
  472.   (*cinfo->methods->subsample_term) (cinfo);
  473.   (*cinfo->methods->entropy_encoder_term) (cinfo);
  474.   (*cinfo->methods->write_scan_trailer) (cinfo);
  475.   cinfo->completed_passes++;
  476.  
  477.   /* Release working memory */
  478.   /* (no work -- we let free_all release what's needful) */
  479. }
  480.  
  481.  
  482. /*
  483.  * Compression pipeline controller used for single-scan files
  484.  * with optimization of entropy parameters.
  485.  */
  486.  
  487. #ifdef ENTROPY_OPT_SUPPORTED
  488.  
  489. METHODDEF void
  490. single_eopt_ccontroller (compress_info_ptr cinfo)
  491. {
  492.   int rows_in_mem;        /* # of sample rows in full-size buffers */
  493.   long fullsize_width;        /* # of samples per row in full-size buffers */
  494.   long cur_pixel_row;        /* counts # of pixel rows processed */
  495.   long mcu_rows_output;        /* # of MCU rows actually emitted */
  496.   int mcu_rows_per_loop;    /* # of MCU rows processed per outer loop */
  497.   /* Work buffer for pre-subsampling data (see comments at head of file) */
  498.   JSAMPIMAGE fullsize_data[2];
  499.   /* Work buffer for subsampled data */
  500.   JSAMPIMAGE subsampled_data;
  501.   int rows_this_time;
  502.   int blocks_in_big_row;
  503.   short ci, whichss, i;
  504.  
  505.   /* Prepare for single scan containing all components */
  506.   if (cinfo->num_components > MAX_COMPS_IN_SCAN)
  507.     ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  508.   cinfo->comps_in_scan = cinfo->num_components;
  509.   for (ci = 0; ci < cinfo->num_components; ci++) {
  510.     cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
  511.   }
  512.   if (cinfo->comps_in_scan == 1) {
  513.     noninterleaved_scan_setup(cinfo);
  514.     /* Vk block rows constitute the same number of MCU rows */
  515.     mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
  516.   } else {
  517.     interleaved_scan_setup(cinfo);
  518.     /* in an interleaved scan, one MCU row contains Vk block rows */
  519.     mcu_rows_per_loop = 1;
  520.   }
  521.   cinfo->total_passes += 2;    /* entropy encoder must add # passes it uses */
  522.  
  523.   /* Compute dimensions of full-size pixel buffers */
  524.   /* Note these are the same whether interleaved or not. */
  525.   rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
  526.   fullsize_width = jround_up(cinfo->image_width,
  527.                  (long) (cinfo->max_h_samp_factor * DCTSIZE));
  528.  
  529.   /* Allocate working memory: */
  530.   /* fullsize_data is sample data before subsampling */
  531.   alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
  532.   /* subsampled_data is sample data after subsampling */
  533.   subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  534.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  535.   for (ci = 0; ci < cinfo->num_components; ci++) {
  536.     subsampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
  537.             (cinfo->comp_info[ci].subsampled_width,
  538.              (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
  539.   }
  540.  
  541.   /* Figure # of MCUs to be packed in a row of whole_scan_MCUs */
  542.   MCUs_in_big_row = MAX_WHOLE_ROW_BLOCKS / cinfo->blocks_in_MCU;
  543.   blocks_in_big_row = MCUs_in_big_row * cinfo->blocks_in_MCU;
  544.  
  545.   /* Request a big array: whole_scan_MCUs saves the MCU data for the scan */
  546.   whole_scan_MCUs = (*cinfo->emethods->request_big_barray)
  547.         ((long) blocks_in_big_row,
  548.          (long) (cinfo->MCUs_per_row * cinfo->MCU_rows_in_scan
  549.              + MCUs_in_big_row-1) / MCUs_in_big_row,
  550.          1L);        /* unit height is 1 row */
  551.  
  552.   next_whole_row = 0;        /* init output ptr for MCU_output_catcher */
  553.   next_MCU_index = MCUs_in_big_row; /* forces access on first call! */
  554.  
  555.   /* Tell the memory manager to instantiate big arrays */
  556.   (*cinfo->emethods->alloc_big_arrays)
  557.     ((long) 0,                /* no more small sarrays */
  558.      (long) 0,                /* no more small barrays */
  559.      (long) 0);                /* no more "medium" objects */
  560.  
  561.   /* Do per-scan object init */
  562.  
  563.   (*cinfo->methods->subsample_init) (cinfo);
  564.   (*cinfo->methods->extract_init) (cinfo);
  565.  
  566.   /* Loop over input image: rows_in_mem pixel rows are processed per loop */
  567.   /* MCU data goes into whole_scan_MCUs, not to the entropy encoder */
  568.  
  569.   mcu_rows_output = 0;
  570.   whichss = 1;            /* arrange to start with fullsize_data[0] */
  571.  
  572.   for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
  573.        cur_pixel_row += rows_in_mem) {
  574.     (*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row,
  575.                      cinfo->image_height);
  576.  
  577.     whichss ^= 1;        /* switch to other fullsize_data buffer */
  578.     
  579.     /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
  580.     /* Then we have exactly DCTSIZE row groups for subsampling. */   
  581.     rows_this_time = (int) MIN((long) rows_in_mem,
  582.                    cinfo->image_height - cur_pixel_row);
  583.  
  584.     (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
  585.                     fullsize_data[whichss]);
  586.     (*cinfo->methods->edge_expand) (cinfo,
  587.                     cinfo->image_width, rows_this_time,
  588.                     fullsize_width, rows_in_mem,
  589.                     fullsize_data[whichss]);
  590.     
  591.     /* Subsample the data (all components) */
  592.     /* First time through is a special case */
  593.     
  594.     if (cur_pixel_row) {
  595.       /* Subsample last row group of previous set */
  596.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  597.         (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
  598.         (short) (DCTSIZE-1));
  599.       /* and dump the previous set's subsampled data */
  600.       (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
  601.                        mcu_rows_per_loop,
  602.                        MCU_output_catcher);
  603.       mcu_rows_output += mcu_rows_per_loop;
  604.       /* Subsample first row group of this set */
  605.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  606.         (short) (DCTSIZE+1), (short) 0, (short) 1,
  607.         (short) 0);
  608.     } else {
  609.       /* Subsample first row group with dummy above-context */
  610.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  611.         (short) (-1), (short) 0, (short) 1,
  612.         (short) 0);
  613.     }
  614.     /* Subsample second through next-to-last row groups of this set */
  615.     for (i = 1; i <= DCTSIZE-2; i++) {
  616.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  617.         (short) (i-1), (short) i, (short) (i+1),
  618.         (short) i);
  619.     }
  620.   } /* end of outer loop */
  621.   
  622.   /* Subsample the last row group with dummy below-context */
  623.   /* Note whichss points to last buffer side used */
  624.   subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  625.         (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
  626.         (short) (DCTSIZE-1));
  627.   /* Dump the remaining data (may be less than full height if uninterleaved) */
  628.   (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
  629.         (int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
  630.         MCU_output_catcher);
  631.  
  632.   /* Clean up after that stuff, then find the optimal entropy parameters */
  633.  
  634.   (*cinfo->methods->extract_term) (cinfo);
  635.   (*cinfo->methods->subsample_term) (cinfo);
  636.  
  637.   cinfo->completed_passes++;
  638.  
  639.   (*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs);
  640.  
  641.   /* Emit scan to output file */
  642.   /* Note: we can't do write_scan_header until entropy parameters are set! */
  643.  
  644.   (*cinfo->methods->write_scan_header) (cinfo);
  645.   cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
  646.   (*cinfo->methods->entropy_encoder_init) (cinfo);
  647.   dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode);
  648.   (*cinfo->methods->entropy_encoder_term) (cinfo);
  649.   (*cinfo->methods->write_scan_trailer) (cinfo);
  650.  
  651.   /* Release working memory */
  652.   /* (no work -- we let free_all release what's needful) */
  653. }
  654.  
  655. #endif /* ENTROPY_OPT_SUPPORTED */
  656.  
  657.  
  658. /*
  659.  * Compression pipeline controller used for multiple-scan files
  660.  * with no optimization of entropy parameters.
  661.  */
  662.  
  663. #ifdef MULTISCAN_FILES_SUPPORTED
  664.  
  665. METHODDEF void
  666. multi_ccontroller (compress_info_ptr cinfo)
  667. {
  668.   ERREXIT(cinfo->emethods, "Not implemented yet");
  669. }
  670.  
  671. #endif /* MULTISCAN_FILES_SUPPORTED */
  672.  
  673.  
  674. /*
  675.  * Compression pipeline controller used for multiple-scan files
  676.  * with optimization of entropy parameters.
  677.  */
  678.  
  679. #ifdef MULTISCAN_FILES_SUPPORTED
  680. #ifdef ENTROPY_OPT_SUPPORTED
  681.  
  682. METHODDEF void
  683. multi_eopt_ccontroller (compress_info_ptr cinfo)
  684. {
  685.   ERREXIT(cinfo->emethods, "Not implemented yet");
  686. }
  687.  
  688. #endif /* ENTROPY_OPT_SUPPORTED */
  689. #endif /* MULTISCAN_FILES_SUPPORTED */
  690.  
  691.  
  692. /*
  693.  * The method selection routine for compression pipeline controllers.
  694.  */
  695.  
  696. GLOBAL void
  697. jselcpipeline (compress_info_ptr cinfo)
  698. {
  699.   if (cinfo->interleave || cinfo->num_components == 1) {
  700.     /* single scan needed */
  701. #ifdef ENTROPY_OPT_SUPPORTED
  702.     if (cinfo->optimize_coding)
  703.       cinfo->methods->c_pipeline_controller = single_eopt_ccontroller;
  704.     else
  705. #endif
  706.       cinfo->methods->c_pipeline_controller = single_ccontroller;
  707.   } else {
  708.     /* multiple scans needed */
  709. #ifdef MULTISCAN_FILES_SUPPORTED
  710. #ifdef ENTROPY_OPT_SUPPORTED
  711.     if (cinfo->optimize_coding)
  712.       cinfo->methods->c_pipeline_controller = multi_eopt_ccontroller;
  713.     else
  714. #endif
  715.       cinfo->methods->c_pipeline_controller = multi_ccontroller;
  716. #else
  717.     ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled");
  718. #endif
  719.   }
  720. }
  721.