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