decode.cc (37938B)
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.h" 7 8 #include <string.h> 9 10 #include <vector> 11 12 #include "lib/jpegli/color_quantize.h" 13 #include "lib/jpegli/decode_internal.h" 14 #include "lib/jpegli/decode_marker.h" 15 #include "lib/jpegli/decode_scan.h" 16 #include "lib/jpegli/error.h" 17 #include "lib/jpegli/memory_manager.h" 18 #include "lib/jpegli/render.h" 19 #include "lib/jxl/base/byte_order.h" 20 #include "lib/jxl/base/status.h" 21 22 namespace jpegli { 23 24 void InitializeImage(j_decompress_ptr cinfo) { 25 cinfo->restart_interval = 0; 26 cinfo->saw_JFIF_marker = FALSE; 27 cinfo->JFIF_major_version = 1; 28 cinfo->JFIF_minor_version = 1; 29 cinfo->density_unit = 0; 30 cinfo->X_density = 1; 31 cinfo->Y_density = 1; 32 cinfo->saw_Adobe_marker = FALSE; 33 cinfo->Adobe_transform = 0; 34 cinfo->CCIR601_sampling = FALSE; // not used 35 cinfo->marker_list = nullptr; 36 cinfo->comp_info = nullptr; 37 cinfo->input_scan_number = 0; 38 cinfo->input_iMCU_row = 0; 39 cinfo->output_scan_number = 0; 40 cinfo->output_iMCU_row = 0; 41 cinfo->output_scanline = 0; 42 cinfo->unread_marker = 0; 43 cinfo->coef_bits = nullptr; 44 // We set all these to zero since we don't yet support arithmetic coding. 45 memset(cinfo->arith_dc_L, 0, sizeof(cinfo->arith_dc_L)); 46 memset(cinfo->arith_dc_U, 0, sizeof(cinfo->arith_dc_U)); 47 memset(cinfo->arith_ac_K, 0, sizeof(cinfo->arith_ac_K)); 48 // Initialize the private fields. 49 jpeg_decomp_master* m = cinfo->master; 50 m->input_buffer_.clear(); 51 m->input_buffer_pos_ = 0; 52 m->codestream_bits_ahead_ = 0; 53 m->is_multiscan_ = false; 54 m->found_soi_ = false; 55 m->found_dri_ = false; 56 m->found_sof_ = false; 57 m->found_sos_ = false; 58 m->found_eoi_ = false; 59 m->icc_index_ = 0; 60 m->icc_total_ = 0; 61 m->icc_profile_.clear(); 62 memset(m->dc_huff_lut_, 0, sizeof(m->dc_huff_lut_)); 63 memset(m->ac_huff_lut_, 0, sizeof(m->ac_huff_lut_)); 64 // Initialize the values to an invalid symbol so that we can recognize it 65 // when reading the bit stream using a Huffman code with space > 0. 66 for (size_t i = 0; i < kAllHuffLutSize; ++i) { 67 m->dc_huff_lut_[i].bits = 0; 68 m->dc_huff_lut_[i].value = 0xffff; 69 m->ac_huff_lut_[i].bits = 0; 70 m->ac_huff_lut_[i].value = 0xffff; 71 } 72 m->colormap_lut_ = nullptr; 73 m->pixels_ = nullptr; 74 m->scanlines_ = nullptr; 75 m->regenerate_inverse_colormap_ = true; 76 for (int i = 0; i < kMaxComponents; ++i) { 77 m->dither_[i] = nullptr; 78 m->error_row_[i] = nullptr; 79 } 80 m->output_passes_done_ = 0; 81 m->xoffset_ = 0; 82 m->dequant_ = nullptr; 83 } 84 85 void InitializeDecompressParams(j_decompress_ptr cinfo) { 86 cinfo->jpeg_color_space = JCS_UNKNOWN; 87 cinfo->out_color_space = JCS_UNKNOWN; 88 cinfo->scale_num = 1; 89 cinfo->scale_denom = 1; 90 cinfo->output_gamma = 0.0f; 91 cinfo->buffered_image = FALSE; 92 cinfo->raw_data_out = FALSE; 93 cinfo->dct_method = JDCT_DEFAULT; 94 cinfo->do_fancy_upsampling = TRUE; 95 cinfo->do_block_smoothing = TRUE; 96 cinfo->quantize_colors = FALSE; 97 cinfo->dither_mode = JDITHER_FS; 98 cinfo->two_pass_quantize = TRUE; 99 cinfo->desired_number_of_colors = 256; 100 cinfo->enable_1pass_quant = FALSE; 101 cinfo->enable_external_quant = FALSE; 102 cinfo->enable_2pass_quant = FALSE; 103 cinfo->actual_number_of_colors = 0; 104 cinfo->colormap = nullptr; 105 } 106 107 void InitProgressMonitor(j_decompress_ptr cinfo, bool coef_only) { 108 if (!cinfo->progress) return; 109 jpeg_decomp_master* m = cinfo->master; 110 int nc = cinfo->num_components; 111 int estimated_num_scans = 112 cinfo->progressive_mode ? 2 + 3 * nc : (m->is_multiscan_ ? nc : 1); 113 cinfo->progress->pass_limit = cinfo->total_iMCU_rows * estimated_num_scans; 114 cinfo->progress->pass_counter = 0; 115 if (coef_only) { 116 cinfo->progress->total_passes = 1; 117 } else { 118 int input_passes = !cinfo->buffered_image && m->is_multiscan_ ? 1 : 0; 119 bool two_pass_quant = FROM_JXL_BOOL(cinfo->quantize_colors) && 120 (cinfo->colormap != nullptr) && 121 FROM_JXL_BOOL(cinfo->two_pass_quantize) && 122 FROM_JXL_BOOL(cinfo->enable_2pass_quant); 123 cinfo->progress->total_passes = input_passes + (two_pass_quant ? 2 : 1); 124 } 125 cinfo->progress->completed_passes = 0; 126 } 127 128 void InitProgressMonitorForOutput(j_decompress_ptr cinfo) { 129 if (!cinfo->progress) return; 130 jpeg_decomp_master* m = cinfo->master; 131 int passes_per_output = cinfo->enable_2pass_quant ? 2 : 1; 132 int output_passes_left = cinfo->buffered_image && !m->found_eoi_ ? 2 : 1; 133 cinfo->progress->total_passes = 134 m->output_passes_done_ + passes_per_output * output_passes_left; 135 cinfo->progress->completed_passes = m->output_passes_done_; 136 } 137 138 void ProgressMonitorInputPass(j_decompress_ptr cinfo) { 139 if (!cinfo->progress) return; 140 cinfo->progress->pass_counter = 141 ((cinfo->input_scan_number - 1) * cinfo->total_iMCU_rows + 142 cinfo->input_iMCU_row); 143 if (cinfo->progress->pass_counter > cinfo->progress->pass_limit) { 144 cinfo->progress->pass_limit = 145 cinfo->input_scan_number * cinfo->total_iMCU_rows; 146 } 147 (*cinfo->progress->progress_monitor)(reinterpret_cast<j_common_ptr>(cinfo)); 148 } 149 150 void ProgressMonitorOutputPass(j_decompress_ptr cinfo) { 151 if (!cinfo->progress) return; 152 jpeg_decomp_master* m = cinfo->master; 153 int input_passes = !cinfo->buffered_image && m->is_multiscan_ ? 1 : 0; 154 cinfo->progress->pass_counter = cinfo->output_scanline; 155 cinfo->progress->pass_limit = cinfo->output_height; 156 cinfo->progress->completed_passes = input_passes + m->output_passes_done_; 157 (*cinfo->progress->progress_monitor)(reinterpret_cast<j_common_ptr>(cinfo)); 158 } 159 160 void BuildHuffmanLookupTable(j_decompress_ptr cinfo, JHUFF_TBL* table, 161 HuffmanTableEntry* huff_lut) { 162 uint32_t counts[kJpegHuffmanMaxBitLength + 1] = {}; 163 counts[0] = 0; 164 int total_count = 0; 165 int space = 1 << kJpegHuffmanMaxBitLength; 166 int max_depth = 1; 167 for (size_t i = 1; i <= kJpegHuffmanMaxBitLength; ++i) { 168 int count = table->bits[i]; 169 if (count != 0) { 170 max_depth = i; 171 } 172 counts[i] = count; 173 total_count += count; 174 space -= count * (1 << (kJpegHuffmanMaxBitLength - i)); 175 } 176 uint32_t values[kJpegHuffmanAlphabetSize + 1] = {}; 177 uint8_t values_seen[256] = {0}; 178 for (int i = 0; i < total_count; ++i) { 179 int value = table->huffval[i]; 180 if (values_seen[value]) { 181 JPEGLI_ERROR("Duplicate Huffman code value %d", value); 182 } 183 values_seen[value] = 1; 184 values[i] = value; 185 } 186 // Add an invalid symbol that will have the all 1 code. 187 ++counts[max_depth]; 188 values[total_count] = kJpegHuffmanAlphabetSize; 189 space -= (1 << (kJpegHuffmanMaxBitLength - max_depth)); 190 if (space < 0) { 191 JPEGLI_ERROR("Invalid Huffman code lengths."); 192 } else if (space > 0 && huff_lut[0].value != 0xffff) { 193 // Re-initialize the values to an invalid symbol so that we can recognize 194 // it when reading the bit stream using a Huffman code with space > 0. 195 for (int i = 0; i < kJpegHuffmanLutSize; ++i) { 196 huff_lut[i].bits = 0; 197 huff_lut[i].value = 0xffff; 198 } 199 } 200 BuildJpegHuffmanTable(&counts[0], &values[0], huff_lut); 201 } 202 203 void PrepareForScan(j_decompress_ptr cinfo) { 204 jpeg_decomp_master* m = cinfo->master; 205 for (int i = 0; i < cinfo->comps_in_scan; ++i) { 206 int comp_idx = cinfo->cur_comp_info[i]->component_index; 207 int* prev_coef_bits = cinfo->coef_bits[comp_idx + cinfo->num_components]; 208 for (int k = std::min(cinfo->Ss, 1); k <= std::max(cinfo->Se, 9); k++) { 209 prev_coef_bits[k] = 210 (cinfo->input_scan_number > 0) ? cinfo->coef_bits[comp_idx][k] : 0; 211 } 212 for (int k = cinfo->Ss; k <= cinfo->Se; ++k) { 213 cinfo->coef_bits[comp_idx][k] = cinfo->Al; 214 } 215 } 216 AddStandardHuffmanTables(reinterpret_cast<j_common_ptr>(cinfo), 217 /*is_dc=*/false); 218 AddStandardHuffmanTables(reinterpret_cast<j_common_ptr>(cinfo), 219 /*is_dc=*/true); 220 // Check that all the Huffman tables needed for this scan are defined and 221 // build derived lookup tables. 222 for (int i = 0; i < cinfo->comps_in_scan; ++i) { 223 if (cinfo->Ss == 0) { 224 int dc_tbl_idx = cinfo->cur_comp_info[i]->dc_tbl_no; 225 JHUFF_TBL* table = cinfo->dc_huff_tbl_ptrs[dc_tbl_idx]; 226 HuffmanTableEntry* huff_lut = 227 &m->dc_huff_lut_[dc_tbl_idx * kJpegHuffmanLutSize]; 228 if (!table) { 229 JPEGLI_ERROR("DC Huffman table %d not found", dc_tbl_idx); 230 } 231 BuildHuffmanLookupTable(cinfo, table, huff_lut); 232 } 233 if (cinfo->Se > 0) { 234 int ac_tbl_idx = cinfo->cur_comp_info[i]->ac_tbl_no; 235 JHUFF_TBL* table = cinfo->ac_huff_tbl_ptrs[ac_tbl_idx]; 236 HuffmanTableEntry* huff_lut = 237 &m->ac_huff_lut_[ac_tbl_idx * kJpegHuffmanLutSize]; 238 if (!table) { 239 JPEGLI_ERROR("AC Huffman table %d not found", ac_tbl_idx); 240 } 241 BuildHuffmanLookupTable(cinfo, table, huff_lut); 242 } 243 } 244 // Copy quantization tables into comp_info. 245 for (int i = 0; i < cinfo->comps_in_scan; ++i) { 246 jpeg_component_info* comp = cinfo->cur_comp_info[i]; 247 int quant_tbl_idx = comp->quant_tbl_no; 248 JQUANT_TBL* quant_table = cinfo->quant_tbl_ptrs[quant_tbl_idx]; 249 if (!quant_table) { 250 JPEGLI_ERROR("Quantization table with index %d not found", quant_tbl_idx); 251 } 252 if (comp->quant_table == nullptr) { 253 comp->quant_table = Allocate<JQUANT_TBL>(cinfo, 1, JPOOL_IMAGE); 254 memcpy(comp->quant_table, quant_table, sizeof(JQUANT_TBL)); 255 } 256 } 257 if (cinfo->comps_in_scan == 1) { 258 const auto& comp = *cinfo->cur_comp_info[0]; 259 cinfo->MCUs_per_row = DivCeil(cinfo->image_width * comp.h_samp_factor, 260 cinfo->max_h_samp_factor * DCTSIZE); 261 cinfo->MCU_rows_in_scan = DivCeil(cinfo->image_height * comp.v_samp_factor, 262 cinfo->max_v_samp_factor * DCTSIZE); 263 m->mcu_rows_per_iMCU_row_ = cinfo->cur_comp_info[0]->v_samp_factor; 264 } else { 265 cinfo->MCU_rows_in_scan = cinfo->total_iMCU_rows; 266 cinfo->MCUs_per_row = m->iMCU_cols_; 267 m->mcu_rows_per_iMCU_row_ = 1; 268 size_t mcu_size = 0; 269 for (int i = 0; i < cinfo->comps_in_scan; ++i) { 270 jpeg_component_info* comp = cinfo->cur_comp_info[i]; 271 mcu_size += comp->h_samp_factor * comp->v_samp_factor; 272 } 273 if (mcu_size > D_MAX_BLOCKS_IN_MCU) { 274 JPEGLI_ERROR("MCU size too big"); 275 } 276 } 277 memset(m->last_dc_coeff_, 0, sizeof(m->last_dc_coeff_)); 278 m->restarts_to_go_ = cinfo->restart_interval; 279 m->next_restart_marker_ = 0; 280 m->eobrun_ = -1; 281 m->scan_mcu_row_ = 0; 282 m->scan_mcu_col_ = 0; 283 m->codestream_bits_ahead_ = 0; 284 ++cinfo->input_scan_number; 285 cinfo->input_iMCU_row = 0; 286 PrepareForiMCURow(cinfo); 287 cinfo->global_state = kDecProcessScan; 288 } 289 290 int ConsumeInput(j_decompress_ptr cinfo) { 291 jpeg_decomp_master* m = cinfo->master; 292 if (cinfo->global_state == kDecProcessScan && m->streaming_mode_ && 293 cinfo->input_iMCU_row > cinfo->output_iMCU_row) { 294 // Prevent input from getting ahead of output in streaming mode. 295 return JPEG_SUSPENDED; 296 } 297 jpeg_source_mgr* src = cinfo->src; 298 int status; 299 for (;;) { 300 const uint8_t* data; 301 size_t len; 302 if (m->input_buffer_.empty()) { 303 data = cinfo->src->next_input_byte; 304 len = cinfo->src->bytes_in_buffer; 305 } else { 306 data = &m->input_buffer_[m->input_buffer_pos_]; 307 len = m->input_buffer_.size() - m->input_buffer_pos_; 308 } 309 size_t pos = 0; 310 if (cinfo->global_state == kDecProcessScan) { 311 status = ProcessScan(cinfo, data, len, &pos, &m->codestream_bits_ahead_); 312 } else { 313 status = ProcessMarkers(cinfo, data, len, &pos); 314 } 315 if (m->input_buffer_.empty()) { 316 cinfo->src->next_input_byte += pos; 317 cinfo->src->bytes_in_buffer -= pos; 318 } else { 319 m->input_buffer_pos_ += pos; 320 size_t bytes_left = m->input_buffer_.size() - m->input_buffer_pos_; 321 if (bytes_left <= src->bytes_in_buffer) { 322 src->next_input_byte += (src->bytes_in_buffer - bytes_left); 323 src->bytes_in_buffer = bytes_left; 324 m->input_buffer_.clear(); 325 m->input_buffer_pos_ = 0; 326 } 327 } 328 if (status == kHandleRestart) { 329 JXL_DASSERT(m->input_buffer_.size() <= 330 m->input_buffer_pos_ + src->bytes_in_buffer); 331 m->input_buffer_.clear(); 332 m->input_buffer_pos_ = 0; 333 if (cinfo->unread_marker == 0xd0 + m->next_restart_marker_) { 334 cinfo->unread_marker = 0; 335 } else { 336 if (!(*cinfo->src->resync_to_restart)(cinfo, m->next_restart_marker_)) { 337 return JPEG_SUSPENDED; 338 } 339 } 340 m->next_restart_marker_ += 1; 341 m->next_restart_marker_ &= 0x7; 342 m->restarts_to_go_ = cinfo->restart_interval; 343 if (cinfo->unread_marker != 0) { 344 JPEGLI_WARN("Failed to resync to next restart marker, skipping scan."); 345 return JPEG_SCAN_COMPLETED; 346 } 347 continue; 348 } 349 if (status == kHandleMarkerProcessor) { 350 JXL_DASSERT(m->input_buffer_.size() <= 351 m->input_buffer_pos_ + src->bytes_in_buffer); 352 m->input_buffer_.clear(); 353 m->input_buffer_pos_ = 0; 354 if (!(*GetMarkerProcessor(cinfo))(cinfo)) { 355 return JPEG_SUSPENDED; 356 } 357 cinfo->unread_marker = 0; 358 continue; 359 } 360 if (status != kNeedMoreInput) { 361 break; 362 } 363 if (m->input_buffer_.empty()) { 364 JXL_DASSERT(m->input_buffer_pos_ == 0); 365 m->input_buffer_.assign(src->next_input_byte, 366 src->next_input_byte + src->bytes_in_buffer); 367 } 368 if (!(*cinfo->src->fill_input_buffer)(cinfo)) { 369 m->input_buffer_.clear(); 370 m->input_buffer_pos_ = 0; 371 return JPEG_SUSPENDED; 372 } 373 if (src->bytes_in_buffer == 0) { 374 JPEGLI_ERROR("Empty input."); 375 } 376 m->input_buffer_.insert(m->input_buffer_.end(), src->next_input_byte, 377 src->next_input_byte + src->bytes_in_buffer); 378 } 379 if (status == JPEG_SCAN_COMPLETED) { 380 cinfo->global_state = kDecProcessMarkers; 381 } else if (status == JPEG_REACHED_SOS) { 382 if (cinfo->global_state == kDecInHeader) { 383 cinfo->global_state = kDecHeaderDone; 384 } else { 385 PrepareForScan(cinfo); 386 } 387 } 388 return status; 389 } 390 391 bool IsInputReady(j_decompress_ptr cinfo) { 392 if (cinfo->master->found_eoi_) { 393 return true; 394 } 395 if (cinfo->input_scan_number > cinfo->output_scan_number) { 396 return true; 397 } 398 if (cinfo->input_scan_number < cinfo->output_scan_number) { 399 return false; 400 } 401 if (cinfo->input_iMCU_row == cinfo->total_iMCU_rows) { 402 return true; 403 } 404 return cinfo->input_iMCU_row > 405 cinfo->output_iMCU_row + (cinfo->master->streaming_mode_ ? 0 : 2); 406 } 407 408 bool ReadOutputPass(j_decompress_ptr cinfo) { 409 jpeg_decomp_master* m = cinfo->master; 410 if (!m->pixels_) { 411 size_t stride = cinfo->out_color_components * cinfo->output_width; 412 size_t num_samples = cinfo->output_height * stride; 413 m->pixels_ = Allocate<uint8_t>(cinfo, num_samples, JPOOL_IMAGE); 414 m->scanlines_ = 415 Allocate<JSAMPROW>(cinfo, cinfo->output_height, JPOOL_IMAGE); 416 for (size_t i = 0; i < cinfo->output_height; ++i) { 417 m->scanlines_[i] = &m->pixels_[i * stride]; 418 } 419 } 420 size_t num_output_rows = 0; 421 while (num_output_rows < cinfo->output_height) { 422 if (IsInputReady(cinfo)) { 423 ProgressMonitorOutputPass(cinfo); 424 ProcessOutput(cinfo, &num_output_rows, m->scanlines_, 425 cinfo->output_height); 426 } else if (ConsumeInput(cinfo) == JPEG_SUSPENDED) { 427 return false; 428 } 429 } 430 cinfo->output_scanline = 0; 431 cinfo->output_iMCU_row = 0; 432 return true; 433 } 434 435 boolean PrepareQuantizedOutput(j_decompress_ptr cinfo) { 436 jpeg_decomp_master* m = cinfo->master; 437 if (cinfo->raw_data_out) { 438 JPEGLI_ERROR("Color quantization is not supported in raw data mode."); 439 } 440 if (m->output_data_type_ != JPEGLI_TYPE_UINT8) { 441 JPEGLI_ERROR("Color quantization must use 8-bit mode."); 442 } 443 if (cinfo->colormap) { 444 m->quant_mode_ = 3; 445 } else if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { 446 m->quant_mode_ = 2; 447 } else if (cinfo->enable_1pass_quant) { 448 m->quant_mode_ = 1; 449 } else { 450 JPEGLI_ERROR("Invalid quantization mode change"); 451 } 452 if (m->quant_mode_ > 1 && cinfo->dither_mode == JDITHER_ORDERED) { 453 cinfo->dither_mode = JDITHER_FS; 454 } 455 if (m->quant_mode_ == 1) { 456 ChooseColorMap1Pass(cinfo); 457 } else if (m->quant_mode_ == 2) { 458 m->quant_pass_ = 0; 459 if (!ReadOutputPass(cinfo)) { 460 return FALSE; 461 } 462 ChooseColorMap2Pass(cinfo); 463 } 464 if (m->quant_mode_ == 2 || 465 (m->quant_mode_ == 3 && m->regenerate_inverse_colormap_)) { 466 CreateInverseColorMap(cinfo); 467 } 468 if (cinfo->dither_mode == JDITHER_ORDERED) { 469 CreateOrderedDitherTables(cinfo); 470 } else if (cinfo->dither_mode == JDITHER_FS) { 471 InitFSDitherState(cinfo); 472 } 473 m->quant_pass_ = 1; 474 return TRUE; 475 } 476 477 void AllocateCoefficientBuffer(j_decompress_ptr cinfo) { 478 jpeg_decomp_master* m = cinfo->master; 479 j_common_ptr comptr = reinterpret_cast<j_common_ptr>(cinfo); 480 jvirt_barray_ptr* coef_arrays = jpegli::Allocate<jvirt_barray_ptr>( 481 cinfo, cinfo->num_components, JPOOL_IMAGE); 482 for (int c = 0; c < cinfo->num_components; ++c) { 483 jpeg_component_info* comp = &cinfo->comp_info[c]; 484 size_t height_in_blocks = 485 m->streaming_mode_ ? comp->v_samp_factor : comp->height_in_blocks; 486 coef_arrays[c] = (*cinfo->mem->request_virt_barray)( 487 comptr, JPOOL_IMAGE, TRUE, comp->width_in_blocks, height_in_blocks, 488 comp->v_samp_factor); 489 } 490 cinfo->master->coef_arrays = coef_arrays; 491 (*cinfo->mem->realize_virt_arrays)(comptr); 492 } 493 494 void AllocateOutputBuffers(j_decompress_ptr cinfo) { 495 jpeg_decomp_master* m = cinfo->master; 496 size_t iMCU_width = cinfo->max_h_samp_factor * m->min_scaled_dct_size; 497 size_t output_stride = m->iMCU_cols_ * iMCU_width; 498 m->need_context_rows_ = false; 499 for (int c = 0; c < cinfo->num_components; ++c) { 500 if (cinfo->do_fancy_upsampling && m->v_factor[c] == 2) { 501 m->need_context_rows_ = true; 502 } 503 } 504 for (int c = 0; c < cinfo->num_components; ++c) { 505 const auto& comp = cinfo->comp_info[c]; 506 size_t cheight = comp.v_samp_factor * m->scaled_dct_size[c]; 507 int downsampled_width = output_stride / m->h_factor[c]; 508 m->raw_height_[c] = comp.height_in_blocks * m->scaled_dct_size[c]; 509 if (m->need_context_rows_) { 510 cheight *= 3; 511 } 512 m->raw_output_[c].Allocate(cinfo, cheight, downsampled_width); 513 } 514 int num_all_components = 515 std::max(cinfo->out_color_components, cinfo->num_components); 516 for (int c = 0; c < num_all_components; ++c) { 517 m->render_output_[c].Allocate(cinfo, cinfo->max_v_samp_factor, 518 output_stride); 519 } 520 m->idct_scratch_ = Allocate<float>(cinfo, 5 * DCTSIZE2, JPOOL_IMAGE_ALIGNED); 521 // Padding for horizontal chroma upsampling. 522 constexpr size_t kPaddingLeft = 64; 523 constexpr size_t kPaddingRight = 64; 524 m->upsample_scratch_ = Allocate<float>( 525 cinfo, output_stride + kPaddingLeft + kPaddingRight, JPOOL_IMAGE_ALIGNED); 526 size_t bytes_per_sample = jpegli_bytes_per_sample(m->output_data_type_); 527 size_t bytes_per_pixel = cinfo->out_color_components * bytes_per_sample; 528 size_t scratch_stride = RoundUpTo(output_stride, HWY_ALIGNMENT); 529 m->output_scratch_ = Allocate<uint8_t>( 530 cinfo, bytes_per_pixel * scratch_stride, JPOOL_IMAGE_ALIGNED); 531 m->smoothing_scratch_ = 532 Allocate<int16_t>(cinfo, DCTSIZE2, JPOOL_IMAGE_ALIGNED); 533 size_t coeffs_per_block = cinfo->num_components * DCTSIZE2; 534 m->nonzeros_ = Allocate<int>(cinfo, coeffs_per_block, JPOOL_IMAGE_ALIGNED); 535 m->sumabs_ = Allocate<int>(cinfo, coeffs_per_block, JPOOL_IMAGE_ALIGNED); 536 m->biases_ = Allocate<float>(cinfo, coeffs_per_block, JPOOL_IMAGE_ALIGNED); 537 m->dequant_ = Allocate<float>(cinfo, coeffs_per_block, JPOOL_IMAGE_ALIGNED); 538 memset(m->dequant_, 0, coeffs_per_block * sizeof(float)); 539 } 540 541 } // namespace jpegli 542 543 void jpegli_CreateDecompress(j_decompress_ptr cinfo, int version, 544 size_t structsize) { 545 cinfo->mem = nullptr; 546 if (structsize != sizeof(*cinfo)) { 547 JPEGLI_ERROR("jpeg_decompress_struct has wrong size."); 548 } 549 jpegli::InitMemoryManager(reinterpret_cast<j_common_ptr>(cinfo)); 550 cinfo->is_decompressor = TRUE; 551 cinfo->progress = nullptr; 552 cinfo->src = nullptr; 553 for (auto& quant_tbl_ptr : cinfo->quant_tbl_ptrs) { 554 quant_tbl_ptr = nullptr; 555 } 556 for (int i = 0; i < NUM_HUFF_TBLS; i++) { 557 cinfo->dc_huff_tbl_ptrs[i] = nullptr; 558 cinfo->ac_huff_tbl_ptrs[i] = nullptr; 559 } 560 cinfo->global_state = jpegli::kDecStart; 561 cinfo->sample_range_limit = nullptr; // not used 562 cinfo->rec_outbuf_height = 1; // output works with any buffer height 563 cinfo->master = new jpeg_decomp_master; 564 jpeg_decomp_master* m = cinfo->master; 565 for (auto& app_marker_parser : m->app_marker_parsers) { 566 app_marker_parser = nullptr; 567 } 568 m->com_marker_parser = nullptr; 569 memset(m->markers_to_save_, 0, sizeof(m->markers_to_save_)); 570 jpegli::InitializeDecompressParams(cinfo); 571 jpegli::InitializeImage(cinfo); 572 } 573 574 void jpegli_destroy_decompress(j_decompress_ptr cinfo) { 575 jpegli_destroy(reinterpret_cast<j_common_ptr>(cinfo)); 576 } 577 578 void jpegli_abort_decompress(j_decompress_ptr cinfo) { 579 jpegli_abort(reinterpret_cast<j_common_ptr>(cinfo)); 580 } 581 582 void jpegli_save_markers(j_decompress_ptr cinfo, int marker_code, 583 unsigned int length_limit) { 584 // TODO(szabadka) Limit our memory usage by taking into account length_limit. 585 jpeg_decomp_master* m = cinfo->master; 586 if (marker_code < 0xe0) { 587 JPEGLI_ERROR("jpegli_save_markers: invalid marker code %d", marker_code); 588 } 589 m->markers_to_save_[marker_code - 0xe0] = 1; 590 } 591 592 void jpegli_set_marker_processor(j_decompress_ptr cinfo, int marker_code, 593 jpeg_marker_parser_method routine) { 594 jpeg_decomp_master* m = cinfo->master; 595 if (marker_code == 0xfe) { 596 m->com_marker_parser = routine; 597 } else if (marker_code >= 0xe0 && marker_code <= 0xef) { 598 m->app_marker_parsers[marker_code - 0xe0] = routine; 599 } else { 600 JPEGLI_ERROR("jpegli_set_marker_processor: invalid marker code %d", 601 marker_code); 602 } 603 } 604 605 int jpegli_consume_input(j_decompress_ptr cinfo) { 606 if (cinfo->global_state == jpegli::kDecStart) { 607 (*cinfo->err->reset_error_mgr)(reinterpret_cast<j_common_ptr>(cinfo)); 608 (*cinfo->src->init_source)(cinfo); 609 jpegli::InitializeDecompressParams(cinfo); 610 jpegli::InitializeImage(cinfo); 611 cinfo->global_state = jpegli::kDecInHeader; 612 } 613 if (cinfo->global_state == jpegli::kDecHeaderDone) { 614 return JPEG_REACHED_SOS; 615 } 616 if (cinfo->master->found_eoi_) { 617 return JPEG_REACHED_EOI; 618 } 619 if (cinfo->global_state == jpegli::kDecInHeader || 620 cinfo->global_state == jpegli::kDecProcessMarkers || 621 cinfo->global_state == jpegli::kDecProcessScan) { 622 return jpegli::ConsumeInput(cinfo); 623 } 624 JPEGLI_ERROR("Unexpected state %d", cinfo->global_state); 625 return JPEG_REACHED_EOI; // return value does not matter 626 } 627 628 int jpegli_read_header(j_decompress_ptr cinfo, boolean require_image) { 629 if (cinfo->global_state != jpegli::kDecStart && 630 cinfo->global_state != jpegli::kDecInHeader) { 631 JPEGLI_ERROR("jpegli_read_header: unexpected state %d", 632 cinfo->global_state); 633 } 634 if (cinfo->src == nullptr) { 635 JPEGLI_ERROR("Missing source."); 636 } 637 for (;;) { 638 int retcode = jpegli_consume_input(cinfo); 639 if (retcode == JPEG_SUSPENDED) { 640 return retcode; 641 } else if (retcode == JPEG_REACHED_SOS) { 642 break; 643 } else if (retcode == JPEG_REACHED_EOI) { 644 if (require_image) { 645 JPEGLI_ERROR("jpegli_read_header: unexpected EOI marker."); 646 } 647 jpegli_abort_decompress(cinfo); 648 return JPEG_HEADER_TABLES_ONLY; 649 } 650 }; 651 return JPEG_HEADER_OK; 652 } 653 654 boolean jpegli_read_icc_profile(j_decompress_ptr cinfo, JOCTET** icc_data_ptr, 655 unsigned int* icc_data_len) { 656 if (cinfo->global_state == jpegli::kDecStart || 657 cinfo->global_state == jpegli::kDecInHeader) { 658 JPEGLI_ERROR("jpegli_read_icc_profile: unexpected state %d", 659 cinfo->global_state); 660 } 661 if (icc_data_ptr == nullptr || icc_data_len == nullptr) { 662 JPEGLI_ERROR("jpegli_read_icc_profile: invalid output buffer"); 663 } 664 jpeg_decomp_master* m = cinfo->master; 665 if (m->icc_profile_.empty()) { 666 *icc_data_ptr = nullptr; 667 *icc_data_len = 0; 668 return FALSE; 669 } 670 *icc_data_len = m->icc_profile_.size(); 671 *icc_data_ptr = static_cast<JOCTET*>(malloc(*icc_data_len)); 672 if (*icc_data_ptr == nullptr) { 673 JPEGLI_ERROR("jpegli_read_icc_profile: Out of memory"); 674 } 675 memcpy(*icc_data_ptr, m->icc_profile_.data(), *icc_data_len); 676 return TRUE; 677 } 678 679 void jpegli_core_output_dimensions(j_decompress_ptr cinfo) { 680 jpeg_decomp_master* m = cinfo->master; 681 if (!m->found_sof_) { 682 JPEGLI_ERROR("No SOF marker found."); 683 } 684 if (cinfo->raw_data_out) { 685 if (cinfo->scale_num != 1 || cinfo->scale_denom != 1) { 686 JPEGLI_ERROR("Output scaling is not supported in raw output mode"); 687 } 688 } 689 if (cinfo->scale_num != 1 || cinfo->scale_denom != 1) { 690 int dctsize = 16; 691 while (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * (dctsize - 1)) { 692 --dctsize; 693 } 694 m->min_scaled_dct_size = dctsize; 695 cinfo->output_width = 696 jpegli::DivCeil(cinfo->image_width * dctsize, DCTSIZE); 697 cinfo->output_height = 698 jpegli::DivCeil(cinfo->image_height * dctsize, DCTSIZE); 699 for (int c = 0; c < cinfo->num_components; ++c) { 700 m->scaled_dct_size[c] = m->min_scaled_dct_size; 701 } 702 } else { 703 cinfo->output_width = cinfo->image_width; 704 cinfo->output_height = cinfo->image_height; 705 m->min_scaled_dct_size = DCTSIZE; 706 for (int c = 0; c < cinfo->num_components; ++c) { 707 m->scaled_dct_size[c] = DCTSIZE; 708 } 709 } 710 } 711 712 void jpegli_calc_output_dimensions(j_decompress_ptr cinfo) { 713 jpeg_decomp_master* m = cinfo->master; 714 jpegli_core_output_dimensions(cinfo); 715 for (int c = 0; c < cinfo->num_components; ++c) { 716 jpeg_component_info* comp = &cinfo->comp_info[c]; 717 m->h_factor[c] = cinfo->max_h_samp_factor / comp->h_samp_factor; 718 m->v_factor[c] = cinfo->max_v_samp_factor / comp->v_samp_factor; 719 } 720 if (cinfo->scale_num != 1 || cinfo->scale_denom != 1) { 721 for (int c = 0; c < cinfo->num_components; ++c) { 722 // Prefer IDCT scaling over 2x upsampling. 723 while (m->scaled_dct_size[c] < DCTSIZE && (m->v_factor[c] % 2) == 0 && 724 (m->h_factor[c] % 2) == 0) { 725 m->scaled_dct_size[c] *= 2; 726 m->v_factor[c] /= 2; 727 m->h_factor[c] /= 2; 728 } 729 } 730 } 731 switch (cinfo->out_color_space) { 732 case JCS_GRAYSCALE: 733 cinfo->out_color_components = 1; 734 break; 735 case JCS_RGB: 736 case JCS_YCbCr: 737 #ifdef JCS_EXTENSIONS 738 case JCS_EXT_RGB: 739 case JCS_EXT_BGR: 740 #endif 741 cinfo->out_color_components = 3; 742 break; 743 case JCS_CMYK: 744 case JCS_YCCK: 745 #ifdef JCS_EXTENSIONS 746 case JCS_EXT_RGBX: 747 case JCS_EXT_BGRX: 748 case JCS_EXT_XBGR: 749 case JCS_EXT_XRGB: 750 #endif 751 #ifdef JCS_ALPHA_EXTENSIONS 752 case JCS_EXT_RGBA: 753 case JCS_EXT_BGRA: 754 case JCS_EXT_ABGR: 755 case JCS_EXT_ARGB: 756 #endif 757 cinfo->out_color_components = 4; 758 break; 759 default: 760 cinfo->out_color_components = cinfo->num_components; 761 } 762 cinfo->output_components = 763 cinfo->quantize_colors ? 1 : cinfo->out_color_components; 764 cinfo->rec_outbuf_height = 1; 765 } 766 767 boolean jpegli_has_multiple_scans(j_decompress_ptr cinfo) { 768 if (cinfo->global_state != jpegli::kDecHeaderDone && 769 cinfo->global_state != jpegli::kDecProcessScan && 770 cinfo->global_state != jpegli::kDecProcessMarkers) { 771 JPEGLI_ERROR("jpegli_has_multiple_scans: unexpected state %d", 772 cinfo->global_state); 773 } 774 return TO_JXL_BOOL(cinfo->master->is_multiscan_); 775 } 776 777 boolean jpegli_input_complete(j_decompress_ptr cinfo) { 778 return TO_JXL_BOOL(cinfo->master->found_eoi_); 779 } 780 781 boolean jpegli_start_decompress(j_decompress_ptr cinfo) { 782 jpeg_decomp_master* m = cinfo->master; 783 if (cinfo->global_state == jpegli::kDecHeaderDone) { 784 m->streaming_mode_ = !m->is_multiscan_ && 785 !FROM_JXL_BOOL(cinfo->buffered_image) && 786 (!FROM_JXL_BOOL(cinfo->quantize_colors) || 787 !FROM_JXL_BOOL(cinfo->two_pass_quantize)); 788 jpegli::AllocateCoefficientBuffer(cinfo); 789 jpegli_calc_output_dimensions(cinfo); 790 jpegli::PrepareForScan(cinfo); 791 if (cinfo->quantize_colors) { 792 if (cinfo->colormap != nullptr) { 793 cinfo->enable_external_quant = TRUE; 794 } else if (cinfo->two_pass_quantize && 795 cinfo->out_color_space == JCS_RGB) { 796 cinfo->enable_2pass_quant = TRUE; 797 } else { 798 cinfo->enable_1pass_quant = TRUE; 799 } 800 } 801 jpegli::InitProgressMonitor(cinfo, /*coef_only=*/false); 802 jpegli::AllocateOutputBuffers(cinfo); 803 if (cinfo->buffered_image == TRUE) { 804 cinfo->output_scan_number = 0; 805 return TRUE; 806 } 807 } else if (!m->is_multiscan_) { 808 JPEGLI_ERROR("jpegli_start_decompress: unexpected state %d", 809 cinfo->global_state); 810 } 811 if (m->is_multiscan_) { 812 if (cinfo->global_state != jpegli::kDecProcessScan && 813 cinfo->global_state != jpegli::kDecProcessMarkers) { 814 JPEGLI_ERROR("jpegli_start_decompress: unexpected state %d", 815 cinfo->global_state); 816 } 817 while (!m->found_eoi_) { 818 jpegli::ProgressMonitorInputPass(cinfo); 819 if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) { 820 return FALSE; 821 } 822 } 823 } 824 cinfo->output_scan_number = cinfo->input_scan_number; 825 jpegli::PrepareForOutput(cinfo); 826 if (cinfo->quantize_colors) { 827 return jpegli::PrepareQuantizedOutput(cinfo); 828 } else { 829 return TRUE; 830 } 831 } 832 833 boolean jpegli_start_output(j_decompress_ptr cinfo, int scan_number) { 834 jpeg_decomp_master* m = cinfo->master; 835 if (!cinfo->buffered_image) { 836 JPEGLI_ERROR("jpegli_start_output: buffered image mode was not set"); 837 } 838 if (cinfo->global_state != jpegli::kDecProcessScan && 839 cinfo->global_state != jpegli::kDecProcessMarkers) { 840 JPEGLI_ERROR("jpegli_start_output: unexpected state %d", 841 cinfo->global_state); 842 } 843 cinfo->output_scan_number = std::max(1, scan_number); 844 if (m->found_eoi_) { 845 cinfo->output_scan_number = 846 std::min(cinfo->output_scan_number, cinfo->input_scan_number); 847 } 848 jpegli::InitProgressMonitorForOutput(cinfo); 849 jpegli::PrepareForOutput(cinfo); 850 if (cinfo->quantize_colors) { 851 return jpegli::PrepareQuantizedOutput(cinfo); 852 } else { 853 return TRUE; 854 } 855 } 856 857 boolean jpegli_finish_output(j_decompress_ptr cinfo) { 858 if (!cinfo->buffered_image) { 859 JPEGLI_ERROR("jpegli_finish_output: buffered image mode was not set"); 860 } 861 if (cinfo->global_state != jpegli::kDecProcessScan && 862 cinfo->global_state != jpegli::kDecProcessMarkers) { 863 JPEGLI_ERROR("jpegli_finish_output: unexpected state %d", 864 cinfo->global_state); 865 } 866 // Advance input to the start of the next scan, or to the end of input. 867 while (cinfo->input_scan_number <= cinfo->output_scan_number && 868 !cinfo->master->found_eoi_) { 869 if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) { 870 return FALSE; 871 } 872 } 873 return TRUE; 874 } 875 876 JDIMENSION jpegli_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines, 877 JDIMENSION max_lines) { 878 jpeg_decomp_master* m = cinfo->master; 879 if (cinfo->global_state != jpegli::kDecProcessScan && 880 cinfo->global_state != jpegli::kDecProcessMarkers) { 881 JPEGLI_ERROR("jpegli_read_scanlines: unexpected state %d", 882 cinfo->global_state); 883 } 884 if (cinfo->buffered_image) { 885 if (cinfo->output_scan_number == 0) { 886 JPEGLI_ERROR( 887 "jpegli_read_scanlines: " 888 "jpegli_start_output() was not called"); 889 } 890 } else if (m->is_multiscan_ && !m->found_eoi_) { 891 JPEGLI_ERROR( 892 "jpegli_read_scanlines: " 893 "jpegli_start_decompress() did not finish"); 894 } 895 if (cinfo->output_scanline + max_lines > cinfo->output_height) { 896 max_lines = cinfo->output_height - cinfo->output_scanline; 897 } 898 jpegli::ProgressMonitorOutputPass(cinfo); 899 size_t num_output_rows = 0; 900 while (num_output_rows < max_lines) { 901 if (jpegli::IsInputReady(cinfo)) { 902 jpegli::ProcessOutput(cinfo, &num_output_rows, scanlines, max_lines); 903 } else if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) { 904 break; 905 } 906 } 907 return num_output_rows; 908 } 909 910 JDIMENSION jpegli_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) { 911 // TODO(szabadka) Skip the IDCT for skipped over blocks. 912 return jpegli_read_scanlines(cinfo, nullptr, num_lines); 913 } 914 915 void jpegli_crop_scanline(j_decompress_ptr cinfo, JDIMENSION* xoffset, 916 JDIMENSION* width) { 917 jpeg_decomp_master* m = cinfo->master; 918 if ((cinfo->global_state != jpegli::kDecProcessScan && 919 cinfo->global_state != jpegli::kDecProcessMarkers) || 920 cinfo->output_scanline != 0) { 921 JPEGLI_ERROR("jpegli_crop_decompress: unexpected state %d", 922 cinfo->global_state); 923 } 924 if (cinfo->raw_data_out) { 925 JPEGLI_ERROR("Output cropping is not supported in raw data mode"); 926 } 927 if (xoffset == nullptr || width == nullptr || *width == 0 || 928 *xoffset + *width > cinfo->output_width) { 929 JPEGLI_ERROR("jpegli_crop_scanline: Invalid arguments"); 930 } 931 // TODO(szabadka) Skip the IDCT for skipped over blocks. 932 size_t xend = *xoffset + *width; 933 size_t iMCU_width = m->min_scaled_dct_size * cinfo->max_h_samp_factor; 934 *xoffset = (*xoffset / iMCU_width) * iMCU_width; 935 *width = xend - *xoffset; 936 cinfo->master->xoffset_ = *xoffset; 937 cinfo->output_width = *width; 938 } 939 940 JDIMENSION jpegli_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, 941 JDIMENSION max_lines) { 942 if ((cinfo->global_state != jpegli::kDecProcessScan && 943 cinfo->global_state != jpegli::kDecProcessMarkers) || 944 !cinfo->raw_data_out) { 945 JPEGLI_ERROR("jpegli_read_raw_data: unexpected state %d", 946 cinfo->global_state); 947 } 948 size_t iMCU_height = cinfo->max_v_samp_factor * DCTSIZE; 949 if (max_lines < iMCU_height) { 950 JPEGLI_ERROR("jpegli_read_raw_data: output buffer too small"); 951 } 952 jpegli::ProgressMonitorOutputPass(cinfo); 953 while (!jpegli::IsInputReady(cinfo)) { 954 if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) { 955 return 0; 956 } 957 } 958 if (cinfo->output_iMCU_row < cinfo->total_iMCU_rows) { 959 jpegli::ProcessRawOutput(cinfo, data); 960 return iMCU_height; 961 } 962 return 0; 963 } 964 965 jvirt_barray_ptr* jpegli_read_coefficients(j_decompress_ptr cinfo) { 966 jpeg_decomp_master* m = cinfo->master; 967 m->streaming_mode_ = false; 968 if (!cinfo->buffered_image && cinfo->global_state == jpegli::kDecHeaderDone) { 969 jpegli::AllocateCoefficientBuffer(cinfo); 970 jpegli_calc_output_dimensions(cinfo); 971 jpegli::InitProgressMonitor(cinfo, /*coef_only=*/true); 972 jpegli::PrepareForScan(cinfo); 973 } 974 if (cinfo->global_state != jpegli::kDecProcessScan && 975 cinfo->global_state != jpegli::kDecProcessMarkers) { 976 JPEGLI_ERROR("jpegli_read_coefficients: unexpected state %d", 977 cinfo->global_state); 978 } 979 if (!cinfo->buffered_image) { 980 while (!m->found_eoi_) { 981 jpegli::ProgressMonitorInputPass(cinfo); 982 if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) { 983 return nullptr; 984 } 985 } 986 cinfo->output_scanline = cinfo->output_height; 987 } 988 return m->coef_arrays; 989 } 990 991 boolean jpegli_finish_decompress(j_decompress_ptr cinfo) { 992 if (cinfo->global_state != jpegli::kDecProcessScan && 993 cinfo->global_state != jpegli::kDecProcessMarkers) { 994 JPEGLI_ERROR("jpegli_finish_decompress: unexpected state %d", 995 cinfo->global_state); 996 } 997 if (!cinfo->buffered_image && cinfo->output_scanline < cinfo->output_height) { 998 JPEGLI_ERROR("Incomplete output"); 999 } 1000 while (!cinfo->master->found_eoi_) { 1001 if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) { 1002 return FALSE; 1003 } 1004 } 1005 (*cinfo->src->term_source)(cinfo); 1006 jpegli_abort_decompress(cinfo); 1007 return TRUE; 1008 } 1009 1010 boolean jpegli_resync_to_restart(j_decompress_ptr cinfo, int desired) { 1011 JPEGLI_WARN("Invalid restart marker found: 0x%02x vs 0x%02x.", 1012 cinfo->unread_marker, 0xd0 + desired); 1013 // This is a trivial implementation, we just let the decoder skip the entire 1014 // scan and attempt to render the partial input. 1015 return TRUE; 1016 } 1017 1018 void jpegli_new_colormap(j_decompress_ptr cinfo) { 1019 if (cinfo->global_state != jpegli::kDecProcessScan && 1020 cinfo->global_state != jpegli::kDecProcessMarkers) { 1021 JPEGLI_ERROR("jpegli_new_colormap: unexpected state %d", 1022 cinfo->global_state); 1023 } 1024 if (!cinfo->buffered_image) { 1025 JPEGLI_ERROR("jpegli_new_colormap: not in buffered image mode"); 1026 } 1027 if (!cinfo->enable_external_quant) { 1028 JPEGLI_ERROR("external colormap quantizer was not enabled"); 1029 } 1030 if (!cinfo->quantize_colors || cinfo->colormap == nullptr) { 1031 JPEGLI_ERROR("jpegli_new_colormap: not in external colormap mode"); 1032 } 1033 cinfo->master->regenerate_inverse_colormap_ = true; 1034 } 1035 1036 void jpegli_set_output_format(j_decompress_ptr cinfo, JpegliDataType data_type, 1037 JpegliEndianness endianness) { 1038 switch (data_type) { 1039 case JPEGLI_TYPE_UINT8: 1040 case JPEGLI_TYPE_UINT16: 1041 case JPEGLI_TYPE_FLOAT: 1042 cinfo->master->output_data_type_ = data_type; 1043 break; 1044 default: 1045 JPEGLI_ERROR("Unsupported data type %d", data_type); 1046 } 1047 switch (endianness) { 1048 case JPEGLI_NATIVE_ENDIAN: 1049 cinfo->master->swap_endianness_ = false; 1050 break; 1051 case JPEGLI_LITTLE_ENDIAN: 1052 cinfo->master->swap_endianness_ = !IsLittleEndian(); 1053 break; 1054 case JPEGLI_BIG_ENDIAN: 1055 cinfo->master->swap_endianness_ = IsLittleEndian(); 1056 break; 1057 default: 1058 JPEGLI_ERROR("Unsupported endianness %d", endianness); 1059 } 1060 }