1 /*
2 * jdpred.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 undifferencing (reconstruction) 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 undifferencing
13 * functions for each case.
14 *
15 * We are able to avoid duplicating source code by implementing the predictors
16 * and undifferencers as macros. Each of the undifferencing functions are
17 * simply wrappers around an UNDIFFERENCE macro with the appropriate PREDICTOR
18 * macro passed as an argument.
19 */
20
21 #define JPEG_INTERNALS
22 #include "jinclude8.h"
23 #include "jpeglib8.h"
24 #include "jlossls8.h" /* Private declarations for lossless codec */
25
26
27 #ifdef D_LOSSLESS_SUPPORTED
28
29 /* Predictor for the first column of the first row: 2^(P-Pt-1) */
30 #define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1))
31
32 /* Predictor for the first column of the remaining rows: Rb */
33 #define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0])
34
35
36 /*
37 * 1-Dimensional undifferencer routine.
38 *
39 * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR
40 * is used as the special case predictor for the first column, which must be
41 * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples
42 * use PREDICTOR1.
43 *
44 * The reconstructed sample is supposed to be calculated modulo 2^16, so we
45 * logically AND the result with 0xFFFF.
46 */
47
48 #define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \
49 unsigned int xindex; \
50 int Ra; \
51 \
52 Ra = (diff_buf[0] + INITIAL_PREDICTOR) & 0xFFFF; \
53 undiff_buf[0] = Ra; \
54 \
55 for (xindex = 1; xindex < width; xindex++) { \
56 Ra = (diff_buf[xindex] + PREDICTOR1) & 0xFFFF; \
57 undiff_buf[xindex] = Ra; \
58 }
59
60 /*
61 * 2-Dimensional undifferencer routine.
62 *
63 * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is
64 * used as the special case predictor for the first column. The remaining
65 * samples use PREDICTOR, which is a function of Ra, Rb, Rc.
66 *
67 * Because prev_row and output_buf may point to the same storage area (in an
68 * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc
69 * before writing the current reconstructed sample value into output_buf.
70 *
71 * The reconstructed sample is supposed to be calculated modulo 2^16, so we
72 * logically AND the result with 0xFFFF.
73 */
74
75 #define UNDIFFERENCE_2D(PREDICTOR) \
76 unsigned int xindex; \
77 int Ra, Rb, Rc; \
78 \
79 Rb = GETJSAMPLE(prev_row[0]); \
80 Ra = (diff_buf[0] + PREDICTOR2) & 0xFFFF; \
81 undiff_buf[0] = Ra; \
82 \
83 for (xindex = 1; xindex < width; xindex++) { \
84 Rc = Rb; \
85 Rb = GETJSAMPLE(prev_row[xindex]); \
86 Ra = (diff_buf[xindex] + PREDICTOR) & 0xFFFF; \
87 undiff_buf[xindex] = Ra; \
88 }
89
90 #define JPEG_UNUSED(x) ((void)x)
91
92 /*
93 * Undifferencers for the all rows but the first in a scan or restart interval.
94 * The first sample in the row is undifferenced using the vertical
95 * predictor (2). The rest of the samples are undifferenced using the
96 * predictor specified in the scan header.
97 */
98
99 METHODDEF(void)
jpeg_undifference1(j_decompress_ptr cinfo,int comp_index,const JDIFFROW diff_buf,const JDIFFROW prev_row,JDIFFROW undiff_buf,JDIMENSION width)100 jpeg_undifference1(j_decompress_ptr cinfo, int comp_index,
101 const JDIFFROW diff_buf, const JDIFFROW prev_row,
102 JDIFFROW undiff_buf, JDIMENSION width)
103 {
104 UNDIFFERENCE_1D(INITIAL_PREDICTOR2);
105 }
106
107 METHODDEF(void)
jpeg_undifference2(j_decompress_ptr cinfo,int comp_index,const JDIFFROW diff_buf,const JDIFFROW prev_row,JDIFFROW undiff_buf,JDIMENSION width)108 jpeg_undifference2(j_decompress_ptr cinfo, int comp_index,
109 const JDIFFROW diff_buf, const JDIFFROW prev_row,
110 JDIFFROW undiff_buf, JDIMENSION width)
111 {
112 UNDIFFERENCE_2D(PREDICTOR2);
113 JPEG_UNUSED(Rc);
114 JPEG_UNUSED(Rb);
115 }
116
117 METHODDEF(void)
jpeg_undifference3(j_decompress_ptr cinfo,int comp_index,const JDIFFROW diff_buf,const JDIFFROW prev_row,JDIFFROW undiff_buf,JDIMENSION width)118 jpeg_undifference3(j_decompress_ptr cinfo, int comp_index,
119 const JDIFFROW diff_buf, const JDIFFROW prev_row,
120 JDIFFROW undiff_buf, JDIMENSION width)
121 {
122 UNDIFFERENCE_2D(PREDICTOR3);
123 JPEG_UNUSED(Rc);
124 JPEG_UNUSED(Rb);
125 }
126
127 METHODDEF(void)
jpeg_undifference4(j_decompress_ptr cinfo,int comp_index,const JDIFFROW diff_buf,const JDIFFROW prev_row,JDIFFROW undiff_buf,JDIMENSION width)128 jpeg_undifference4(j_decompress_ptr cinfo, int comp_index,
129 const JDIFFROW diff_buf, const JDIFFROW prev_row,
130 JDIFFROW undiff_buf, JDIMENSION width)
131 {
132 UNDIFFERENCE_2D(PREDICTOR4);
133 JPEG_UNUSED(Rc);
134 JPEG_UNUSED(Rb);
135 }
136
137 METHODDEF(void)
jpeg_undifference5(j_decompress_ptr cinfo,int comp_index,const JDIFFROW diff_buf,const JDIFFROW prev_row,JDIFFROW undiff_buf,JDIMENSION width)138 jpeg_undifference5(j_decompress_ptr cinfo, int comp_index,
139 const JDIFFROW diff_buf, const JDIFFROW prev_row,
140 JDIFFROW undiff_buf, JDIMENSION width)
141 {
142 SHIFT_TEMPS
143 UNDIFFERENCE_2D(PREDICTOR5);
144 JPEG_UNUSED(Rc);
145 JPEG_UNUSED(Rb);
146 }
147
148 METHODDEF(void)
jpeg_undifference6(j_decompress_ptr cinfo,int comp_index,const JDIFFROW diff_buf,const JDIFFROW prev_row,JDIFFROW undiff_buf,JDIMENSION width)149 jpeg_undifference6(j_decompress_ptr cinfo, int comp_index,
150 const JDIFFROW diff_buf, const JDIFFROW prev_row,
151 JDIFFROW undiff_buf, JDIMENSION width)
152 {
153 SHIFT_TEMPS
154 UNDIFFERENCE_2D(PREDICTOR6);
155 JPEG_UNUSED(Rc);
156 JPEG_UNUSED(Rb);
157 }
158
159 METHODDEF(void)
jpeg_undifference7(j_decompress_ptr cinfo,int comp_index,const JDIFFROW diff_buf,const JDIFFROW prev_row,JDIFFROW undiff_buf,JDIMENSION width)160 jpeg_undifference7(j_decompress_ptr cinfo, int comp_index,
161 const JDIFFROW diff_buf, const JDIFFROW prev_row,
162 JDIFFROW undiff_buf, JDIMENSION width)
163 {
164 SHIFT_TEMPS
165 UNDIFFERENCE_2D(PREDICTOR7);
166 JPEG_UNUSED(Rc);
167 JPEG_UNUSED(Rb);
168 }
169
170
171 /*
172 * Undifferencer for the first row in a scan or restart interval. The first
173 * sample in the row is undifferenced using the special predictor constant
174 * x=2^(P-Pt-1). The rest of the samples are undifferenced using the
175 * 1-D horizontal predictor (1).
176 */
177
178 METHODDEF(void)
jpeg_undifference_first_row(j_decompress_ptr cinfo,int comp_index,const JDIFFROW diff_buf,JDIFFROW prev_row,JDIFFROW undiff_buf,JDIMENSION width)179 jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index,
180 const JDIFFROW diff_buf, JDIFFROW prev_row,
181 JDIFFROW undiff_buf, JDIMENSION width)
182 {
183 j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
184
185 UNDIFFERENCE_1D(INITIAL_PREDICTORx);
186
187 /*
188 * Now that we have undifferenced the first row, we want to use the
189 * undifferencer which corresponds to the predictor specified in the
190 * scan header.
191 */
192 switch (cinfo->Ss) {
193 case 1:
194 losslsd->predict_undifference[comp_index] = jpeg_undifference1;
195 break;
196 case 2:
197 losslsd->predict_undifference[comp_index] = jpeg_undifference2;
198 break;
199 case 3:
200 losslsd->predict_undifference[comp_index] = jpeg_undifference3;
201 break;
202 case 4:
203 losslsd->predict_undifference[comp_index] = jpeg_undifference4;
204 break;
205 case 5:
206 losslsd->predict_undifference[comp_index] = jpeg_undifference5;
207 break;
208 case 6:
209 losslsd->predict_undifference[comp_index] = jpeg_undifference6;
210 break;
211 case 7:
212 losslsd->predict_undifference[comp_index] = jpeg_undifference7;
213 break;
214 }
215 }
216
217
218 /*
219 * Initialize for an input processing pass.
220 */
221
222 METHODDEF(void)
predict_start_pass(j_decompress_ptr cinfo)223 predict_start_pass (j_decompress_ptr cinfo)
224 {
225 j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
226 int ci;
227
228 /* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG.
229 *
230 * Ss is the predictor selection value (psv). Legal values for sequential
231 * lossless JPEG are: 1 <= psv <= 7.
232 *
233 * Se and Ah are not used and should be zero.
234 *
235 * Al specifies the point transform (Pt). Legal values are: 0 <= Pt <= 15.
236 */
237 if (cinfo->Ss < 1 || cinfo->Ss > 7 ||
238 cinfo->Se != 0 || cinfo->Ah != 0 ||
239 cinfo->Al > 15) /* need not check for < 0 */
240 ERREXIT4(cinfo, JERR_BAD_LOSSLESS,
241 cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
242
243 /* Set undifference functions to first row function */
244 for (ci = 0; ci < cinfo->num_components; ci++)
245 losslsd->predict_undifference[ci] = jpeg_undifference_first_row;
246 }
247
248
249 /*
250 * Module initialization routine for the undifferencer.
251 */
252
253 GLOBAL(void)
jinit_undifferencer(j_decompress_ptr cinfo)254 jinit_undifferencer (j_decompress_ptr cinfo)
255 {
256 j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
257
258 losslsd->predict_start_pass = predict_start_pass;
259 losslsd->predict_process_restart = predict_start_pass;
260 }
261
262 #endif /* D_LOSSLESS_SUPPORTED */
263
264