ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

jccoefct.c
Go to the documentation of this file.
00001 /*
00002  * jccoefct.c
00003  *
00004  * Copyright (C) 1994-1997, Thomas G. Lane.
00005  * This file is part of the Independent JPEG Group's software.
00006  * For conditions of distribution and use, see the accompanying README file.
00007  *
00008  * This file contains the coefficient buffer controller for compression.
00009  * This controller is the top level of the JPEG compressor proper.
00010  * The coefficient buffer lies between forward-DCT and entropy encoding steps.
00011  */
00012 
00013 #define JPEG_INTERNALS
00014 #include "jinclude.h"
00015 #include "jpeglib.h"
00016 
00017 
00018 /* We use a full-image coefficient buffer when doing Huffman optimization,
00019  * and also for writing multiple-scan JPEG files.  In all cases, the DCT
00020  * step is run during the first pass, and subsequent passes need only read
00021  * the buffered coefficients.
00022  */
00023 #ifdef ENTROPY_OPT_SUPPORTED
00024 #define FULL_COEF_BUFFER_SUPPORTED
00025 #else
00026 #ifdef C_MULTISCAN_FILES_SUPPORTED
00027 #define FULL_COEF_BUFFER_SUPPORTED
00028 #endif
00029 #endif
00030 
00031 
00032 /* Private buffer controller object */
00033 
00034 typedef struct {
00035   struct jpeg_c_coef_controller pub; /* public fields */
00036 
00037   JDIMENSION iMCU_row_num;  /* iMCU row # within image */
00038   JDIMENSION mcu_ctr;       /* counts MCUs processed in current row */
00039   int MCU_vert_offset;      /* counts MCU rows within iMCU row */
00040   int MCU_rows_per_iMCU_row;    /* number of such rows needed */
00041 
00042   /* For single-pass compression, it's sufficient to buffer just one MCU
00043    * (although this may prove a bit slow in practice).  We allocate a
00044    * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
00045    * MCU constructed and sent.  (On 80x86, the workspace is FAR even though
00046    * it's not really very big; this is to keep the module interfaces unchanged
00047    * when a large coefficient buffer is necessary.)
00048    * In multi-pass modes, this array points to the current MCU's blocks
00049    * within the virtual arrays.
00050    */
00051   JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
00052 
00053   /* In multi-pass modes, we need a virtual block array for each component. */
00054   jvirt_barray_ptr whole_image[MAX_COMPONENTS];
00055 } my_coef_controller;
00056 
00057 typedef my_coef_controller * my_coef_ptr;
00058 
00059 
00060 /* Forward declarations */
00061 METHODDEF(boolean) compress_data
00062     JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
00063 #ifdef FULL_COEF_BUFFER_SUPPORTED
00064 METHODDEF(boolean) compress_first_pass
00065     JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
00066 METHODDEF(boolean) compress_output
00067     JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
00068 #endif
00069 
00070 
00071 LOCAL(void)
00072 start_iMCU_row (j_compress_ptr cinfo)
00073 /* Reset within-iMCU-row counters for a new row */
00074 {
00075   my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
00076 
00077   /* In an interleaved scan, an MCU row is the same as an iMCU row.
00078    * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
00079    * But at the bottom of the image, process only what's left.
00080    */
00081   if (cinfo->comps_in_scan > 1) {
00082     coef->MCU_rows_per_iMCU_row = 1;
00083   } else {
00084     if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
00085       coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
00086     else
00087       coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
00088   }
00089 
00090   coef->mcu_ctr = 0;
00091   coef->MCU_vert_offset = 0;
00092 }
00093 
00094 
00095 /*
00096  * Initialize for a processing pass.
00097  */
00098 
00099 METHODDEF(void)
00100 start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
00101 {
00102   my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
00103 
00104   coef->iMCU_row_num = 0;
00105   start_iMCU_row(cinfo);
00106 
00107   switch (pass_mode) {
00108   case JBUF_PASS_THRU:
00109     if (coef->whole_image[0] != NULL)
00110       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
00111     coef->pub.compress_data = compress_data;
00112     break;
00113 #ifdef FULL_COEF_BUFFER_SUPPORTED
00114   case JBUF_SAVE_AND_PASS:
00115     if (coef->whole_image[0] == NULL)
00116       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
00117     coef->pub.compress_data = compress_first_pass;
00118     break;
00119   case JBUF_CRANK_DEST:
00120     if (coef->whole_image[0] == NULL)
00121       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
00122     coef->pub.compress_data = compress_output;
00123     break;
00124 #endif
00125   default:
00126     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
00127     break;
00128   }
00129 }
00130 
00131 
00132 /*
00133  * Process some data in the single-pass case.
00134  * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
00135  * per call, ie, v_samp_factor block rows for each component in the image.
00136  * Returns TRUE if the iMCU row is completed, FALSE if suspended.
00137  *
00138  * NB: input_buf contains a plane for each component in image,
00139  * which we index according to the component's SOF position.
00140  */
00141 
00142 METHODDEF(boolean)
00143 compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
00144 {
00145   my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
00146   JDIMENSION MCU_col_num;   /* index of current MCU within row */
00147   JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
00148   JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
00149   int blkn, bi, ci, yindex, yoffset, blockcnt;
00150   JDIMENSION ypos, xpos;
00151   jpeg_component_info *compptr;
00152   forward_DCT_ptr forward_DCT;
00153 
00154   /* Loop to write as much as one whole iMCU row */
00155   for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
00156        yoffset++) {
00157     for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
00158      MCU_col_num++) {
00159       /* Determine where data comes from in input_buf and do the DCT thing.
00160        * Each call on forward_DCT processes a horizontal row of DCT blocks
00161        * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
00162        * sequentially.  Dummy blocks at the right or bottom edge are filled in
00163        * specially.  The data in them does not matter for image reconstruction,
00164        * so we fill them with values that will encode to the smallest amount of
00165        * data, viz: all zeroes in the AC entries, DC entries equal to previous
00166        * block's DC value.  (Thanks to Thomas Kinsman for this idea.)
00167        */
00168       blkn = 0;
00169       for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
00170     compptr = cinfo->cur_comp_info[ci];
00171     forward_DCT = cinfo->fdct->forward_DCT[compptr->component_index];
00172     blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
00173                         : compptr->last_col_width;
00174     xpos = MCU_col_num * compptr->MCU_sample_width;
00175     ypos = yoffset * compptr->DCT_v_scaled_size;
00176     /* ypos == (yoffset+yindex) * DCTSIZE */
00177     for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
00178       if (coef->iMCU_row_num < last_iMCU_row ||
00179           yoffset+yindex < compptr->last_row_height) {
00180         (*forward_DCT) (cinfo, compptr,
00181                 input_buf[compptr->component_index],
00182                 coef->MCU_buffer[blkn],
00183                 ypos, xpos, (JDIMENSION) blockcnt);
00184         if (blockcnt < compptr->MCU_width) {
00185           /* Create some dummy blocks at the right edge of the image. */
00186           jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
00187             (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
00188           for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
00189         coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
00190           }
00191         }
00192       } else {
00193         /* Create a row of dummy blocks at the bottom of the image. */
00194         jzero_far((void FAR *) coef->MCU_buffer[blkn],
00195               compptr->MCU_width * SIZEOF(JBLOCK));
00196         for (bi = 0; bi < compptr->MCU_width; bi++) {
00197           coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
00198         }
00199       }
00200       blkn += compptr->MCU_width;
00201       ypos += compptr->DCT_v_scaled_size;
00202     }
00203       }
00204       /* Try to write the MCU.  In event of a suspension failure, we will
00205        * re-DCT the MCU on restart (a bit inefficient, could be fixed...)
00206        */
00207       if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
00208     /* Suspension forced; update state counters and exit */
00209     coef->MCU_vert_offset = yoffset;
00210     coef->mcu_ctr = MCU_col_num;
00211     return FALSE;
00212       }
00213     }
00214     /* Completed an MCU row, but perhaps not an iMCU row */
00215     coef->mcu_ctr = 0;
00216   }
00217   /* Completed the iMCU row, advance counters for next one */
00218   coef->iMCU_row_num++;
00219   start_iMCU_row(cinfo);
00220   return TRUE;
00221 }
00222 
00223 
00224 #ifdef FULL_COEF_BUFFER_SUPPORTED
00225 
00226 /*
00227  * Process some data in the first pass of a multi-pass case.
00228  * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
00229  * per call, ie, v_samp_factor block rows for each component in the image.
00230  * This amount of data is read from the source buffer, DCT'd and quantized,
00231  * and saved into the virtual arrays.  We also generate suitable dummy blocks
00232  * as needed at the right and lower edges.  (The dummy blocks are constructed
00233  * in the virtual arrays, which have been padded appropriately.)  This makes
00234  * it possible for subsequent passes not to worry about real vs. dummy blocks.
00235  *
00236  * We must also emit the data to the entropy encoder.  This is conveniently
00237  * done by calling compress_output() after we've loaded the current strip
00238  * of the virtual arrays.
00239  *
00240  * NB: input_buf contains a plane for each component in image.  All
00241  * components are DCT'd and loaded into the virtual arrays in this pass.
00242  * However, it may be that only a subset of the components are emitted to
00243  * the entropy encoder during this first pass; be careful about looking
00244  * at the scan-dependent variables (MCU dimensions, etc).
00245  */
00246 
00247 METHODDEF(boolean)
00248 compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
00249 {
00250   my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
00251   JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
00252   JDIMENSION blocks_across, MCUs_across, MCUindex;
00253   int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
00254   JCOEF lastDC;
00255   jpeg_component_info *compptr;
00256   JBLOCKARRAY buffer;
00257   JBLOCKROW thisblockrow, lastblockrow;
00258   forward_DCT_ptr forward_DCT;
00259 
00260   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
00261        ci++, compptr++) {
00262     /* Align the virtual buffer for this component. */
00263     buffer = (*cinfo->mem->access_virt_barray)
00264       ((j_common_ptr) cinfo, coef->whole_image[ci],
00265        coef->iMCU_row_num * compptr->v_samp_factor,
00266        (JDIMENSION) compptr->v_samp_factor, TRUE);
00267     /* Count non-dummy DCT block rows in this iMCU row. */
00268     if (coef->iMCU_row_num < last_iMCU_row)
00269       block_rows = compptr->v_samp_factor;
00270     else {
00271       /* NB: can't use last_row_height here, since may not be set! */
00272       block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
00273       if (block_rows == 0) block_rows = compptr->v_samp_factor;
00274     }
00275     blocks_across = compptr->width_in_blocks;
00276     h_samp_factor = compptr->h_samp_factor;
00277     /* Count number of dummy blocks to be added at the right margin. */
00278     ndummy = (int) (blocks_across % h_samp_factor);
00279     if (ndummy > 0)
00280       ndummy = h_samp_factor - ndummy;
00281     forward_DCT = cinfo->fdct->forward_DCT[ci];
00282     /* Perform DCT for all non-dummy blocks in this iMCU row.  Each call
00283      * on forward_DCT processes a complete horizontal row of DCT blocks.
00284      */
00285     for (block_row = 0; block_row < block_rows; block_row++) {
00286       thisblockrow = buffer[block_row];
00287       (*forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow,
00288               (JDIMENSION) (block_row * compptr->DCT_v_scaled_size),
00289               (JDIMENSION) 0, blocks_across);
00290       if (ndummy > 0) {
00291     /* Create dummy blocks at the right edge of the image. */
00292     thisblockrow += blocks_across; /* => first dummy block */
00293     jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
00294     lastDC = thisblockrow[-1][0];
00295     for (bi = 0; bi < ndummy; bi++) {
00296       thisblockrow[bi][0] = lastDC;
00297     }
00298       }
00299     }
00300     /* If at end of image, create dummy block rows as needed.
00301      * The tricky part here is that within each MCU, we want the DC values
00302      * of the dummy blocks to match the last real block's DC value.
00303      * This squeezes a few more bytes out of the resulting file...
00304      */
00305     if (coef->iMCU_row_num == last_iMCU_row) {
00306       blocks_across += ndummy;  /* include lower right corner */
00307       MCUs_across = blocks_across / h_samp_factor;
00308       for (block_row = block_rows; block_row < compptr->v_samp_factor;
00309        block_row++) {
00310     thisblockrow = buffer[block_row];
00311     lastblockrow = buffer[block_row-1];
00312     jzero_far((void FAR *) thisblockrow,
00313           (size_t) (blocks_across * SIZEOF(JBLOCK)));
00314     for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
00315       lastDC = lastblockrow[h_samp_factor-1][0];
00316       for (bi = 0; bi < h_samp_factor; bi++) {
00317         thisblockrow[bi][0] = lastDC;
00318       }
00319       thisblockrow += h_samp_factor; /* advance to next MCU in row */
00320       lastblockrow += h_samp_factor;
00321     }
00322       }
00323     }
00324   }
00325   /* NB: compress_output will increment iMCU_row_num if successful.
00326    * A suspension return will result in redoing all the work above next time.
00327    */
00328 
00329   /* Emit data to the entropy encoder, sharing code with subsequent passes */
00330   return compress_output(cinfo, input_buf);
00331 }
00332 
00333 
00334 /*
00335  * Process some data in subsequent passes of a multi-pass case.
00336  * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
00337  * per call, ie, v_samp_factor block rows for each component in the scan.
00338  * The data is obtained from the virtual arrays and fed to the entropy coder.
00339  * Returns TRUE if the iMCU row is completed, FALSE if suspended.
00340  *
00341  * NB: input_buf is ignored; it is likely to be a NULL pointer.
00342  */
00343 
00344 METHODDEF(boolean)
00345 compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
00346 {
00347   my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
00348   JDIMENSION MCU_col_num;   /* index of current MCU within row */
00349   int blkn, ci, xindex, yindex, yoffset;
00350   JDIMENSION start_col;
00351   JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
00352   JBLOCKROW buffer_ptr;
00353   jpeg_component_info *compptr;
00354 
00355   /* Align the virtual buffers for the components used in this scan.
00356    * NB: during first pass, this is safe only because the buffers will
00357    * already be aligned properly, so jmemmgr.c won't need to do any I/O.
00358    */
00359   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
00360     compptr = cinfo->cur_comp_info[ci];
00361     buffer[ci] = (*cinfo->mem->access_virt_barray)
00362       ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
00363        coef->iMCU_row_num * compptr->v_samp_factor,
00364        (JDIMENSION) compptr->v_samp_factor, FALSE);
00365   }
00366 
00367   /* Loop to process one whole iMCU row */
00368   for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
00369        yoffset++) {
00370     for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
00371      MCU_col_num++) {
00372       /* Construct list of pointers to DCT blocks belonging to this MCU */
00373       blkn = 0;         /* index of current DCT block within MCU */
00374       for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
00375     compptr = cinfo->cur_comp_info[ci];
00376     start_col = MCU_col_num * compptr->MCU_width;
00377     for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
00378       buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
00379       for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
00380         coef->MCU_buffer[blkn++] = buffer_ptr++;
00381       }
00382     }
00383       }
00384       /* Try to write the MCU. */
00385       if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
00386     /* Suspension forced; update state counters and exit */
00387     coef->MCU_vert_offset = yoffset;
00388     coef->mcu_ctr = MCU_col_num;
00389     return FALSE;
00390       }
00391     }
00392     /* Completed an MCU row, but perhaps not an iMCU row */
00393     coef->mcu_ctr = 0;
00394   }
00395   /* Completed the iMCU row, advance counters for next one */
00396   coef->iMCU_row_num++;
00397   start_iMCU_row(cinfo);
00398   return TRUE;
00399 }
00400 
00401 #endif /* FULL_COEF_BUFFER_SUPPORTED */
00402 
00403 
00404 /*
00405  * Initialize coefficient buffer controller.
00406  */
00407 
00408 GLOBAL(void)
00409 jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
00410 {
00411   my_coef_ptr coef;
00412 
00413   coef = (my_coef_ptr)
00414     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00415                 SIZEOF(my_coef_controller));
00416   cinfo->coef = (struct jpeg_c_coef_controller *) coef;
00417   coef->pub.start_pass = start_pass_coef;
00418 
00419   /* Create the coefficient buffer. */
00420   if (need_full_buffer) {
00421 #ifdef FULL_COEF_BUFFER_SUPPORTED
00422     /* Allocate a full-image virtual array for each component, */
00423     /* padded to a multiple of samp_factor DCT blocks in each direction. */
00424     int ci;
00425     jpeg_component_info *compptr;
00426 
00427     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
00428      ci++, compptr++) {
00429       coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
00430     ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
00431      (JDIMENSION) jround_up((long) compptr->width_in_blocks,
00432                 (long) compptr->h_samp_factor),
00433      (JDIMENSION) jround_up((long) compptr->height_in_blocks,
00434                 (long) compptr->v_samp_factor),
00435      (JDIMENSION) compptr->v_samp_factor);
00436     }
00437 #else
00438     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
00439 #endif
00440   } else {
00441     /* We only need a single-MCU buffer. */
00442     JBLOCKROW buffer;
00443     int i;
00444 
00445     buffer = (JBLOCKROW)
00446       (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00447                   C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
00448     for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
00449       coef->MCU_buffer[i] = buffer + i;
00450     }
00451     coef->whole_image[0] = NULL; /* flag for no virtual arrays */
00452   }
00453 }

Generated on Fri May 25 2012 04:17:31 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.