tor-browser

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

jdlhuff.c (10030B)


      1 /*
      2 * jdlhuff.c
      3 *
      4 * This file was part of the Independent JPEG Group's software:
      5 * Copyright (C) 1991-1997, 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 Huffman entropy decoding routines for lossless JPEG.
     14 *
     15 * Much of the complexity here has to do with supporting input suspension.
     16 * If the data source module demands suspension, we want to be able to back
     17 * up to the start of the current MCU.  To do this, we copy state variables
     18 * into local working storage, and update them back to the permanent
     19 * storage only upon successful completion of an MCU.
     20 */
     21 
     22 #define JPEG_INTERNALS
     23 #include "jinclude.h"
     24 #include "jpeglib.h"
     25 #include "jlossls.h"            /* Private declarations for lossless codec */
     26 #include "jdhuff.h"             /* Declarations shared with jd*huff.c */
     27 
     28 
     29 #ifdef D_LOSSLESS_SUPPORTED
     30 
     31 typedef struct {
     32  int ci, yoffset, MCU_width;
     33 } lhd_output_ptr_info;
     34 
     35 /*
     36 * Expanded entropy decoder object for Huffman decoding in lossless mode.
     37 */
     38 
     39 typedef struct {
     40  struct jpeg_entropy_decoder pub; /* public fields */
     41 
     42  /* These fields are loaded into local variables at start of each MCU.
     43   * In case of suspension, we exit WITHOUT updating them.
     44   */
     45  bitread_perm_state bitstate;  /* Bit buffer at start of MCU */
     46 
     47  /* Pointers to derived tables (these workspaces have image lifespan) */
     48  d_derived_tbl *derived_tbls[NUM_HUFF_TBLS];
     49 
     50  /* Precalculated info set up by start_pass for use in decode_mcus: */
     51 
     52  /* Pointers to derived tables to be used for each data unit within an MCU */
     53  d_derived_tbl *cur_tbls[D_MAX_BLOCKS_IN_MCU];
     54 
     55  /* Pointers to the proper output difference row for each group of data units
     56   * within an MCU.  For each component, there are Vi groups of Hi data units.
     57   */
     58  JDIFFROW output_ptr[D_MAX_BLOCKS_IN_MCU];
     59 
     60  /* Number of output pointers in use for the current MCU.  This is the sum
     61   * of all Vi in the MCU.
     62   */
     63  int num_output_ptrs;
     64 
     65  /* Information used for positioning the output pointers within the output
     66   * difference rows.
     67   */
     68  lhd_output_ptr_info output_ptr_info[D_MAX_BLOCKS_IN_MCU];
     69 
     70  /* Index of the proper output pointer for each data unit within an MCU */
     71  int output_ptr_index[D_MAX_BLOCKS_IN_MCU];
     72 
     73 } lhuff_entropy_decoder;
     74 
     75 typedef lhuff_entropy_decoder *lhuff_entropy_ptr;
     76 
     77 
     78 /*
     79 * Initialize for a Huffman-compressed scan.
     80 */
     81 
     82 METHODDEF(void)
     83 start_pass_lhuff_decoder(j_decompress_ptr cinfo)
     84 {
     85  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy;
     86  int ci, dctbl, sampn, ptrn, yoffset, xoffset;
     87  jpeg_component_info *compptr;
     88 
     89  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
     90    compptr = cinfo->cur_comp_info[ci];
     91    dctbl = compptr->dc_tbl_no;
     92    /* Make sure requested tables are present */
     93    if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS ||
     94        cinfo->dc_huff_tbl_ptrs[dctbl] == NULL)
     95      ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
     96    /* Compute derived values for Huffman tables */
     97    /* We may do this more than once for a table, but it's not expensive */
     98    jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
     99                            &entropy->derived_tbls[dctbl]);
    100  }
    101 
    102  /* Precalculate decoding info for each sample in an MCU of this scan */
    103  for (sampn = 0, ptrn = 0; sampn < cinfo->blocks_in_MCU;) {
    104    compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]];
    105    ci = compptr->component_index;
    106    for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) {
    107      /* Precalculate the setup info for each output pointer */
    108      entropy->output_ptr_info[ptrn].ci = ci;
    109      entropy->output_ptr_info[ptrn].yoffset = yoffset;
    110      entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width;
    111      for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) {
    112        /* Precalculate the output pointer index for each sample */
    113        entropy->output_ptr_index[sampn] = ptrn;
    114        /* Precalculate which table to use for each sample */
    115        entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no];
    116      }
    117    }
    118  }
    119  entropy->num_output_ptrs = ptrn;
    120 
    121  /* Initialize bitread state variables */
    122  entropy->bitstate.bits_left = 0;
    123  entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
    124  entropy->pub.insufficient_data = FALSE;
    125 }
    126 
    127 
    128 /*
    129 * Figure F.12: extend sign bit.
    130 * On some machines, a shift and add will be faster than a table lookup.
    131 */
    132 
    133 #define AVOID_TABLES
    134 #ifdef AVOID_TABLES
    135 
    136 #define NEG_1  ((unsigned int)-1)
    137 #define HUFF_EXTEND(x, s) \
    138  ((x) + ((((x) - (1 << ((s) - 1))) >> 31) & (((NEG_1) << (s)) + 1)))
    139 
    140 #else
    141 
    142 #define HUFF_EXTEND(x, s) \
    143  ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
    144 
    145 static const int extend_test[16] = {   /* entry n is 2**(n-1) */
    146  0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
    147  0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
    148 };
    149 
    150 static const int extend_offset[16] = { /* entry n is (-1 << n) + 1 */
    151  0, ((-1) << 1) + 1, ((-1) << 2) + 1, ((-1) << 3) + 1, ((-1) << 4) + 1,
    152  ((-1) << 5) + 1, ((-1) << 6) + 1, ((-1) << 7) + 1, ((-1) << 8) + 1,
    153  ((-1) << 9) + 1, ((-1) << 10) + 1, ((-1) << 11) + 1, ((-1) << 12) + 1,
    154  ((-1) << 13) + 1, ((-1) << 14) + 1, ((-1) << 15) + 1
    155 };
    156 
    157 #endif /* AVOID_TABLES */
    158 
    159 
    160 /*
    161 * Check for a restart marker & resynchronize decoder.
    162 * Returns FALSE if must suspend.
    163 */
    164 
    165 LOCAL(boolean)
    166 process_restart(j_decompress_ptr cinfo)
    167 {
    168  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy;
    169 
    170  /* Throw away any unused bits remaining in bit buffer; */
    171  /* include any full bytes in next_marker's count of discarded bytes */
    172  cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
    173  entropy->bitstate.bits_left = 0;
    174 
    175  /* Advance past the RSTn marker */
    176  if (!(*cinfo->marker->read_restart_marker) (cinfo))
    177    return FALSE;
    178 
    179  /* Reset out-of-data flag, unless read_restart_marker left us smack up
    180   * against a marker.  In that case we will end up treating the next data
    181   * segment as empty, and we can avoid producing bogus output pixels by
    182   * leaving the flag set.
    183   */
    184  if (cinfo->unread_marker == 0)
    185    entropy->pub.insufficient_data = FALSE;
    186 
    187  return TRUE;
    188 }
    189 
    190 
    191 /*
    192 * Decode and return nMCU MCUs' worth of Huffman-compressed differences.
    193 * Each MCU is also disassembled and placed accordingly in diff_buf.
    194 *
    195 * MCU_col_num specifies the column of the first MCU being requested within
    196 * the MCU row.  This tells us where to position the output row pointers in
    197 * diff_buf.
    198 *
    199 * Returns the number of MCUs decoded.  This may be less than nMCU MCUs if
    200 * data source requested suspension.  In that case no changes have been made
    201 * to permanent state.  (Exception: some output differences may already have
    202 * been assigned.  This is harmless for this module, since we'll just
    203 * re-assign them on the next call.)
    204 */
    205 
    206 METHODDEF(JDIMENSION)
    207 decode_mcus(j_decompress_ptr cinfo, JDIFFIMAGE diff_buf,
    208            JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU)
    209 {
    210  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy;
    211  int sampn, ci, yoffset, MCU_width, ptrn;
    212  JDIMENSION mcu_num;
    213  BITREAD_STATE_VARS;
    214 
    215  /* Set output pointer locations based on MCU_col_num */
    216  for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) {
    217    ci = entropy->output_ptr_info[ptrn].ci;
    218    yoffset = entropy->output_ptr_info[ptrn].yoffset;
    219    MCU_width = entropy->output_ptr_info[ptrn].MCU_width;
    220    entropy->output_ptr[ptrn] =
    221      diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
    222  }
    223 
    224  /*
    225   * If we've run out of data, zero out the buffers and return.
    226   * By resetting the undifferencer, the output samples will be CENTERJSAMPLE.
    227   *
    228   * NB: We should find a way to do this without interacting with the
    229   * undifferencer module directly.
    230   */
    231  if (entropy->pub.insufficient_data) {
    232    for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++)
    233      jzero_far((void FAR *)entropy->output_ptr[ptrn],
    234                nMCU * entropy->output_ptr_info[ptrn].MCU_width *
    235                sizeof(JDIFF));
    236 
    237    (*cinfo->idct->start_pass) (cinfo);
    238 
    239  } else {
    240 
    241    /* Load up working state */
    242    BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
    243 
    244    /* Outer loop handles the number of MCUs requested */
    245 
    246    for (mcu_num = 0; mcu_num < nMCU; mcu_num++) {
    247 
    248      /* Inner loop handles the samples in the MCU */
    249      for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) {
    250        d_derived_tbl *dctbl = entropy->cur_tbls[sampn];
    251        register int s, r;
    252 
    253        /* Section H.2.2: decode the sample difference */
    254        HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1);
    255        if (s) {
    256          if (s == 16)  /* special case: always output 32768 */
    257            s = 32768;
    258          else {        /* normal case: fetch subsequent bits */
    259            CHECK_BIT_BUFFER(br_state, s, return mcu_num);
    260            r = GET_BITS(s);
    261            s = HUFF_EXTEND(r, s);
    262          }
    263        }
    264 
    265        /* Output the sample difference */
    266        *entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF)s;
    267      }
    268 
    269      /* Completed MCU, so update state */
    270      BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
    271    }
    272  }
    273 
    274 return nMCU;
    275 }
    276 
    277 
    278 /*
    279 * Module initialization routine for lossless mode Huffman entropy decoding.
    280 */
    281 
    282 GLOBAL(void)
    283 jinit_lhuff_decoder(j_decompress_ptr cinfo)
    284 {
    285  lhuff_entropy_ptr entropy;
    286  int i;
    287 
    288  entropy = (lhuff_entropy_ptr)
    289    (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
    290                                sizeof(lhuff_entropy_decoder));
    291  cinfo->entropy = (struct jpeg_entropy_decoder *)entropy;
    292  entropy->pub.start_pass = start_pass_lhuff_decoder;
    293  entropy->pub.decode_mcus = decode_mcus;
    294  entropy->pub.process_restart = process_restart;
    295 
    296  /* Mark tables unallocated */
    297  for (i = 0; i < NUM_HUFF_TBLS; i++) {
    298    entropy->derived_tbls[i] = NULL;
    299  }
    300 }
    301 
    302 #endif /* D_LOSSLESS_SUPPORTED */