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