/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 | 29.0M |   lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; \ | 
| 61 | 29.0M |   boolean restart = FALSE; \ | 
| 62 | 29.0M |   int samp, Ra; \ | 
| 63 | 29.0M |   \ | 
| 64 | 29.0M |   samp = *input_buf++; \ | 
| 65 | 29.0M |   *diff_buf++ = samp - INITIAL_PREDICTOR; \ | 
| 66 | 29.0M |   \ | 
| 67 | 158M |   while (--width) { \ | 
| 68 | 129M |     Ra = samp; \ | 
| 69 | 129M |     samp = *input_buf++; \ | 
| 70 | 129M |     *diff_buf++ = samp - PREDICTOR1; \ | 
| 71 | 129M |   } \ | 
| 72 | 29.0M |   \ | 
| 73 | 29.0M |   /* Account for restart interval (no-op if not using restarts) */ \ | 
| 74 | 29.0M |   if (cinfo->restart_interval) { \ | 
| 75 | 29.0M |     if (--(losslessc->restart_rows_to_go[ci]) == 0) { \ | 
| 76 | 29.0M |       reset_predictor(cinfo, ci); \ | 
| 77 | 29.0M |       restart = TRUE; \ | 
| 78 | 29.0M |     } \ | 
| 79 | 29.0M |   } | 
| 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 | 53.2M |   lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; \ | 
| 96 | 53.2M |   int samp, Ra, Rb, Rc; \ | 
| 97 | 53.2M |   \ | 
| 98 | 53.2M |   Rb = *prev_row++; \ | 
| 99 | 53.2M |   samp = *input_buf++; \ | 
| 100 | 53.2M |   *diff_buf++ = samp - PREDICTOR2; \ | 
| 101 | 53.2M |   \ | 
| 102 | 174M |   while (--width) { \ | 
| 103 | 121M |     Rc = Rb; \ | 
| 104 | 121M |     Rb = *prev_row++; \ | 
| 105 | 121M |     Ra = samp; \ | 
| 106 | 121M |     samp = *input_buf++; \ | 
| 107 | 121M |     *diff_buf++ = samp - PREDICTOR; \ | 
| 108 | 121M |   } \ | 
| 109 | 53.2M |   \ | 
| 110 | 53.2M |   /* Account for restart interval (no-op if not using restarts) */ \ | 
| 111 | 53.2M |   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 | 12.4M | { | 
| 138 | 12.4M |   DIFFERENCE_2D(PREDICTOR2); | 
| 139 | 12.4M |   (void)(Ra); | 
| 140 | 12.4M |   (void)(Rc); | 
| 141 | 12.4M | } | 
| 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 | 12.4M | { | 
| 148 | 12.4M |   DIFFERENCE_2D(PREDICTOR3); | 
| 149 | 12.4M |   (void)(Ra); | 
| 150 | 12.4M | } | 
| 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 | 12.4M | { | 
| 157 | 12.4M |   DIFFERENCE_2D(PREDICTOR4); | 
| 158 | 12.4M | } | 
| 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 | 12.4M | { | 
| 165 | 12.4M |   DIFFERENCE_2D(PREDICTOR5); | 
| 166 | 12.4M | } | 
| 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 | 3.46M | { | 
| 173 | 3.46M |   DIFFERENCE_2D(PREDICTOR6); | 
| 174 | 3.46M | } | 
| 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 | 29.0M | { | 
| 198 | 29.0M |   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 | 29.0M |   if (!restart) { | 
| 209 | 16.1k |     switch (cinfo->Ss) { | 
| 210 | 0 |     case 1: | 
| 211 | 0 |       losslessc->predict_difference[ci] = jpeg_difference1; | 
| 212 | 0 |       break; | 
| 213 | 3.76k |     case 2: | 
| 214 | 3.76k |       losslessc->predict_difference[ci] = jpeg_difference2; | 
| 215 | 3.76k |       break; | 
| 216 | 3.76k |     case 3: | 
| 217 | 3.76k |       losslessc->predict_difference[ci] = jpeg_difference3; | 
| 218 | 3.76k |       break; | 
| 219 | 3.76k |     case 4: | 
| 220 | 3.76k |       losslessc->predict_difference[ci] = jpeg_difference4; | 
| 221 | 3.76k |       break; | 
| 222 | 3.76k |     case 5: | 
| 223 | 3.76k |       losslessc->predict_difference[ci] = jpeg_difference5; | 
| 224 | 3.76k |       break; | 
| 225 | 1.07k |     case 6: | 
| 226 | 1.07k |       losslessc->predict_difference[ci] = jpeg_difference6; | 
| 227 | 1.07k |       break; | 
| 228 | 0 |     case 7: | 
| 229 | 0 |       losslessc->predict_difference[ci] = jpeg_difference7; | 
| 230 | 0 |       break; | 
| 231 | 16.1k |     } | 
| 232 | 16.1k |   } | 
| 233 | 29.0M | } | 
| 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 | 29.0M | { | 
| 242 | 29.0M |   lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; | 
| 243 |  |  | 
| 244 |  |   /* Initialize restart counter */ | 
| 245 | 29.0M |   losslessc->restart_rows_to_go[ci] = | 
| 246 | 29.0M |     cinfo->restart_interval / cinfo->MCUs_per_row; | 
| 247 |  |  | 
| 248 |  |   /* Set difference function to first row function */ | 
| 249 | 29.0M |   losslessc->predict_difference[ci] = jpeg_difference_first_row; | 
| 250 | 29.0M | } | 
| 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 | 53.2M | { | 
| 259 | 215M |   do { | 
| 260 | 215M |     *output_buf++ = (_JSAMPLE)RIGHT_SHIFT(*input_buf++, cinfo->Al); | 
| 261 | 215M |   } while (--width); | 
| 262 | 53.2M | } | 
| 263 |  |  | 
| 264 |  |  | 
| 265 |  | METHODDEF(void) | 
| 266 |  | noscale(j_compress_ptr cinfo, | 
| 267 |  |         _JSAMPROW input_buf, _JSAMPROW output_buf, JDIMENSION width) | 
| 268 | 29.0M | { | 
| 269 | 29.0M |   memcpy(output_buf, input_buf, width * sizeof(_JSAMPLE)); | 
| 270 | 29.0M | } | 
| 271 |  |  | 
| 272 |  |  | 
| 273 |  | /* | 
| 274 |  |  * Initialize for a processing pass. | 
| 275 |  |  */ | 
| 276 |  |  | 
| 277 |  | METHODDEF(void) | 
| 278 |  | start_pass_lossless(j_compress_ptr cinfo) | 
| 279 | 8.61k | { | 
| 280 | 8.61k |   lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; | 
| 281 | 8.61k |   int ci; | 
| 282 |  |  | 
| 283 |  |   /* Set scaler function based on Pt */ | 
| 284 | 8.61k |   if (cinfo->Al) | 
| 285 | 6.09k |     losslessc->scaler_scale = simple_downscale; | 
| 286 | 2.51k |   else | 
| 287 | 2.51k |     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 | 8.61k |   if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) | 
| 293 | 0 |     ERREXIT2(cinfo, JERR_BAD_RESTART, | 
| 294 | 8.61k |              cinfo->restart_interval, cinfo->MCUs_per_row); | 
| 295 |  |  | 
| 296 |  |   /* Set predictors for start of pass */ | 
| 297 | 33.5k |   for (ci = 0; ci < cinfo->num_components; ci++) | 
| 298 | 24.9k |     reset_predictor(cinfo, ci); | 
| 299 | 8.61k | } | 
| 300 |  |  | 
| 301 |  |  | 
| 302 |  | /* | 
| 303 |  |  * Initialize the lossless compressor. | 
| 304 |  |  */ | 
| 305 |  |  | 
| 306 |  | GLOBAL(void) | 
| 307 |  | _jinit_lossless_compressor(j_compress_ptr cinfo) | 
| 308 | 4.30k | { | 
| 309 | 4.30k |   lossless_comp_ptr losslessc; | 
| 310 |  |  | 
| 311 |  |   /* Create subobject in permanent pool */ | 
| 312 | 4.30k |   losslessc = (lossless_comp_ptr) | 
| 313 | 4.30k |     (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, | 
| 314 | 4.30k |                                 sizeof(jpeg_lossless_compressor)); | 
| 315 | 4.30k |   cinfo->fdct = (struct jpeg_forward_dct *)losslessc; | 
| 316 | 4.30k |   losslessc->pub.start_pass = start_pass_lossless; | 
| 317 | 4.30k | } Unexecuted instantiation: j12init_lossless_compressorUnexecuted instantiation: j16init_lossless_compressorjinit_lossless_compressor| Line | Count | Source |  | 308 | 4.30k | { |  | 309 | 4.30k |   lossless_comp_ptr losslessc; |  | 310 |  |  |  | 311 |  |   /* Create subobject in permanent pool */ |  | 312 | 4.30k |   losslessc = (lossless_comp_ptr) |  | 313 | 4.30k |     (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, |  | 314 | 4.30k |                                 sizeof(jpeg_lossless_compressor)); |  | 315 | 4.30k |   cinfo->fdct = (struct jpeg_forward_dct *)losslessc; |  | 316 | 4.30k |   losslessc->pub.start_pass = start_pass_lossless; |  | 317 | 4.30k | } | 
 | 
| 318 |  |  | 
| 319 |  | #endif /* C_LOSSLESS_SUPPORTED */ |