1 /*
2 * jcpred.c
3 *
4 * Copyright (C) 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 sample differencing for lossless JPEG.
9 *
10 * In order to avoid paying the performance penalty of having to check the
11 * predictor being used and the row being processed for each call of the
12 * undifferencer, and to promote optimization, we have separate differencing
13 * functions for each case.
14 *
15 * We are able to avoid duplicating source code by implementing the predictors
16 * and differencers as macros. Each of the differencing functions are
17 * simply wrappers around a DIFFERENCE macro with the appropriate PREDICTOR
18 * macro passed as an argument.
19 */
20
21 #define JPEG_INTERNALS
22 #include "jinclude.h"
23 #include "jpeglib.h"
24 #include "jlossls.h" /* Private declarations for lossless codec */
25
26
27 #ifdef C_LOSSLESS_SUPPORTED
28
29 /* Private predictor object */
30
31 typedef struct {
32 /* MCU-rows left in the restart interval for each component */
33 unsigned int restart_rows_to_go[MAX_COMPONENTS];
34 } c_predictor;
35
36 typedef c_predictor * c_pred_ptr;
37
38 /* Forward declarations */
39 LOCAL(void) reset_predictor
40 JPP((j_compress_ptr cinfo, int ci));
41 METHODDEF(void) start_pass
42 JPP((j_compress_ptr cinfo));
43
44
45 /* Predictor for the first column of the first row: 2^(P-Pt-1) */
46 #define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1))
47
48 /* Predictor for the first column of the remaining rows: Rb */
49 #define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0])
50
51
52 /*
53 * 1-Dimensional differencer routine.
54 *
55 * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR
56 * is used as the special case predictor for the first column, which must be
57 * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples
58 * use PREDICTOR1.
59 */
60
61 #define DIFFERENCE_1D(INITIAL_PREDICTOR) \
62 j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \
63 c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \
64 boolean restart = FALSE; \
65 unsigned int xindex; \
66 int samp, Ra; \
67 \
68 samp = GETJSAMPLE(input_buf[0]); \
69 diff_buf[0] = samp - INITIAL_PREDICTOR; \
70 \
71 for (xindex = 1; xindex < width; xindex++) { \
72 Ra = samp; \
73 samp = GETJSAMPLE(input_buf[xindex]); \
74 diff_buf[xindex] = samp - PREDICTOR1; \
75 } \
76 \
77 /* Account for restart interval (no-op if not using restarts) */ \
78 if (cinfo->restart_interval) { \
79 if (--(pred->restart_rows_to_go[ci]) == 0) { \
80 reset_predictor(cinfo, ci); \
81 restart = TRUE; \
82 } \
83 }
84
85
86 /*
87 * 2-Dimensional differencer routine.
88 *
89 * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is
90 * used as the special case predictor for the first column. The remaining
91 * samples use PREDICTOR, which is a function of Ra, Rb, Rc.
92 *
93 * Because prev_row and output_buf may point to the same storage area (in an
94 * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc
95 * before writing the current reconstructed sample value into output_buf.
96 */
97
98 #define DIFFERENCE_2D(PREDICTOR) \
99 j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \
100 c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \
101 unsigned int xindex; \
102 int samp, Ra, Rb, Rc; \
103 \
104 Rb = GETJSAMPLE(prev_row[0]); \
105 samp = GETJSAMPLE(input_buf[0]); \
106 diff_buf[0] = samp - PREDICTOR2; \
107 \
108 for (xindex = 1; xindex < width; xindex++) { \
109 Rc = Rb; \
110 Rb = GETJSAMPLE(prev_row[xindex]); \
111 Ra = samp; \
112 samp = GETJSAMPLE(input_buf[xindex]); \
113 diff_buf[xindex] = samp - PREDICTOR; \
114 } \
115 \
116 /* Account for restart interval (no-op if not using restarts) */ \
117 if (cinfo->restart_interval) { \
118 if (--pred->restart_rows_to_go[ci] == 0) \
119 reset_predictor(cinfo, ci); \
120 }
121
122
123 /*
124 * Differencers for the all rows but the first in a scan or restart interval.
125 * The first sample in the row is differenced using the vertical
126 * predictor (2). The rest of the samples are differenced using the
127 * predictor specified in the scan header.
128 */
129
130 METHODDEF(void)
jpeg_difference1(j_compress_ptr cinfo,int ci,JSAMPROW input_buf,JSAMPROW prev_row,JDIFFROW diff_buf,JDIMENSION width)131 jpeg_difference1(j_compress_ptr cinfo, int ci,
132 JSAMPROW input_buf, JSAMPROW prev_row,
133 JDIFFROW diff_buf, JDIMENSION width)
134 {
135 DIFFERENCE_1D(INITIAL_PREDICTOR2);
136 }
137
138 METHODDEF(void)
jpeg_difference2(j_compress_ptr cinfo,int ci,JSAMPROW input_buf,JSAMPROW prev_row,JDIFFROW diff_buf,JDIMENSION width)139 jpeg_difference2(j_compress_ptr cinfo, int ci,
140 JSAMPROW input_buf, JSAMPROW prev_row,
141 JDIFFROW diff_buf, JDIMENSION width)
142 {
143 DIFFERENCE_2D(PREDICTOR2);
144 }
145
146 METHODDEF(void)
jpeg_difference3(j_compress_ptr cinfo,int ci,JSAMPROW input_buf,JSAMPROW prev_row,JDIFFROW diff_buf,JDIMENSION width)147 jpeg_difference3(j_compress_ptr cinfo, int ci,
148 JSAMPROW input_buf, JSAMPROW prev_row,
149 JDIFFROW diff_buf, JDIMENSION width)
150 {
151 DIFFERENCE_2D(PREDICTOR3);
152 }
153
154 METHODDEF(void)
jpeg_difference4(j_compress_ptr cinfo,int ci,JSAMPROW input_buf,JSAMPROW prev_row,JDIFFROW diff_buf,JDIMENSION width)155 jpeg_difference4(j_compress_ptr cinfo, int ci,
156 JSAMPROW input_buf, JSAMPROW prev_row,
157 JDIFFROW diff_buf, JDIMENSION width)
158 {
159 DIFFERENCE_2D(PREDICTOR4);
160 }
161
162 METHODDEF(void)
jpeg_difference5(j_compress_ptr cinfo,int ci,JSAMPROW input_buf,JSAMPROW prev_row,JDIFFROW diff_buf,JDIMENSION width)163 jpeg_difference5(j_compress_ptr cinfo, int ci,
164 JSAMPROW input_buf, JSAMPROW prev_row,
165 JDIFFROW diff_buf, JDIMENSION width)
166 {
167 SHIFT_TEMPS
168 DIFFERENCE_2D(PREDICTOR5);
169 }
170
171 METHODDEF(void)
jpeg_difference6(j_compress_ptr cinfo,int ci,JSAMPROW input_buf,JSAMPROW prev_row,JDIFFROW diff_buf,JDIMENSION width)172 jpeg_difference6(j_compress_ptr cinfo, int ci,
173 JSAMPROW input_buf, JSAMPROW prev_row,
174 JDIFFROW diff_buf, JDIMENSION width)
175 {
176 SHIFT_TEMPS
177 DIFFERENCE_2D(PREDICTOR6);
178 }
179
180 METHODDEF(void)
jpeg_difference7(j_compress_ptr cinfo,int ci,JSAMPROW input_buf,JSAMPROW prev_row,JDIFFROW diff_buf,JDIMENSION width)181 jpeg_difference7(j_compress_ptr cinfo, int ci,
182 JSAMPROW input_buf, JSAMPROW prev_row,
183 JDIFFROW diff_buf, JDIMENSION width)
184 {
185 SHIFT_TEMPS
186 DIFFERENCE_2D(PREDICTOR7);
187 }
188
189
190 /*
191 * Differencer for the first row in a scan or restart interval. The first
192 * sample in the row is differenced using the special predictor constant
193 * x=2^(P-Pt-1). The rest of the samples are differenced using the
194 * 1-D horizontal predictor (1).
195 */
196
197 METHODDEF(void)
jpeg_difference_first_row(j_compress_ptr cinfo,int ci,JSAMPROW input_buf,JSAMPROW prev_row,JDIFFROW diff_buf,JDIMENSION width)198 jpeg_difference_first_row(j_compress_ptr cinfo, int ci,
199 JSAMPROW input_buf, JSAMPROW prev_row,
200 JDIFFROW diff_buf, JDIMENSION width)
201 {
202 DIFFERENCE_1D(INITIAL_PREDICTORx);
203 (void)prev_row;
204
205 /*
206 * Now that we have differenced the first row, we want to use the
207 * differencer which corresponds to the predictor specified in the
208 * scan header.
209 *
210 * Note that we don't to do this if we have just reset the predictor
211 * for a new restart interval.
212 */
213 if (!restart) {
214 switch (cinfo->Ss) {
215 case 1:
216 losslsc->predict_difference[ci] = jpeg_difference1;
217 break;
218 case 2:
219 losslsc->predict_difference[ci] = jpeg_difference2;
220 break;
221 case 3:
222 losslsc->predict_difference[ci] = jpeg_difference3;
223 break;
224 case 4:
225 losslsc->predict_difference[ci] = jpeg_difference4;
226 break;
227 case 5:
228 losslsc->predict_difference[ci] = jpeg_difference5;
229 break;
230 case 6:
231 losslsc->predict_difference[ci] = jpeg_difference6;
232 break;
233 case 7:
234 losslsc->predict_difference[ci] = jpeg_difference7;
235 break;
236 }
237 }
238 }
239
240 /*
241 * Reset predictor at the start of a pass or restart interval.
242 */
243
244 LOCAL(void)
reset_predictor(j_compress_ptr cinfo,int ci)245 reset_predictor (j_compress_ptr cinfo, int ci)
246 {
247 j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
248 c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private;
249
250 /* Initialize restart counter */
251 pred->restart_rows_to_go[ci] =
252 cinfo->restart_interval / cinfo->MCUs_per_row;
253
254 /* Set difference function to first row function */
255 losslsc->predict_difference[ci] = jpeg_difference_first_row;
256 }
257
258
259 /*
260 * Initialize for an input processing pass.
261 */
262
263 METHODDEF(void)
start_pass(j_compress_ptr cinfo)264 start_pass (j_compress_ptr cinfo)
265 {
266 /* j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; */
267 /* c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; */
268 int ci;
269
270 /* Check that the restart interval is an integer multiple of the number
271 * of MCU in an MCU-row.
272 */
273 if (cinfo->restart_interval % cinfo->MCUs_per_row != 0)
274 ERREXIT2(cinfo, JERR_BAD_RESTART,
275 cinfo->restart_interval, cinfo->MCUs_per_row);
276
277 /* Set predictors for start of pass */
278 for (ci = 0; ci < cinfo->num_components; ci++)
279 reset_predictor(cinfo, ci);
280 }
281
282
283 /*
284 * Module initialization routine for the differencer.
285 */
286
287 GLOBAL(void)
jinit_differencer(j_compress_ptr cinfo)288 jinit_differencer (j_compress_ptr cinfo)
289 {
290 j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
291 c_pred_ptr pred;
292
293 pred = (c_pred_ptr)
294 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
295 SIZEOF(c_predictor));
296 losslsc->pred_private = (void *) pred;
297 losslsc->predict_start_pass = start_pass;
298 }
299
300 #endif /* C_LOSSLESS_SUPPORTED */
301