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