decode_marker.cc (21285B)
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/jpegli/decode_marker.h" 7 8 #include <jxl/types.h> 9 #include <string.h> 10 11 #include "lib/jpegli/common.h" 12 #include "lib/jpegli/decode_internal.h" 13 #include "lib/jpegli/error.h" 14 #include "lib/jpegli/huffman.h" 15 #include "lib/jpegli/memory_manager.h" 16 #include "lib/jxl/base/printf_macros.h" 17 18 namespace jpegli { 19 namespace { 20 21 constexpr int kMaxDimPixels = 65535; 22 constexpr uint8_t kIccProfileTag[12] = "ICC_PROFILE"; 23 24 // Macros for commonly used error conditions. 25 26 #define JPEG_VERIFY_LEN(n) \ 27 if (pos + (n) > len) { \ 28 return JPEGLI_ERROR("Unexpected end of marker: pos=%" PRIuS \ 29 " need=%d len=%" PRIuS, \ 30 pos, static_cast<int>(n), len); \ 31 } 32 33 #define JPEG_VERIFY_INPUT(var, low, high) \ 34 if ((var) < (low) || (var) > (high)) { \ 35 return JPEGLI_ERROR("Invalid " #var ": %d", static_cast<int>(var)); \ 36 } 37 38 #define JPEG_VERIFY_MARKER_END() \ 39 if (pos != len) { \ 40 return JPEGLI_ERROR("Invalid marker length: declared=%" PRIuS \ 41 " actual=%" PRIuS, \ 42 len, pos); \ 43 } 44 45 inline int ReadUint8(const uint8_t* data, size_t* pos) { 46 return data[(*pos)++]; 47 } 48 49 inline int ReadUint16(const uint8_t* data, size_t* pos) { 50 int v = (data[*pos] << 8) + data[*pos + 1]; 51 *pos += 2; 52 return v; 53 } 54 55 void ProcessSOF(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 56 jpeg_decomp_master* m = cinfo->master; 57 if (!m->found_soi_) { 58 JPEGLI_ERROR("Unexpected SOF marker."); 59 } 60 if (m->found_sof_) { 61 JPEGLI_ERROR("Duplicate SOF marker."); 62 } 63 m->found_sof_ = true; 64 cinfo->progressive_mode = TO_JXL_BOOL(cinfo->unread_marker == 0xc2); 65 cinfo->arith_code = 0; 66 size_t pos = 2; 67 JPEG_VERIFY_LEN(6); 68 cinfo->data_precision = ReadUint8(data, &pos); 69 cinfo->image_height = ReadUint16(data, &pos); 70 cinfo->image_width = ReadUint16(data, &pos); 71 cinfo->num_components = ReadUint8(data, &pos); 72 JPEG_VERIFY_INPUT(cinfo->data_precision, kJpegPrecision, kJpegPrecision); 73 JPEG_VERIFY_INPUT(cinfo->image_height, 1, kMaxDimPixels); 74 JPEG_VERIFY_INPUT(cinfo->image_width, 1, kMaxDimPixels); 75 JPEG_VERIFY_INPUT(cinfo->num_components, 1, kMaxComponents); 76 JPEG_VERIFY_LEN(3 * cinfo->num_components); 77 cinfo->comp_info = jpegli::Allocate<jpeg_component_info>( 78 cinfo, cinfo->num_components, JPOOL_IMAGE); 79 80 // Read sampling factors and quant table index for each component. 81 uint8_t ids_seen[256] = {0}; 82 cinfo->max_h_samp_factor = 1; 83 cinfo->max_v_samp_factor = 1; 84 for (int i = 0; i < cinfo->num_components; ++i) { 85 jpeg_component_info* comp = &cinfo->comp_info[i]; 86 comp->component_index = i; 87 const int id = ReadUint8(data, &pos); 88 if (ids_seen[id]) { // (cf. section B.2.2, syntax of Ci) 89 JPEGLI_ERROR("Duplicate ID %d in SOF.", id); 90 } 91 ids_seen[id] = 1; 92 comp->component_id = id; 93 int factor = ReadUint8(data, &pos); 94 int h_samp_factor = factor >> 4; 95 int v_samp_factor = factor & 0xf; 96 JPEG_VERIFY_INPUT(h_samp_factor, 1, MAX_SAMP_FACTOR); 97 JPEG_VERIFY_INPUT(v_samp_factor, 1, MAX_SAMP_FACTOR); 98 comp->h_samp_factor = h_samp_factor; 99 comp->v_samp_factor = v_samp_factor; 100 cinfo->max_h_samp_factor = 101 std::max(cinfo->max_h_samp_factor, h_samp_factor); 102 cinfo->max_v_samp_factor = 103 std::max(cinfo->max_v_samp_factor, v_samp_factor); 104 int quant_tbl_idx = ReadUint8(data, &pos); 105 JPEG_VERIFY_INPUT(quant_tbl_idx, 0, NUM_QUANT_TBLS - 1); 106 comp->quant_tbl_no = quant_tbl_idx; 107 if (cinfo->quant_tbl_ptrs[quant_tbl_idx] == nullptr) { 108 JPEGLI_ERROR("Quantization table with index %u not found", quant_tbl_idx); 109 } 110 comp->quant_table = nullptr; // will be allocated after SOS marker 111 } 112 JPEG_VERIFY_MARKER_END(); 113 114 // Set the input colorspace based on the markers we have seen and set 115 // default output colorspace. 116 if (cinfo->num_components == 1) { 117 cinfo->jpeg_color_space = JCS_GRAYSCALE; 118 cinfo->out_color_space = JCS_GRAYSCALE; 119 } else if (cinfo->num_components == 3) { 120 if (cinfo->saw_JFIF_marker) { 121 cinfo->jpeg_color_space = JCS_YCbCr; 122 } else if (cinfo->saw_Adobe_marker) { 123 cinfo->jpeg_color_space = 124 cinfo->Adobe_transform == 0 ? JCS_RGB : JCS_YCbCr; 125 } else { 126 cinfo->jpeg_color_space = JCS_YCbCr; 127 if (cinfo->comp_info[0].component_id == 'R' && // 128 cinfo->comp_info[1].component_id == 'G' && // 129 cinfo->comp_info[2].component_id == 'B') { 130 cinfo->jpeg_color_space = JCS_RGB; 131 } 132 } 133 cinfo->out_color_space = JCS_RGB; 134 } else if (cinfo->num_components == 4) { 135 if (cinfo->saw_Adobe_marker) { 136 cinfo->jpeg_color_space = 137 cinfo->Adobe_transform == 0 ? JCS_CMYK : JCS_YCCK; 138 } else { 139 cinfo->jpeg_color_space = JCS_CMYK; 140 } 141 cinfo->out_color_space = JCS_CMYK; 142 } 143 144 // We have checked above that none of the sampling factors are 0, so the max 145 // sampling factors can not be 0. 146 cinfo->total_iMCU_rows = 147 DivCeil(cinfo->image_height, cinfo->max_v_samp_factor * DCTSIZE); 148 m->iMCU_cols_ = 149 DivCeil(cinfo->image_width, cinfo->max_h_samp_factor * DCTSIZE); 150 // Compute the block dimensions for each component. 151 for (int i = 0; i < cinfo->num_components; ++i) { 152 jpeg_component_info* comp = &cinfo->comp_info[i]; 153 if (cinfo->max_h_samp_factor % comp->h_samp_factor != 0 || 154 cinfo->max_v_samp_factor % comp->v_samp_factor != 0) { 155 JPEGLI_ERROR("Non-integral subsampling ratios."); 156 } 157 m->h_factor[i] = cinfo->max_h_samp_factor / comp->h_samp_factor; 158 m->v_factor[i] = cinfo->max_v_samp_factor / comp->v_samp_factor; 159 comp->downsampled_width = DivCeil(cinfo->image_width, m->h_factor[i]); 160 comp->downsampled_height = DivCeil(cinfo->image_height, m->v_factor[i]); 161 comp->width_in_blocks = DivCeil(comp->downsampled_width, DCTSIZE); 162 comp->height_in_blocks = DivCeil(comp->downsampled_height, DCTSIZE); 163 } 164 memset(m->scan_progression_, 0, sizeof(m->scan_progression_)); 165 } 166 167 void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 168 jpeg_decomp_master* m = cinfo->master; 169 if (!m->found_sof_) { 170 JPEGLI_ERROR("Unexpected SOS marker."); 171 } 172 size_t pos = 2; 173 JPEG_VERIFY_LEN(1); 174 cinfo->comps_in_scan = ReadUint8(data, &pos); 175 JPEG_VERIFY_INPUT(cinfo->comps_in_scan, 1, cinfo->num_components); 176 JPEG_VERIFY_INPUT(cinfo->comps_in_scan, 1, MAX_COMPS_IN_SCAN); 177 178 JPEG_VERIFY_LEN(2 * cinfo->comps_in_scan); 179 bool is_interleaved = (cinfo->comps_in_scan > 1); 180 uint8_t ids_seen[256] = {0}; 181 cinfo->blocks_in_MCU = 0; 182 for (int i = 0; i < cinfo->comps_in_scan; ++i) { 183 int id = ReadUint8(data, &pos); 184 if (ids_seen[id]) { // (cf. section B.2.3, regarding CSj) 185 return JPEGLI_ERROR("Duplicate ID %d in SOS.", id); 186 } 187 ids_seen[id] = 1; 188 jpeg_component_info* comp = nullptr; 189 for (int j = 0; j < cinfo->num_components; ++j) { 190 if (cinfo->comp_info[j].component_id == id) { 191 comp = &cinfo->comp_info[j]; 192 cinfo->cur_comp_info[i] = comp; 193 } 194 } 195 if (!comp) { 196 return JPEGLI_ERROR("SOS marker: Could not find component with id %d", 197 id); 198 } 199 int c = ReadUint8(data, &pos); 200 comp->dc_tbl_no = c >> 4; 201 comp->ac_tbl_no = c & 0xf; 202 JPEG_VERIFY_INPUT(comp->dc_tbl_no, 0, 3); 203 JPEG_VERIFY_INPUT(comp->ac_tbl_no, 0, 3); 204 comp->MCU_width = is_interleaved ? comp->h_samp_factor : 1; 205 comp->MCU_height = is_interleaved ? comp->v_samp_factor : 1; 206 comp->MCU_blocks = comp->MCU_width * comp->MCU_height; 207 if (cinfo->blocks_in_MCU + comp->MCU_blocks > D_MAX_BLOCKS_IN_MCU) { 208 JPEGLI_ERROR("Too many blocks in MCU."); 209 } 210 for (int j = 0; j < comp->MCU_blocks; ++j) { 211 cinfo->MCU_membership[cinfo->blocks_in_MCU++] = i; 212 } 213 } 214 JPEG_VERIFY_LEN(3); 215 cinfo->Ss = ReadUint8(data, &pos); 216 cinfo->Se = ReadUint8(data, &pos); 217 JPEG_VERIFY_INPUT(cinfo->Ss, 0, 63); 218 JPEG_VERIFY_INPUT(cinfo->Se, cinfo->Ss, 63); 219 int c = ReadUint8(data, &pos); 220 cinfo->Ah = c >> 4; 221 cinfo->Al = c & 0xf; 222 JPEG_VERIFY_MARKER_END(); 223 224 if (cinfo->input_scan_number == 0) { 225 m->is_multiscan_ = (cinfo->comps_in_scan < cinfo->num_components || 226 FROM_JXL_BOOL(cinfo->progressive_mode)); 227 } 228 if (cinfo->Ah != 0 && cinfo->Al != cinfo->Ah - 1) { 229 // section G.1.1.1.2 : Successive approximation control only improves 230 // by one bit at a time. 231 JPEGLI_ERROR("Invalid progressive parameters: Al=%d Ah=%d", cinfo->Al, 232 cinfo->Ah); 233 } 234 if (!cinfo->progressive_mode) { 235 cinfo->Ss = 0; 236 cinfo->Se = 63; 237 cinfo->Ah = 0; 238 cinfo->Al = 0; 239 } 240 const uint16_t scan_bitmask = 241 cinfo->Ah == 0 ? (0xffff << cinfo->Al) : (1u << cinfo->Al); 242 const uint16_t refinement_bitmask = (1 << cinfo->Al) - 1; 243 if (!cinfo->coef_bits) { 244 cinfo->coef_bits = 245 Allocate<int[DCTSIZE2]>(cinfo, cinfo->num_components * 2, JPOOL_IMAGE); 246 m->coef_bits_latch = 247 Allocate<int[SAVED_COEFS]>(cinfo, cinfo->num_components, JPOOL_IMAGE); 248 m->prev_coef_bits_latch = 249 Allocate<int[SAVED_COEFS]>(cinfo, cinfo->num_components, JPOOL_IMAGE); 250 251 for (int c = 0; c < cinfo->num_components; ++c) { 252 for (int i = 0; i < DCTSIZE2; ++i) { 253 cinfo->coef_bits[c][i] = -1; 254 if (i < SAVED_COEFS) { 255 m->coef_bits_latch[c][i] = -1; 256 } 257 } 258 } 259 } 260 261 for (int i = 0; i < cinfo->comps_in_scan; ++i) { 262 int comp_idx = cinfo->cur_comp_info[i]->component_index; 263 for (int k = cinfo->Ss; k <= cinfo->Se; ++k) { 264 if (m->scan_progression_[comp_idx][k] & scan_bitmask) { 265 return JPEGLI_ERROR( 266 "Overlapping scans: component=%d k=%d prev_mask: %u cur_mask %u", 267 comp_idx, k, m->scan_progression_[i][k], scan_bitmask); 268 } 269 if (m->scan_progression_[comp_idx][k] & refinement_bitmask) { 270 return JPEGLI_ERROR( 271 "Invalid scan order, a more refined scan was already done: " 272 "component=%d k=%d prev_mask=%u cur_mask=%u", 273 comp_idx, k, m->scan_progression_[i][k], scan_bitmask); 274 } 275 m->scan_progression_[comp_idx][k] |= scan_bitmask; 276 } 277 } 278 if (cinfo->Al > 10) { 279 return JPEGLI_ERROR("Scan parameter Al=%d is not supported.", cinfo->Al); 280 } 281 } 282 283 // Reads the Define Huffman Table (DHT) marker segment and builds the Huffman 284 // decoding table in either dc_huff_lut_ or ac_huff_lut_, depending on the type 285 // and solt_id of Huffman code being read. 286 void ProcessDHT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 287 size_t pos = 2; 288 if (pos == len) { 289 return JPEGLI_ERROR("DHT marker: no Huffman table found"); 290 } 291 while (pos < len) { 292 JPEG_VERIFY_LEN(1 + kJpegHuffmanMaxBitLength); 293 // The index of the Huffman code in the current set of Huffman codes. For AC 294 // component Huffman codes, 0x10 is added to the index. 295 int slot_id = ReadUint8(data, &pos); 296 int huffman_index = slot_id; 297 bool is_ac_table = ((slot_id & 0x10) != 0); 298 JHUFF_TBL** table; 299 if (is_ac_table) { 300 huffman_index -= 0x10; 301 JPEG_VERIFY_INPUT(huffman_index, 0, NUM_HUFF_TBLS - 1); 302 table = &cinfo->ac_huff_tbl_ptrs[huffman_index]; 303 } else { 304 JPEG_VERIFY_INPUT(huffman_index, 0, NUM_HUFF_TBLS - 1); 305 table = &cinfo->dc_huff_tbl_ptrs[huffman_index]; 306 } 307 if (*table == nullptr) { 308 *table = jpegli_alloc_huff_table(reinterpret_cast<j_common_ptr>(cinfo)); 309 } 310 int total_count = 0; 311 for (size_t i = 1; i <= kJpegHuffmanMaxBitLength; ++i) { 312 int count = ReadUint8(data, &pos); 313 (*table)->bits[i] = count; 314 total_count += count; 315 } 316 if (is_ac_table) { 317 JPEG_VERIFY_INPUT(total_count, 0, kJpegHuffmanAlphabetSize); 318 } else { 319 // Allow symbols up to 15 here, we check later whether any invalid symbols 320 // are actually decoded. 321 // TODO(szabadka) Make sure decoder works (does not crash) with up to 322 // 15-nbits DC symbols and then increase kJpegDCAlphabetSize. 323 JPEG_VERIFY_INPUT(total_count, 0, 16); 324 } 325 JPEG_VERIFY_LEN(total_count); 326 for (int i = 0; i < total_count; ++i) { 327 int value = ReadUint8(data, &pos); 328 if (!is_ac_table) { 329 JPEG_VERIFY_INPUT(value, 0, 15); 330 } 331 (*table)->huffval[i] = value; 332 } 333 for (int i = total_count; i < kJpegHuffmanAlphabetSize; ++i) { 334 (*table)->huffval[i] = 0; 335 } 336 } 337 JPEG_VERIFY_MARKER_END(); 338 } 339 340 void ProcessDQT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 341 jpeg_decomp_master* m = cinfo->master; 342 if (m->found_sof_) { 343 JPEGLI_ERROR("Updating quant tables between scans is not supported."); 344 } 345 size_t pos = 2; 346 if (pos == len) { 347 return JPEGLI_ERROR("DQT marker: no quantization table found"); 348 } 349 while (pos < len) { 350 JPEG_VERIFY_LEN(1); 351 int quant_table_index = ReadUint8(data, &pos); 352 int precision = quant_table_index >> 4; 353 JPEG_VERIFY_INPUT(precision, 0, 1); 354 quant_table_index &= 0xf; 355 JPEG_VERIFY_INPUT(quant_table_index, 0, NUM_QUANT_TBLS - 1); 356 JPEG_VERIFY_LEN((precision + 1) * DCTSIZE2); 357 358 if (cinfo->quant_tbl_ptrs[quant_table_index] == nullptr) { 359 cinfo->quant_tbl_ptrs[quant_table_index] = 360 jpegli_alloc_quant_table(reinterpret_cast<j_common_ptr>(cinfo)); 361 } 362 JQUANT_TBL* quant_table = cinfo->quant_tbl_ptrs[quant_table_index]; 363 364 for (size_t i = 0; i < DCTSIZE2; ++i) { 365 int quant_val = 366 precision ? ReadUint16(data, &pos) : ReadUint8(data, &pos); 367 JPEG_VERIFY_INPUT(quant_val, 1, 65535); 368 quant_table->quantval[kJPEGNaturalOrder[i]] = quant_val; 369 } 370 } 371 JPEG_VERIFY_MARKER_END(); 372 } 373 374 void ProcessDNL(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 375 // Ignore marker. 376 } 377 378 void ProcessDRI(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 379 jpeg_decomp_master* m = cinfo->master; 380 if (m->found_dri_) { 381 return JPEGLI_ERROR("Duplicate DRI marker."); 382 } 383 m->found_dri_ = true; 384 size_t pos = 2; 385 JPEG_VERIFY_LEN(2); 386 cinfo->restart_interval = ReadUint16(data, &pos); 387 JPEG_VERIFY_MARKER_END(); 388 } 389 390 void ProcessAPP(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 391 jpeg_decomp_master* m = cinfo->master; 392 const uint8_t marker = cinfo->unread_marker; 393 const uint8_t* payload = data + 2; 394 size_t payload_size = len - 2; 395 if (marker == 0xE0) { 396 if (payload_size >= 14 && memcmp(payload, "JFIF", 4) == 0) { 397 cinfo->saw_JFIF_marker = TRUE; 398 cinfo->JFIF_major_version = payload[5]; 399 cinfo->JFIF_minor_version = payload[6]; 400 cinfo->density_unit = payload[7]; 401 cinfo->X_density = (payload[8] << 8) + payload[9]; 402 cinfo->Y_density = (payload[10] << 8) + payload[11]; 403 } 404 } else if (marker == 0xEE) { 405 if (payload_size >= 12 && memcmp(payload, "Adobe", 5) == 0) { 406 cinfo->saw_Adobe_marker = TRUE; 407 cinfo->Adobe_transform = payload[11]; 408 } 409 } else if (marker == 0xE2) { 410 if (payload_size >= sizeof(kIccProfileTag) && 411 memcmp(payload, kIccProfileTag, sizeof(kIccProfileTag)) == 0) { 412 payload += sizeof(kIccProfileTag); 413 payload_size -= sizeof(kIccProfileTag); 414 if (payload_size < 2) { 415 return JPEGLI_ERROR("ICC chunk is too small."); 416 } 417 uint8_t index = payload[0]; 418 uint8_t total = payload[1]; 419 ++m->icc_index_; 420 if (m->icc_index_ != index) { 421 return JPEGLI_ERROR("Invalid ICC chunk order."); 422 } 423 if (total == 0) { 424 return JPEGLI_ERROR("Invalid ICC chunk total."); 425 } 426 if (m->icc_total_ == 0) { 427 m->icc_total_ = total; 428 } else if (m->icc_total_ != total) { 429 return JPEGLI_ERROR("Invalid ICC chunk total."); 430 } 431 if (m->icc_index_ > m->icc_total_) { 432 return JPEGLI_ERROR("Invalid ICC chunk index."); 433 } 434 m->icc_profile_.insert(m->icc_profile_.end(), payload + 2, 435 payload + payload_size); 436 } 437 } 438 } 439 440 void ProcessCOM(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 441 // Ignore marker. 442 } 443 444 void ProcessSOI(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 445 jpeg_decomp_master* m = cinfo->master; 446 if (m->found_soi_) { 447 JPEGLI_ERROR("Duplicate SOI marker"); 448 } 449 m->found_soi_ = true; 450 } 451 452 void ProcessEOI(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 453 cinfo->master->found_eoi_ = true; 454 } 455 456 void SaveMarker(j_decompress_ptr cinfo, const uint8_t* data, size_t len) { 457 const uint8_t marker = cinfo->unread_marker; 458 const uint8_t* payload = data + 2; 459 size_t payload_size = len - 2; 460 461 // Insert new saved marker to the head of the list. 462 jpeg_saved_marker_ptr next = cinfo->marker_list; 463 cinfo->marker_list = 464 jpegli::Allocate<jpeg_marker_struct>(cinfo, 1, JPOOL_IMAGE); 465 cinfo->marker_list->next = next; 466 cinfo->marker_list->marker = marker; 467 cinfo->marker_list->original_length = payload_size; 468 cinfo->marker_list->data_length = payload_size; 469 cinfo->marker_list->data = 470 jpegli::Allocate<uint8_t>(cinfo, payload_size, JPOOL_IMAGE); 471 memcpy(cinfo->marker_list->data, payload, payload_size); 472 } 473 474 uint8_t ProcessNextMarker(j_decompress_ptr cinfo, const uint8_t* const data, 475 const size_t len, size_t* pos) { 476 jpeg_decomp_master* m = cinfo->master; 477 size_t num_skipped = 0; 478 uint8_t marker = cinfo->unread_marker; 479 if (marker == 0) { 480 // kIsValidMarker[i] == 1 means (0xc0 + i) is a valid marker. 481 static const uint8_t kIsValidMarker[] = { 482 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 483 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 484 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 485 }; 486 // Skip bytes between markers. 487 while (*pos + 1 < len && (data[*pos] != 0xff || data[*pos + 1] < 0xc0 || 488 !kIsValidMarker[data[*pos + 1] - 0xc0])) { 489 ++(*pos); 490 ++num_skipped; 491 } 492 if (*pos + 2 > len) { 493 return kNeedMoreInput; 494 } 495 marker = data[*pos + 1]; 496 if (num_skipped > 0) { 497 if (m->found_soi_) { 498 JPEGLI_WARN("Skipped %d bytes before marker 0x%02x", 499 static_cast<int>(num_skipped), marker); 500 } else { 501 JPEGLI_ERROR("Did not find SOI marker."); 502 } 503 } 504 *pos += 2; 505 cinfo->unread_marker = marker; 506 } 507 if (!m->found_soi_ && marker != 0xd8) { 508 JPEGLI_ERROR("Did not find SOI marker."); 509 } 510 if (GetMarkerProcessor(cinfo)) { 511 return kHandleMarkerProcessor; 512 } 513 const uint8_t* marker_data = &data[*pos]; 514 size_t marker_len = 0; 515 if (marker != 0xd8 && marker != 0xd9) { 516 if (*pos + 2 > len) { 517 return kNeedMoreInput; 518 } 519 marker_len += (data[*pos] << 8) + data[*pos + 1]; 520 if (marker_len < 2) { 521 JPEGLI_ERROR("Invalid marker length"); 522 } 523 if (*pos + marker_len > len) { 524 // TODO(szabadka) Limit our memory usage by using the skip_input_data 525 // source manager callback on APP markers that are not saved. 526 return kNeedMoreInput; 527 } 528 if (marker >= 0xe0 && m->markers_to_save_[marker - 0xe0]) { 529 SaveMarker(cinfo, marker_data, marker_len); 530 } 531 } 532 if (marker == 0xc0 || marker == 0xc1 || marker == 0xc2) { 533 ProcessSOF(cinfo, marker_data, marker_len); 534 } else if (marker == 0xc4) { 535 ProcessDHT(cinfo, marker_data, marker_len); 536 } else if (marker == 0xda) { 537 ProcessSOS(cinfo, marker_data, marker_len); 538 } else if (marker == 0xdb) { 539 ProcessDQT(cinfo, marker_data, marker_len); 540 } else if (marker == 0xdc) { 541 ProcessDNL(cinfo, marker_data, marker_len); 542 } else if (marker == 0xdd) { 543 ProcessDRI(cinfo, marker_data, marker_len); 544 } else if (marker >= 0xe0 && marker <= 0xef) { 545 ProcessAPP(cinfo, marker_data, marker_len); 546 } else if (marker == 0xfe) { 547 ProcessCOM(cinfo, marker_data, marker_len); 548 } else if (marker == 0xd8) { 549 ProcessSOI(cinfo, marker_data, marker_len); 550 } else if (marker == 0xd9) { 551 ProcessEOI(cinfo, marker_data, marker_len); 552 } else { 553 JPEGLI_ERROR("Unexpected marker 0x%x", marker); 554 } 555 *pos += marker_len; 556 cinfo->unread_marker = 0; 557 if (marker == 0xda) { 558 return JPEG_REACHED_SOS; 559 } else if (marker == 0xd9) { 560 return JPEG_REACHED_EOI; 561 } 562 return kProcessNextMarker; 563 } 564 565 } // namespace 566 567 jpeg_marker_parser_method GetMarkerProcessor(j_decompress_ptr cinfo) { 568 jpeg_decomp_master* m = cinfo->master; 569 uint8_t marker = cinfo->unread_marker; 570 jpeg_marker_parser_method callback = nullptr; 571 if (marker >= 0xe0 && marker <= 0xef) { 572 callback = m->app_marker_parsers[marker - 0xe0]; 573 } else if (marker == 0xfe) { 574 callback = m->com_marker_parser; 575 } 576 return callback; 577 } 578 579 int ProcessMarkers(j_decompress_ptr cinfo, const uint8_t* const data, 580 const size_t len, size_t* pos) { 581 for (;;) { 582 int status = ProcessNextMarker(cinfo, data, len, pos); 583 if (status != kProcessNextMarker) { 584 return status; 585 } 586 } 587 } 588 589 } // namespace jpegli