17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier * jccoefct.c
37dd7cddfSDavid du Colombier *
4*593dc095SDavid du Colombier * Copyright (C) 1994-1997, Thomas G. Lane.
57dd7cddfSDavid du Colombier * This file is part of the Independent JPEG Group's software.
67dd7cddfSDavid du Colombier * For conditions of distribution and use, see the accompanying README file.
77dd7cddfSDavid du Colombier *
87dd7cddfSDavid du Colombier * This file contains the coefficient buffer controller for compression.
97dd7cddfSDavid du Colombier * This controller is the top level of the JPEG compressor proper.
107dd7cddfSDavid du Colombier * The coefficient buffer lies between forward-DCT and entropy encoding steps.
117dd7cddfSDavid du Colombier */
127dd7cddfSDavid du Colombier
137dd7cddfSDavid du Colombier #define JPEG_INTERNALS
147dd7cddfSDavid du Colombier #include "jinclude.h"
157dd7cddfSDavid du Colombier #include "jpeglib.h"
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier
187dd7cddfSDavid du Colombier /* We use a full-image coefficient buffer when doing Huffman optimization,
197dd7cddfSDavid du Colombier * and also for writing multiple-scan JPEG files. In all cases, the DCT
207dd7cddfSDavid du Colombier * step is run during the first pass, and subsequent passes need only read
217dd7cddfSDavid du Colombier * the buffered coefficients.
227dd7cddfSDavid du Colombier */
237dd7cddfSDavid du Colombier #ifdef ENTROPY_OPT_SUPPORTED
247dd7cddfSDavid du Colombier #define FULL_COEF_BUFFER_SUPPORTED
257dd7cddfSDavid du Colombier #else
267dd7cddfSDavid du Colombier #ifdef C_MULTISCAN_FILES_SUPPORTED
277dd7cddfSDavid du Colombier #define FULL_COEF_BUFFER_SUPPORTED
287dd7cddfSDavid du Colombier #endif
297dd7cddfSDavid du Colombier #endif
307dd7cddfSDavid du Colombier
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier /* Private buffer controller object */
337dd7cddfSDavid du Colombier
347dd7cddfSDavid du Colombier typedef struct {
357dd7cddfSDavid du Colombier struct jpeg_c_coef_controller pub; /* public fields */
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier JDIMENSION iMCU_row_num; /* iMCU row # within image */
387dd7cddfSDavid du Colombier JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
397dd7cddfSDavid du Colombier int MCU_vert_offset; /* counts MCU rows within iMCU row */
407dd7cddfSDavid du Colombier int MCU_rows_per_iMCU_row; /* number of such rows needed */
417dd7cddfSDavid du Colombier
427dd7cddfSDavid du Colombier /* For single-pass compression, it's sufficient to buffer just one MCU
437dd7cddfSDavid du Colombier * (although this may prove a bit slow in practice). We allocate a
447dd7cddfSDavid du Colombier * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
457dd7cddfSDavid du Colombier * MCU constructed and sent. (On 80x86, the workspace is FAR even though
467dd7cddfSDavid du Colombier * it's not really very big; this is to keep the module interfaces unchanged
477dd7cddfSDavid du Colombier * when a large coefficient buffer is necessary.)
487dd7cddfSDavid du Colombier * In multi-pass modes, this array points to the current MCU's blocks
497dd7cddfSDavid du Colombier * within the virtual arrays.
507dd7cddfSDavid du Colombier */
517dd7cddfSDavid du Colombier JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier /* In multi-pass modes, we need a virtual block array for each component. */
547dd7cddfSDavid du Colombier jvirt_barray_ptr whole_image[MAX_COMPONENTS];
557dd7cddfSDavid du Colombier } my_coef_controller;
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier typedef my_coef_controller * my_coef_ptr;
587dd7cddfSDavid du Colombier
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier /* Forward declarations */
617dd7cddfSDavid du Colombier METHODDEF(boolean) compress_data
627dd7cddfSDavid du Colombier JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
637dd7cddfSDavid du Colombier #ifdef FULL_COEF_BUFFER_SUPPORTED
647dd7cddfSDavid du Colombier METHODDEF(boolean) compress_first_pass
657dd7cddfSDavid du Colombier JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
667dd7cddfSDavid du Colombier METHODDEF(boolean) compress_output
677dd7cddfSDavid du Colombier JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
687dd7cddfSDavid du Colombier #endif
697dd7cddfSDavid du Colombier
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier LOCAL(void)
start_iMCU_row(j_compress_ptr cinfo)727dd7cddfSDavid du Colombier start_iMCU_row (j_compress_ptr cinfo)
737dd7cddfSDavid du Colombier /* Reset within-iMCU-row counters for a new row */
747dd7cddfSDavid du Colombier {
757dd7cddfSDavid du Colombier my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
767dd7cddfSDavid du Colombier
777dd7cddfSDavid du Colombier /* In an interleaved scan, an MCU row is the same as an iMCU row.
787dd7cddfSDavid du Colombier * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
797dd7cddfSDavid du Colombier * But at the bottom of the image, process only what's left.
807dd7cddfSDavid du Colombier */
817dd7cddfSDavid du Colombier if (cinfo->comps_in_scan > 1) {
827dd7cddfSDavid du Colombier coef->MCU_rows_per_iMCU_row = 1;
837dd7cddfSDavid du Colombier } else {
847dd7cddfSDavid du Colombier if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
857dd7cddfSDavid du Colombier coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
867dd7cddfSDavid du Colombier else
877dd7cddfSDavid du Colombier coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier
907dd7cddfSDavid du Colombier coef->mcu_ctr = 0;
917dd7cddfSDavid du Colombier coef->MCU_vert_offset = 0;
927dd7cddfSDavid du Colombier }
937dd7cddfSDavid du Colombier
947dd7cddfSDavid du Colombier
957dd7cddfSDavid du Colombier /*
967dd7cddfSDavid du Colombier * Initialize for a processing pass.
977dd7cddfSDavid du Colombier */
987dd7cddfSDavid du Colombier
997dd7cddfSDavid du Colombier METHODDEF(void)
start_pass_coef(j_compress_ptr cinfo,J_BUF_MODE pass_mode)1007dd7cddfSDavid du Colombier start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
1017dd7cddfSDavid du Colombier {
1027dd7cddfSDavid du Colombier my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
1037dd7cddfSDavid du Colombier
1047dd7cddfSDavid du Colombier coef->iMCU_row_num = 0;
1057dd7cddfSDavid du Colombier start_iMCU_row(cinfo);
1067dd7cddfSDavid du Colombier
1077dd7cddfSDavid du Colombier switch (pass_mode) {
1087dd7cddfSDavid du Colombier case JBUF_PASS_THRU:
1097dd7cddfSDavid du Colombier if (coef->whole_image[0] != NULL)
1107dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
1117dd7cddfSDavid du Colombier coef->pub.compress_data = compress_data;
1127dd7cddfSDavid du Colombier break;
1137dd7cddfSDavid du Colombier #ifdef FULL_COEF_BUFFER_SUPPORTED
1147dd7cddfSDavid du Colombier case JBUF_SAVE_AND_PASS:
1157dd7cddfSDavid du Colombier if (coef->whole_image[0] == NULL)
1167dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
1177dd7cddfSDavid du Colombier coef->pub.compress_data = compress_first_pass;
1187dd7cddfSDavid du Colombier break;
1197dd7cddfSDavid du Colombier case JBUF_CRANK_DEST:
1207dd7cddfSDavid du Colombier if (coef->whole_image[0] == NULL)
1217dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
1227dd7cddfSDavid du Colombier coef->pub.compress_data = compress_output;
1237dd7cddfSDavid du Colombier break;
1247dd7cddfSDavid du Colombier #endif
1257dd7cddfSDavid du Colombier default:
1267dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
1277dd7cddfSDavid du Colombier break;
1287dd7cddfSDavid du Colombier }
1297dd7cddfSDavid du Colombier }
1307dd7cddfSDavid du Colombier
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier /*
1337dd7cddfSDavid du Colombier * Process some data in the single-pass case.
1347dd7cddfSDavid du Colombier * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
1357dd7cddfSDavid du Colombier * per call, ie, v_samp_factor block rows for each component in the image.
1367dd7cddfSDavid du Colombier * Returns TRUE if the iMCU row is completed, FALSE if suspended.
1377dd7cddfSDavid du Colombier *
138*593dc095SDavid du Colombier * NB: input_buf contains a plane for each component in image,
139*593dc095SDavid du Colombier * which we index according to the component's SOF position.
1407dd7cddfSDavid du Colombier */
1417dd7cddfSDavid du Colombier
1427dd7cddfSDavid du Colombier METHODDEF(boolean)
compress_data(j_compress_ptr cinfo,JSAMPIMAGE input_buf)1437dd7cddfSDavid du Colombier compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
1447dd7cddfSDavid du Colombier {
1457dd7cddfSDavid du Colombier my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
1467dd7cddfSDavid du Colombier JDIMENSION MCU_col_num; /* index of current MCU within row */
1477dd7cddfSDavid du Colombier JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
1487dd7cddfSDavid du Colombier JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
1497dd7cddfSDavid du Colombier int blkn, bi, ci, yindex, yoffset, blockcnt;
1507dd7cddfSDavid du Colombier JDIMENSION ypos, xpos;
1517dd7cddfSDavid du Colombier jpeg_component_info *compptr;
1527dd7cddfSDavid du Colombier
1537dd7cddfSDavid du Colombier /* Loop to write as much as one whole iMCU row */
1547dd7cddfSDavid du Colombier for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
1557dd7cddfSDavid du Colombier yoffset++) {
1567dd7cddfSDavid du Colombier for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
1577dd7cddfSDavid du Colombier MCU_col_num++) {
1587dd7cddfSDavid du Colombier /* Determine where data comes from in input_buf and do the DCT thing.
1597dd7cddfSDavid du Colombier * Each call on forward_DCT processes a horizontal row of DCT blocks
1607dd7cddfSDavid du Colombier * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
1617dd7cddfSDavid du Colombier * sequentially. Dummy blocks at the right or bottom edge are filled in
1627dd7cddfSDavid du Colombier * specially. The data in them does not matter for image reconstruction,
1637dd7cddfSDavid du Colombier * so we fill them with values that will encode to the smallest amount of
1647dd7cddfSDavid du Colombier * data, viz: all zeroes in the AC entries, DC entries equal to previous
1657dd7cddfSDavid du Colombier * block's DC value. (Thanks to Thomas Kinsman for this idea.)
1667dd7cddfSDavid du Colombier */
1677dd7cddfSDavid du Colombier blkn = 0;
1687dd7cddfSDavid du Colombier for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
1697dd7cddfSDavid du Colombier compptr = cinfo->cur_comp_info[ci];
1707dd7cddfSDavid du Colombier blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
1717dd7cddfSDavid du Colombier : compptr->last_col_width;
1727dd7cddfSDavid du Colombier xpos = MCU_col_num * compptr->MCU_sample_width;
1737dd7cddfSDavid du Colombier ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
1747dd7cddfSDavid du Colombier for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
1757dd7cddfSDavid du Colombier if (coef->iMCU_row_num < last_iMCU_row ||
1767dd7cddfSDavid du Colombier yoffset+yindex < compptr->last_row_height) {
1777dd7cddfSDavid du Colombier (*cinfo->fdct->forward_DCT) (cinfo, compptr,
178*593dc095SDavid du Colombier input_buf[compptr->component_index],
179*593dc095SDavid du Colombier coef->MCU_buffer[blkn],
1807dd7cddfSDavid du Colombier ypos, xpos, (JDIMENSION) blockcnt);
1817dd7cddfSDavid du Colombier if (blockcnt < compptr->MCU_width) {
1827dd7cddfSDavid du Colombier /* Create some dummy blocks at the right edge of the image. */
1837dd7cddfSDavid du Colombier jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
1847dd7cddfSDavid du Colombier (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
1857dd7cddfSDavid du Colombier for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
1867dd7cddfSDavid du Colombier coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
1877dd7cddfSDavid du Colombier }
1887dd7cddfSDavid du Colombier }
1897dd7cddfSDavid du Colombier } else {
1907dd7cddfSDavid du Colombier /* Create a row of dummy blocks at the bottom of the image. */
1917dd7cddfSDavid du Colombier jzero_far((void FAR *) coef->MCU_buffer[blkn],
1927dd7cddfSDavid du Colombier compptr->MCU_width * SIZEOF(JBLOCK));
1937dd7cddfSDavid du Colombier for (bi = 0; bi < compptr->MCU_width; bi++) {
1947dd7cddfSDavid du Colombier coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier blkn += compptr->MCU_width;
1987dd7cddfSDavid du Colombier ypos += DCTSIZE;
1997dd7cddfSDavid du Colombier }
2007dd7cddfSDavid du Colombier }
2017dd7cddfSDavid du Colombier /* Try to write the MCU. In event of a suspension failure, we will
2027dd7cddfSDavid du Colombier * re-DCT the MCU on restart (a bit inefficient, could be fixed...)
2037dd7cddfSDavid du Colombier */
2047dd7cddfSDavid du Colombier if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
2057dd7cddfSDavid du Colombier /* Suspension forced; update state counters and exit */
2067dd7cddfSDavid du Colombier coef->MCU_vert_offset = yoffset;
2077dd7cddfSDavid du Colombier coef->mcu_ctr = MCU_col_num;
2087dd7cddfSDavid du Colombier return FALSE;
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier }
2117dd7cddfSDavid du Colombier /* Completed an MCU row, but perhaps not an iMCU row */
2127dd7cddfSDavid du Colombier coef->mcu_ctr = 0;
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier /* Completed the iMCU row, advance counters for next one */
2157dd7cddfSDavid du Colombier coef->iMCU_row_num++;
2167dd7cddfSDavid du Colombier start_iMCU_row(cinfo);
2177dd7cddfSDavid du Colombier return TRUE;
2187dd7cddfSDavid du Colombier }
2197dd7cddfSDavid du Colombier
2207dd7cddfSDavid du Colombier
2217dd7cddfSDavid du Colombier #ifdef FULL_COEF_BUFFER_SUPPORTED
2227dd7cddfSDavid du Colombier
2237dd7cddfSDavid du Colombier /*
2247dd7cddfSDavid du Colombier * Process some data in the first pass of a multi-pass case.
2257dd7cddfSDavid du Colombier * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
2267dd7cddfSDavid du Colombier * per call, ie, v_samp_factor block rows for each component in the image.
2277dd7cddfSDavid du Colombier * This amount of data is read from the source buffer, DCT'd and quantized,
2287dd7cddfSDavid du Colombier * and saved into the virtual arrays. We also generate suitable dummy blocks
2297dd7cddfSDavid du Colombier * as needed at the right and lower edges. (The dummy blocks are constructed
2307dd7cddfSDavid du Colombier * in the virtual arrays, which have been padded appropriately.) This makes
2317dd7cddfSDavid du Colombier * it possible for subsequent passes not to worry about real vs. dummy blocks.
2327dd7cddfSDavid du Colombier *
2337dd7cddfSDavid du Colombier * We must also emit the data to the entropy encoder. This is conveniently
2347dd7cddfSDavid du Colombier * done by calling compress_output() after we've loaded the current strip
2357dd7cddfSDavid du Colombier * of the virtual arrays.
2367dd7cddfSDavid du Colombier *
2377dd7cddfSDavid du Colombier * NB: input_buf contains a plane for each component in image. All
2387dd7cddfSDavid du Colombier * components are DCT'd and loaded into the virtual arrays in this pass.
2397dd7cddfSDavid du Colombier * However, it may be that only a subset of the components are emitted to
2407dd7cddfSDavid du Colombier * the entropy encoder during this first pass; be careful about looking
2417dd7cddfSDavid du Colombier * at the scan-dependent variables (MCU dimensions, etc).
2427dd7cddfSDavid du Colombier */
2437dd7cddfSDavid du Colombier
2447dd7cddfSDavid du Colombier METHODDEF(boolean)
compress_first_pass(j_compress_ptr cinfo,JSAMPIMAGE input_buf)2457dd7cddfSDavid du Colombier compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
2467dd7cddfSDavid du Colombier {
2477dd7cddfSDavid du Colombier my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
2487dd7cddfSDavid du Colombier JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
2497dd7cddfSDavid du Colombier JDIMENSION blocks_across, MCUs_across, MCUindex;
2507dd7cddfSDavid du Colombier int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
2517dd7cddfSDavid du Colombier JCOEF lastDC;
2527dd7cddfSDavid du Colombier jpeg_component_info *compptr;
2537dd7cddfSDavid du Colombier JBLOCKARRAY buffer;
2547dd7cddfSDavid du Colombier JBLOCKROW thisblockrow, lastblockrow;
2557dd7cddfSDavid du Colombier
2567dd7cddfSDavid du Colombier for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
2577dd7cddfSDavid du Colombier ci++, compptr++) {
2587dd7cddfSDavid du Colombier /* Align the virtual buffer for this component. */
2597dd7cddfSDavid du Colombier buffer = (*cinfo->mem->access_virt_barray)
2607dd7cddfSDavid du Colombier ((j_common_ptr) cinfo, coef->whole_image[ci],
2617dd7cddfSDavid du Colombier coef->iMCU_row_num * compptr->v_samp_factor,
2627dd7cddfSDavid du Colombier (JDIMENSION) compptr->v_samp_factor, TRUE);
2637dd7cddfSDavid du Colombier /* Count non-dummy DCT block rows in this iMCU row. */
2647dd7cddfSDavid du Colombier if (coef->iMCU_row_num < last_iMCU_row)
2657dd7cddfSDavid du Colombier block_rows = compptr->v_samp_factor;
2667dd7cddfSDavid du Colombier else {
2677dd7cddfSDavid du Colombier /* NB: can't use last_row_height here, since may not be set! */
2687dd7cddfSDavid du Colombier block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
2697dd7cddfSDavid du Colombier if (block_rows == 0) block_rows = compptr->v_samp_factor;
2707dd7cddfSDavid du Colombier }
2717dd7cddfSDavid du Colombier blocks_across = compptr->width_in_blocks;
2727dd7cddfSDavid du Colombier h_samp_factor = compptr->h_samp_factor;
2737dd7cddfSDavid du Colombier /* Count number of dummy blocks to be added at the right margin. */
2747dd7cddfSDavid du Colombier ndummy = (int) (blocks_across % h_samp_factor);
2757dd7cddfSDavid du Colombier if (ndummy > 0)
2767dd7cddfSDavid du Colombier ndummy = h_samp_factor - ndummy;
2777dd7cddfSDavid du Colombier /* Perform DCT for all non-dummy blocks in this iMCU row. Each call
2787dd7cddfSDavid du Colombier * on forward_DCT processes a complete horizontal row of DCT blocks.
2797dd7cddfSDavid du Colombier */
2807dd7cddfSDavid du Colombier for (block_row = 0; block_row < block_rows; block_row++) {
2817dd7cddfSDavid du Colombier thisblockrow = buffer[block_row];
2827dd7cddfSDavid du Colombier (*cinfo->fdct->forward_DCT) (cinfo, compptr,
2837dd7cddfSDavid du Colombier input_buf[ci], thisblockrow,
2847dd7cddfSDavid du Colombier (JDIMENSION) (block_row * DCTSIZE),
2857dd7cddfSDavid du Colombier (JDIMENSION) 0, blocks_across);
2867dd7cddfSDavid du Colombier if (ndummy > 0) {
2877dd7cddfSDavid du Colombier /* Create dummy blocks at the right edge of the image. */
2887dd7cddfSDavid du Colombier thisblockrow += blocks_across; /* => first dummy block */
2897dd7cddfSDavid du Colombier jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
2907dd7cddfSDavid du Colombier lastDC = thisblockrow[-1][0];
2917dd7cddfSDavid du Colombier for (bi = 0; bi < ndummy; bi++) {
2927dd7cddfSDavid du Colombier thisblockrow[bi][0] = lastDC;
2937dd7cddfSDavid du Colombier }
2947dd7cddfSDavid du Colombier }
2957dd7cddfSDavid du Colombier }
2967dd7cddfSDavid du Colombier /* If at end of image, create dummy block rows as needed.
2977dd7cddfSDavid du Colombier * The tricky part here is that within each MCU, we want the DC values
2987dd7cddfSDavid du Colombier * of the dummy blocks to match the last real block's DC value.
2997dd7cddfSDavid du Colombier * This squeezes a few more bytes out of the resulting file...
3007dd7cddfSDavid du Colombier */
3017dd7cddfSDavid du Colombier if (coef->iMCU_row_num == last_iMCU_row) {
3027dd7cddfSDavid du Colombier blocks_across += ndummy; /* include lower right corner */
3037dd7cddfSDavid du Colombier MCUs_across = blocks_across / h_samp_factor;
3047dd7cddfSDavid du Colombier for (block_row = block_rows; block_row < compptr->v_samp_factor;
3057dd7cddfSDavid du Colombier block_row++) {
3067dd7cddfSDavid du Colombier thisblockrow = buffer[block_row];
3077dd7cddfSDavid du Colombier lastblockrow = buffer[block_row-1];
3087dd7cddfSDavid du Colombier jzero_far((void FAR *) thisblockrow,
3097dd7cddfSDavid du Colombier (size_t) (blocks_across * SIZEOF(JBLOCK)));
3107dd7cddfSDavid du Colombier for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
3117dd7cddfSDavid du Colombier lastDC = lastblockrow[h_samp_factor-1][0];
3127dd7cddfSDavid du Colombier for (bi = 0; bi < h_samp_factor; bi++) {
3137dd7cddfSDavid du Colombier thisblockrow[bi][0] = lastDC;
3147dd7cddfSDavid du Colombier }
3157dd7cddfSDavid du Colombier thisblockrow += h_samp_factor; /* advance to next MCU in row */
3167dd7cddfSDavid du Colombier lastblockrow += h_samp_factor;
3177dd7cddfSDavid du Colombier }
3187dd7cddfSDavid du Colombier }
3197dd7cddfSDavid du Colombier }
3207dd7cddfSDavid du Colombier }
3217dd7cddfSDavid du Colombier /* NB: compress_output will increment iMCU_row_num if successful.
3227dd7cddfSDavid du Colombier * A suspension return will result in redoing all the work above next time.
3237dd7cddfSDavid du Colombier */
3247dd7cddfSDavid du Colombier
3257dd7cddfSDavid du Colombier /* Emit data to the entropy encoder, sharing code with subsequent passes */
3267dd7cddfSDavid du Colombier return compress_output(cinfo, input_buf);
3277dd7cddfSDavid du Colombier }
3287dd7cddfSDavid du Colombier
3297dd7cddfSDavid du Colombier
3307dd7cddfSDavid du Colombier /*
3317dd7cddfSDavid du Colombier * Process some data in subsequent passes of a multi-pass case.
3327dd7cddfSDavid du Colombier * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
3337dd7cddfSDavid du Colombier * per call, ie, v_samp_factor block rows for each component in the scan.
3347dd7cddfSDavid du Colombier * The data is obtained from the virtual arrays and fed to the entropy coder.
3357dd7cddfSDavid du Colombier * Returns TRUE if the iMCU row is completed, FALSE if suspended.
3367dd7cddfSDavid du Colombier *
3377dd7cddfSDavid du Colombier * NB: input_buf is ignored; it is likely to be a NULL pointer.
3387dd7cddfSDavid du Colombier */
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier METHODDEF(boolean)
compress_output(j_compress_ptr cinfo,JSAMPIMAGE input_buf)3417dd7cddfSDavid du Colombier compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
3427dd7cddfSDavid du Colombier {
3437dd7cddfSDavid du Colombier my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
3447dd7cddfSDavid du Colombier JDIMENSION MCU_col_num; /* index of current MCU within row */
3457dd7cddfSDavid du Colombier int blkn, ci, xindex, yindex, yoffset;
3467dd7cddfSDavid du Colombier JDIMENSION start_col;
3477dd7cddfSDavid du Colombier JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
3487dd7cddfSDavid du Colombier JBLOCKROW buffer_ptr;
3497dd7cddfSDavid du Colombier jpeg_component_info *compptr;
3507dd7cddfSDavid du Colombier
3517dd7cddfSDavid du Colombier /* Align the virtual buffers for the components used in this scan.
3527dd7cddfSDavid du Colombier * NB: during first pass, this is safe only because the buffers will
3537dd7cddfSDavid du Colombier * already be aligned properly, so jmemmgr.c won't need to do any I/O.
3547dd7cddfSDavid du Colombier */
3557dd7cddfSDavid du Colombier for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
3567dd7cddfSDavid du Colombier compptr = cinfo->cur_comp_info[ci];
3577dd7cddfSDavid du Colombier buffer[ci] = (*cinfo->mem->access_virt_barray)
3587dd7cddfSDavid du Colombier ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
3597dd7cddfSDavid du Colombier coef->iMCU_row_num * compptr->v_samp_factor,
3607dd7cddfSDavid du Colombier (JDIMENSION) compptr->v_samp_factor, FALSE);
3617dd7cddfSDavid du Colombier }
3627dd7cddfSDavid du Colombier
3637dd7cddfSDavid du Colombier /* Loop to process one whole iMCU row */
3647dd7cddfSDavid du Colombier for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
3657dd7cddfSDavid du Colombier yoffset++) {
3667dd7cddfSDavid du Colombier for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
3677dd7cddfSDavid du Colombier MCU_col_num++) {
3687dd7cddfSDavid du Colombier /* Construct list of pointers to DCT blocks belonging to this MCU */
3697dd7cddfSDavid du Colombier blkn = 0; /* index of current DCT block within MCU */
3707dd7cddfSDavid du Colombier for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
3717dd7cddfSDavid du Colombier compptr = cinfo->cur_comp_info[ci];
3727dd7cddfSDavid du Colombier start_col = MCU_col_num * compptr->MCU_width;
3737dd7cddfSDavid du Colombier for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
3747dd7cddfSDavid du Colombier buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
3757dd7cddfSDavid du Colombier for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
3767dd7cddfSDavid du Colombier coef->MCU_buffer[blkn++] = buffer_ptr++;
3777dd7cddfSDavid du Colombier }
3787dd7cddfSDavid du Colombier }
3797dd7cddfSDavid du Colombier }
3807dd7cddfSDavid du Colombier /* Try to write the MCU. */
3817dd7cddfSDavid du Colombier if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
3827dd7cddfSDavid du Colombier /* Suspension forced; update state counters and exit */
3837dd7cddfSDavid du Colombier coef->MCU_vert_offset = yoffset;
3847dd7cddfSDavid du Colombier coef->mcu_ctr = MCU_col_num;
3857dd7cddfSDavid du Colombier return FALSE;
3867dd7cddfSDavid du Colombier }
3877dd7cddfSDavid du Colombier }
3887dd7cddfSDavid du Colombier /* Completed an MCU row, but perhaps not an iMCU row */
3897dd7cddfSDavid du Colombier coef->mcu_ctr = 0;
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier /* Completed the iMCU row, advance counters for next one */
3927dd7cddfSDavid du Colombier coef->iMCU_row_num++;
3937dd7cddfSDavid du Colombier start_iMCU_row(cinfo);
3947dd7cddfSDavid du Colombier return TRUE;
3957dd7cddfSDavid du Colombier }
3967dd7cddfSDavid du Colombier
3977dd7cddfSDavid du Colombier #endif /* FULL_COEF_BUFFER_SUPPORTED */
3987dd7cddfSDavid du Colombier
3997dd7cddfSDavid du Colombier
4007dd7cddfSDavid du Colombier /*
4017dd7cddfSDavid du Colombier * Initialize coefficient buffer controller.
4027dd7cddfSDavid du Colombier */
4037dd7cddfSDavid du Colombier
4047dd7cddfSDavid du Colombier GLOBAL(void)
jinit_c_coef_controller(j_compress_ptr cinfo,boolean need_full_buffer)4057dd7cddfSDavid du Colombier jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
4067dd7cddfSDavid du Colombier {
4077dd7cddfSDavid du Colombier my_coef_ptr coef;
4087dd7cddfSDavid du Colombier
4097dd7cddfSDavid du Colombier coef = (my_coef_ptr)
4107dd7cddfSDavid du Colombier (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
4117dd7cddfSDavid du Colombier SIZEOF(my_coef_controller));
4127dd7cddfSDavid du Colombier cinfo->coef = (struct jpeg_c_coef_controller *) coef;
4137dd7cddfSDavid du Colombier coef->pub.start_pass = start_pass_coef;
4147dd7cddfSDavid du Colombier
4157dd7cddfSDavid du Colombier /* Create the coefficient buffer. */
4167dd7cddfSDavid du Colombier if (need_full_buffer) {
4177dd7cddfSDavid du Colombier #ifdef FULL_COEF_BUFFER_SUPPORTED
4187dd7cddfSDavid du Colombier /* Allocate a full-image virtual array for each component, */
4197dd7cddfSDavid du Colombier /* padded to a multiple of samp_factor DCT blocks in each direction. */
4207dd7cddfSDavid du Colombier int ci;
4217dd7cddfSDavid du Colombier jpeg_component_info *compptr;
4227dd7cddfSDavid du Colombier
4237dd7cddfSDavid du Colombier for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
4247dd7cddfSDavid du Colombier ci++, compptr++) {
4257dd7cddfSDavid du Colombier coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
4267dd7cddfSDavid du Colombier ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
4277dd7cddfSDavid du Colombier (JDIMENSION) jround_up((long) compptr->width_in_blocks,
4287dd7cddfSDavid du Colombier (long) compptr->h_samp_factor),
4297dd7cddfSDavid du Colombier (JDIMENSION) jround_up((long) compptr->height_in_blocks,
4307dd7cddfSDavid du Colombier (long) compptr->v_samp_factor),
4317dd7cddfSDavid du Colombier (JDIMENSION) compptr->v_samp_factor);
4327dd7cddfSDavid du Colombier }
4337dd7cddfSDavid du Colombier #else
4347dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
4357dd7cddfSDavid du Colombier #endif
4367dd7cddfSDavid du Colombier } else {
4377dd7cddfSDavid du Colombier /* We only need a single-MCU buffer. */
4387dd7cddfSDavid du Colombier JBLOCKROW buffer;
4397dd7cddfSDavid du Colombier int i;
4407dd7cddfSDavid du Colombier
4417dd7cddfSDavid du Colombier buffer = (JBLOCKROW)
4427dd7cddfSDavid du Colombier (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
4437dd7cddfSDavid du Colombier C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
4447dd7cddfSDavid du Colombier for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
4457dd7cddfSDavid du Colombier coef->MCU_buffer[i] = buffer + i;
4467dd7cddfSDavid du Colombier }
4477dd7cddfSDavid du Colombier coef->whole_image[0] = NULL; /* flag for no virtual arrays */
4487dd7cddfSDavid du Colombier }
4497dd7cddfSDavid du Colombier }
450