tor-browser

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

jdlossls.c (8522B)


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