1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
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"
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"
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;
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;
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;
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;
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
;
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;
115 cinfo
->progress
->total_passes
= 1;
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] = {};
162 int space
= 1 << kJpegHuffmanMaxBitLength
;
164 for (size_t i
= 1; i
<= kJpegHuffmanMaxBitLength
; ++i
) {
165 int count
= table
->bits
[i
];
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;
183 // Add an invalid symbol that will have the all 1 code.
185 values
[total_count
] = kJpegHuffmanAlphabetSize
;
186 space
-= (1 << (kJpegHuffmanMaxBitLength
- max_depth
));
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
++) {
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
),
215 AddStandardHuffmanTables(reinterpret_cast<j_common_ptr
>(cinfo
),
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
];
226 return JPEGLI_ERROR("DC Huffman table %d not found", dc_tbl_idx
);
228 BuildHuffmanLookupTable(cinfo
, table
, huff_lut
);
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
];
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
],
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
;
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;
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;
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
;
295 if (m
->input_buffer_
.empty()) {
296 data
= cinfo
->src
->next_input_byte
;
297 len
= cinfo
->src
->bytes_in_buffer
;
299 data
= &m
->input_buffer_
[m
->input_buffer_pos_
];
300 len
= m
->input_buffer_
.size() - m
->input_buffer_pos_
;
303 if (cinfo
->global_state
== kDecProcessScan
) {
304 status
= ProcessScan(cinfo
, data
, len
, &pos
, &m
->codestream_bits_ahead_
);
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
;
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;
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
;
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;
353 if (status
!= kNeedMoreInput
) {
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
;
378 PrepareForScan(cinfo
);
384 bool IsInputReady(j_decompress_ptr cinfo
) {
385 if (cinfo
->master
->found_eoi_
) {
388 if (cinfo
->input_scan_number
> cinfo
->output_scan_number
) {
391 if (cinfo
->input_scan_number
< cinfo
->output_scan_number
) {
394 if (cinfo
->input_iMCU_row
== cinfo
->total_iMCU_rows
) {
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
;
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
);
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
) {
423 cinfo
->output_scanline
= 0;
424 cinfo
->output_iMCU_row
= 0;
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
) {
438 } else if (cinfo
->two_pass_quantize
&& cinfo
->enable_2pass_quant
) {
440 } else if (cinfo
->enable_1pass_quant
) {
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) {
452 if (!ReadOutputPass(cinfo
)) {
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
);
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_
) {
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
,
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
,
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
;
593 JPEGLI_ERROR("jpegli_set_marker_processor: invalid marker code %d",
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.");
631 int retcode
= jpegli_consume_input(cinfo
);
632 if (retcode
== JPEG_SUSPENDED
) {
634 } else if (retcode
== JPEG_REACHED_SOS
) {
636 } else if (retcode
== JPEG_REACHED_EOI
) {
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;
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
);
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) {
684 while (cinfo
->scale_num
* DCTSIZE
<= cinfo
->scale_denom
* (dctsize
- 1)) {
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
;
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;
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;
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
;
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;
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
) {
792 cinfo
->output_scan_number
= cinfo
->input_scan_number
;
793 jpegli::PrepareForOutput(cinfo
);
794 if (cinfo
->quantize_colors
) {
795 return jpegli::PrepareQuantizedOutput(cinfo
);
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
);
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
);
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
) {
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) {
855 "jpegli_read_scanlines: "
856 "jpegli_start_output() was not called");
858 } else if (m
->is_multiscan_
&& !m
->found_eoi_
) {
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
) {
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
,
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
) {
926 if (cinfo
->output_iMCU_row
< cinfo
->total_iMCU_rows
) {
927 jpegli::ProcessRawOutput(cinfo
, data
);
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
) {
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
) {
973 (*cinfo
->src
->term_source
)(cinfo
);
974 jpegli_abort_decompress(cinfo
);
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.
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
;
1013 JPEGLI_ERROR("Unsupported data type %d", data_type
);
1015 switch (endianness
) {
1016 case JPEGLI_NATIVE_ENDIAN
:
1017 cinfo
->master
->swap_endianness_
= false;
1019 case JPEGLI_LITTLE_ENDIAN
:
1020 cinfo
->master
->swap_endianness_
= !IsLittleEndian();
1022 case JPEGLI_BIG_ENDIAN
:
1023 cinfo
->master
->swap_endianness_
= IsLittleEndian();
1026 JPEGLI_ERROR("Unsupported endianness %d", endianness
);