4 * This file was part of the Independent JPEG Group's software:
5 * Copyright (C) 1994-1997, Thomas G. Lane.
6 * Lossless JPEG Modifications:
7 * Copyright (C) 1999, Ken Murchison.
8 * libjpeg-turbo Modifications:
9 * Copyright (C) 2022, D. R. Commander.
10 * For conditions of distribution and use, see the accompanying README.ijg
13 * This file contains the difference buffer controller for compression.
14 * This controller is the top level of the lossless JPEG compressor proper.
15 * The difference buffer lies between the prediction/differencing and entropy
19 #define JPEG_INTERNALS
22 #include "jlossls.h" /* Private declarations for lossless codec */
25 #ifdef C_LOSSLESS_SUPPORTED
27 /* We use a full-image sample buffer when doing Huffman optimization,
28 * and also for writing multiple-scan JPEG files. In all cases, the
29 * full-image buffer is filled during the first pass, and the scaling,
30 * prediction and differencing steps are run during subsequent passes.
32 #ifdef ENTROPY_OPT_SUPPORTED
33 #define FULL_SAMP_BUFFER_SUPPORTED
35 #ifdef C_MULTISCAN_FILES_SUPPORTED
36 #define FULL_SAMP_BUFFER_SUPPORTED
41 /* Private buffer controller object */
44 struct jpeg_c_coef_controller pub; /* public fields */
46 JDIMENSION iMCU_row_num; /* iMCU row # within image */
47 JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
48 int MCU_vert_offset; /* counts MCU rows within iMCU row */
49 int MCU_rows_per_iMCU_row; /* number of such rows needed */
51 _JSAMPROW cur_row[MAX_COMPONENTS]; /* row of point-transformed samples */
52 _JSAMPROW prev_row[MAX_COMPONENTS]; /* previous row of Pt'd samples */
53 JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */
55 /* In multi-pass modes, we need a virtual sample array for each component. */
56 jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
59 typedef my_diff_controller *my_diff_ptr;
62 /* Forward declarations */
63 METHODDEF(boolean) compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf);
64 #ifdef FULL_SAMP_BUFFER_SUPPORTED
65 METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo,
66 _JSAMPIMAGE input_buf);
67 METHODDEF(boolean) compress_output(j_compress_ptr cinfo,
68 _JSAMPIMAGE input_buf);
73 start_iMCU_row(j_compress_ptr cinfo)
74 /* Reset within-iMCU-row counters for a new row */
76 my_diff_ptr diff = (my_diff_ptr)cinfo->coef;
78 /* In an interleaved scan, an MCU row is the same as an iMCU row.
79 * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
80 * But at the bottom of the image, process only what's left.
82 if (cinfo->comps_in_scan > 1) {
83 diff->MCU_rows_per_iMCU_row = 1;
85 if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1))
86 diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
88 diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
92 diff->MCU_vert_offset = 0;
97 * Initialize for a processing pass.
101 start_pass_diff(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
103 my_diff_ptr diff = (my_diff_ptr)cinfo->coef;
105 /* Because it is hitching a ride on the jpeg_forward_dct struct,
106 * start_pass_lossless() will be called at the start of the initial pass.
107 * This ensures that it will be called at the start of the Huffman
108 * optimization and output passes as well.
110 if (pass_mode == JBUF_CRANK_DEST)
111 (*cinfo->fdct->start_pass) (cinfo);
113 diff->iMCU_row_num = 0;
114 start_iMCU_row(cinfo);
118 if (diff->whole_image[0] != NULL)
119 ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
120 diff->pub._compress_data = compress_data;
122 #ifdef FULL_SAMP_BUFFER_SUPPORTED
123 case JBUF_SAVE_AND_PASS:
124 if (diff->whole_image[0] == NULL)
125 ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
126 diff->pub._compress_data = compress_first_pass;
128 case JBUF_CRANK_DEST:
129 if (diff->whole_image[0] == NULL)
130 ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
131 diff->pub._compress_data = compress_output;
135 ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
141 #define SWAP_ROWS(rowa, rowb) { \
142 _JSAMPROW temp = rowa; \
143 rowa = rowb; rowb = temp; \
147 * Process some data in the single-pass case.
148 * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
149 * per call, ie, v_samp_factor rows for each component in the image.
150 * Returns TRUE if the iMCU row is completed, FALSE if suspended.
152 * NB: input_buf contains a plane for each component in image,
153 * which we index according to the component's SOF position.
157 compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf)
159 my_diff_ptr diff = (my_diff_ptr)cinfo->coef;
160 lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct;
161 JDIMENSION MCU_col_num; /* index of current MCU within row */
162 JDIMENSION MCU_count; /* number of MCUs encoded */
163 JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
164 int ci, compi, yoffset, samp_row, samp_rows, samps_across;
165 jpeg_component_info *compptr;
167 /* Loop to write as much as one whole iMCU row */
168 for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row;
171 MCU_col_num = diff->mcu_ctr;
173 /* Scale and predict each scanline of the MCU row separately.
175 * Note: We only do this if we are at the start of an MCU row, ie,
176 * we don't want to reprocess a row suspended by the output.
178 if (MCU_col_num == 0) {
179 for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
180 compptr = cinfo->cur_comp_info[ci];
181 compi = compptr->component_index;
182 if (diff->iMCU_row_num < last_iMCU_row)
183 samp_rows = compptr->v_samp_factor;
185 /* NB: can't use last_row_height here, since may not be set! */
187 (int)(compptr->height_in_blocks % compptr->v_samp_factor);
188 if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
190 /* Fill dummy difference rows at the bottom edge with zeros, which
191 * will encode to the smallest amount of data.
193 for (samp_row = samp_rows; samp_row < compptr->v_samp_factor;
195 memset(diff->diff_buf[compi][samp_row], 0,
196 jround_up((long)compptr->width_in_blocks,
197 (long)compptr->h_samp_factor) * sizeof(JDIFF));
200 samps_across = compptr->width_in_blocks;
202 for (samp_row = 0; samp_row < samp_rows; samp_row++) {
203 (*losslessc->scaler_scale) (cinfo,
204 input_buf[compi][samp_row],
205 diff->cur_row[compi],
207 (*losslessc->predict_difference[compi])
208 (cinfo, compi, diff->cur_row[compi], diff->prev_row[compi],
209 diff->diff_buf[compi][samp_row], samps_across);
210 SWAP_ROWS(diff->cur_row[compi], diff->prev_row[compi]);
214 /* Try to write the MCU row (or remaining portion of suspended MCU row). */
216 (*cinfo->entropy->encode_mcus) (cinfo,
217 diff->diff_buf, yoffset, MCU_col_num,
218 cinfo->MCUs_per_row - MCU_col_num);
219 if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) {
220 /* Suspension forced; update state counters and exit */
221 diff->MCU_vert_offset = yoffset;
222 diff->mcu_ctr += MCU_col_num;
225 /* Completed an MCU row, but perhaps not an iMCU row */
228 /* Completed the iMCU row, advance counters for next one */
229 diff->iMCU_row_num++;
230 start_iMCU_row(cinfo);
235 #ifdef FULL_SAMP_BUFFER_SUPPORTED
238 * Process some data in the first pass of a multi-pass case.
239 * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
240 * per call, ie, v_samp_factor rows for each component in the image.
241 * This amount of data is read from the source buffer and saved into the
244 * We must also emit the data to the compressor. This is conveniently
245 * done by calling compress_output() after we've loaded the current strip
246 * of the virtual arrays.
248 * NB: input_buf contains a plane for each component in image. All components
249 * are loaded into the virtual arrays in this pass. However, it may be that
250 * only a subset of the components are emitted to the compressor during
251 * this first pass; be careful about looking at the scan-dependent variables
252 * (MCU dimensions, etc).
256 compress_first_pass(j_compress_ptr cinfo, _JSAMPIMAGE input_buf)
258 my_diff_ptr diff = (my_diff_ptr)cinfo->coef;
259 JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
260 JDIMENSION samps_across;
261 int ci, samp_row, samp_rows;
263 jpeg_component_info *compptr;
265 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
267 /* Align the virtual buffer for this component. */
268 buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray)
269 ((j_common_ptr)cinfo, diff->whole_image[ci],
270 diff->iMCU_row_num * compptr->v_samp_factor,
271 (JDIMENSION)compptr->v_samp_factor, TRUE);
273 /* Count non-dummy sample rows in this iMCU row. */
274 if (diff->iMCU_row_num < last_iMCU_row)
275 samp_rows = compptr->v_samp_factor;
277 /* NB: can't use last_row_height here, since may not be set! */
278 samp_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
279 if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
281 samps_across = compptr->width_in_blocks;
283 /* Perform point transform scaling and prediction/differencing for all
284 * non-dummy rows in this iMCU row. Each call on these functions
285 * processes a complete row of samples.
287 for (samp_row = 0; samp_row < samp_rows; samp_row++) {
288 memcpy(buffer[samp_row], input_buf[ci][samp_row],
289 samps_across * sizeof(_JSAMPLE));
292 /* NB: compress_output will increment iMCU_row_num if successful.
293 * A suspension return will result in redoing all the work above next time.
296 /* Emit data to the compressor, sharing code with subsequent passes */
297 return compress_output(cinfo, input_buf);
302 * Process some data in subsequent passes of a multi-pass case.
303 * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
304 * per call, ie, v_samp_factor rows for each component in the scan.
305 * The data is obtained from the virtual arrays and fed to the compressor.
306 * Returns TRUE if the iMCU row is completed, FALSE if suspended.
308 * NB: input_buf is ignored; it is likely to be a NULL pointer.
312 compress_output(j_compress_ptr cinfo, _JSAMPIMAGE input_buf)
314 my_diff_ptr diff = (my_diff_ptr)cinfo->coef;
316 _JSAMPARRAY buffer[MAX_COMPS_IN_SCAN];
317 jpeg_component_info *compptr;
319 /* Align the virtual buffers for the components used in this scan.
320 * NB: during first pass, this is safe only because the buffers will
321 * already be aligned properly, so jmemmgr.c won't need to do any I/O.
323 for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
324 compptr = cinfo->cur_comp_info[ci];
325 compi = compptr->component_index;
326 buffer[compi] = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray)
327 ((j_common_ptr)cinfo, diff->whole_image[compi],
328 diff->iMCU_row_num * compptr->v_samp_factor,
329 (JDIMENSION)compptr->v_samp_factor, FALSE);
332 return compress_data(cinfo, buffer);
335 #endif /* FULL_SAMP_BUFFER_SUPPORTED */
339 * Initialize difference buffer controller.
343 _jinit_c_diff_controller(j_compress_ptr cinfo, boolean need_full_buffer)
347 jpeg_component_info *compptr;
350 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
351 sizeof(my_diff_controller));
352 cinfo->coef = (struct jpeg_c_coef_controller *)diff;
353 diff->pub.start_pass = start_pass_diff;
355 /* Create the prediction row buffers. */
356 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
358 diff->cur_row[ci] = *(_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
359 ((j_common_ptr)cinfo, JPOOL_IMAGE,
360 (JDIMENSION)jround_up((long)compptr->width_in_blocks,
361 (long)compptr->h_samp_factor),
363 diff->prev_row[ci] = *(_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
364 ((j_common_ptr)cinfo, JPOOL_IMAGE,
365 (JDIMENSION)jround_up((long)compptr->width_in_blocks,
366 (long)compptr->h_samp_factor),
370 /* Create the difference buffer. */
371 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
374 ALLOC_DARRAY(JPOOL_IMAGE,
375 (JDIMENSION)jround_up((long)compptr->width_in_blocks,
376 (long)compptr->h_samp_factor),
377 (JDIMENSION)compptr->v_samp_factor);
378 /* Prefill difference rows with zeros. We do this because only actual
379 * data is placed in the buffers during prediction/differencing, leaving
380 * any dummy differences at the right edge as zeros, which will encode
381 * to the smallest amount of data.
383 for (row = 0; row < compptr->v_samp_factor; row++)
384 memset(diff->diff_buf[ci][row], 0,
385 jround_up((long)compptr->width_in_blocks,
386 (long)compptr->h_samp_factor) * sizeof(JDIFF));
389 /* Create the sample buffer. */
390 if (need_full_buffer) {
391 #ifdef FULL_SAMP_BUFFER_SUPPORTED
392 /* Allocate a full-image virtual array for each component, */
393 /* padded to a multiple of samp_factor differences in each direction. */
394 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
396 diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
397 ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
398 (JDIMENSION)jround_up((long)compptr->width_in_blocks,
399 (long)compptr->h_samp_factor),
400 (JDIMENSION)jround_up((long)compptr->height_in_blocks,
401 (long)compptr->v_samp_factor),
402 (JDIMENSION)compptr->v_samp_factor);
405 ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
408 diff->whole_image[0] = NULL; /* flag for no virtual arrays */
411 #endif /* C_LOSSLESS_SUPPORTED */