istereo

diff libs/libjpeg/jccoefct.c @ 26:862a3329a8f0

wohooo, added a shitload of code from zlib/libpng/libjpeg. When the good lord was raining shared libraries the iphone held a fucking umbrella...
author John Tsiombikas <nuclear@mutantstargoat.com>
date Thu, 08 Sep 2011 06:28:38 +0300
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/libjpeg/jccoefct.c	Thu Sep 08 06:28:38 2011 +0300
     1.3 @@ -0,0 +1,449 @@
     1.4 +/*
     1.5 + * jccoefct.c
     1.6 + *
     1.7 + * Copyright (C) 1994-1997, Thomas G. Lane.
     1.8 + * This file is part of the Independent JPEG Group's software.
     1.9 + * For conditions of distribution and use, see the accompanying README file.
    1.10 + *
    1.11 + * This file contains the coefficient buffer controller for compression.
    1.12 + * This controller is the top level of the JPEG compressor proper.
    1.13 + * The coefficient buffer lies between forward-DCT and entropy encoding steps.
    1.14 + */
    1.15 +
    1.16 +#define JPEG_INTERNALS
    1.17 +#include "jinclude.h"
    1.18 +#include "jpeglib.h"
    1.19 +
    1.20 +
    1.21 +/* We use a full-image coefficient buffer when doing Huffman optimization,
    1.22 + * and also for writing multiple-scan JPEG files.  In all cases, the DCT
    1.23 + * step is run during the first pass, and subsequent passes need only read
    1.24 + * the buffered coefficients.
    1.25 + */
    1.26 +#ifdef ENTROPY_OPT_SUPPORTED
    1.27 +#define FULL_COEF_BUFFER_SUPPORTED
    1.28 +#else
    1.29 +#ifdef C_MULTISCAN_FILES_SUPPORTED
    1.30 +#define FULL_COEF_BUFFER_SUPPORTED
    1.31 +#endif
    1.32 +#endif
    1.33 +
    1.34 +
    1.35 +/* Private buffer controller object */
    1.36 +
    1.37 +typedef struct {
    1.38 +  struct jpeg_c_coef_controller pub; /* public fields */
    1.39 +
    1.40 +  JDIMENSION iMCU_row_num;	/* iMCU row # within image */
    1.41 +  JDIMENSION mcu_ctr;		/* counts MCUs processed in current row */
    1.42 +  int MCU_vert_offset;		/* counts MCU rows within iMCU row */
    1.43 +  int MCU_rows_per_iMCU_row;	/* number of such rows needed */
    1.44 +
    1.45 +  /* For single-pass compression, it's sufficient to buffer just one MCU
    1.46 +   * (although this may prove a bit slow in practice).  We allocate a
    1.47 +   * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
    1.48 +   * MCU constructed and sent.  (On 80x86, the workspace is FAR even though
    1.49 +   * it's not really very big; this is to keep the module interfaces unchanged
    1.50 +   * when a large coefficient buffer is necessary.)
    1.51 +   * In multi-pass modes, this array points to the current MCU's blocks
    1.52 +   * within the virtual arrays.
    1.53 +   */
    1.54 +  JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
    1.55 +
    1.56 +  /* In multi-pass modes, we need a virtual block array for each component. */
    1.57 +  jvirt_barray_ptr whole_image[MAX_COMPONENTS];
    1.58 +} my_coef_controller;
    1.59 +
    1.60 +typedef my_coef_controller * my_coef_ptr;
    1.61 +
    1.62 +
    1.63 +/* Forward declarations */
    1.64 +METHODDEF(boolean) compress_data
    1.65 +    JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
    1.66 +#ifdef FULL_COEF_BUFFER_SUPPORTED
    1.67 +METHODDEF(boolean) compress_first_pass
    1.68 +    JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
    1.69 +METHODDEF(boolean) compress_output
    1.70 +    JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
    1.71 +#endif
    1.72 +
    1.73 +
    1.74 +LOCAL(void)
    1.75 +start_iMCU_row (j_compress_ptr cinfo)
    1.76 +/* Reset within-iMCU-row counters for a new row */
    1.77 +{
    1.78 +  my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
    1.79 +
    1.80 +  /* In an interleaved scan, an MCU row is the same as an iMCU row.
    1.81 +   * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
    1.82 +   * But at the bottom of the image, process only what's left.
    1.83 +   */
    1.84 +  if (cinfo->comps_in_scan > 1) {
    1.85 +    coef->MCU_rows_per_iMCU_row = 1;
    1.86 +  } else {
    1.87 +    if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
    1.88 +      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
    1.89 +    else
    1.90 +      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
    1.91 +  }
    1.92 +
    1.93 +  coef->mcu_ctr = 0;
    1.94 +  coef->MCU_vert_offset = 0;
    1.95 +}
    1.96 +
    1.97 +
    1.98 +/*
    1.99 + * Initialize for a processing pass.
   1.100 + */
   1.101 +
   1.102 +METHODDEF(void)
   1.103 +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
   1.104 +{
   1.105 +  my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
   1.106 +
   1.107 +  coef->iMCU_row_num = 0;
   1.108 +  start_iMCU_row(cinfo);
   1.109 +
   1.110 +  switch (pass_mode) {
   1.111 +  case JBUF_PASS_THRU:
   1.112 +    if (coef->whole_image[0] != NULL)
   1.113 +      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
   1.114 +    coef->pub.compress_data = compress_data;
   1.115 +    break;
   1.116 +#ifdef FULL_COEF_BUFFER_SUPPORTED
   1.117 +  case JBUF_SAVE_AND_PASS:
   1.118 +    if (coef->whole_image[0] == NULL)
   1.119 +      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
   1.120 +    coef->pub.compress_data = compress_first_pass;
   1.121 +    break;
   1.122 +  case JBUF_CRANK_DEST:
   1.123 +    if (coef->whole_image[0] == NULL)
   1.124 +      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
   1.125 +    coef->pub.compress_data = compress_output;
   1.126 +    break;
   1.127 +#endif
   1.128 +  default:
   1.129 +    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
   1.130 +    break;
   1.131 +  }
   1.132 +}
   1.133 +
   1.134 +
   1.135 +/*
   1.136 + * Process some data in the single-pass case.
   1.137 + * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
   1.138 + * per call, ie, v_samp_factor block rows for each component in the image.
   1.139 + * Returns TRUE if the iMCU row is completed, FALSE if suspended.
   1.140 + *
   1.141 + * NB: input_buf contains a plane for each component in image,
   1.142 + * which we index according to the component's SOF position.
   1.143 + */
   1.144 +
   1.145 +METHODDEF(boolean)
   1.146 +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
   1.147 +{
   1.148 +  my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
   1.149 +  JDIMENSION MCU_col_num;	/* index of current MCU within row */
   1.150 +  JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
   1.151 +  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
   1.152 +  int blkn, bi, ci, yindex, yoffset, blockcnt;
   1.153 +  JDIMENSION ypos, xpos;
   1.154 +  jpeg_component_info *compptr;
   1.155 +
   1.156 +  /* Loop to write as much as one whole iMCU row */
   1.157 +  for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
   1.158 +       yoffset++) {
   1.159 +    for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
   1.160 +	 MCU_col_num++) {
   1.161 +      /* Determine where data comes from in input_buf and do the DCT thing.
   1.162 +       * Each call on forward_DCT processes a horizontal row of DCT blocks
   1.163 +       * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
   1.164 +       * sequentially.  Dummy blocks at the right or bottom edge are filled in
   1.165 +       * specially.  The data in them does not matter for image reconstruction,
   1.166 +       * so we fill them with values that will encode to the smallest amount of
   1.167 +       * data, viz: all zeroes in the AC entries, DC entries equal to previous
   1.168 +       * block's DC value.  (Thanks to Thomas Kinsman for this idea.)
   1.169 +       */
   1.170 +      blkn = 0;
   1.171 +      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
   1.172 +	compptr = cinfo->cur_comp_info[ci];
   1.173 +	blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
   1.174 +						: compptr->last_col_width;
   1.175 +	xpos = MCU_col_num * compptr->MCU_sample_width;
   1.176 +	ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
   1.177 +	for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
   1.178 +	  if (coef->iMCU_row_num < last_iMCU_row ||
   1.179 +	      yoffset+yindex < compptr->last_row_height) {
   1.180 +	    (*cinfo->fdct->forward_DCT) (cinfo, compptr,
   1.181 +					 input_buf[compptr->component_index],
   1.182 +					 coef->MCU_buffer[blkn],
   1.183 +					 ypos, xpos, (JDIMENSION) blockcnt);
   1.184 +	    if (blockcnt < compptr->MCU_width) {
   1.185 +	      /* Create some dummy blocks at the right edge of the image. */
   1.186 +	      jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
   1.187 +			(compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
   1.188 +	      for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
   1.189 +		coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
   1.190 +	      }
   1.191 +	    }
   1.192 +	  } else {
   1.193 +	    /* Create a row of dummy blocks at the bottom of the image. */
   1.194 +	    jzero_far((void FAR *) coef->MCU_buffer[blkn],
   1.195 +		      compptr->MCU_width * SIZEOF(JBLOCK));
   1.196 +	    for (bi = 0; bi < compptr->MCU_width; bi++) {
   1.197 +	      coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
   1.198 +	    }
   1.199 +	  }
   1.200 +	  blkn += compptr->MCU_width;
   1.201 +	  ypos += DCTSIZE;
   1.202 +	}
   1.203 +      }
   1.204 +      /* Try to write the MCU.  In event of a suspension failure, we will
   1.205 +       * re-DCT the MCU on restart (a bit inefficient, could be fixed...)
   1.206 +       */
   1.207 +      if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
   1.208 +	/* Suspension forced; update state counters and exit */
   1.209 +	coef->MCU_vert_offset = yoffset;
   1.210 +	coef->mcu_ctr = MCU_col_num;
   1.211 +	return FALSE;
   1.212 +      }
   1.213 +    }
   1.214 +    /* Completed an MCU row, but perhaps not an iMCU row */
   1.215 +    coef->mcu_ctr = 0;
   1.216 +  }
   1.217 +  /* Completed the iMCU row, advance counters for next one */
   1.218 +  coef->iMCU_row_num++;
   1.219 +  start_iMCU_row(cinfo);
   1.220 +  return TRUE;
   1.221 +}
   1.222 +
   1.223 +
   1.224 +#ifdef FULL_COEF_BUFFER_SUPPORTED
   1.225 +
   1.226 +/*
   1.227 + * Process some data in the first pass of a multi-pass case.
   1.228 + * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
   1.229 + * per call, ie, v_samp_factor block rows for each component in the image.
   1.230 + * This amount of data is read from the source buffer, DCT'd and quantized,
   1.231 + * and saved into the virtual arrays.  We also generate suitable dummy blocks
   1.232 + * as needed at the right and lower edges.  (The dummy blocks are constructed
   1.233 + * in the virtual arrays, which have been padded appropriately.)  This makes
   1.234 + * it possible for subsequent passes not to worry about real vs. dummy blocks.
   1.235 + *
   1.236 + * We must also emit the data to the entropy encoder.  This is conveniently
   1.237 + * done by calling compress_output() after we've loaded the current strip
   1.238 + * of the virtual arrays.
   1.239 + *
   1.240 + * NB: input_buf contains a plane for each component in image.  All
   1.241 + * components are DCT'd and loaded into the virtual arrays in this pass.
   1.242 + * However, it may be that only a subset of the components are emitted to
   1.243 + * the entropy encoder during this first pass; be careful about looking
   1.244 + * at the scan-dependent variables (MCU dimensions, etc).
   1.245 + */
   1.246 +
   1.247 +METHODDEF(boolean)
   1.248 +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
   1.249 +{
   1.250 +  my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
   1.251 +  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
   1.252 +  JDIMENSION blocks_across, MCUs_across, MCUindex;
   1.253 +  int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
   1.254 +  JCOEF lastDC;
   1.255 +  jpeg_component_info *compptr;
   1.256 +  JBLOCKARRAY buffer;
   1.257 +  JBLOCKROW thisblockrow, lastblockrow;
   1.258 +
   1.259 +  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
   1.260 +       ci++, compptr++) {
   1.261 +    /* Align the virtual buffer for this component. */
   1.262 +    buffer = (*cinfo->mem->access_virt_barray)
   1.263 +      ((j_common_ptr) cinfo, coef->whole_image[ci],
   1.264 +       coef->iMCU_row_num * compptr->v_samp_factor,
   1.265 +       (JDIMENSION) compptr->v_samp_factor, TRUE);
   1.266 +    /* Count non-dummy DCT block rows in this iMCU row. */
   1.267 +    if (coef->iMCU_row_num < last_iMCU_row)
   1.268 +      block_rows = compptr->v_samp_factor;
   1.269 +    else {
   1.270 +      /* NB: can't use last_row_height here, since may not be set! */
   1.271 +      block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
   1.272 +      if (block_rows == 0) block_rows = compptr->v_samp_factor;
   1.273 +    }
   1.274 +    blocks_across = compptr->width_in_blocks;
   1.275 +    h_samp_factor = compptr->h_samp_factor;
   1.276 +    /* Count number of dummy blocks to be added at the right margin. */
   1.277 +    ndummy = (int) (blocks_across % h_samp_factor);
   1.278 +    if (ndummy > 0)
   1.279 +      ndummy = h_samp_factor - ndummy;
   1.280 +    /* Perform DCT for all non-dummy blocks in this iMCU row.  Each call
   1.281 +     * on forward_DCT processes a complete horizontal row of DCT blocks.
   1.282 +     */
   1.283 +    for (block_row = 0; block_row < block_rows; block_row++) {
   1.284 +      thisblockrow = buffer[block_row];
   1.285 +      (*cinfo->fdct->forward_DCT) (cinfo, compptr,
   1.286 +				   input_buf[ci], thisblockrow,
   1.287 +				   (JDIMENSION) (block_row * DCTSIZE),
   1.288 +				   (JDIMENSION) 0, blocks_across);
   1.289 +      if (ndummy > 0) {
   1.290 +	/* Create dummy blocks at the right edge of the image. */
   1.291 +	thisblockrow += blocks_across; /* => first dummy block */
   1.292 +	jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
   1.293 +	lastDC = thisblockrow[-1][0];
   1.294 +	for (bi = 0; bi < ndummy; bi++) {
   1.295 +	  thisblockrow[bi][0] = lastDC;
   1.296 +	}
   1.297 +      }
   1.298 +    }
   1.299 +    /* If at end of image, create dummy block rows as needed.
   1.300 +     * The tricky part here is that within each MCU, we want the DC values
   1.301 +     * of the dummy blocks to match the last real block's DC value.
   1.302 +     * This squeezes a few more bytes out of the resulting file...
   1.303 +     */
   1.304 +    if (coef->iMCU_row_num == last_iMCU_row) {
   1.305 +      blocks_across += ndummy;	/* include lower right corner */
   1.306 +      MCUs_across = blocks_across / h_samp_factor;
   1.307 +      for (block_row = block_rows; block_row < compptr->v_samp_factor;
   1.308 +	   block_row++) {
   1.309 +	thisblockrow = buffer[block_row];
   1.310 +	lastblockrow = buffer[block_row-1];
   1.311 +	jzero_far((void FAR *) thisblockrow,
   1.312 +		  (size_t) (blocks_across * SIZEOF(JBLOCK)));
   1.313 +	for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
   1.314 +	  lastDC = lastblockrow[h_samp_factor-1][0];
   1.315 +	  for (bi = 0; bi < h_samp_factor; bi++) {
   1.316 +	    thisblockrow[bi][0] = lastDC;
   1.317 +	  }
   1.318 +	  thisblockrow += h_samp_factor; /* advance to next MCU in row */
   1.319 +	  lastblockrow += h_samp_factor;
   1.320 +	}
   1.321 +      }
   1.322 +    }
   1.323 +  }
   1.324 +  /* NB: compress_output will increment iMCU_row_num if successful.
   1.325 +   * A suspension return will result in redoing all the work above next time.
   1.326 +   */
   1.327 +
   1.328 +  /* Emit data to the entropy encoder, sharing code with subsequent passes */
   1.329 +  return compress_output(cinfo, input_buf);
   1.330 +}
   1.331 +
   1.332 +
   1.333 +/*
   1.334 + * Process some data in subsequent passes of a multi-pass case.
   1.335 + * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
   1.336 + * per call, ie, v_samp_factor block rows for each component in the scan.
   1.337 + * The data is obtained from the virtual arrays and fed to the entropy coder.
   1.338 + * Returns TRUE if the iMCU row is completed, FALSE if suspended.
   1.339 + *
   1.340 + * NB: input_buf is ignored; it is likely to be a NULL pointer.
   1.341 + */
   1.342 +
   1.343 +METHODDEF(boolean)
   1.344 +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
   1.345 +{
   1.346 +  my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
   1.347 +  JDIMENSION MCU_col_num;	/* index of current MCU within row */
   1.348 +  int blkn, ci, xindex, yindex, yoffset;
   1.349 +  JDIMENSION start_col;
   1.350 +  JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
   1.351 +  JBLOCKROW buffer_ptr;
   1.352 +  jpeg_component_info *compptr;
   1.353 +
   1.354 +  /* Align the virtual buffers for the components used in this scan.
   1.355 +   * NB: during first pass, this is safe only because the buffers will
   1.356 +   * already be aligned properly, so jmemmgr.c won't need to do any I/O.
   1.357 +   */
   1.358 +  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
   1.359 +    compptr = cinfo->cur_comp_info[ci];
   1.360 +    buffer[ci] = (*cinfo->mem->access_virt_barray)
   1.361 +      ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
   1.362 +       coef->iMCU_row_num * compptr->v_samp_factor,
   1.363 +       (JDIMENSION) compptr->v_samp_factor, FALSE);
   1.364 +  }
   1.365 +
   1.366 +  /* Loop to process one whole iMCU row */
   1.367 +  for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
   1.368 +       yoffset++) {
   1.369 +    for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
   1.370 +	 MCU_col_num++) {
   1.371 +      /* Construct list of pointers to DCT blocks belonging to this MCU */
   1.372 +      blkn = 0;			/* index of current DCT block within MCU */
   1.373 +      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
   1.374 +	compptr = cinfo->cur_comp_info[ci];
   1.375 +	start_col = MCU_col_num * compptr->MCU_width;
   1.376 +	for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
   1.377 +	  buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
   1.378 +	  for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
   1.379 +	    coef->MCU_buffer[blkn++] = buffer_ptr++;
   1.380 +	  }
   1.381 +	}
   1.382 +      }
   1.383 +      /* Try to write the MCU. */
   1.384 +      if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
   1.385 +	/* Suspension forced; update state counters and exit */
   1.386 +	coef->MCU_vert_offset = yoffset;
   1.387 +	coef->mcu_ctr = MCU_col_num;
   1.388 +	return FALSE;
   1.389 +      }
   1.390 +    }
   1.391 +    /* Completed an MCU row, but perhaps not an iMCU row */
   1.392 +    coef->mcu_ctr = 0;
   1.393 +  }
   1.394 +  /* Completed the iMCU row, advance counters for next one */
   1.395 +  coef->iMCU_row_num++;
   1.396 +  start_iMCU_row(cinfo);
   1.397 +  return TRUE;
   1.398 +}
   1.399 +
   1.400 +#endif /* FULL_COEF_BUFFER_SUPPORTED */
   1.401 +
   1.402 +
   1.403 +/*
   1.404 + * Initialize coefficient buffer controller.
   1.405 + */
   1.406 +
   1.407 +GLOBAL(void)
   1.408 +jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
   1.409 +{
   1.410 +  my_coef_ptr coef;
   1.411 +
   1.412 +  coef = (my_coef_ptr)
   1.413 +    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
   1.414 +				SIZEOF(my_coef_controller));
   1.415 +  cinfo->coef = (struct jpeg_c_coef_controller *) coef;
   1.416 +  coef->pub.start_pass = start_pass_coef;
   1.417 +
   1.418 +  /* Create the coefficient buffer. */
   1.419 +  if (need_full_buffer) {
   1.420 +#ifdef FULL_COEF_BUFFER_SUPPORTED
   1.421 +    /* Allocate a full-image virtual array for each component, */
   1.422 +    /* padded to a multiple of samp_factor DCT blocks in each direction. */
   1.423 +    int ci;
   1.424 +    jpeg_component_info *compptr;
   1.425 +
   1.426 +    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
   1.427 +	 ci++, compptr++) {
   1.428 +      coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
   1.429 +	((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
   1.430 +	 (JDIMENSION) jround_up((long) compptr->width_in_blocks,
   1.431 +				(long) compptr->h_samp_factor),
   1.432 +	 (JDIMENSION) jround_up((long) compptr->height_in_blocks,
   1.433 +				(long) compptr->v_samp_factor),
   1.434 +	 (JDIMENSION) compptr->v_samp_factor);
   1.435 +    }
   1.436 +#else
   1.437 +    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
   1.438 +#endif
   1.439 +  } else {
   1.440 +    /* We only need a single-MCU buffer. */
   1.441 +    JBLOCKROW buffer;
   1.442 +    int i;
   1.443 +
   1.444 +    buffer = (JBLOCKROW)
   1.445 +      (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
   1.446 +				  C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
   1.447 +    for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
   1.448 +      coef->MCU_buffer[i] = buffer + i;
   1.449 +    }
   1.450 +    coef->whole_image[0] = NULL; /* flag for no virtual arrays */
   1.451 +  }
   1.452 +}