Backed out 3 changesets (bug 1790375) for causing wd failures on fetch_error.py....
[gecko.git] / third_party / jpeg-xl / lib / jpegli / decode.cc
blob758babeb5ecd4f3da13c415f15960beee9c2fcfb
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.
6 #include "lib/jpegli/decode.h"
8 #include <string.h>
10 #include <vector>
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"
22 namespace jpegli {
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_eoi_ = false;
58 m->icc_index_ = 0;
59 m->icc_total_ = 0;
60 m->icc_profile_.clear();
61 memset(m->dc_huff_lut_, 0, sizeof(m->dc_huff_lut_));
62 memset(m->ac_huff_lut_, 0, sizeof(m->ac_huff_lut_));
63 // Initialize the values to an invalid symbol so that we can recognize it
64 // when reading the bit stream using a Huffman code with space > 0.
65 for (size_t i = 0; i < kAllHuffLutSize; ++i) {
66 m->dc_huff_lut_[i].bits = 0;
67 m->dc_huff_lut_[i].value = 0xffff;
68 m->ac_huff_lut_[i].bits = 0;
69 m->ac_huff_lut_[i].value = 0xffff;
71 m->colormap_lut_ = nullptr;
72 m->pixels_ = nullptr;
73 m->scanlines_ = nullptr;
74 m->regenerate_inverse_colormap_ = true;
75 for (int i = 0; i < kMaxComponents; ++i) {
76 m->dither_[i] = nullptr;
77 m->error_row_[i] = nullptr;
79 m->output_passes_done_ = 0;
80 m->xoffset_ = 0;
81 m->dequant_ = nullptr;
84 void InitializeDecompressParams(j_decompress_ptr cinfo) {
85 cinfo->jpeg_color_space = JCS_UNKNOWN;
86 cinfo->out_color_space = JCS_UNKNOWN;
87 cinfo->scale_num = 1;
88 cinfo->scale_denom = 1;
89 cinfo->output_gamma = 0.0f;
90 cinfo->buffered_image = FALSE;
91 cinfo->raw_data_out = FALSE;
92 cinfo->dct_method = JDCT_DEFAULT;
93 cinfo->do_fancy_upsampling = TRUE;
94 cinfo->do_block_smoothing = TRUE;
95 cinfo->quantize_colors = FALSE;
96 cinfo->dither_mode = JDITHER_FS;
97 cinfo->two_pass_quantize = TRUE;
98 cinfo->desired_number_of_colors = 256;
99 cinfo->enable_1pass_quant = FALSE;
100 cinfo->enable_external_quant = FALSE;
101 cinfo->enable_2pass_quant = FALSE;
102 cinfo->actual_number_of_colors = 0;
103 cinfo->colormap = nullptr;
106 void InitProgressMonitor(j_decompress_ptr cinfo, bool coef_only) {
107 if (!cinfo->progress) return;
108 jpeg_decomp_master* m = cinfo->master;
109 int nc = cinfo->num_components;
110 int estimated_num_scans =
111 cinfo->progressive_mode ? 2 + 3 * nc : (m->is_multiscan_ ? nc : 1);
112 cinfo->progress->pass_limit = cinfo->total_iMCU_rows * estimated_num_scans;
113 cinfo->progress->pass_counter = 0;
114 if (coef_only) {
115 cinfo->progress->total_passes = 1;
116 } else {
117 int input_passes = !cinfo->buffered_image && m->is_multiscan_ ? 1 : 0;
118 bool two_pass_quant = cinfo->quantize_colors && !cinfo->colormap &&
119 cinfo->two_pass_quantize && cinfo->enable_2pass_quant;
120 cinfo->progress->total_passes = input_passes + (two_pass_quant ? 2 : 1);
122 cinfo->progress->completed_passes = 0;
125 void InitProgressMonitorForOutput(j_decompress_ptr cinfo) {
126 if (!cinfo->progress) return;
127 jpeg_decomp_master* m = cinfo->master;
128 int passes_per_output = cinfo->enable_2pass_quant ? 2 : 1;
129 int output_passes_left = cinfo->buffered_image && !m->found_eoi_ ? 2 : 1;
130 cinfo->progress->total_passes =
131 m->output_passes_done_ + passes_per_output * output_passes_left;
132 cinfo->progress->completed_passes = m->output_passes_done_;
135 void ProgressMonitorInputPass(j_decompress_ptr cinfo) {
136 if (!cinfo->progress) return;
137 cinfo->progress->pass_counter =
138 ((cinfo->input_scan_number - 1) * cinfo->total_iMCU_rows +
139 cinfo->input_iMCU_row);
140 if (cinfo->progress->pass_counter > cinfo->progress->pass_limit) {
141 cinfo->progress->pass_limit =
142 cinfo->input_scan_number * cinfo->total_iMCU_rows;
144 (*cinfo->progress->progress_monitor)(reinterpret_cast<j_common_ptr>(cinfo));
147 void ProgressMonitorOutputPass(j_decompress_ptr cinfo) {
148 if (!cinfo->progress) return;
149 jpeg_decomp_master* m = cinfo->master;
150 int input_passes = !cinfo->buffered_image && m->is_multiscan_ ? 1 : 0;
151 cinfo->progress->pass_counter = cinfo->output_scanline;
152 cinfo->progress->pass_limit = cinfo->output_height;
153 cinfo->progress->completed_passes = input_passes + m->output_passes_done_;
154 (*cinfo->progress->progress_monitor)(reinterpret_cast<j_common_ptr>(cinfo));
157 void BuildHuffmanLookupTable(j_decompress_ptr cinfo, JHUFF_TBL* table,
158 HuffmanTableEntry* huff_lut) {
159 uint32_t counts[kJpegHuffmanMaxBitLength + 1] = {};
160 counts[0] = 0;
161 int total_count = 0;
162 int space = 1 << kJpegHuffmanMaxBitLength;
163 int max_depth = 1;
164 for (size_t i = 1; i <= kJpegHuffmanMaxBitLength; ++i) {
165 int count = table->bits[i];
166 if (count != 0) {
167 max_depth = i;
169 counts[i] = count;
170 total_count += count;
171 space -= count * (1 << (kJpegHuffmanMaxBitLength - i));
173 uint32_t values[kJpegHuffmanAlphabetSize + 1] = {};
174 uint8_t values_seen[256] = {0};
175 for (int i = 0; i < total_count; ++i) {
176 int value = table->huffval[i];
177 if (values_seen[value]) {
178 return JPEGLI_ERROR("Duplicate Huffman code value %d", value);
180 values_seen[value] = 1;
181 values[i] = value;
183 // Add an invalid symbol that will have the all 1 code.
184 ++counts[max_depth];
185 values[total_count] = kJpegHuffmanAlphabetSize;
186 space -= (1 << (kJpegHuffmanMaxBitLength - max_depth));
187 if (space < 0) {
188 JPEGLI_ERROR("Invalid Huffman code lengths.");
189 } else if (space > 0 && huff_lut[0].value != 0xffff) {
190 // Re-initialize the values to an invalid symbol so that we can recognize
191 // it when reading the bit stream using a Huffman code with space > 0.
192 for (int i = 0; i < kJpegHuffmanLutSize; ++i) {
193 huff_lut[i].bits = 0;
194 huff_lut[i].value = 0xffff;
197 BuildJpegHuffmanTable(&counts[0], &values[0], huff_lut);
200 void PrepareForScan(j_decompress_ptr cinfo) {
201 jpeg_decomp_master* m = cinfo->master;
202 for (int i = 0; i < cinfo->comps_in_scan; ++i) {
203 int comp_idx = cinfo->cur_comp_info[i]->component_index;
204 int* prev_coef_bits = cinfo->coef_bits[comp_idx + cinfo->num_components];
205 for (int k = std::min(cinfo->Ss, 1); k <= std::max(cinfo->Se, 9); k++) {
206 prev_coef_bits[k] =
207 (cinfo->input_scan_number > 0) ? cinfo->coef_bits[comp_idx][k] : 0;
209 for (int k = cinfo->Ss; k <= cinfo->Se; ++k) {
210 cinfo->coef_bits[comp_idx][k] = cinfo->Al;
213 AddStandardHuffmanTables(reinterpret_cast<j_common_ptr>(cinfo),
214 /*is_dc=*/false);
215 AddStandardHuffmanTables(reinterpret_cast<j_common_ptr>(cinfo),
216 /*is_dc=*/true);
217 // Check that all the Huffman tables needed for this scan are defined and
218 // build derived lookup tables.
219 for (int i = 0; i < cinfo->comps_in_scan; ++i) {
220 if (cinfo->Ss == 0) {
221 int dc_tbl_idx = cinfo->cur_comp_info[i]->dc_tbl_no;
222 JHUFF_TBL* table = cinfo->dc_huff_tbl_ptrs[dc_tbl_idx];
223 HuffmanTableEntry* huff_lut =
224 &m->dc_huff_lut_[dc_tbl_idx * kJpegHuffmanLutSize];
225 if (!table) {
226 return JPEGLI_ERROR("DC Huffman table %d not found", dc_tbl_idx);
228 BuildHuffmanLookupTable(cinfo, table, huff_lut);
230 if (cinfo->Se > 0) {
231 int ac_tbl_idx = cinfo->cur_comp_info[i]->ac_tbl_no;
232 JHUFF_TBL* table = cinfo->ac_huff_tbl_ptrs[ac_tbl_idx];
233 HuffmanTableEntry* huff_lut =
234 &m->ac_huff_lut_[ac_tbl_idx * kJpegHuffmanLutSize];
235 if (!table) {
236 return JPEGLI_ERROR("AC Huffman table %d not found", ac_tbl_idx);
238 BuildHuffmanLookupTable(cinfo, table, huff_lut);
241 // Copy quantization tables into comp_info.
242 for (int i = 0; i < cinfo->comps_in_scan; ++i) {
243 jpeg_component_info* comp = cinfo->cur_comp_info[i];
244 if (comp->quant_table == nullptr) {
245 comp->quant_table = Allocate<JQUANT_TBL>(cinfo, 1, JPOOL_IMAGE);
246 memcpy(comp->quant_table, cinfo->quant_tbl_ptrs[comp->quant_tbl_no],
247 sizeof(JQUANT_TBL));
250 if (cinfo->comps_in_scan == 1) {
251 const auto& comp = *cinfo->cur_comp_info[0];
252 cinfo->MCUs_per_row = DivCeil(cinfo->image_width * comp.h_samp_factor,
253 cinfo->max_h_samp_factor * DCTSIZE);
254 cinfo->MCU_rows_in_scan = DivCeil(cinfo->image_height * comp.v_samp_factor,
255 cinfo->max_v_samp_factor * DCTSIZE);
256 m->mcu_rows_per_iMCU_row_ = cinfo->cur_comp_info[0]->v_samp_factor;
257 } else {
258 cinfo->MCU_rows_in_scan = cinfo->total_iMCU_rows;
259 cinfo->MCUs_per_row = m->iMCU_cols_;
260 m->mcu_rows_per_iMCU_row_ = 1;
261 size_t mcu_size = 0;
262 for (int i = 0; i < cinfo->comps_in_scan; ++i) {
263 jpeg_component_info* comp = cinfo->cur_comp_info[i];
264 mcu_size += comp->h_samp_factor * comp->v_samp_factor;
266 if (mcu_size > D_MAX_BLOCKS_IN_MCU) {
267 JPEGLI_ERROR("MCU size too big");
270 memset(m->last_dc_coeff_, 0, sizeof(m->last_dc_coeff_));
271 m->restarts_to_go_ = cinfo->restart_interval;
272 m->next_restart_marker_ = 0;
273 m->eobrun_ = -1;
274 m->scan_mcu_row_ = 0;
275 m->scan_mcu_col_ = 0;
276 m->codestream_bits_ahead_ = 0;
277 ++cinfo->input_scan_number;
278 cinfo->input_iMCU_row = 0;
279 PrepareForiMCURow(cinfo);
280 cinfo->global_state = kDecProcessScan;
283 int ConsumeInput(j_decompress_ptr cinfo) {
284 jpeg_decomp_master* m = cinfo->master;
285 if (cinfo->global_state == kDecProcessScan && m->streaming_mode_ &&
286 cinfo->input_iMCU_row > cinfo->output_iMCU_row) {
287 // Prevent input from getting ahead of output in streaming mode.
288 return JPEG_SUSPENDED;
290 jpeg_source_mgr* src = cinfo->src;
291 int status;
292 for (;;) {
293 const uint8_t* data;
294 size_t len;
295 if (m->input_buffer_.empty()) {
296 data = cinfo->src->next_input_byte;
297 len = cinfo->src->bytes_in_buffer;
298 } else {
299 data = &m->input_buffer_[m->input_buffer_pos_];
300 len = m->input_buffer_.size() - m->input_buffer_pos_;
302 size_t pos = 0;
303 if (cinfo->global_state == kDecProcessScan) {
304 status = ProcessScan(cinfo, data, len, &pos, &m->codestream_bits_ahead_);
305 } else {
306 status = ProcessMarkers(cinfo, data, len, &pos);
308 if (m->input_buffer_.empty()) {
309 cinfo->src->next_input_byte += pos;
310 cinfo->src->bytes_in_buffer -= pos;
311 } else {
312 m->input_buffer_pos_ += pos;
313 size_t bytes_left = m->input_buffer_.size() - m->input_buffer_pos_;
314 if (bytes_left <= src->bytes_in_buffer) {
315 src->next_input_byte += (src->bytes_in_buffer - bytes_left);
316 src->bytes_in_buffer = bytes_left;
317 m->input_buffer_.clear();
318 m->input_buffer_pos_ = 0;
321 if (status == kHandleRestart) {
322 JXL_DASSERT(m->input_buffer_.size() <=
323 m->input_buffer_pos_ + src->bytes_in_buffer);
324 m->input_buffer_.clear();
325 m->input_buffer_pos_ = 0;
326 if (cinfo->unread_marker == 0xd0 + m->next_restart_marker_) {
327 cinfo->unread_marker = 0;
328 } else {
329 if (!(*cinfo->src->resync_to_restart)(cinfo, m->next_restart_marker_)) {
330 return JPEG_SUSPENDED;
333 m->next_restart_marker_ += 1;
334 m->next_restart_marker_ &= 0x7;
335 m->restarts_to_go_ = cinfo->restart_interval;
336 if (cinfo->unread_marker != 0) {
337 JPEGLI_WARN("Failed to resync to next restart marker, skipping scan.");
338 return JPEG_SCAN_COMPLETED;
340 continue;
342 if (status == kHandleMarkerProcessor) {
343 JXL_DASSERT(m->input_buffer_.size() <=
344 m->input_buffer_pos_ + src->bytes_in_buffer);
345 m->input_buffer_.clear();
346 m->input_buffer_pos_ = 0;
347 if (!(*GetMarkerProcessor(cinfo))(cinfo)) {
348 return JPEG_SUSPENDED;
350 cinfo->unread_marker = 0;
351 continue;
353 if (status != kNeedMoreInput) {
354 break;
356 if (m->input_buffer_.empty()) {
357 JXL_DASSERT(m->input_buffer_pos_ == 0);
358 m->input_buffer_.assign(src->next_input_byte,
359 src->next_input_byte + src->bytes_in_buffer);
361 if (!(*cinfo->src->fill_input_buffer)(cinfo)) {
362 m->input_buffer_.clear();
363 m->input_buffer_pos_ = 0;
364 return JPEG_SUSPENDED;
366 if (src->bytes_in_buffer == 0) {
367 JPEGLI_ERROR("Empty input.");
369 m->input_buffer_.insert(m->input_buffer_.end(), src->next_input_byte,
370 src->next_input_byte + src->bytes_in_buffer);
372 if (status == JPEG_SCAN_COMPLETED) {
373 cinfo->global_state = kDecProcessMarkers;
374 } else if (status == JPEG_REACHED_SOS) {
375 if (cinfo->global_state == kDecInHeader) {
376 cinfo->global_state = kDecHeaderDone;
377 } else {
378 PrepareForScan(cinfo);
381 return status;
384 bool IsInputReady(j_decompress_ptr cinfo) {
385 if (cinfo->master->found_eoi_) {
386 return true;
388 if (cinfo->input_scan_number > cinfo->output_scan_number) {
389 return true;
391 if (cinfo->input_scan_number < cinfo->output_scan_number) {
392 return false;
394 if (cinfo->input_iMCU_row == cinfo->total_iMCU_rows) {
395 return true;
397 return cinfo->input_iMCU_row >
398 cinfo->output_iMCU_row + (cinfo->master->streaming_mode_ ? 0 : 2);
401 bool ReadOutputPass(j_decompress_ptr cinfo) {
402 jpeg_decomp_master* m = cinfo->master;
403 if (!m->pixels_) {
404 size_t stride = cinfo->out_color_components * cinfo->output_width;
405 size_t num_samples = cinfo->output_height * stride;
406 m->pixels_ = Allocate<uint8_t>(cinfo, num_samples, JPOOL_IMAGE);
407 m->scanlines_ =
408 Allocate<JSAMPROW>(cinfo, cinfo->output_height, JPOOL_IMAGE);
409 for (size_t i = 0; i < cinfo->output_height; ++i) {
410 m->scanlines_[i] = &m->pixels_[i * stride];
413 size_t num_output_rows = 0;
414 while (num_output_rows < cinfo->output_height) {
415 if (IsInputReady(cinfo)) {
416 ProgressMonitorOutputPass(cinfo);
417 ProcessOutput(cinfo, &num_output_rows, m->scanlines_,
418 cinfo->output_height);
419 } else if (ConsumeInput(cinfo) == JPEG_SUSPENDED) {
420 return false;
423 cinfo->output_scanline = 0;
424 cinfo->output_iMCU_row = 0;
425 return true;
428 boolean PrepareQuantizedOutput(j_decompress_ptr cinfo) {
429 jpeg_decomp_master* m = cinfo->master;
430 if (cinfo->raw_data_out) {
431 JPEGLI_ERROR("Color quantization is not supported in raw data mode.");
433 if (m->output_data_type_ != JPEGLI_TYPE_UINT8) {
434 JPEGLI_ERROR("Color quantization must use 8-bit mode.");
436 if (cinfo->colormap) {
437 m->quant_mode_ = 3;
438 } else if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) {
439 m->quant_mode_ = 2;
440 } else if (cinfo->enable_1pass_quant) {
441 m->quant_mode_ = 1;
442 } else {
443 JPEGLI_ERROR("Invalid quantization mode change");
445 if (m->quant_mode_ > 1 && cinfo->dither_mode == JDITHER_ORDERED) {
446 cinfo->dither_mode = JDITHER_FS;
448 if (m->quant_mode_ == 1) {
449 ChooseColorMap1Pass(cinfo);
450 } else if (m->quant_mode_ == 2) {
451 m->quant_pass_ = 0;
452 if (!ReadOutputPass(cinfo)) {
453 return FALSE;
455 ChooseColorMap2Pass(cinfo);
457 if (m->quant_mode_ == 2 ||
458 (m->quant_mode_ == 3 && m->regenerate_inverse_colormap_)) {
459 CreateInverseColorMap(cinfo);
461 if (cinfo->dither_mode == JDITHER_ORDERED) {
462 CreateOrderedDitherTables(cinfo);
463 } else if (cinfo->dither_mode == JDITHER_FS) {
464 InitFSDitherState(cinfo);
466 m->quant_pass_ = 1;
467 return TRUE;
470 void AllocateCoefficientBuffer(j_decompress_ptr cinfo) {
471 jpeg_decomp_master* m = cinfo->master;
472 j_common_ptr comptr = reinterpret_cast<j_common_ptr>(cinfo);
473 jvirt_barray_ptr* coef_arrays = jpegli::Allocate<jvirt_barray_ptr>(
474 cinfo, cinfo->num_components, JPOOL_IMAGE);
475 for (int c = 0; c < cinfo->num_components; ++c) {
476 jpeg_component_info* comp = &cinfo->comp_info[c];
477 size_t height_in_blocks =
478 m->streaming_mode_ ? comp->v_samp_factor : comp->height_in_blocks;
479 coef_arrays[c] = (*cinfo->mem->request_virt_barray)(
480 comptr, JPOOL_IMAGE, TRUE, comp->width_in_blocks, height_in_blocks,
481 comp->v_samp_factor);
483 cinfo->master->coef_arrays = coef_arrays;
484 (*cinfo->mem->realize_virt_arrays)(comptr);
487 void AllocateOutputBuffers(j_decompress_ptr cinfo) {
488 jpeg_decomp_master* m = cinfo->master;
489 size_t iMCU_width = cinfo->max_h_samp_factor * m->min_scaled_dct_size;
490 size_t output_stride = m->iMCU_cols_ * iMCU_width;
491 m->need_context_rows_ = false;
492 for (int c = 0; c < cinfo->num_components; ++c) {
493 if (cinfo->do_fancy_upsampling && m->v_factor[c] == 2) {
494 m->need_context_rows_ = true;
497 for (int c = 0; c < cinfo->num_components; ++c) {
498 const auto& comp = cinfo->comp_info[c];
499 size_t cheight = comp.v_samp_factor * m->scaled_dct_size[c];
500 int downsampled_width = output_stride / m->h_factor[c];
501 m->raw_height_[c] = cinfo->total_iMCU_rows * cheight;
502 if (m->need_context_rows_) {
503 cheight *= 3;
505 m->raw_output_[c].Allocate(cinfo, cheight, downsampled_width);
507 int num_all_components =
508 std::max(cinfo->out_color_components, cinfo->num_components);
509 for (int c = 0; c < num_all_components; ++c) {
510 m->render_output_[c].Allocate(cinfo, cinfo->max_v_samp_factor,
511 output_stride);
513 m->idct_scratch_ = Allocate<float>(cinfo, 5 * DCTSIZE2, JPOOL_IMAGE_ALIGNED);
514 // Padding for horizontal chroma upsampling.
515 constexpr size_t kPaddingLeft = 64;
516 constexpr size_t kPaddingRight = 64;
517 m->upsample_scratch_ = Allocate<float>(
518 cinfo, output_stride + kPaddingLeft + kPaddingRight, JPOOL_IMAGE_ALIGNED);
519 size_t bytes_per_sample = jpegli_bytes_per_sample(m->output_data_type_);
520 size_t bytes_per_pixel = cinfo->out_color_components * bytes_per_sample;
521 size_t scratch_stride = RoundUpTo(output_stride, HWY_ALIGNMENT);
522 m->output_scratch_ = Allocate<uint8_t>(
523 cinfo, bytes_per_pixel * scratch_stride, JPOOL_IMAGE_ALIGNED);
524 m->smoothing_scratch_ =
525 Allocate<int16_t>(cinfo, DCTSIZE2, JPOOL_IMAGE_ALIGNED);
526 size_t coeffs_per_block = cinfo->num_components * DCTSIZE2;
527 m->nonzeros_ = Allocate<int>(cinfo, coeffs_per_block, JPOOL_IMAGE_ALIGNED);
528 m->sumabs_ = Allocate<int>(cinfo, coeffs_per_block, JPOOL_IMAGE_ALIGNED);
529 m->biases_ = Allocate<float>(cinfo, coeffs_per_block, JPOOL_IMAGE_ALIGNED);
530 m->dequant_ = Allocate<float>(cinfo, coeffs_per_block, JPOOL_IMAGE_ALIGNED);
531 memset(m->dequant_, 0, coeffs_per_block * sizeof(float));
534 } // namespace jpegli
536 void jpegli_CreateDecompress(j_decompress_ptr cinfo, int version,
537 size_t structsize) {
538 cinfo->mem = nullptr;
539 if (structsize != sizeof(*cinfo)) {
540 JPEGLI_ERROR("jpeg_decompress_struct has wrong size.");
542 jpegli::InitMemoryManager(reinterpret_cast<j_common_ptr>(cinfo));
543 cinfo->is_decompressor = TRUE;
544 cinfo->progress = nullptr;
545 cinfo->src = nullptr;
546 for (int i = 0; i < NUM_QUANT_TBLS; i++) {
547 cinfo->quant_tbl_ptrs[i] = nullptr;
549 for (int i = 0; i < NUM_HUFF_TBLS; i++) {
550 cinfo->dc_huff_tbl_ptrs[i] = nullptr;
551 cinfo->ac_huff_tbl_ptrs[i] = nullptr;
553 cinfo->global_state = jpegli::kDecStart;
554 cinfo->sample_range_limit = nullptr; // not used
555 cinfo->rec_outbuf_height = 1; // output works with any buffer height
556 cinfo->master = new jpeg_decomp_master;
557 jpeg_decomp_master* m = cinfo->master;
558 for (int i = 0; i < 16; ++i) {
559 m->app_marker_parsers[i] = nullptr;
561 m->com_marker_parser = nullptr;
562 memset(m->markers_to_save_, 0, sizeof(m->markers_to_save_));
563 jpegli::InitializeDecompressParams(cinfo);
564 jpegli::InitializeImage(cinfo);
567 void jpegli_destroy_decompress(j_decompress_ptr cinfo) {
568 jpegli_destroy(reinterpret_cast<j_common_ptr>(cinfo));
571 void jpegli_abort_decompress(j_decompress_ptr cinfo) {
572 jpegli_abort(reinterpret_cast<j_common_ptr>(cinfo));
575 void jpegli_save_markers(j_decompress_ptr cinfo, int marker_code,
576 unsigned int length_limit) {
577 // TODO(szabadka) Limit our memory usage by taking into account length_limit.
578 jpeg_decomp_master* m = cinfo->master;
579 if (marker_code < 0xe0) {
580 JPEGLI_ERROR("jpegli_save_markers: invalid marker code %d", marker_code);
582 m->markers_to_save_[marker_code - 0xe0] = 1;
585 void jpegli_set_marker_processor(j_decompress_ptr cinfo, int marker_code,
586 jpeg_marker_parser_method routine) {
587 jpeg_decomp_master* m = cinfo->master;
588 if (marker_code == 0xfe) {
589 m->com_marker_parser = routine;
590 } else if (marker_code >= 0xe0 && marker_code <= 0xef) {
591 m->app_marker_parsers[marker_code - 0xe0] = routine;
592 } else {
593 JPEGLI_ERROR("jpegli_set_marker_processor: invalid marker code %d",
594 marker_code);
598 int jpegli_consume_input(j_decompress_ptr cinfo) {
599 if (cinfo->global_state == jpegli::kDecStart) {
600 (*cinfo->err->reset_error_mgr)(reinterpret_cast<j_common_ptr>(cinfo));
601 (*cinfo->src->init_source)(cinfo);
602 jpegli::InitializeDecompressParams(cinfo);
603 jpegli::InitializeImage(cinfo);
604 cinfo->global_state = jpegli::kDecInHeader;
606 if (cinfo->global_state == jpegli::kDecHeaderDone) {
607 return JPEG_REACHED_SOS;
609 if (cinfo->master->found_eoi_) {
610 return JPEG_REACHED_EOI;
612 if (cinfo->global_state == jpegli::kDecInHeader ||
613 cinfo->global_state == jpegli::kDecProcessMarkers ||
614 cinfo->global_state == jpegli::kDecProcessScan) {
615 return jpegli::ConsumeInput(cinfo);
617 JPEGLI_ERROR("Unexpected state %d", cinfo->global_state);
618 return JPEG_REACHED_EOI; // return value does not matter
621 int jpegli_read_header(j_decompress_ptr cinfo, boolean require_image) {
622 if (cinfo->global_state != jpegli::kDecStart &&
623 cinfo->global_state != jpegli::kDecInHeader) {
624 JPEGLI_ERROR("jpegli_read_header: unexpected state %d",
625 cinfo->global_state);
627 if (cinfo->src == nullptr) {
628 JPEGLI_ERROR("Missing source.");
630 for (;;) {
631 int retcode = jpegli_consume_input(cinfo);
632 if (retcode == JPEG_SUSPENDED) {
633 return retcode;
634 } else if (retcode == JPEG_REACHED_SOS) {
635 break;
636 } else if (retcode == JPEG_REACHED_EOI) {
637 if (require_image) {
638 JPEGLI_ERROR("jpegli_read_header: unexpected EOI marker.");
640 jpegli_abort_decompress(cinfo);
641 return JPEG_HEADER_TABLES_ONLY;
644 return JPEG_HEADER_OK;
647 boolean jpegli_read_icc_profile(j_decompress_ptr cinfo, JOCTET** icc_data_ptr,
648 unsigned int* icc_data_len) {
649 if (cinfo->global_state == jpegli::kDecStart ||
650 cinfo->global_state == jpegli::kDecInHeader) {
651 JPEGLI_ERROR("jpegli_read_icc_profile: unexpected state %d",
652 cinfo->global_state);
654 if (icc_data_ptr == nullptr || icc_data_len == nullptr) {
655 JPEGLI_ERROR("jpegli_read_icc_profile: invalid output buffer");
657 jpeg_decomp_master* m = cinfo->master;
658 if (m->icc_profile_.empty()) {
659 *icc_data_ptr = nullptr;
660 *icc_data_len = 0;
661 return FALSE;
663 *icc_data_len = m->icc_profile_.size();
664 *icc_data_ptr = (JOCTET*)malloc(*icc_data_len);
665 if (*icc_data_ptr == nullptr) {
666 JPEGLI_ERROR("jpegli_read_icc_profile: Out of memory");
668 memcpy(*icc_data_ptr, m->icc_profile_.data(), *icc_data_len);
669 return TRUE;
672 void jpegli_core_output_dimensions(j_decompress_ptr cinfo) {
673 jpeg_decomp_master* m = cinfo->master;
674 if (!m->found_sof_) {
675 JPEGLI_ERROR("No SOF marker found.");
677 if (cinfo->raw_data_out) {
678 if (cinfo->scale_num != 1 || cinfo->scale_denom != 1) {
679 JPEGLI_ERROR("Output scaling is not supported in raw output mode");
682 if (cinfo->scale_num != 1 || cinfo->scale_denom != 1) {
683 int dctsize = 16;
684 while (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * (dctsize - 1)) {
685 --dctsize;
687 m->min_scaled_dct_size = dctsize;
688 cinfo->output_width =
689 jpegli::DivCeil(cinfo->image_width * dctsize, DCTSIZE);
690 cinfo->output_height =
691 jpegli::DivCeil(cinfo->image_height * dctsize, DCTSIZE);
692 for (int c = 0; c < cinfo->num_components; ++c) {
693 m->scaled_dct_size[c] = m->min_scaled_dct_size;
695 } else {
696 cinfo->output_width = cinfo->image_width;
697 cinfo->output_height = cinfo->image_height;
698 m->min_scaled_dct_size = DCTSIZE;
699 for (int c = 0; c < cinfo->num_components; ++c) {
700 m->scaled_dct_size[c] = DCTSIZE;
705 void jpegli_calc_output_dimensions(j_decompress_ptr cinfo) {
706 jpeg_decomp_master* m = cinfo->master;
707 jpegli_core_output_dimensions(cinfo);
708 for (int c = 0; c < cinfo->num_components; ++c) {
709 jpeg_component_info* comp = &cinfo->comp_info[c];
710 m->h_factor[c] = cinfo->max_h_samp_factor / comp->h_samp_factor;
711 m->v_factor[c] = cinfo->max_v_samp_factor / comp->v_samp_factor;
713 if (cinfo->scale_num != 1 || cinfo->scale_denom != 1) {
714 for (int c = 0; c < cinfo->num_components; ++c) {
715 // Prefer IDCT scaling over 2x upsampling.
716 while (m->scaled_dct_size[c] < DCTSIZE && (m->v_factor[c] % 2) == 0 &&
717 (m->h_factor[c] % 2) == 0) {
718 m->scaled_dct_size[c] *= 2;
719 m->v_factor[c] /= 2;
720 m->h_factor[c] /= 2;
724 if (cinfo->out_color_space == JCS_GRAYSCALE) {
725 cinfo->out_color_components = 1;
726 } else if (cinfo->out_color_space == JCS_RGB ||
727 cinfo->out_color_space == JCS_YCbCr) {
728 cinfo->out_color_components = 3;
729 } else if (cinfo->out_color_space == JCS_CMYK ||
730 cinfo->out_color_space == JCS_YCCK) {
731 cinfo->out_color_components = 4;
732 } else {
733 cinfo->out_color_components = cinfo->num_components;
735 cinfo->output_components =
736 cinfo->quantize_colors ? 1 : cinfo->out_color_components;
737 cinfo->rec_outbuf_height = 1;
740 boolean jpegli_has_multiple_scans(j_decompress_ptr cinfo) {
741 if (cinfo->input_scan_number == 0) {
742 JPEGLI_ERROR("No SOS marker found.");
744 return cinfo->master->is_multiscan_;
747 boolean jpegli_input_complete(j_decompress_ptr cinfo) {
748 return cinfo->master->found_eoi_;
751 boolean jpegli_start_decompress(j_decompress_ptr cinfo) {
752 jpeg_decomp_master* m = cinfo->master;
753 if (cinfo->global_state == jpegli::kDecHeaderDone) {
754 m->streaming_mode_ = !m->is_multiscan_ && !cinfo->buffered_image &&
755 (!cinfo->quantize_colors || !cinfo->two_pass_quantize);
756 jpegli::AllocateCoefficientBuffer(cinfo);
757 jpegli_calc_output_dimensions(cinfo);
758 jpegli::PrepareForScan(cinfo);
759 if (cinfo->quantize_colors) {
760 if (cinfo->colormap != nullptr) {
761 cinfo->enable_external_quant = TRUE;
762 } else if (cinfo->two_pass_quantize &&
763 cinfo->out_color_space == JCS_RGB) {
764 cinfo->enable_2pass_quant = TRUE;
765 } else {
766 cinfo->enable_1pass_quant = TRUE;
769 jpegli::InitProgressMonitor(cinfo, /*coef_only=*/false);
770 jpegli::AllocateOutputBuffers(cinfo);
771 if (cinfo->buffered_image == TRUE) {
772 cinfo->output_scan_number = 0;
773 return TRUE;
775 } else if (!m->is_multiscan_) {
776 JPEGLI_ERROR("jpegli_start_decompress: unexpected state %d",
777 cinfo->global_state);
779 if (m->is_multiscan_) {
780 if (cinfo->global_state != jpegli::kDecProcessScan &&
781 cinfo->global_state != jpegli::kDecProcessMarkers) {
782 JPEGLI_ERROR("jpegli_start_decompress: unexpected state %d",
783 cinfo->global_state);
785 while (!m->found_eoi_) {
786 jpegli::ProgressMonitorInputPass(cinfo);
787 if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) {
788 return FALSE;
792 cinfo->output_scan_number = cinfo->input_scan_number;
793 jpegli::PrepareForOutput(cinfo);
794 if (cinfo->quantize_colors) {
795 return jpegli::PrepareQuantizedOutput(cinfo);
796 } else {
797 return TRUE;
801 boolean jpegli_start_output(j_decompress_ptr cinfo, int scan_number) {
802 jpeg_decomp_master* m = cinfo->master;
803 if (!cinfo->buffered_image) {
804 JPEGLI_ERROR("jpegli_start_output: buffered image mode was not set");
806 if (cinfo->global_state != jpegli::kDecProcessScan &&
807 cinfo->global_state != jpegli::kDecProcessMarkers) {
808 JPEGLI_ERROR("jpegli_start_output: unexpected state %d",
809 cinfo->global_state);
811 cinfo->output_scan_number = std::max(1, scan_number);
812 if (m->found_eoi_) {
813 cinfo->output_scan_number =
814 std::min(cinfo->output_scan_number, cinfo->input_scan_number);
816 jpegli::InitProgressMonitorForOutput(cinfo);
817 jpegli::PrepareForOutput(cinfo);
818 if (cinfo->quantize_colors) {
819 return jpegli::PrepareQuantizedOutput(cinfo);
820 } else {
821 return TRUE;
825 boolean jpegli_finish_output(j_decompress_ptr cinfo) {
826 if (!cinfo->buffered_image) {
827 JPEGLI_ERROR("jpegli_finish_output: buffered image mode was not set");
829 if (cinfo->global_state != jpegli::kDecProcessScan &&
830 cinfo->global_state != jpegli::kDecProcessMarkers) {
831 JPEGLI_ERROR("jpegli_finish_output: unexpected state %d",
832 cinfo->global_state);
834 // Advance input to the start of the next scan, or to the end of input.
835 while (cinfo->input_scan_number <= cinfo->output_scan_number &&
836 !cinfo->master->found_eoi_) {
837 if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) {
838 return FALSE;
841 return TRUE;
844 JDIMENSION jpegli_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines,
845 JDIMENSION max_lines) {
846 jpeg_decomp_master* m = cinfo->master;
847 if (cinfo->global_state != jpegli::kDecProcessScan &&
848 cinfo->global_state != jpegli::kDecProcessMarkers) {
849 JPEGLI_ERROR("jpegli_read_scanlines: unexpected state %d",
850 cinfo->global_state);
852 if (cinfo->buffered_image) {
853 if (cinfo->output_scan_number == 0) {
854 JPEGLI_ERROR(
855 "jpegli_read_scanlines: "
856 "jpegli_start_output() was not called");
858 } else if (m->is_multiscan_ && !m->found_eoi_) {
859 JPEGLI_ERROR(
860 "jpegli_read_scanlines: "
861 "jpegli_start_decompress() did not finish");
863 if (cinfo->output_scanline + max_lines > cinfo->output_height) {
864 max_lines = cinfo->output_height - cinfo->output_scanline;
866 jpegli::ProgressMonitorOutputPass(cinfo);
867 size_t num_output_rows = 0;
868 while (num_output_rows < max_lines) {
869 if (jpegli::IsInputReady(cinfo)) {
870 jpegli::ProcessOutput(cinfo, &num_output_rows, scanlines, max_lines);
871 } else if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) {
872 break;
875 return num_output_rows;
878 JDIMENSION jpegli_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) {
879 // TODO(szabadka) Skip the IDCT for skipped over blocks.
880 return jpegli_read_scanlines(cinfo, nullptr, num_lines);
883 void jpegli_crop_scanline(j_decompress_ptr cinfo, JDIMENSION* xoffset,
884 JDIMENSION* width) {
885 jpeg_decomp_master* m = cinfo->master;
886 if ((cinfo->global_state != jpegli::kDecProcessScan &&
887 cinfo->global_state != jpegli::kDecProcessMarkers) ||
888 cinfo->output_scanline != 0) {
889 JPEGLI_ERROR("jpegli_crop_decompress: unexpected state %d",
890 cinfo->global_state);
892 if (cinfo->raw_data_out) {
893 JPEGLI_ERROR("Output cropping is not supported in raw data mode");
895 if (xoffset == nullptr || width == nullptr || *width == 0 ||
896 *xoffset + *width > cinfo->output_width) {
897 JPEGLI_ERROR("jpegli_crop_scanline: Invalid arguments");
899 // TODO(szabadka) Skip the IDCT for skipped over blocks.
900 size_t xend = *xoffset + *width;
901 size_t iMCU_width = m->min_scaled_dct_size * cinfo->max_h_samp_factor;
902 *xoffset = (*xoffset / iMCU_width) * iMCU_width;
903 *width = xend - *xoffset;
904 cinfo->master->xoffset_ = *xoffset;
905 cinfo->output_width = *width;
908 JDIMENSION jpegli_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data,
909 JDIMENSION max_lines) {
910 if ((cinfo->global_state != jpegli::kDecProcessScan &&
911 cinfo->global_state != jpegli::kDecProcessMarkers) ||
912 !cinfo->raw_data_out) {
913 JPEGLI_ERROR("jpegli_read_raw_data: unexpected state %d",
914 cinfo->global_state);
916 size_t iMCU_height = cinfo->max_v_samp_factor * DCTSIZE;
917 if (max_lines < iMCU_height) {
918 JPEGLI_ERROR("jpegli_read_raw_data: output buffer too small");
920 jpegli::ProgressMonitorOutputPass(cinfo);
921 while (!jpegli::IsInputReady(cinfo)) {
922 if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) {
923 return 0;
926 if (cinfo->output_iMCU_row < cinfo->total_iMCU_rows) {
927 jpegli::ProcessRawOutput(cinfo, data);
928 return iMCU_height;
930 return 0;
933 jvirt_barray_ptr* jpegli_read_coefficients(j_decompress_ptr cinfo) {
934 jpeg_decomp_master* m = cinfo->master;
935 m->streaming_mode_ = false;
936 if (!cinfo->buffered_image && cinfo->global_state == jpegli::kDecHeaderDone) {
937 jpegli::AllocateCoefficientBuffer(cinfo);
938 jpegli_calc_output_dimensions(cinfo);
939 jpegli::InitProgressMonitor(cinfo, /*coef_only=*/true);
940 jpegli::PrepareForScan(cinfo);
942 if (cinfo->global_state != jpegli::kDecProcessScan &&
943 cinfo->global_state != jpegli::kDecProcessMarkers) {
944 JPEGLI_ERROR("jpegli_read_coefficients: unexpected state %d",
945 cinfo->global_state);
947 if (!cinfo->buffered_image) {
948 while (!m->found_eoi_) {
949 jpegli::ProgressMonitorInputPass(cinfo);
950 if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) {
951 return nullptr;
954 cinfo->output_scanline = cinfo->output_height;
956 return m->coef_arrays;
959 boolean jpegli_finish_decompress(j_decompress_ptr cinfo) {
960 if (cinfo->global_state != jpegli::kDecProcessScan &&
961 cinfo->global_state != jpegli::kDecProcessMarkers) {
962 JPEGLI_ERROR("jpegli_finish_decompress: unexpected state %d",
963 cinfo->global_state);
965 if (!cinfo->buffered_image && cinfo->output_scanline < cinfo->output_height) {
966 JPEGLI_ERROR("Incomplete output");
968 while (!cinfo->master->found_eoi_) {
969 if (jpegli::ConsumeInput(cinfo) == JPEG_SUSPENDED) {
970 return FALSE;
973 (*cinfo->src->term_source)(cinfo);
974 jpegli_abort_decompress(cinfo);
975 return TRUE;
978 boolean jpegli_resync_to_restart(j_decompress_ptr cinfo, int desired) {
979 JPEGLI_WARN("Invalid restart marker found: 0x%02x vs 0x%02x.",
980 cinfo->unread_marker, 0xd0 + desired);
981 // This is a trivial implementation, we just let the decoder skip the entire
982 // scan and attempt to render the partial input.
983 return TRUE;
986 void jpegli_new_colormap(j_decompress_ptr cinfo) {
987 if (cinfo->global_state != jpegli::kDecProcessScan &&
988 cinfo->global_state != jpegli::kDecProcessMarkers) {
989 JPEGLI_ERROR("jpegli_new_colormap: unexpected state %d",
990 cinfo->global_state);
992 if (!cinfo->buffered_image) {
993 JPEGLI_ERROR("jpegli_new_colormap: not in buffered image mode");
995 if (!cinfo->enable_external_quant) {
996 JPEGLI_ERROR("external colormap quantizer was not enabled");
998 if (!cinfo->quantize_colors || cinfo->colormap == nullptr) {
999 JPEGLI_ERROR("jpegli_new_colormap: not in external colormap mode");
1001 cinfo->master->regenerate_inverse_colormap_ = true;
1004 void jpegli_set_output_format(j_decompress_ptr cinfo, JpegliDataType data_type,
1005 JpegliEndianness endianness) {
1006 switch (data_type) {
1007 case JPEGLI_TYPE_UINT8:
1008 case JPEGLI_TYPE_UINT16:
1009 case JPEGLI_TYPE_FLOAT:
1010 cinfo->master->output_data_type_ = data_type;
1011 break;
1012 default:
1013 JPEGLI_ERROR("Unsupported data type %d", data_type);
1015 switch (endianness) {
1016 case JPEGLI_NATIVE_ENDIAN:
1017 cinfo->master->swap_endianness_ = false;
1018 break;
1019 case JPEGLI_LITTLE_ENDIAN:
1020 cinfo->master->swap_endianness_ = !IsLittleEndian();
1021 break;
1022 case JPEGLI_BIG_ENDIAN:
1023 cinfo->master->swap_endianness_ = IsLittleEndian();
1024 break;
1025 default:
1026 JPEGLI_ERROR("Unsupported endianness %d", endianness);