tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

jclossls.c (8895B)


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