libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

enc_jpeg_data_reader.cc (35782B)


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