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