]> Creatis software - gdcm.git/blob - src/gdcmjpeg/jcdiffct.c
ENH: Final -hopefully- change to jpeg lib. In order to match ITK structure, and be...
[gdcm.git] / src / gdcmjpeg / jcdiffct.c
1 /*
2  * jcdiffct.c
3  *
4  * Copyright (C) 1994-1998, Thomas G. Lane.
5  * This file is part of the Independent JPEG Group's software.
6  * For conditions of distribution and use, see the accompanying README file.
7  *
8  * This file contains the difference buffer controller for compression.
9  * This controller is the top level of the lossless JPEG compressor proper.
10  * The difference buffer lies between prediction/differencing and entropy
11  * encoding.
12  */
13
14 #define JPEG_INTERNALS
15 #include "jinclude.h"
16 #include "jpeglib.h"
17 #include "jlossls.h"    /* Private declarations for lossless codec */
18
19
20 #ifdef C_LOSSLESS_SUPPORTED
21
22 /* We use a full-image sample buffer when doing Huffman optimization,
23  * and also for writing multiple-scan JPEG files.  In all cases, the
24  * full-image buffer is filled during the first pass, and the scaling,
25  * prediction and differencing steps are run during subsequent passes.
26  */
27 #ifdef ENTROPY_OPT_SUPPORTED
28 #define FULL_SAMP_BUFFER_SUPPORTED
29 #else
30 #ifdef C_MULTISCAN_FILES_SUPPORTED
31 #define FULL_SAMP_BUFFER_SUPPORTED
32 #endif
33 #endif
34
35
36 /* Private buffer controller object */
37
38 typedef struct {
39   JDIMENSION iMCU_row_num;  /* iMCU row # within image */
40   JDIMENSION mcu_ctr;    /* counts MCUs processed in current row */
41   int MCU_vert_offset;    /* counts MCU rows within iMCU row */
42   int MCU_rows_per_iMCU_row;  /* number of such rows needed */
43
44   JSAMPROW cur_row[MAX_COMPONENTS];  /* row of point transformed samples */
45   JSAMPROW prev_row[MAX_COMPONENTS];  /* previous row of Pt'd samples */
46   JDIFFARRAY diff_buf[MAX_COMPONENTS];  /* iMCU row of differences */
47
48   /* In multi-pass modes, we need a virtual sample array for each component. */
49   jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
50 } c_diff_controller;
51
52 typedef c_diff_controller * c_diff_ptr;
53
54
55 /* Forward declarations */
56 METHODDEF(boolean) compress_data
57     JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
58 #ifdef FULL_SAMP_BUFFER_SUPPORTED
59 METHODDEF(boolean) compress_first_pass
60     JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
61 METHODDEF(boolean) compress_output
62     JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
63 #endif
64
65
66 LOCAL(void)
67 start_iMCU_row (j_compress_ptr cinfo)
68 /* Reset within-iMCU-row counters for a new row */
69 {
70   j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
71   c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
72
73   /* In an interleaved scan, an MCU row is the same as an iMCU row.
74    * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
75    * But at the bottom of the image, process only what's left.
76    */
77   if (cinfo->comps_in_scan > 1) {
78     diff->MCU_rows_per_iMCU_row = 1;
79   } else {
80     if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1))
81       diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
82     else
83       diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
84   }
85
86   diff->mcu_ctr = 0;
87   diff->MCU_vert_offset = 0;
88 }
89
90
91 /*
92  * Initialize for a processing pass.
93  */
94
95 METHODDEF(void)
96 start_pass_diff (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
97 {
98   j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
99   c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
100
101   diff->iMCU_row_num = 0;
102   start_iMCU_row(cinfo);
103
104   switch (pass_mode) {
105   case JBUF_PASS_THRU:
106     if (diff->whole_image[0] != NULL)
107       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
108     losslsc->pub.compress_data = compress_data;
109     break;
110 #ifdef FULL_SAMP_BUFFER_SUPPORTED
111   case JBUF_SAVE_AND_PASS:
112     if (diff->whole_image[0] == NULL)
113       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
114     losslsc->pub.compress_data = compress_first_pass;
115     break;
116   case JBUF_CRANK_DEST:
117     if (diff->whole_image[0] == NULL)
118       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
119     losslsc->pub.compress_data = compress_output;
120     break;
121 #endif
122   default:
123     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
124     break;
125   }
126 }
127
128
129 #define SWAP_ROWS(rowa,rowb) {JSAMPROW temp; temp=rowa; rowa=rowb; rowb=temp;}
130
131 /*
132  * Process some data in the single-pass case.
133  * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
134  * per call, ie, v_samp_factor rows for each component in the image.
135  * Returns TRUE if the iMCU row is completed, FALSE if suspended.
136  *
137  * NB: input_buf contains a plane for each component in image,
138  * which we index according to the component's SOF position.
139  */
140
141 METHODDEF(boolean)
142 compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
143 {
144   j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
145   c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
146   JDIMENSION MCU_col_num;  /* index of current MCU within row */
147   JDIMENSION MCU_count;    /* number of MCUs encoded */
148   /* JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; */
149   JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
150   int comp, ci, yoffset, samp_row, samp_rows, samps_across;
151   jpeg_component_info *compptr;
152
153   /* Loop to write as much as one whole iMCU row */
154   for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row;
155        yoffset++) {
156
157     MCU_col_num = diff->mcu_ctr;
158
159     /* Scale and predict each scanline of the MCU-row separately.
160      *
161      * Note: We only do this if we are at the start of a MCU-row, ie,
162      * we don't want to reprocess a row suspended by the output.
163      */
164     if (MCU_col_num == 0) {
165       for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
166   compptr = cinfo->cur_comp_info[comp];
167   ci = compptr->component_index;
168   if (diff->iMCU_row_num < last_iMCU_row)
169     samp_rows = compptr->v_samp_factor;
170   else {
171     /* NB: can't use last_row_height here, since may not be set! */
172     samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
173     if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
174     else {
175       /* Fill dummy difference rows at the bottom edge with zeros, which
176        * will encode to the smallest amount of data.
177        */
178       for (samp_row = samp_rows; samp_row < compptr->v_samp_factor;
179      samp_row++)
180         MEMZERO(diff->diff_buf[ci][samp_row],
181           jround_up((long) compptr->width_in_data_units,
182         (long) compptr->h_samp_factor) * SIZEOF(JDIFF));
183     }
184   }
185   samps_across = compptr->width_in_data_units;
186
187   for (samp_row = 0; samp_row < samp_rows; samp_row++) {
188     (*losslsc->scaler_scale) (cinfo,
189             input_buf[ci][samp_row],
190             diff->cur_row[ci], samps_across);
191     (*losslsc->predict_difference[ci]) (cinfo, ci,
192                 diff->cur_row[ci],
193                 diff->prev_row[ci],
194                 diff->diff_buf[ci][samp_row],
195                 samps_across);
196     SWAP_ROWS(diff->cur_row[ci], diff->prev_row[ci]);
197   }
198       }
199     }
200
201     /* Try to write the MCU-row (or remaining portion of suspended MCU-row). */
202     MCU_count =
203       (*losslsc->entropy_encode_mcus) (cinfo,
204                diff->diff_buf, yoffset, MCU_col_num,
205                cinfo->MCUs_per_row - MCU_col_num);
206     if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) {
207       /* Suspension forced; update state counters and exit */
208       diff->MCU_vert_offset = yoffset;
209       diff->mcu_ctr += MCU_col_num;
210       return FALSE;
211     }
212
213     /* Completed an MCU row, but perhaps not an iMCU row */
214     diff->mcu_ctr = 0;
215   }
216
217   /* Completed the iMCU row, advance counters for next one */
218   diff->iMCU_row_num++;
219   start_iMCU_row(cinfo);
220   return TRUE;
221 }
222
223
224 #ifdef FULL_SAMP_BUFFER_SUPPORTED
225
226 /*
227  * Process some data in the first pass of a multi-pass case.
228  * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
229  * per call, ie, v_samp_factor rows for each component in the image.
230  * This amount of data is read from the source buffer and saved into the
231  * virtual arrays.
232  *
233  * We must also emit the data to the compressor.  This is conveniently
234  * done by calling compress_output() after we've loaded the current strip
235  * of the virtual arrays.
236  *
237  * NB: input_buf contains a plane for each component in image.  All components
238  * are loaded into the virtual arrays in this pass.  However, it may be that
239  * only a subset of the components are emitted to the compressor during
240  * this first pass; be careful about looking at the scan-dependent variables
241  * (MCU dimensions, etc).
242  */
243
244 METHODDEF(boolean)
245 compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
246 {
247   j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
248   c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
249   JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
250   JDIMENSION samps_across;
251   int ci, samp_row, samp_rows;
252   JSAMPARRAY buffer[MAX_COMPONENTS];
253   jpeg_component_info *compptr;
254
255   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
256        ci++, compptr++) {
257     /* Align the virtual buffers for this component. */
258     buffer[ci] = (*cinfo->mem->access_virt_sarray)
259       ((j_common_ptr) cinfo, diff->whole_image[ci],
260        diff->iMCU_row_num * compptr->v_samp_factor,
261        (JDIMENSION) compptr->v_samp_factor, TRUE);
262
263     /* Count non-dummy sample rows in this iMCU row. */
264     if (diff->iMCU_row_num < last_iMCU_row)
265       samp_rows = compptr->v_samp_factor;
266     else {
267       /* NB: can't use last_row_height here, since may not be set! */
268       samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
269       if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
270     }
271     samps_across = compptr->width_in_data_units;
272
273     /* Perform point transform scaling and prediction/differencing for all
274      * non-dummy rows in this iMCU row.  Each call on these functions
275      * process a complete row of samples.
276      */
277     for (samp_row = 0; samp_row < samp_rows; samp_row++) {
278       MEMCOPY(buffer[ci][samp_row], input_buf[ci][samp_row],
279         samps_across * SIZEOF(JSAMPLE));
280     }
281   }
282
283   /* NB: compress_output will increment iMCU_row_num if successful.
284    * A suspension return will result in redoing all the work above next time.
285    */
286
287   /* Emit data to the compressor, sharing code with subsequent passes */
288   return compress_output(cinfo, input_buf);
289 }
290
291
292 /*
293  * Process some data in subsequent passes of a multi-pass case.
294  * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
295  * per call, ie, v_samp_factor rows for each component in the scan.
296  * The data is obtained from the virtual arrays and fed to the compressor.
297  * Returns TRUE if the iMCU row is completed, FALSE if suspended.
298  *
299  * NB: input_buf is ignored; it is likely to be a NULL pointer.
300  */
301
302 METHODDEF(boolean)
303 compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
304 {
305   j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
306   c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
307   /* JDIMENSION MCU_col_num; */  /* index of current MCU within row */
308   /* JDIMENSION MCU_count; */  /* number of MCUs encoded */
309   int comp, ci /* , yoffset */ ;
310   JSAMPARRAY buffer[MAX_COMPONENTS];
311   jpeg_component_info *compptr;
312   (void)input_buf;
313
314   /* Align the virtual buffers for the components used in this scan.
315    * NB: during first pass, this is safe only because the buffers will
316    * already be aligned properly, so jmemmgr.c won't need to do any I/O.
317    */
318   for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
319     compptr = cinfo->cur_comp_info[comp];
320     ci = compptr->component_index;
321     buffer[ci] = (*cinfo->mem->access_virt_sarray)
322       ((j_common_ptr) cinfo, diff->whole_image[ci],
323        diff->iMCU_row_num * compptr->v_samp_factor,
324        (JDIMENSION) compptr->v_samp_factor, FALSE);
325   }
326
327   return compress_data(cinfo, buffer);
328 }
329
330 #endif /* FULL_SAMP_BUFFER_SUPPORTED */
331
332
333 /*
334  * Initialize difference buffer controller.
335  */
336
337 GLOBAL(void)
338 jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer)
339 {
340   j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
341   c_diff_ptr diff;
342   int ci, row;
343   jpeg_component_info *compptr;
344
345   diff = (c_diff_ptr)
346     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
347         SIZEOF(c_diff_controller));
348   losslsc->diff_private = (void *) diff;
349   losslsc->diff_start_pass = start_pass_diff;
350
351   /* Create the prediction row buffers. */
352   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
353        ci++, compptr++) {
354     diff->cur_row[ci] = *(*cinfo->mem->alloc_sarray)
355       ((j_common_ptr) cinfo, JPOOL_IMAGE,
356        (JDIMENSION) jround_up((long) compptr->width_in_data_units,
357             (long) compptr->h_samp_factor),
358        (JDIMENSION) 1);
359     diff->prev_row[ci] = *(*cinfo->mem->alloc_sarray)
360       ((j_common_ptr) cinfo, JPOOL_IMAGE,
361        (JDIMENSION) jround_up((long) compptr->width_in_data_units,
362             (long) compptr->h_samp_factor),
363        (JDIMENSION) 1);
364   }
365
366   /* Create the difference buffer. */
367   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
368        ci++, compptr++) {
369     diff->diff_buf[ci] = (*cinfo->mem->alloc_darray)
370       ((j_common_ptr) cinfo, JPOOL_IMAGE,
371        (JDIMENSION) jround_up((long) compptr->width_in_data_units,
372             (long) compptr->h_samp_factor),
373        (JDIMENSION) compptr->v_samp_factor);
374     /* Prefill difference rows with zeros.  We do this because only actual
375      * data is placed in the buffers during prediction/differencing, leaving
376      * any dummy differences at the right edge as zeros, which will encode
377      * to the smallest amount of data.
378      */
379     for (row = 0; row < compptr->v_samp_factor; row++)
380       MEMZERO(diff->diff_buf[ci][row],
381         jround_up((long) compptr->width_in_data_units,
382       (long) compptr->h_samp_factor) * SIZEOF(JDIFF));
383   }
384
385   /* Create the sample buffer. */
386   if (need_full_buffer) {
387 #ifdef FULL_SAMP_BUFFER_SUPPORTED
388     /* Allocate a full-image virtual array for each component, */
389     /* padded to a multiple of samp_factor differences in each direction. */
390     int ci;
391     jpeg_component_info *compptr;
392
393     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
394    ci++, compptr++) {
395       diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
396   ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
397    (JDIMENSION) jround_up((long) compptr->width_in_data_units,
398         (long) compptr->h_samp_factor),
399    (JDIMENSION) jround_up((long) compptr->height_in_data_units,
400         (long) compptr->v_samp_factor),
401    (JDIMENSION) compptr->v_samp_factor);
402     }
403 #else
404     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
405 #endif
406   } else
407     diff->whole_image[0] = NULL; /* flag for no virtual arrays */
408 }
409
410 #endif /* C_LOSSLESS_SUPPORTED */