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