tor-browser

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

enc_jpeg_data_reader.cc (35602B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #include "lib/jxl/jpeg/enc_jpeg_data_reader.h"
      7 
      8 #include <inttypes.h>
      9 #include <string.h>
     10 
     11 #include <algorithm>
     12 #include <string>
     13 #include <vector>
     14 
     15 #include "lib/jxl/base/common.h"
     16 #include "lib/jxl/base/printf_macros.h"
     17 #include "lib/jxl/base/status.h"
     18 #include "lib/jxl/frame_dimensions.h"
     19 #include "lib/jxl/jpeg/enc_jpeg_huffman_decode.h"
     20 #include "lib/jxl/jpeg/jpeg_data.h"
     21 
     22 namespace jxl {
     23 namespace jpeg {
     24 
     25 namespace {
     26 const int kBrunsliMaxSampling = 15;
     27 
     28 // Macros for commonly used error conditions.
     29 
     30 #define JXL_JPEG_VERIFY_LEN(n)                                \
     31  if (*pos + (n) > len) {                                     \
     32    return JXL_FAILURE("Unexpected end of input: pos=%" PRIuS \
     33                       " need=%d len=%" PRIuS,                \
     34                       *pos, static_cast<int>(n), len);       \
     35  }
     36 
     37 #define JXL_JPEG_VERIFY_INPUT(var, low, high, code)                    \
     38  if ((var) < (low) || (var) > (high)) {                               \
     39    return JXL_FAILURE("Invalid " #var ": %d", static_cast<int>(var)); \
     40  }
     41 
     42 #define JXL_JPEG_VERIFY_MARKER_END()                             \
     43  if (start_pos + marker_len != *pos) {                          \
     44    return JXL_FAILURE("Invalid marker length: declared=%" PRIuS \
     45                       " actual=%" PRIuS,                        \
     46                       marker_len, (*pos - start_pos));          \
     47  }
     48 
     49 #define JXL_JPEG_EXPECT_MARKER()                                 \
     50  if (pos + 2 > len || data[pos] != 0xff) {                      \
     51    return JXL_FAILURE(                                          \
     52        "Marker byte (0xff) expected, found: 0x%.2x pos=%" PRIuS \
     53        " len=%" PRIuS,                                          \
     54        (pos < len ? data[pos] : 0), pos, len);                  \
     55  }
     56 
     57 inline int ReadUint8(const uint8_t* data, size_t* pos) {
     58  return data[(*pos)++];
     59 }
     60 
     61 inline int ReadUint16(const uint8_t* data, size_t* pos) {
     62  int v = (data[*pos] << 8) + data[*pos + 1];
     63  *pos += 2;
     64  return v;
     65 }
     66 
     67 // Reads the Start of Frame (SOF) marker segment and fills in *jpg with the
     68 // parsed data.
     69 bool ProcessSOF(const uint8_t* data, const size_t len, JpegReadMode mode,
     70                size_t* pos, JPEGData* jpg) {
     71  if (jpg->width != 0) {
     72    return JXL_FAILURE("Duplicate SOF marker.");
     73  }
     74  const size_t start_pos = *pos;
     75  JXL_JPEG_VERIFY_LEN(8);
     76  size_t marker_len = ReadUint16(data, pos);
     77  int precision = ReadUint8(data, pos);
     78  int height = ReadUint16(data, pos);
     79  int width = ReadUint16(data, pos);
     80  int num_components = ReadUint8(data, pos);
     81  // 'jbrd' is hardcoded for 8bits:
     82  JXL_JPEG_VERIFY_INPUT(precision, 8, 8, PRECISION);
     83  JXL_JPEG_VERIFY_INPUT(height, 1, kMaxDimPixels, HEIGHT);
     84  JXL_JPEG_VERIFY_INPUT(width, 1, kMaxDimPixels, WIDTH);
     85  JXL_JPEG_VERIFY_INPUT(num_components, 1, kMaxComponents, NUMCOMP);
     86  JXL_JPEG_VERIFY_LEN(3 * num_components);
     87  jpg->height = height;
     88  jpg->width = width;
     89  jpg->components.resize(num_components);
     90 
     91  // Read sampling factors and quant table index for each component.
     92  std::vector<bool> ids_seen(256, false);
     93  int max_h_samp_factor = 1;
     94  int max_v_samp_factor = 1;
     95  for (auto& component : jpg->components) {
     96    const int id = ReadUint8(data, pos);
     97    if (ids_seen[id]) {  // (cf. section B.2.2, syntax of Ci)
     98      return JXL_FAILURE("Duplicate ID %d in SOF.", id);
     99    }
    100    ids_seen[id] = true;
    101    component.id = id;
    102    int factor = ReadUint8(data, pos);
    103    int h_samp_factor = factor >> 4;
    104    int v_samp_factor = factor & 0xf;
    105    JXL_JPEG_VERIFY_INPUT(h_samp_factor, 1, kBrunsliMaxSampling, SAMP_FACTOR);
    106    JXL_JPEG_VERIFY_INPUT(v_samp_factor, 1, kBrunsliMaxSampling, SAMP_FACTOR);
    107    component.h_samp_factor = h_samp_factor;
    108    component.v_samp_factor = v_samp_factor;
    109    component.quant_idx = ReadUint8(data, pos);
    110    max_h_samp_factor = std::max(max_h_samp_factor, h_samp_factor);
    111    max_v_samp_factor = std::max(max_v_samp_factor, v_samp_factor);
    112  }
    113 
    114  // We have checked above that none of the sampling factors are 0, so the max
    115  // sampling factors can not be 0.
    116  int MCU_rows = DivCeil(jpg->height, max_v_samp_factor * 8);
    117  int MCU_cols = DivCeil(jpg->width, max_h_samp_factor * 8);
    118  // Compute the block dimensions for each component.
    119  for (JPEGComponent& c : jpg->components) {
    120    if (max_h_samp_factor % c.h_samp_factor != 0 ||
    121        max_v_samp_factor % c.v_samp_factor != 0) {
    122      return JXL_FAILURE("Non-integral subsampling ratios.");
    123    }
    124    c.width_in_blocks = MCU_cols * c.h_samp_factor;
    125    c.height_in_blocks = MCU_rows * c.v_samp_factor;
    126    const uint64_t num_blocks =
    127        static_cast<uint64_t>(c.width_in_blocks) * c.height_in_blocks;
    128    if (mode == JpegReadMode::kReadAll) {
    129      c.coeffs.resize(num_blocks * kDCTBlockSize);
    130    }
    131  }
    132  JXL_JPEG_VERIFY_MARKER_END();
    133  return true;
    134 }
    135 
    136 // Reads the Start of Scan (SOS) marker segment and fills in *scan_info with the
    137 // parsed data.
    138 bool ProcessSOS(const uint8_t* data, const size_t len, size_t* pos,
    139                JPEGData* jpg) {
    140  const size_t start_pos = *pos;
    141  JXL_JPEG_VERIFY_LEN(3);
    142  size_t marker_len = ReadUint16(data, pos);
    143  size_t comps_in_scan = ReadUint8(data, pos);
    144  JXL_JPEG_VERIFY_INPUT(comps_in_scan, 1, jpg->components.size(),
    145                        COMPS_IN_SCAN);
    146 
    147  JPEGScanInfo scan_info;
    148  scan_info.num_components = comps_in_scan;
    149  JXL_JPEG_VERIFY_LEN(2 * comps_in_scan);
    150  std::vector<bool> ids_seen(256, false);
    151  for (size_t i = 0; i < comps_in_scan; ++i) {
    152    uint32_t id = ReadUint8(data, pos);
    153    if (ids_seen[id]) {  // (cf. section B.2.3, regarding CSj)
    154      return JXL_FAILURE("Duplicate ID %d in SOS.", id);
    155    }
    156    ids_seen[id] = true;
    157    bool found_index = false;
    158    for (size_t j = 0; j < jpg->components.size(); ++j) {
    159      if (jpg->components[j].id == id) {
    160        scan_info.components[i].comp_idx = j;
    161        found_index = true;
    162      }
    163    }
    164    if (!found_index) {
    165      return JXL_FAILURE("SOS marker: Could not find component with id %d", id);
    166    }
    167    int c = ReadUint8(data, pos);
    168    int dc_tbl_idx = c >> 4;
    169    int ac_tbl_idx = c & 0xf;
    170    JXL_JPEG_VERIFY_INPUT(dc_tbl_idx, 0, 3, HUFFMAN_INDEX);
    171    JXL_JPEG_VERIFY_INPUT(ac_tbl_idx, 0, 3, HUFFMAN_INDEX);
    172    scan_info.components[i].dc_tbl_idx = dc_tbl_idx;
    173    scan_info.components[i].ac_tbl_idx = ac_tbl_idx;
    174  }
    175  JXL_JPEG_VERIFY_LEN(3);
    176  scan_info.Ss = ReadUint8(data, pos);
    177  scan_info.Se = ReadUint8(data, pos);
    178  JXL_JPEG_VERIFY_INPUT(static_cast<int>(scan_info.Ss), 0, 63, START_OF_SCAN);
    179  JXL_JPEG_VERIFY_INPUT(scan_info.Se, scan_info.Ss, 63, END_OF_SCAN);
    180  int c = ReadUint8(data, pos);
    181  scan_info.Ah = c >> 4;
    182  scan_info.Al = c & 0xf;
    183  if (scan_info.Ah != 0 && scan_info.Al != scan_info.Ah - 1) {
    184    // section G.1.1.1.2 : Successive approximation control only improves
    185    // by one bit at a time. But it's not always respected, so we just issue
    186    // a warning.
    187    JXL_WARNING("Invalid progressive parameters: Al=%d Ah=%d", scan_info.Al,
    188                scan_info.Ah);
    189  }
    190  // Check that all the Huffman tables needed for this scan are defined.
    191  for (size_t i = 0; i < comps_in_scan; ++i) {
    192    bool found_dc_table = false;
    193    bool found_ac_table = false;
    194    for (const auto& code : jpg->huffman_code) {
    195      uint32_t slot_id = code.slot_id;
    196      if (slot_id == scan_info.components[i].dc_tbl_idx) {
    197        found_dc_table = true;
    198      } else if (slot_id == scan_info.components[i].ac_tbl_idx + 16) {
    199        found_ac_table = true;
    200      }
    201    }
    202    if (scan_info.Ss == 0 && !found_dc_table) {
    203      return JXL_FAILURE(
    204          "SOS marker: Could not find DC Huffman table with index %d",
    205          scan_info.components[i].dc_tbl_idx);
    206    }
    207    if (scan_info.Se > 0 && !found_ac_table) {
    208      return JXL_FAILURE(
    209          "SOS marker: Could not find AC Huffman table with index %d",
    210          scan_info.components[i].ac_tbl_idx);
    211    }
    212  }
    213  jpg->scan_info.push_back(scan_info);
    214  JXL_JPEG_VERIFY_MARKER_END();
    215  return true;
    216 }
    217 
    218 // Reads the Define Huffman Table (DHT) marker segment and fills in *jpg with
    219 // the parsed data. Builds the Huffman decoding table in either dc_huff_lut or
    220 // ac_huff_lut, depending on the type and solt_id of Huffman code being read.
    221 bool ProcessDHT(const uint8_t* data, const size_t len, JpegReadMode mode,
    222                std::vector<HuffmanTableEntry>* dc_huff_lut,
    223                std::vector<HuffmanTableEntry>* ac_huff_lut, size_t* pos,
    224                JPEGData* jpg) {
    225  const size_t start_pos = *pos;
    226  JXL_JPEG_VERIFY_LEN(2);
    227  size_t marker_len = ReadUint16(data, pos);
    228  if (marker_len == 2) {
    229    return JXL_FAILURE("DHT marker: no Huffman table found");
    230  }
    231  while (*pos < start_pos + marker_len) {
    232    JXL_JPEG_VERIFY_LEN(1 + kJpegHuffmanMaxBitLength);
    233    JPEGHuffmanCode huff;
    234    huff.slot_id = ReadUint8(data, pos);
    235    int huffman_index = huff.slot_id;
    236    bool is_ac_table = ((huff.slot_id & 0x10) != 0);
    237    HuffmanTableEntry* huff_lut;
    238    if (is_ac_table) {
    239      huffman_index -= 0x10;
    240      JXL_JPEG_VERIFY_INPUT(huffman_index, 0, 3, HUFFMAN_INDEX);
    241      huff_lut = &(*ac_huff_lut)[huffman_index * kJpegHuffmanLutSize];
    242    } else {
    243      JXL_JPEG_VERIFY_INPUT(huffman_index, 0, 3, HUFFMAN_INDEX);
    244      huff_lut = &(*dc_huff_lut)[huffman_index * kJpegHuffmanLutSize];
    245    }
    246    huff.counts[0] = 0;
    247    int total_count = 0;
    248    int space = 1 << kJpegHuffmanMaxBitLength;
    249    int max_depth = 1;
    250    for (size_t i = 1; i <= kJpegHuffmanMaxBitLength; ++i) {
    251      int count = ReadUint8(data, pos);
    252      if (count != 0) {
    253        max_depth = i;
    254      }
    255      huff.counts[i] = count;
    256      total_count += count;
    257      space -= count * (1 << (kJpegHuffmanMaxBitLength - i));
    258    }
    259    if (is_ac_table) {
    260      JXL_JPEG_VERIFY_INPUT(total_count, 0, kJpegHuffmanAlphabetSize,
    261                            HUFFMAN_CODE);
    262    } else {
    263      JXL_JPEG_VERIFY_INPUT(total_count, 0, kJpegDCAlphabetSize, HUFFMAN_CODE);
    264    }
    265    JXL_JPEG_VERIFY_LEN(total_count);
    266    std::vector<bool> values_seen(256, false);
    267    for (int i = 0; i < total_count; ++i) {
    268      int value = ReadUint8(data, pos);
    269      if (!is_ac_table) {
    270        JXL_JPEG_VERIFY_INPUT(value, 0, kJpegDCAlphabetSize - 1, HUFFMAN_CODE);
    271      }
    272      if (values_seen[value]) {
    273        return JXL_FAILURE("Duplicate Huffman code value %d", value);
    274      }
    275      values_seen[value] = true;
    276      huff.values[i] = value;
    277    }
    278    // Add an invalid symbol that will have the all 1 code.
    279    ++huff.counts[max_depth];
    280    huff.values[total_count] = kJpegHuffmanAlphabetSize;
    281    space -= (1 << (kJpegHuffmanMaxBitLength - max_depth));
    282    if (space < 0) {
    283      return JXL_FAILURE("Invalid Huffman code lengths.");
    284    } else if (space > 0 && huff_lut[0].value != 0xffff) {
    285      // Re-initialize the values to an invalid symbol so that we can recognize
    286      // it when reading the bit stream using a Huffman code with space > 0.
    287      for (int i = 0; i < kJpegHuffmanLutSize; ++i) {
    288        huff_lut[i].bits = 0;
    289        huff_lut[i].value = 0xffff;
    290      }
    291    }
    292    huff.is_last = (*pos == start_pos + marker_len);
    293    if (mode == JpegReadMode::kReadAll) {
    294      BuildJpegHuffmanTable(huff.counts.data(), huff.values.data(), huff_lut);
    295    }
    296    jpg->huffman_code.push_back(huff);
    297  }
    298  JXL_JPEG_VERIFY_MARKER_END();
    299  return true;
    300 }
    301 
    302 // Reads the Define Quantization Table (DQT) marker segment and fills in *jpg
    303 // with the parsed data.
    304 bool ProcessDQT(const uint8_t* data, const size_t len, size_t* pos,
    305                JPEGData* jpg) {
    306  const size_t start_pos = *pos;
    307  JXL_JPEG_VERIFY_LEN(2);
    308  size_t marker_len = ReadUint16(data, pos);
    309  if (marker_len == 2) {
    310    return JXL_FAILURE("DQT marker: no quantization table found");
    311  }
    312  while (*pos < start_pos + marker_len && jpg->quant.size() < kMaxQuantTables) {
    313    JXL_JPEG_VERIFY_LEN(1);
    314    int quant_table_index = ReadUint8(data, pos);
    315    int quant_table_precision = quant_table_index >> 4;
    316    JXL_JPEG_VERIFY_INPUT(quant_table_precision, 0, 1, QUANT_TBL_PRECISION);
    317    quant_table_index &= 0xf;
    318    JXL_JPEG_VERIFY_INPUT(quant_table_index, 0, 3, QUANT_TBL_INDEX);
    319    JXL_JPEG_VERIFY_LEN((quant_table_precision + 1) * kDCTBlockSize);
    320    JPEGQuantTable table;
    321    table.index = quant_table_index;
    322    table.precision = quant_table_precision;
    323    for (size_t i = 0; i < kDCTBlockSize; ++i) {
    324      int quant_val =
    325          quant_table_precision ? ReadUint16(data, pos) : ReadUint8(data, pos);
    326      JXL_JPEG_VERIFY_INPUT(quant_val, 1, 65535, QUANT_VAL);
    327      table.values[kJPEGNaturalOrder[i]] = quant_val;
    328    }
    329    table.is_last = (*pos == start_pos + marker_len);
    330    jpg->quant.push_back(table);
    331  }
    332  JXL_JPEG_VERIFY_MARKER_END();
    333  return true;
    334 }
    335 
    336 // Reads the DRI marker and saves the restart interval into *jpg.
    337 bool ProcessDRI(const uint8_t* data, const size_t len, size_t* pos,
    338                bool* found_dri, JPEGData* jpg) {
    339  if (*found_dri) {
    340    return JXL_FAILURE("Duplicate DRI marker.");
    341  }
    342  *found_dri = true;
    343  const size_t start_pos = *pos;
    344  JXL_JPEG_VERIFY_LEN(4);
    345  size_t marker_len = ReadUint16(data, pos);
    346  int restart_interval = ReadUint16(data, pos);
    347  jpg->restart_interval = restart_interval;
    348  JXL_JPEG_VERIFY_MARKER_END();
    349  return true;
    350 }
    351 
    352 // Saves the APP marker segment as a string to *jpg.
    353 bool ProcessAPP(const uint8_t* data, const size_t len, size_t* pos,
    354                JPEGData* jpg) {
    355  JXL_JPEG_VERIFY_LEN(2);
    356  size_t marker_len = ReadUint16(data, pos);
    357  JXL_JPEG_VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN);
    358  JXL_JPEG_VERIFY_LEN(marker_len - 2);
    359  JXL_ENSURE(*pos >= 3);
    360  // Save the marker type together with the app data.
    361  const uint8_t* app_str_start = data + *pos - 3;
    362  std::vector<uint8_t> app_str(app_str_start, app_str_start + marker_len + 1);
    363  *pos += marker_len - 2;
    364  jpg->app_data.push_back(app_str);
    365  return true;
    366 }
    367 
    368 // Saves the COM marker segment as a string to *jpg.
    369 bool ProcessCOM(const uint8_t* data, const size_t len, size_t* pos,
    370                JPEGData* jpg) {
    371  JXL_JPEG_VERIFY_LEN(2);
    372  size_t marker_len = ReadUint16(data, pos);
    373  JXL_JPEG_VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN);
    374  JXL_JPEG_VERIFY_LEN(marker_len - 2);
    375  const uint8_t* com_str_start = data + *pos - 3;
    376  std::vector<uint8_t> com_str(com_str_start, com_str_start + marker_len + 1);
    377  *pos += marker_len - 2;
    378  jpg->com_data.push_back(com_str);
    379  return true;
    380 }
    381 
    382 // Helper structure to read bits from the entropy coded data segment.
    383 struct BitReaderState {
    384  BitReaderState(const uint8_t* data, const size_t len, size_t pos)
    385      : data_(data), len_(len) {
    386    Reset(pos);
    387  }
    388 
    389  void Reset(size_t pos) {
    390    pos_ = pos;
    391    val_ = 0;
    392    bits_left_ = 0;
    393    next_marker_pos_ = len_ - 2;
    394    FillBitWindow();
    395  }
    396 
    397  // Returns the next byte and skips the 0xff/0x00 escape sequences.
    398  uint8_t GetNextByte() {
    399    if (pos_ >= next_marker_pos_) {
    400      ++pos_;
    401      return 0;
    402    }
    403    uint8_t c = data_[pos_++];
    404    if (c == 0xff) {
    405      uint8_t escape = data_[pos_];
    406      if (escape == 0) {
    407        ++pos_;
    408      } else {
    409        // 0xff was followed by a non-zero byte, which means that we found the
    410        // start of the next marker segment.
    411        next_marker_pos_ = pos_ - 1;
    412      }
    413    }
    414    return c;
    415  }
    416 
    417  void FillBitWindow() {
    418    if (bits_left_ <= 16) {
    419      while (bits_left_ <= 56) {
    420        val_ <<= 8;
    421        val_ |= static_cast<uint64_t>(GetNextByte());
    422        bits_left_ += 8;
    423      }
    424    }
    425  }
    426 
    427  int ReadBits(int nbits) {
    428    FillBitWindow();
    429    uint64_t val = (val_ >> (bits_left_ - nbits)) & ((1ULL << nbits) - 1);
    430    bits_left_ -= nbits;
    431    return val;
    432  }
    433 
    434  // Sets *pos to the next stream position where parsing should continue.
    435  // Enqueue the padding bits seen (0 or 1).
    436  // Returns false if there is inconsistent or invalid padding or the stream
    437  // ended too early.
    438  bool FinishStream(JPEGData* jpg, size_t* pos) {
    439    int npadbits = bits_left_ & 7;
    440    if (npadbits > 0) {
    441      uint64_t padmask = (1ULL << npadbits) - 1;
    442      uint64_t padbits = (val_ >> (bits_left_ - npadbits)) & padmask;
    443      if (padbits != padmask) {
    444        jpg->has_zero_padding_bit = true;
    445      }
    446      for (int i = npadbits - 1; i >= 0; --i) {
    447        jpg->padding_bits.push_back((padbits >> i) & 1);
    448      }
    449    }
    450    // Give back some bytes that we did not use.
    451    int unused_bytes_left = bits_left_ >> 3;
    452    while (unused_bytes_left-- > 0) {
    453      --pos_;
    454      // If we give back a 0 byte, we need to check if it was a 0xff/0x00 escape
    455      // sequence, and if yes, we need to give back one more byte.
    456      if (pos_ < next_marker_pos_ && data_[pos_] == 0 &&
    457          data_[pos_ - 1] == 0xff) {
    458        --pos_;
    459      }
    460    }
    461    if (pos_ > next_marker_pos_) {
    462      // Data ran out before the scan was complete.
    463      return JXL_FAILURE("Unexpected end of scan.");
    464    }
    465    *pos = pos_;
    466    return true;
    467  }
    468 
    469  const uint8_t* data_;
    470  const size_t len_;
    471  size_t pos_;
    472  uint64_t val_;
    473  int bits_left_;
    474  size_t next_marker_pos_;
    475 };
    476 
    477 // Returns the next Huffman-coded symbol.
    478 int ReadSymbol(const HuffmanTableEntry* table, BitReaderState* br) {
    479  int nbits;
    480  br->FillBitWindow();
    481  int val = (br->val_ >> (br->bits_left_ - 8)) & 0xff;
    482  table += val;
    483  nbits = table->bits - 8;
    484  if (nbits > 0) {
    485    br->bits_left_ -= 8;
    486    table += table->value;
    487    val = (br->val_ >> (br->bits_left_ - nbits)) & ((1 << nbits) - 1);
    488    table += val;
    489  }
    490  br->bits_left_ -= table->bits;
    491  return table->value;
    492 }
    493 
    494 /**
    495 * Returns the DC diff or AC value for extra bits value x and prefix code s.
    496 *
    497 * CCITT Rec. T.81 (1992 E)
    498 * Table F.1 – Difference magnitude categories for DC coding
    499 *  SSSS | DIFF values
    500 * ------+--------------------------
    501 *     0 | 0
    502 *     1 | –1, 1
    503 *     2 | –3, –2, 2, 3
    504 *     3 | –7..–4, 4..7
    505 * ......|..........................
    506 *    11 | –2047..–1024, 1024..2047
    507 *
    508 * CCITT Rec. T.81 (1992 E)
    509 * Table F.2 – Categories assigned to coefficient values
    510 * [ Same as Table F.1, but does not include SSSS equal to 0 and 11]
    511 *
    512 *
    513 * CCITT Rec. T.81 (1992 E)
    514 * F.1.2.1.1 Structure of DC code table
    515 * For each category,... additional bits... appended... to uniquely identify
    516 * which difference... occurred... When DIFF is positive... SSSS... bits of DIFF
    517 * are appended. When DIFF is negative... SSSS... bits of (DIFF – 1) are
    518 * appended... Most significant bit... is 0 for negative differences and 1 for
    519 * positive differences.
    520 *
    521 * In other words the upper half of extra bits range represents DIFF as is.
    522 * The lower half represents the negative DIFFs with an offset.
    523 */
    524 int HuffExtend(int x, int s) {
    525  JXL_DASSERT(s >= 1);
    526  int half = 1 << (s - 1);
    527  if (x >= half) {
    528    JXL_DASSERT(x < (1 << s));
    529    return x;
    530  } else {
    531    return x - (1 << s) + 1;
    532  }
    533 }
    534 
    535 // Decodes one 8x8 block of DCT coefficients from the bit stream.
    536 bool DecodeDCTBlock(const HuffmanTableEntry* dc_huff,
    537                    const HuffmanTableEntry* ac_huff, int Ss, int Se, int Al,
    538                    int* eobrun, bool* reset_state, int* num_zero_runs,
    539                    BitReaderState* br, JPEGData* jpg, coeff_t* last_dc_coeff,
    540                    coeff_t* coeffs) {
    541  // Nowadays multiplication is even faster than variable shift.
    542  int Am = 1 << Al;
    543  bool eobrun_allowed = Ss > 0;
    544  if (Ss == 0) {
    545    int s = ReadSymbol(dc_huff, br);
    546    if (s >= kJpegDCAlphabetSize) {
    547      return JXL_FAILURE("Invalid Huffman symbol %d  for DC coefficient.", s);
    548    }
    549    int diff = 0;
    550    if (s > 0) {
    551      int bits = br->ReadBits(s);
    552      diff = HuffExtend(bits, s);
    553    }
    554    int coeff = diff + *last_dc_coeff;
    555    const int dc_coeff = coeff * Am;
    556    coeffs[0] = dc_coeff;
    557    // TODO(eustas): is there a more elegant / explicit way to check this?
    558    if (dc_coeff != coeffs[0]) {
    559      return JXL_FAILURE("Invalid DC coefficient %d", dc_coeff);
    560    }
    561    *last_dc_coeff = coeff;
    562    ++Ss;
    563  }
    564  if (Ss > Se) {
    565    return true;
    566  }
    567  if (*eobrun > 0) {
    568    --(*eobrun);
    569    return true;
    570  }
    571  *num_zero_runs = 0;
    572  for (int k = Ss; k <= Se; k++) {
    573    int sr = ReadSymbol(ac_huff, br);
    574    if (sr >= kJpegHuffmanAlphabetSize) {
    575      return JXL_FAILURE("Invalid Huffman symbol %d for AC coefficient %d", sr,
    576                         k);
    577    }
    578    int r = sr >> 4;
    579    int s = sr & 15;
    580    if (s > 0) {
    581      k += r;
    582      if (k > Se) {
    583        return JXL_FAILURE("Out-of-band coefficient %d band was %d-%d", k, Ss,
    584                           Se);
    585      }
    586      if (s + Al >= kJpegDCAlphabetSize) {
    587        return JXL_FAILURE(
    588            "Out of range AC coefficient value: s = %d Al = %d k = %d", s, Al,
    589            k);
    590      }
    591      int bits = br->ReadBits(s);
    592      int coeff = HuffExtend(bits, s);
    593      coeffs[kJPEGNaturalOrder[k]] = coeff * Am;
    594      *num_zero_runs = 0;
    595    } else if (r == 15) {
    596      k += 15;
    597      ++(*num_zero_runs);
    598    } else {
    599      if (eobrun_allowed && k == Ss && *eobrun == 0) {
    600        // We have two end-of-block runs right after each other, so we signal
    601        // the jpeg encoder to force a state reset at this point.
    602        *reset_state = true;
    603      }
    604      *eobrun = 1 << r;
    605      if (r > 0) {
    606        if (!eobrun_allowed) {
    607          return JXL_FAILURE("End-of-block run crossing DC coeff.");
    608        }
    609        *eobrun += br->ReadBits(r);
    610      }
    611      break;
    612    }
    613  }
    614  --(*eobrun);
    615  return true;
    616 }
    617 
    618 bool RefineDCTBlock(const HuffmanTableEntry* ac_huff, int Ss, int Se, int Al,
    619                    int* eobrun, bool* reset_state, BitReaderState* br,
    620                    JPEGData* jpg, coeff_t* coeffs) {
    621  // Nowadays multiplication is even faster than variable shift.
    622  int Am = 1 << Al;
    623  bool eobrun_allowed = Ss > 0;
    624  if (Ss == 0) {
    625    int s = br->ReadBits(1);
    626    coeff_t dc_coeff = coeffs[0];
    627    dc_coeff |= s * Am;
    628    coeffs[0] = dc_coeff;
    629    ++Ss;
    630  }
    631  if (Ss > Se) {
    632    return true;
    633  }
    634  int p1 = Am;
    635  int m1 = -Am;
    636  int k = Ss;
    637  int r;
    638  int s;
    639  bool in_zero_run = false;
    640  if (*eobrun <= 0) {
    641    for (; k <= Se; k++) {
    642      s = ReadSymbol(ac_huff, br);
    643      if (s >= kJpegHuffmanAlphabetSize) {
    644        return JXL_FAILURE("Invalid Huffman symbol %d for AC coefficient %d", s,
    645                           k);
    646      }
    647      r = s >> 4;
    648      s &= 15;
    649      if (s) {
    650        if (s != 1) {
    651          return JXL_FAILURE("Invalid Huffman symbol %d for AC coefficient %d",
    652                             s, k);
    653        }
    654        s = br->ReadBits(1) ? p1 : m1;
    655        in_zero_run = false;
    656      } else {
    657        if (r != 15) {
    658          if (eobrun_allowed && k == Ss && *eobrun == 0) {
    659            // We have two end-of-block runs right after each other, so we
    660            // signal the jpeg encoder to force a state reset at this point.
    661            *reset_state = true;
    662          }
    663          *eobrun = 1 << r;
    664          if (r > 0) {
    665            if (!eobrun_allowed) {
    666              return JXL_FAILURE("End-of-block run crossing DC coeff.");
    667            }
    668            *eobrun += br->ReadBits(r);
    669          }
    670          break;
    671        }
    672        in_zero_run = true;
    673      }
    674      do {
    675        coeff_t thiscoef = coeffs[kJPEGNaturalOrder[k]];
    676        if (thiscoef != 0) {
    677          if (br->ReadBits(1)) {
    678            if ((thiscoef & p1) == 0) {
    679              if (thiscoef >= 0) {
    680                thiscoef += p1;
    681              } else {
    682                thiscoef += m1;
    683              }
    684            }
    685          }
    686          coeffs[kJPEGNaturalOrder[k]] = thiscoef;
    687        } else {
    688          if (--r < 0) {
    689            break;
    690          }
    691        }
    692        k++;
    693      } while (k <= Se);
    694      if (s) {
    695        if (k > Se) {
    696          return JXL_FAILURE("Out-of-band coefficient %d band was %d-%d", k, Ss,
    697                             Se);
    698        }
    699        coeffs[kJPEGNaturalOrder[k]] = s;
    700      }
    701    }
    702  }
    703  if (in_zero_run) {
    704    return JXL_FAILURE("Extra zero run before end-of-block.");
    705  }
    706  if (*eobrun > 0) {
    707    for (; k <= Se; k++) {
    708      coeff_t thiscoef = coeffs[kJPEGNaturalOrder[k]];
    709      if (thiscoef != 0) {
    710        if (br->ReadBits(1)) {
    711          if ((thiscoef & p1) == 0) {
    712            if (thiscoef >= 0) {
    713              thiscoef += p1;
    714            } else {
    715              thiscoef += m1;
    716            }
    717          }
    718        }
    719        coeffs[kJPEGNaturalOrder[k]] = thiscoef;
    720      }
    721    }
    722  }
    723  --(*eobrun);
    724  return true;
    725 }
    726 
    727 bool ProcessRestart(const uint8_t* data, const size_t len,
    728                    int* next_restart_marker, BitReaderState* br,
    729                    JPEGData* jpg) {
    730  size_t pos = 0;
    731  if (!br->FinishStream(jpg, &pos)) {
    732    return JXL_FAILURE("Invalid scan");
    733  }
    734  int expected_marker = 0xd0 + *next_restart_marker;
    735  JXL_JPEG_EXPECT_MARKER();
    736  int marker = data[pos + 1];
    737  if (marker != expected_marker) {
    738    return JXL_FAILURE("Did not find expected restart marker %d actual %d",
    739                       expected_marker, marker);
    740  }
    741  br->Reset(pos + 2);
    742  *next_restart_marker += 1;
    743  *next_restart_marker &= 0x7;
    744  return true;
    745 }
    746 
    747 bool ProcessScan(const uint8_t* data, const size_t len,
    748                 const std::vector<HuffmanTableEntry>& dc_huff_lut,
    749                 const std::vector<HuffmanTableEntry>& ac_huff_lut,
    750                 uint16_t scan_progression[kMaxComponents][kDCTBlockSize],
    751                 bool is_progressive, size_t* pos, JPEGData* jpg) {
    752  if (!ProcessSOS(data, len, pos, jpg)) {
    753    return false;
    754  }
    755  JPEGScanInfo* scan_info = &jpg->scan_info.back();
    756  bool is_interleaved = (scan_info->num_components > 1);
    757  int max_h_samp_factor = 1;
    758  int max_v_samp_factor = 1;
    759  for (const auto& component : jpg->components) {
    760    max_h_samp_factor = std::max(max_h_samp_factor, component.h_samp_factor);
    761    max_v_samp_factor = std::max(max_v_samp_factor, component.v_samp_factor);
    762  }
    763 
    764  int MCU_rows = DivCeil(jpg->height, max_v_samp_factor * 8);
    765  int MCUs_per_row = DivCeil(jpg->width, max_h_samp_factor * 8);
    766  if (!is_interleaved) {
    767    const JPEGComponent& c = jpg->components[scan_info->components[0].comp_idx];
    768    MCUs_per_row = DivCeil(jpg->width * c.h_samp_factor, 8 * max_h_samp_factor);
    769    MCU_rows = DivCeil(jpg->height * c.v_samp_factor, 8 * max_v_samp_factor);
    770  }
    771  coeff_t last_dc_coeff[kMaxComponents] = {0};
    772  BitReaderState br(data, len, *pos);
    773  int restarts_to_go = jpg->restart_interval;
    774  int next_restart_marker = 0;
    775  int eobrun = -1;
    776  int block_scan_index = 0;
    777  const int Al = is_progressive ? scan_info->Al : 0;
    778  const int Ah = is_progressive ? scan_info->Ah : 0;
    779  const int Ss = is_progressive ? scan_info->Ss : 0;
    780  const int Se = is_progressive ? scan_info->Se : 63;
    781  const uint16_t scan_bitmask = Ah == 0 ? (0xffff << Al) : (1u << Al);
    782  const uint16_t refinement_bitmask = (1 << Al) - 1;
    783  for (size_t i = 0; i < scan_info->num_components; ++i) {
    784    int comp_idx = scan_info->components[i].comp_idx;
    785    for (int k = Ss; k <= Se; ++k) {
    786      if (scan_progression[comp_idx][k] & scan_bitmask) {
    787        return JXL_FAILURE(
    788            "Overlapping scans: component=%d k=%d prev_mask: %u cur_mask %u",
    789            comp_idx, k, scan_progression[i][k], scan_bitmask);
    790      }
    791      if (scan_progression[comp_idx][k] & refinement_bitmask) {
    792        return JXL_FAILURE(
    793            "Invalid scan order, a more refined scan was already done: "
    794            "component=%d k=%d prev_mask=%u cur_mask=%u",
    795            comp_idx, k, scan_progression[i][k], scan_bitmask);
    796      }
    797      scan_progression[comp_idx][k] |= scan_bitmask;
    798    }
    799  }
    800  if (Al > 10) {
    801    return JXL_FAILURE("Scan parameter Al=%d is not supported.", Al);
    802  }
    803  for (int mcu_y = 0; mcu_y < MCU_rows; ++mcu_y) {
    804    for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
    805      // Handle the restart intervals.
    806      if (jpg->restart_interval > 0) {
    807        if (restarts_to_go == 0) {
    808          if (ProcessRestart(data, len, &next_restart_marker, &br, jpg)) {
    809            restarts_to_go = jpg->restart_interval;
    810            memset(static_cast<void*>(last_dc_coeff), 0, sizeof(last_dc_coeff));
    811            if (eobrun > 0) {
    812              return JXL_FAILURE("End-of-block run too long.");
    813            }
    814            eobrun = -1;  // fresh start
    815          } else {
    816            return JXL_FAILURE("Could not process restart.");
    817          }
    818        }
    819        --restarts_to_go;
    820      }
    821      // Decode one MCU.
    822      for (size_t i = 0; i < scan_info->num_components; ++i) {
    823        JPEGComponentScanInfo* si = &scan_info->components[i];
    824        JPEGComponent* c = &jpg->components[si->comp_idx];
    825        const HuffmanTableEntry* dc_lut =
    826            &dc_huff_lut[si->dc_tbl_idx * kJpegHuffmanLutSize];
    827        const HuffmanTableEntry* ac_lut =
    828            &ac_huff_lut[si->ac_tbl_idx * kJpegHuffmanLutSize];
    829        int nblocks_y = is_interleaved ? c->v_samp_factor : 1;
    830        int nblocks_x = is_interleaved ? c->h_samp_factor : 1;
    831        for (int iy = 0; iy < nblocks_y; ++iy) {
    832          for (int ix = 0; ix < nblocks_x; ++ix) {
    833            int block_y = mcu_y * nblocks_y + iy;
    834            int block_x = mcu_x * nblocks_x + ix;
    835            int block_idx = block_y * c->width_in_blocks + block_x;
    836            bool reset_state = false;
    837            int num_zero_runs = 0;
    838            coeff_t* coeffs = &c->coeffs[block_idx * kDCTBlockSize];
    839            if (Ah == 0) {
    840              if (!DecodeDCTBlock(dc_lut, ac_lut, Ss, Se, Al, &eobrun,
    841                                  &reset_state, &num_zero_runs, &br, jpg,
    842                                  &last_dc_coeff[si->comp_idx], coeffs)) {
    843                return false;
    844              }
    845            } else {
    846              if (!RefineDCTBlock(ac_lut, Ss, Se, Al, &eobrun, &reset_state,
    847                                  &br, jpg, coeffs)) {
    848                return false;
    849              }
    850            }
    851            if (reset_state) {
    852              scan_info->reset_points.emplace_back(block_scan_index);
    853            }
    854            if (num_zero_runs > 0) {
    855              JPEGScanInfo::ExtraZeroRunInfo info;
    856              info.block_idx = block_scan_index;
    857              info.num_extra_zero_runs = num_zero_runs;
    858              scan_info->extra_zero_runs.push_back(info);
    859            }
    860            ++block_scan_index;
    861          }
    862        }
    863      }
    864    }
    865  }
    866  if (eobrun > 0) {
    867    return JXL_FAILURE("End-of-block run too long.");
    868  }
    869  if (!br.FinishStream(jpg, pos)) {
    870    return JXL_FAILURE("Invalid scan.");
    871  }
    872  if (*pos > len) {
    873    return JXL_FAILURE("Unexpected end of file during scan. pos=%" PRIuS
    874                       " len=%" PRIuS,
    875                       *pos, len);
    876  }
    877  return true;
    878 }
    879 
    880 // Changes the quant_idx field of the components to refer to the index of the
    881 // quant table in the jpg->quant array.
    882 bool FixupIndexes(JPEGData* jpg) {
    883  for (size_t i = 0; i < jpg->components.size(); ++i) {
    884    JPEGComponent* c = &jpg->components[i];
    885    bool found_index = false;
    886    for (size_t j = 0; j < jpg->quant.size(); ++j) {
    887      if (jpg->quant[j].index == c->quant_idx) {
    888        c->quant_idx = j;
    889        found_index = true;
    890        break;
    891      }
    892    }
    893    if (!found_index) {
    894      return JXL_FAILURE("Quantization table with index %u not found",
    895                         c->quant_idx);
    896    }
    897  }
    898  return true;
    899 }
    900 
    901 size_t FindNextMarker(const uint8_t* data, const size_t len, size_t pos) {
    902  // kIsValidMarker[i] == 1 means (0xc0 + i) is a valid marker.
    903  static const uint8_t kIsValidMarker[] = {
    904      1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
    905      1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    906      1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
    907  };
    908  size_t num_skipped = 0;
    909  while (pos + 1 < len && (data[pos] != 0xff || data[pos + 1] < 0xc0 ||
    910                           !kIsValidMarker[data[pos + 1] - 0xc0])) {
    911    ++pos;
    912    ++num_skipped;
    913  }
    914  return num_skipped;
    915 }
    916 
    917 }  // namespace
    918 
    919 bool ReadJpeg(const uint8_t* data, const size_t len, JpegReadMode mode,
    920              JPEGData* jpg) {
    921  size_t pos = 0;
    922  // Check SOI marker.
    923  JXL_JPEG_EXPECT_MARKER();
    924  int marker = data[pos + 1];
    925  pos += 2;
    926  if (marker != 0xd8) {
    927    return JXL_FAILURE("Did not find expected SOI marker, actual=%d", marker);
    928  }
    929  int lut_size = kMaxHuffmanTables * kJpegHuffmanLutSize;
    930  std::vector<HuffmanTableEntry> dc_huff_lut(lut_size);
    931  std::vector<HuffmanTableEntry> ac_huff_lut(lut_size);
    932  bool found_sof = false;
    933  bool found_dri = false;
    934  uint16_t scan_progression[kMaxComponents][kDCTBlockSize] = {{0}};
    935 
    936  jpg->padding_bits.resize(0);
    937  bool is_progressive = false;  // default
    938  do {
    939    // Read next marker.
    940    size_t num_skipped = FindNextMarker(data, len, pos);
    941    if (num_skipped > 0) {
    942      // Add a fake marker to indicate arbitrary in-between-markers data.
    943      jpg->marker_order.push_back(0xff);
    944      jpg->inter_marker_data.emplace_back(data + pos, data + pos + num_skipped);
    945      pos += num_skipped;
    946    }
    947    JXL_JPEG_EXPECT_MARKER();
    948    marker = data[pos + 1];
    949    pos += 2;
    950    bool ok = true;
    951    switch (marker) {
    952      case 0xc0:
    953      case 0xc1:
    954      case 0xc2:
    955        is_progressive = (marker == 0xc2);
    956        ok = ProcessSOF(data, len, mode, &pos, jpg);
    957        found_sof = true;
    958        break;
    959      case 0xc4:
    960        ok = ProcessDHT(data, len, mode, &dc_huff_lut, &ac_huff_lut, &pos, jpg);
    961        break;
    962      case 0xd0:
    963      case 0xd1:
    964      case 0xd2:
    965      case 0xd3:
    966      case 0xd4:
    967      case 0xd5:
    968      case 0xd6:
    969      case 0xd7:
    970        // RST markers do not have any data.
    971        break;
    972      case 0xd9:
    973        // Found end marker.
    974        break;
    975      case 0xda:
    976        if (mode == JpegReadMode::kReadAll) {
    977          ok = ProcessScan(data, len, dc_huff_lut, ac_huff_lut,
    978                           scan_progression, is_progressive, &pos, jpg);
    979        }
    980        break;
    981      case 0xdb:
    982        ok = ProcessDQT(data, len, &pos, jpg);
    983        break;
    984      case 0xdd:
    985        ok = ProcessDRI(data, len, &pos, &found_dri, jpg);
    986        break;
    987      case 0xe0:
    988      case 0xe1:
    989      case 0xe2:
    990      case 0xe3:
    991      case 0xe4:
    992      case 0xe5:
    993      case 0xe6:
    994      case 0xe7:
    995      case 0xe8:
    996      case 0xe9:
    997      case 0xea:
    998      case 0xeb:
    999      case 0xec:
   1000      case 0xed:
   1001      case 0xee:
   1002      case 0xef:
   1003        if (mode != JpegReadMode::kReadTables) {
   1004          ok = ProcessAPP(data, len, &pos, jpg);
   1005        }
   1006        break;
   1007      case 0xfe:
   1008        if (mode != JpegReadMode::kReadTables) {
   1009          ok = ProcessCOM(data, len, &pos, jpg);
   1010        }
   1011        break;
   1012      default:
   1013        return JXL_FAILURE("Unsupported marker: %d pos=%" PRIuS " len=%" PRIuS,
   1014                           marker, pos, len);
   1015    }
   1016    if (!ok) {
   1017      return false;
   1018    }
   1019    jpg->marker_order.push_back(marker);
   1020    if (mode == JpegReadMode::kReadHeader && found_sof) {
   1021      break;
   1022    }
   1023  } while (marker != 0xd9);
   1024 
   1025  if (!found_sof) {
   1026    return JXL_FAILURE("Missing SOF marker.");
   1027  }
   1028 
   1029  // Supplemental checks.
   1030  if (mode == JpegReadMode::kReadAll) {
   1031    if (pos < len) {
   1032      jpg->tail_data = std::vector<uint8_t>(data + pos, data + len);
   1033    }
   1034    if (!FixupIndexes(jpg)) {
   1035      return false;
   1036    }
   1037    if (jpg->huffman_code.empty()) {
   1038      // Section B.2.4.2: "If a table has never been defined for a particular
   1039      // destination, then when this destination is specified in a scan header,
   1040      // the results are unpredictable."
   1041      return JXL_FAILURE("Need at least one Huffman code table.");
   1042    }
   1043    if (jpg->huffman_code.size() >= kMaxDHTMarkers) {
   1044      return JXL_FAILURE("Too many Huffman tables.");
   1045    }
   1046  }
   1047  return true;
   1048 }
   1049 
   1050 }  // namespace jpeg
   1051 }  // namespace jxl