22 * jccoefct.c
33 *
44 * Copyright (C) 1994-1997, Thomas G. Lane.
5- * Modified 2003-2011 by Guido Vollbeding.
5+ * Modified 2003-2020 by Guido Vollbeding.
66 * This file is part of the Independent JPEG Group's software.
77 * For conditions of distribution and use, see the accompanying README file.
88 *
@@ -36,23 +36,24 @@ typedef struct {
3636 struct jpeg_c_coef_controller pub ; /* public fields */
3737
3838 JDIMENSION iMCU_row_num ; /* iMCU row # within image */
39- JDIMENSION mcu_ctr ; /* counts MCUs processed in current row */
39+ JDIMENSION MCU_ctr ; /* counts MCUs processed in current row */
4040 int MCU_vert_offset ; /* counts MCU rows within iMCU row */
4141 int MCU_rows_per_iMCU_row ; /* number of such rows needed */
4242
4343 /* For single-pass compression, it's sufficient to buffer just one MCU
44- * (although this may prove a bit slow in practice). We allocate a
45- * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
46- * MCU constructed and sent. (On 80x86, the workspace is FAR even though
47- * it's not really very big; this is to keep the module interfaces unchanged
48- * when a large coefficient buffer is necessary.)
44+ * (although this may prove a bit slow in practice). We append a
45+ * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it
46+ * for each MCU constructed and sent.
4947 * In multi-pass modes, this array points to the current MCU's blocks
5048 * within the virtual arrays.
5149 */
5250 JBLOCKROW MCU_buffer [C_MAX_BLOCKS_IN_MCU ];
5351
5452 /* In multi-pass modes, we need a virtual block array for each component. */
5553 jvirt_barray_ptr whole_image [MAX_COMPONENTS ];
54+
55+ /* Workspace for single-pass compression (omitted otherwise). */
56+ JBLOCK blk_buffer [C_MAX_BLOCKS_IN_MCU ];
5657} my_coef_controller ;
5758
5859typedef my_coef_controller * my_coef_ptr ;
@@ -88,7 +89,7 @@ start_iMCU_row (j_compress_ptr cinfo)
8889 coef -> MCU_rows_per_iMCU_row = cinfo -> cur_comp_info [0 ]-> last_row_height ;
8990 }
9091
91- coef -> mcu_ctr = 0 ;
92+ coef -> MCU_ctr = 0 ;
9293 coef -> MCU_vert_offset = 0 ;
9394}
9495
@@ -125,7 +126,6 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
125126#endif
126127 default :
127128 ERREXIT (cinfo , JERR_BAD_BUFFER_MODE );
128- break ;
129129 }
130130}
131131
@@ -147,59 +147,56 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
147147 JDIMENSION MCU_col_num ; /* index of current MCU within row */
148148 JDIMENSION last_MCU_col = cinfo -> MCUs_per_row - 1 ;
149149 JDIMENSION last_iMCU_row = cinfo -> total_iMCU_rows - 1 ;
150- int blkn , bi , ci , yindex , yoffset , blockcnt ;
151- JDIMENSION ypos , xpos ;
150+ int ci , xindex , yindex , yoffset , blockcnt ;
151+ JBLOCKROW blkp ;
152+ JSAMPARRAY input_ptr ;
153+ JDIMENSION xpos ;
152154 jpeg_component_info * compptr ;
153155 forward_DCT_ptr forward_DCT ;
154156
155157 /* Loop to write as much as one whole iMCU row */
156158 for (yoffset = coef -> MCU_vert_offset ; yoffset < coef -> MCU_rows_per_iMCU_row ;
157159 yoffset ++ ) {
158- for (MCU_col_num = coef -> mcu_ctr ; MCU_col_num <= last_MCU_col ;
160+ for (MCU_col_num = coef -> MCU_ctr ; MCU_col_num <= last_MCU_col ;
159161 MCU_col_num ++ ) {
160162 /* Determine where data comes from in input_buf and do the DCT thing.
161- * Each call on forward_DCT processes a horizontal row of DCT blocks
162- * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
163- * sequentially. Dummy blocks at the right or bottom edge are filled in
163+ * Each call on forward_DCT processes a horizontal row of DCT blocks as
164+ * wide as an MCU. Dummy blocks at the right or bottom edge are filled in
164165 * specially. The data in them does not matter for image reconstruction,
165166 * so we fill them with values that will encode to the smallest amount of
166167 * data, viz: all zeroes in the AC entries, DC entries equal to previous
167168 * block's DC value. (Thanks to Thomas Kinsman for this idea.)
168169 */
169- blkn = 0 ;
170+ blkp = coef -> blk_buffer ; /* pointer to current DCT block within MCU */
170171 for (ci = 0 ; ci < cinfo -> comps_in_scan ; ci ++ ) {
171172 compptr = cinfo -> cur_comp_info [ci ];
172173 forward_DCT = cinfo -> fdct -> forward_DCT [compptr -> component_index ];
174+ input_ptr = input_buf [compptr -> component_index ] +
175+ yoffset * compptr -> DCT_v_scaled_size ;
176+ /* ypos == (yoffset + yindex) * compptr->DCT_v_scaled_size */
173177 blockcnt = (MCU_col_num < last_MCU_col ) ? compptr -> MCU_width
174178 : compptr -> last_col_width ;
175179 xpos = MCU_col_num * compptr -> MCU_sample_width ;
176- ypos = yoffset * compptr -> DCT_v_scaled_size ;
177- /* ypos == (yoffset+yindex) * DCTSIZE */
178180 for (yindex = 0 ; yindex < compptr -> MCU_height ; yindex ++ ) {
179181 if (coef -> iMCU_row_num < last_iMCU_row ||
180- yoffset + yindex < compptr -> last_row_height ) {
181- (* forward_DCT ) (cinfo , compptr ,
182- input_buf [compptr -> component_index ],
183- coef -> MCU_buffer [blkn ],
184- ypos , xpos , (JDIMENSION ) blockcnt );
185- if (blockcnt < compptr -> MCU_width ) {
186- /* Create some dummy blocks at the right edge of the image. */
187- FMEMZERO ((void FAR * ) coef -> MCU_buffer [blkn + blockcnt ],
188- (compptr -> MCU_width - blockcnt ) * SIZEOF (JBLOCK ));
189- for (bi = blockcnt ; bi < compptr -> MCU_width ; bi ++ ) {
190- coef -> MCU_buffer [blkn + bi ][0 ][0 ] = coef -> MCU_buffer [blkn + bi - 1 ][0 ][0 ];
191- }
192- }
182+ yoffset + yindex < compptr -> last_row_height ) {
183+ (* forward_DCT ) (cinfo , compptr , input_ptr , blkp ,
184+ xpos , (JDIMENSION ) blockcnt );
185+ input_ptr += compptr -> DCT_v_scaled_size ;
186+ blkp += blockcnt ;
187+ /* Dummy blocks at right edge */
188+ if ((xindex = compptr -> MCU_width - blockcnt ) == 0 )
189+ continue ;
193190 } else {
194- /* Create a row of dummy blocks at the bottom of the image. */
195- FMEMZERO ((void FAR * ) coef -> MCU_buffer [blkn ],
196- compptr -> MCU_width * SIZEOF (JBLOCK ));
197- for (bi = 0 ; bi < compptr -> MCU_width ; bi ++ ) {
198- coef -> MCU_buffer [blkn + bi ][0 ][0 ] = coef -> MCU_buffer [blkn - 1 ][0 ][0 ];
199- }
191+ /* At bottom of image, need a whole row of dummy blocks */
192+ xindex = compptr -> MCU_width ;
200193 }
201- blkn += compptr -> MCU_width ;
202- ypos += compptr -> DCT_v_scaled_size ;
194+ /* Fill in any dummy blocks needed in this row */
195+ MEMZERO (blkp , xindex * SIZEOF (JBLOCK ));
196+ do {
197+ blkp [0 ][0 ] = blkp [-1 ][0 ];
198+ blkp ++ ;
199+ } while (-- xindex );
203200 }
204201 }
205202 /* Try to write the MCU. In event of a suspension failure, we will
@@ -208,12 +205,12 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
208205 if (! (* cinfo -> entropy -> encode_mcu ) (cinfo , coef -> MCU_buffer )) {
209206 /* Suspension forced; update state counters and exit */
210207 coef -> MCU_vert_offset = yoffset ;
211- coef -> mcu_ctr = MCU_col_num ;
208+ coef -> MCU_ctr = MCU_col_num ;
212209 return FALSE;
213210 }
214211 }
215212 /* Completed an MCU row, but perhaps not an iMCU row */
216- coef -> mcu_ctr = 0 ;
213+ coef -> MCU_ctr = 0 ;
217214 }
218215 /* Completed the iMCU row, advance counters for next one */
219216 coef -> iMCU_row_num ++ ;
@@ -256,6 +253,7 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
256253 jpeg_component_info * compptr ;
257254 JBLOCKARRAY buffer ;
258255 JBLOCKROW thisblockrow , lastblockrow ;
256+ JSAMPARRAY input_ptr ;
259257 forward_DCT_ptr forward_DCT ;
260258
261259 for (ci = 0 , compptr = cinfo -> comp_info ; ci < cinfo -> num_components ;
@@ -280,14 +278,15 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
280278 if (ndummy > 0 )
281279 ndummy = h_samp_factor - ndummy ;
282280 forward_DCT = cinfo -> fdct -> forward_DCT [ci ];
281+ input_ptr = input_buf [ci ];
283282 /* Perform DCT for all non-dummy blocks in this iMCU row. Each call
284283 * on forward_DCT processes a complete horizontal row of DCT blocks.
285284 */
286285 for (block_row = 0 ; block_row < block_rows ; block_row ++ ) {
287286 thisblockrow = buffer [block_row ];
288- (* forward_DCT ) (cinfo , compptr , input_buf [ci ], thisblockrow ,
289- (JDIMENSION ) (block_row * compptr -> DCT_v_scaled_size ),
287+ (* forward_DCT ) (cinfo , compptr , input_ptr , thisblockrow ,
290288 (JDIMENSION ) 0 , blocks_across );
289+ input_ptr += compptr -> DCT_v_scaled_size ;
291290 if (ndummy > 0 ) {
292291 /* Create dummy blocks at the right edge of the image. */
293292 thisblockrow += blocks_across ; /* => first dummy block */
@@ -303,15 +302,14 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
303302 * of the dummy blocks to match the last real block's DC value.
304303 * This squeezes a few more bytes out of the resulting file...
305304 */
306- if (coef -> iMCU_row_num == last_iMCU_row ) {
305+ if (block_row < compptr -> v_samp_factor ) {
307306 blocks_across += ndummy ; /* include lower right corner */
308307 MCUs_across = blocks_across / h_samp_factor ;
309- for (block_row = block_rows ; block_row < compptr -> v_samp_factor ;
310- block_row ++ ) {
308+ do {
311309 thisblockrow = buffer [block_row ];
312310 lastblockrow = buffer [block_row - 1 ];
313311 FMEMZERO ((void FAR * ) thisblockrow ,
314- (size_t ) ( blocks_across * SIZEOF (JBLOCK ) ));
312+ (size_t ) blocks_across * SIZEOF (JBLOCK ));
315313 for (MCUindex = 0 ; MCUindex < MCUs_across ; MCUindex ++ ) {
316314 lastDC = lastblockrow [h_samp_factor - 1 ][0 ];
317315 for (bi = 0 ; bi < h_samp_factor ; bi ++ ) {
@@ -320,7 +318,7 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
320318 thisblockrow += h_samp_factor ; /* advance to next MCU in row */
321319 lastblockrow += h_samp_factor ;
322320 }
323- }
321+ } while ( ++ block_row < compptr -> v_samp_factor );
324322 }
325323 }
326324 /* NB: compress_output will increment iMCU_row_num if successful.
@@ -347,8 +345,9 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
347345{
348346 my_coef_ptr coef = (my_coef_ptr ) cinfo -> coef ;
349347 JDIMENSION MCU_col_num ; /* index of current MCU within row */
350- int blkn , ci , xindex , yindex , yoffset ;
348+ int ci , xindex , yindex , yoffset ;
351349 JDIMENSION start_col ;
350+ JBLOCKARRAY blkp ;
352351 JBLOCKARRAY buffer [MAX_COMPS_IN_SCAN ];
353352 JBLOCKROW buffer_ptr ;
354353 jpeg_component_info * compptr ;
@@ -368,30 +367,31 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
368367 /* Loop to process one whole iMCU row */
369368 for (yoffset = coef -> MCU_vert_offset ; yoffset < coef -> MCU_rows_per_iMCU_row ;
370369 yoffset ++ ) {
371- for (MCU_col_num = coef -> mcu_ctr ; MCU_col_num < cinfo -> MCUs_per_row ;
370+ for (MCU_col_num = coef -> MCU_ctr ; MCU_col_num < cinfo -> MCUs_per_row ;
372371 MCU_col_num ++ ) {
373372 /* Construct list of pointers to DCT blocks belonging to this MCU */
374- blkn = 0 ; /* index of current DCT block within MCU */
373+ blkp = coef -> MCU_buffer ; /* pointer to current DCT block within MCU */
375374 for (ci = 0 ; ci < cinfo -> comps_in_scan ; ci ++ ) {
376375 compptr = cinfo -> cur_comp_info [ci ];
377376 start_col = MCU_col_num * compptr -> MCU_width ;
378377 for (yindex = 0 ; yindex < compptr -> MCU_height ; yindex ++ ) {
379- buffer_ptr = buffer [ci ][yindex + yoffset ] + start_col ;
380- for (xindex = 0 ; xindex < compptr -> MCU_width ; xindex ++ ) {
381- coef -> MCU_buffer [blkn ++ ] = buffer_ptr ++ ;
382- }
378+ buffer_ptr = buffer [ci ][yoffset + yindex ] + start_col ;
379+ xindex = compptr -> MCU_width ;
380+ do {
381+ * blkp ++ = buffer_ptr ++ ;
382+ } while (-- xindex );
383383 }
384384 }
385385 /* Try to write the MCU. */
386386 if (! (* cinfo -> entropy -> encode_mcu ) (cinfo , coef -> MCU_buffer )) {
387387 /* Suspension forced; update state counters and exit */
388388 coef -> MCU_vert_offset = yoffset ;
389- coef -> mcu_ctr = MCU_col_num ;
389+ coef -> MCU_ctr = MCU_col_num ;
390390 return FALSE;
391391 }
392392 }
393393 /* Completed an MCU row, but perhaps not an iMCU row */
394- coef -> mcu_ctr = 0 ;
394+ coef -> MCU_ctr = 0 ;
395395 }
396396 /* Completed the iMCU row, advance counters for next one */
397397 coef -> iMCU_row_num ++ ;
@@ -411,20 +411,16 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
411411{
412412 my_coef_ptr coef ;
413413
414- coef = (my_coef_ptr )
415- (* cinfo -> mem -> alloc_small ) ((j_common_ptr ) cinfo , JPOOL_IMAGE ,
416- SIZEOF (my_coef_controller ));
417- cinfo -> coef = (struct jpeg_c_coef_controller * ) coef ;
418- coef -> pub .start_pass = start_pass_coef ;
419-
420- /* Create the coefficient buffer. */
421414 if (need_full_buffer ) {
422415#ifdef FULL_COEF_BUFFER_SUPPORTED
423416 /* Allocate a full-image virtual array for each component, */
424417 /* padded to a multiple of samp_factor DCT blocks in each direction. */
425418 int ci ;
426419 jpeg_component_info * compptr ;
427420
421+ coef = (my_coef_ptr ) (* cinfo -> mem -> alloc_small )
422+ ((j_common_ptr ) cinfo , JPOOL_IMAGE ,
423+ SIZEOF (my_coef_controller ) - SIZEOF (coef -> blk_buffer ));
428424 for (ci = 0 , compptr = cinfo -> comp_info ; ci < cinfo -> num_components ;
429425 ci ++ , compptr ++ ) {
430426 coef -> whole_image [ci ] = (* cinfo -> mem -> request_virt_barray )
@@ -440,15 +436,21 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
440436#endif
441437 } else {
442438 /* We only need a single-MCU buffer. */
443- JBLOCKROW buffer ;
444- int i ;
445-
446- buffer = (JBLOCKROW )
447- (* cinfo -> mem -> alloc_large ) ((j_common_ptr ) cinfo , JPOOL_IMAGE ,
448- C_MAX_BLOCKS_IN_MCU * SIZEOF (JBLOCK ));
449- for (i = 0 ; i < C_MAX_BLOCKS_IN_MCU ; i ++ ) {
450- coef -> MCU_buffer [i ] = buffer + i ;
451- }
439+ JBLOCKARRAY blkp ;
440+ JBLOCKROW buffer_ptr ;
441+ int bi ;
442+
443+ coef = (my_coef_ptr ) (* cinfo -> mem -> alloc_small )
444+ ((j_common_ptr ) cinfo , JPOOL_IMAGE , SIZEOF (my_coef_controller ));
445+ blkp = coef -> MCU_buffer ;
446+ buffer_ptr = coef -> blk_buffer ;
447+ bi = C_MAX_BLOCKS_IN_MCU ;
448+ do {
449+ * blkp ++ = buffer_ptr ++ ;
450+ } while (-- bi );
452451 coef -> whole_image [0 ] = NULL ; /* flag for no virtual arrays */
453452 }
453+
454+ coef -> pub .start_pass = start_pass_coef ;
455+ cinfo -> coef = & coef -> pub ;
454456}
0 commit comments