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