summaryrefslogtreecommitdiffstats
path: root/third_party/jpeg-xl/lib
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/jpeg-xl/lib')
-rw-r--r--third_party/jpeg-xl/lib/BUILD11
-rw-r--r--third_party/jpeg-xl/lib/CMakeLists.txt10
-rw-r--r--third_party/jpeg-xl/lib/extras/alpha_blend.cc7
-rw-r--r--third_party/jpeg-xl/lib/extras/alpha_blend.h2
-rw-r--r--third_party/jpeg-xl/lib/extras/codec.h2
-rw-r--r--third_party/jpeg-xl/lib/extras/codec_test.cc36
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/apng.cc119
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/color_description.cc99
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/color_hints.cc9
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/decode.cc6
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/decode.h2
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/exr.cc9
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/gif.cc28
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/jpegli.cc21
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/jpg.cc30
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/jxl.cc90
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/jxl.h4
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/pgx.cc11
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/pnm.cc31
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/apng.cc29
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/encode.cc2
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/encode.h2
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/exr.cc4
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jpegli.cc82
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jpg.cc81
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jxl.cc45
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jxl.h8
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/npy.cc35
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/pgx.cc4
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/pnm.cc2
-rw-r--r--third_party/jpeg-xl/lib/extras/jpegli_test.cc18
-rw-r--r--third_party/jpeg-xl/lib/extras/mmap.cc7
-rw-r--r--third_party/jpeg-xl/lib/extras/packed_image.h55
-rw-r--r--third_party/jpeg-xl/lib/extras/packed_image_convert.cc51
-rw-r--r--third_party/jpeg-xl/lib/extras/tone_mapping.cc2
-rw-r--r--third_party/jpeg-xl/lib/extras/tone_mapping_gbench.cc6
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/cms_interface.h27
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/codestream_header.h35
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/color_encoding.h39
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/decode.h411
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/encode.h403
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/parallel_runner.h35
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/resizable_parallel_runner.h10
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/stats.h8
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/thread_parallel_runner.h8
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/types.h10
-rw-r--r--third_party/jpeg-xl/lib/jpegli.cmake1
-rw-r--r--third_party/jpeg-xl/lib/jpegli/adaptive_quantization.cc19
-rw-r--r--third_party/jpeg-xl/lib/jpegli/bitstream.cc7
-rw-r--r--third_party/jpeg-xl/lib/jpegli/bitstream.h5
-rw-r--r--third_party/jpeg-xl/lib/jpegli/color_quantize.cc40
-rw-r--r--third_party/jpeg-xl/lib/jpegli/color_quantize.h2
-rw-r--r--third_party/jpeg-xl/lib/jpegli/dct-inl.h10
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode.cc39
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_api_test.cc35
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_internal.h17
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_marker.cc63
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_marker.h4
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_scan.cc9
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_scan.h4
-rw-r--r--third_party/jpeg-xl/lib/jpegli/destination_manager.cc16
-rw-r--r--third_party/jpeg-xl/lib/jpegli/downsample.cc8
-rw-r--r--third_party/jpeg-xl/lib/jpegli/encode.cc33
-rw-r--r--third_party/jpeg-xl/lib/jpegli/encode_api_test.cc24
-rw-r--r--third_party/jpeg-xl/lib/jpegli/encode_finish.cc2
-rw-r--r--third_party/jpeg-xl/lib/jpegli/entropy_coding.cc58
-rw-r--r--third_party/jpeg-xl/lib/jpegli/error.h5
-rw-r--r--third_party/jpeg-xl/lib/jpegli/error_handling_test.cc21
-rw-r--r--third_party/jpeg-xl/lib/jpegli/huffman.cc5
-rw-r--r--third_party/jpeg-xl/lib/jpegli/idct.cc5
-rw-r--r--third_party/jpeg-xl/lib/jpegli/input.cc18
-rw-r--r--third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc30
-rw-r--r--third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc15
-rw-r--r--third_party/jpeg-xl/lib/jpegli/libjpeg_wrapper.cc4
-rw-r--r--third_party/jpeg-xl/lib/jpegli/memory_manager.h3
-rw-r--r--third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc12
-rw-r--r--third_party/jpeg-xl/lib/jpegli/quant.cc18
-rw-r--r--third_party/jpeg-xl/lib/jpegli/render.cc31
-rw-r--r--third_party/jpeg-xl/lib/jpegli/source_manager.cc4
-rw-r--r--third_party/jpeg-xl/lib/jpegli/source_manager_test.cc4
-rw-r--r--third_party/jpeg-xl/lib/jpegli/streaming_test.cc18
-rw-r--r--third_party/jpeg-xl/lib/jpegli/test_utils-inl.h40
-rw-r--r--third_party/jpeg-xl/lib/jpegli/test_utils.cc81
-rw-r--r--third_party/jpeg-xl/lib/jpegli/testing.h20
-rw-r--r--third_party/jpeg-xl/lib/jpegli/transpose-inl.h8
-rw-r--r--third_party/jpeg-xl/lib/jpegli/upsample.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl.cmake4
-rw-r--r--third_party/jpeg-xl/lib/jxl/ac_strategy.cc13
-rw-r--r--third_party/jpeg-xl/lib/jxl/ac_strategy.h13
-rw-r--r--third_party/jpeg-xl/lib/jxl/ac_strategy_test.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/alpha_test.cc111
-rw-r--r--third_party/jpeg-xl/lib/jxl/ans_common.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/ans_test.cc17
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/bits.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/byte_order.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/common.h44
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/exif.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/float.h10
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/matrix_ops.h78
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/override.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/rational_polynomial-inl.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/scope_guard.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/span.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/status.h15
-rw-r--r--third_party/jpeg-xl/lib/jxl/bits_test.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/blending.cc14
-rw-r--r--third_party/jpeg-xl/lib/jxl/blending.h10
-rw-r--r--third_party/jpeg-xl/lib/jxl/blending_test.cc8
-rw-r--r--third_party/jpeg-xl/lib/jxl/box_content_decoder.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.cc340
-rw-r--r--third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.h45
-rw-r--r--third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli_test.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/cache_aligned.cc3
-rw-r--r--third_party/jpeg-xl/lib/jxl/cache_aligned.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/chroma_from_luma.cc22
-rw-r--r--third_party/jpeg-xl/lib/jxl/chroma_from_luma.h11
-rw-r--r--third_party/jpeg-xl/lib/jxl/cms/color_encoding_cms.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/cms/jxl_cms.cc95
-rw-r--r--third_party/jpeg-xl/lib/jxl/cms/jxl_cms_internal.h179
-rw-r--r--third_party/jpeg-xl/lib/jxl/cms/opsin_params.h27
-rw-r--r--third_party/jpeg-xl/lib/jxl/cms/tone_mapping-inl.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h52
-rw-r--r--third_party/jpeg-xl/lib/jxl/cms/tone_mapping_test.cc30
-rw-r--r--third_party/jpeg-xl/lib/jxl/coeff_order.h25
-rw-r--r--third_party/jpeg-xl/lib/jxl/color_encoding_internal.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/color_encoding_internal.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/color_encoding_internal_test.cc23
-rw-r--r--third_party/jpeg-xl/lib/jxl/color_management_test.cc226
-rw-r--r--third_party/jpeg-xl/lib/jxl/common.h32
-rw-r--r--third_party/jpeg-xl/lib/jxl/compressed_dc.cc40
-rw-r--r--third_party/jpeg-xl/lib/jxl/compressed_dc.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve-inl.h20
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve_separable5.cc10
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve_symmetric3.cc11
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve_symmetric5.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve_test.cc33
-rw-r--r--third_party/jpeg-xl/lib/jxl/dct-inl.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/dct_block-inl.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/dct_util.h13
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_ans.cc14
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_ans.h13
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_cache.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_cache.h27
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_context_map.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_external_image.cc42
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_external_image_gbench.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_frame.cc74
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_frame.h18
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_group.cc39
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_huffman.cc35
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_modular.cc64
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_modular.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_noise.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.cc45
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.h5
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.cc10
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_xyb-inl.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_xyb.cc43
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_xyb.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/decode.cc144
-rw-r--r--third_party/jpeg-xl/lib/jxl/decode_test.cc434
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ac_strategy.cc65
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ac_strategy.h16
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.cc227
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.h19
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ans.cc172
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ans.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ans_params.h11
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ar_control_field.cc30
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ar_control_field.h24
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_aux_out.cc20
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_bit_writer.cc8
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_butteraugli_comparator.cc42
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_butteraugli_comparator.h16
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_cache.cc56
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_cache.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.cc21
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_cluster.cc19
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_cluster.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_coeff_order.cc13
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_comparator.cc27
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_comparator.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_context_map.cc28
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_debug_image.cc78
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_debug_image.h20
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_detect_dots.cc154
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_detect_dots.h5
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.cc19
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.h10
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_entropy_coder.cc20
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_entropy_coder.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_external_image.cc17
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc59
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_fields.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_frame.cc308
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_frame.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_gaborish.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_gaborish.h5
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_gaborish_test.cc14
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_group.cc16
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_heuristics.cc188
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_heuristics.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_huffman.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_huffman_tree.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_icc_codec.cc26
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_icc_codec.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_image_bundle.cc25
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_linalg.cc37
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_linalg.h10
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_linalg_test.cc106
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_modular.cc631
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_modular.h67
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_noise.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_optimize_test.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_params.h39
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc106
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.h19
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_photon_noise_test.cc47
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_quant_weights.cc29
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_quant_weights.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_splines.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_transforms.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_transforms.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_xyb.cc43
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_xyb.h5
-rw-r--r--third_party/jpeg-xl/lib/jxl/encode.cc123
-rw-r--r--third_party/jpeg-xl/lib/jxl/encode_internal.h19
-rw-r--r--third_party/jpeg-xl/lib/jxl/encode_test.cc186
-rw-r--r--third_party/jpeg-xl/lib/jxl/entropy_coder.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/fast_dct-inl.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/fast_dct.cc37
-rw-r--r--third_party/jpeg-xl/lib/jxl/fast_dct.h9
-rw-r--r--third_party/jpeg-xl/lib/jxl/fast_dct_test.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/fast_math_test.cc8
-rw-r--r--third_party/jpeg-xl/lib/jxl/fields.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/fields.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/fields_test.cc25
-rw-r--r--third_party/jpeg-xl/lib/jxl/frame_header.cc14
-rw-r--r--third_party/jpeg-xl/lib/jxl/frame_header.h10
-rw-r--r--third_party/jpeg-xl/lib/jxl/gradient_test.cc116
-rw-r--r--third_party/jpeg-xl/lib/jxl/headers.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/icc_codec.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/icc_codec.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/icc_codec_common.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/icc_codec_common.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/icc_codec_test.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/image.cc210
-rw-r--r--third_party/jpeg-xl/lib/jxl/image.h86
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_bundle.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_metadata.cc16
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_metadata.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_ops.cc91
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_ops.h183
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_ops_test.cc54
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_test_utils.h42
-rw-r--r--third_party/jpeg-xl/lib/jxl/inverse_mtf-inl.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/jpeg/dec_jpeg_data_writer.cc54
-rw-r--r--third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data.cc24
-rw-r--r--third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data_reader.cc8
-rw-r--r--third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data_reader.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/jpeg/jpeg_data.cc13
-rw-r--r--third_party/jpeg-xl/lib/jxl/jxl_test.cc326
-rw-r--r--third_party/jpeg-xl/lib/jxl/libjxl.pc.in4
-rw-r--r--third_party/jpeg-xl/lib/jxl/libjxl_cms.pc.in4
-rw-r--r--third_party/jpeg-xl/lib/jxl/memory_manager_internal.h10
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h12
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/encoding/dec_ma.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/encoding/enc_encoding.cc82
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/encoding/enc_ma.cc15
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc12
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/modular_image.cc35
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/modular_image.h36
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/options.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc38
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/enc_squeeze.cc49
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc19
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/palette.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc19
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/transform.h14
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular_test.cc67
-rw-r--r--third_party/jpeg-xl/lib/jxl/noise.h7
-rw-r--r--third_party/jpeg-xl/lib/jxl/opsin_image_test.cc36
-rw-r--r--third_party/jpeg-xl/lib/jxl/opsin_inverse_test.cc12
-rw-r--r--third_party/jpeg-xl/lib/jxl/opsin_params.cc22
-rw-r--r--third_party/jpeg-xl/lib/jxl/opsin_params.h5
-rw-r--r--third_party/jpeg-xl/lib/jxl/padded_bytes.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/passes_state.cc30
-rw-r--r--third_party/jpeg-xl/lib/jxl/passes_test.cc46
-rw-r--r--third_party/jpeg-xl/lib/jxl/patch_dictionary_test.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/preview_test.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/quant_weights.cc25
-rw-r--r--third_party/jpeg-xl/lib/jxl/quant_weights.h29
-rw-r--r--third_party/jpeg-xl/lib/jxl/quant_weights_test.cc20
-rw-r--r--third_party/jpeg-xl/lib/jxl/quantizer.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/quantizer_test.cc11
-rw-r--r--third_party/jpeg-xl/lib/jxl/rational_polynomial_test.cc10
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.cc131
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.h16
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.cc19
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.h14
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_stage.h14
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_test.cc28
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.cc58
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_blending.cc17
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_chroma_upsampling.cc14
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_cms.cc23
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_epf.cc22
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_from_linear.cc12
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_gaborish.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_noise.cc27
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_patches.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_splines.cc7
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_spot.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_to_linear.cc12
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_tone_mapping.cc12
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_upsampling.cc7
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.cc56
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_xyb.cc22
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_ycbcr.cc7
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/test_render_pipeline_stages.h30
-rw-r--r--third_party/jpeg-xl/lib/jxl/roundtrip_test.cc98
-rw-r--r--third_party/jpeg-xl/lib/jxl/sanitizers.h30
-rw-r--r--third_party/jpeg-xl/lib/jxl/simd_util.cc39
-rw-r--r--third_party/jpeg-xl/lib/jxl/simd_util.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/speed_tier_test.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/splines.cc36
-rw-r--r--third_party/jpeg-xl/lib/jxl/splines.h7
-rw-r--r--third_party/jpeg-xl/lib/jxl/splines_gbench.cc19
-rw-r--r--third_party/jpeg-xl/lib/jxl/splines_test.cc256
-rw-r--r--third_party/jpeg-xl/lib/jxl/test_image.cc20
-rw-r--r--third_party/jpeg-xl/lib/jxl/test_utils.cc57
-rw-r--r--third_party/jpeg-xl/lib/jxl/test_utils.h24
-rw-r--r--third_party/jpeg-xl/lib/jxl/testing.h33
-rw-r--r--third_party/jpeg-xl/lib/jxl/toc.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/transpose-inl.h18
-rw-r--r--third_party/jpeg-xl/lib/jxl/version.h.in2
-rw-r--r--third_party/jpeg-xl/lib/jxl_cms.cmake2
-rw-r--r--third_party/jpeg-xl/lib/jxl_lists.bzl3
-rw-r--r--third_party/jpeg-xl/lib/jxl_lists.cmake3
-rw-r--r--third_party/jpeg-xl/lib/jxl_tests.cmake1
-rw-r--r--third_party/jpeg-xl/lib/jxl_vars.bzl5
-rw-r--r--third_party/jpeg-xl/lib/nothing.cc7
-rw-r--r--third_party/jpeg-xl/lib/threads/thread_parallel_runner.cc10
-rw-r--r--third_party/jpeg-xl/lib/threads/thread_parallel_runner_internal.cc7
-rw-r--r--third_party/jpeg-xl/lib/threads/thread_parallel_runner_internal.h4
350 files changed, 6604 insertions, 5494 deletions
diff --git a/third_party/jpeg-xl/lib/BUILD b/third_party/jpeg-xl/lib/BUILD
index 39e61de0eb..d93858f22d 100644
--- a/third_party/jpeg-xl/lib/BUILD
+++ b/third_party/jpeg-xl/lib/BUILD
@@ -23,8 +23,8 @@ load(
"libjxl_enc_sources",
"libjxl_extras_for_tools_sources",
"libjxl_extras_sources",
- #'libjxl_gbench_sources',
- "libjxl_jpegli_lib_version",
+ # "libjxl_gbench_sources",
+ # "libjxl_jpegli_lib_version",
"libjxl_jpegli_libjpeg_helper_files",
"libjxl_jpegli_sources",
"libjxl_jpegli_testlib_files",
@@ -51,13 +51,14 @@ load(
"libjxl_deps_png",
"libjxl_deps_runfiles",
"libjxl_deps_skcms",
- "libjxl_deps_testdata",
+ # "libjxl_deps_testdata",
+ # "libjxl_deps_webp",
"libjxl_root_package",
"libjxl_test_shards",
"libjxl_test_timeouts",
)
-load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
+load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
DEFAULT_VISIBILITY = ["//:__subpackages__"]
@@ -66,7 +67,7 @@ DEFAULT_COMPATIBILITY = []
INCLUDES_DIR = "include"
package(
- default_visibility = ["//:__subpackages__"],
+ default_visibility = DEFAULT_VISIBILITY,
)
licenses(["notice"])
diff --git a/third_party/jpeg-xl/lib/CMakeLists.txt b/third_party/jpeg-xl/lib/CMakeLists.txt
index 938f15dcbb..1e6f4abf74 100644
--- a/third_party/jpeg-xl/lib/CMakeLists.txt
+++ b/third_party/jpeg-xl/lib/CMakeLists.txt
@@ -149,6 +149,16 @@ else()
set(PKGCONFIG_TARGET_LIBS "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
endif()
+include(CheckCXXSymbolExists)
+set(PKGCONFIG_CXX_LIB "")
+check_cxx_symbol_exists(__GLIBCXX__ iostream LIBSTDCXX)
+check_cxx_symbol_exists(_LIBCPP_VERSION iostream LIBCXX)
+if(LIBSTDCXX)
+ set(PKGCONFIG_CXX_LIB "-lstdc++")
+elseif(LIBCXX)
+ set(PKGCONFIG_CXX_LIB "-lc++")
+endif()
+
# The jxl_cms library definition.
include(jxl_cms.cmake)
# The jxl library definition.
diff --git a/third_party/jpeg-xl/lib/extras/alpha_blend.cc b/third_party/jpeg-xl/lib/extras/alpha_blend.cc
index 50c141c6fb..afb37b0a7d 100644
--- a/third_party/jpeg-xl/lib/extras/alpha_blend.cc
+++ b/third_party/jpeg-xl/lib/extras/alpha_blend.cc
@@ -12,7 +12,7 @@ namespace extras {
namespace {
-void AlphaBlend(PackedFrame* frame, float background[3]) {
+void AlphaBlend(PackedFrame* frame, const float background[3]) {
if (!frame) return;
const PackedImage& im = frame->color;
JxlPixelFormat format = im.format;
@@ -20,7 +20,8 @@ void AlphaBlend(PackedFrame* frame, float background[3]) {
return;
}
--format.num_channels;
- PackedImage blended(im.xsize, im.ysize, format);
+ JXL_ASSIGN_OR_DIE(PackedImage blended,
+ PackedImage::Create(im.xsize, im.ysize, format));
// TODO(szabadka) SIMDify this and make it work for float16.
for (size_t y = 0; y < im.ysize; ++y) {
for (size_t x = 0; x < im.xsize; ++x) {
@@ -48,7 +49,7 @@ void AlphaBlend(PackedFrame* frame, float background[3]) {
} // namespace
-void AlphaBlend(PackedPixelFile* ppf, float background[3]) {
+void AlphaBlend(PackedPixelFile* ppf, const float background[3]) {
if (!ppf || ppf->info.alpha_bits == 0) {
return;
}
diff --git a/third_party/jpeg-xl/lib/extras/alpha_blend.h b/third_party/jpeg-xl/lib/extras/alpha_blend.h
index 4d78e8681b..e49349393c 100644
--- a/third_party/jpeg-xl/lib/extras/alpha_blend.h
+++ b/third_party/jpeg-xl/lib/extras/alpha_blend.h
@@ -11,7 +11,7 @@
namespace jxl {
namespace extras {
-void AlphaBlend(PackedPixelFile* ppf, float background[3]);
+void AlphaBlend(PackedPixelFile* ppf, const float background[3]);
} // namespace extras
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/extras/codec.h b/third_party/jpeg-xl/lib/extras/codec.h
index b7bc2a397e..9fd61503cb 100644
--- a/third_party/jpeg-xl/lib/extras/codec.h
+++ b/third_party/jpeg-xl/lib/extras/codec.h
@@ -43,7 +43,7 @@ JXL_INLINE Status SetFromBytes(const Span<const uint8_t> bytes, CodecInOut* io,
orig_codec);
}
-Status Encode(const extras::PackedPixelFile& ppf, const extras::Codec codec,
+Status Encode(const extras::PackedPixelFile& ppf, extras::Codec codec,
std::vector<uint8_t>* bytes, ThreadPool* pool);
Status Encode(const extras::PackedPixelFile& ppf, const std::string& pathname,
diff --git a/third_party/jpeg-xl/lib/extras/codec_test.cc b/third_party/jpeg-xl/lib/extras/codec_test.cc
index 4d8a60cb33..50d5e37bc9 100644
--- a/third_party/jpeg-xl/lib/extras/codec_test.cc
+++ b/third_party/jpeg-xl/lib/extras/codec_test.cc
@@ -40,12 +40,6 @@ using test::ThreadPoolForTests;
namespace extras {
namespace {
-using ::testing::AllOf;
-using ::testing::Contains;
-using ::testing::Field;
-using ::testing::IsEmpty;
-using ::testing::SizeIs;
-
std::string ExtensionFromCodec(Codec codec, const bool is_gray,
const bool has_alpha,
const size_t bits_per_sample) {
@@ -78,8 +72,8 @@ void VerifySameImage(const PackedImage& im0, size_t bits_per_sample0,
};
double factor0 = get_factor(im0.format, bits_per_sample0);
double factor1 = get_factor(im1.format, bits_per_sample1);
- auto pixels0 = static_cast<const uint8_t*>(im0.pixels());
- auto pixels1 = static_cast<const uint8_t*>(im1.pixels());
+ const auto* pixels0 = static_cast<const uint8_t*>(im0.pixels());
+ const auto* pixels1 = static_cast<const uint8_t*>(im1.pixels());
auto rgba0 =
test::ConvertToRGBA32(pixels0, im0.xsize, im0.ysize, im0.format, factor0);
auto rgba1 =
@@ -227,19 +221,23 @@ void CreateTestImage(const TestImageParams& params, PackedPixelFile* ppf) {
ppf->info.exponent_bits_per_sample = params.bits_per_sample == 32 ? 8 : 0;
ppf->info.num_color_channels = params.is_gray ? 1 : 3;
ppf->info.alpha_bits = params.add_alpha ? params.bits_per_sample : 0;
- ppf->info.alpha_premultiplied = (params.codec == Codec::kEXR);
+ ppf->info.alpha_premultiplied = TO_JXL_BOOL(params.codec == Codec::kEXR);
JxlColorEncoding color_encoding = CreateTestColorEncoding(params.is_gray);
ppf->icc = GenerateICC(color_encoding);
ppf->color_encoding = color_encoding;
- PackedFrame frame(params.xsize, params.ysize, params.PixelFormat());
+ JXL_ASSIGN_OR_DIE(
+ PackedFrame frame,
+ PackedFrame::Create(params.xsize, params.ysize, params.PixelFormat()));
FillPackedImage(params.bits_per_sample, &frame.color);
if (params.add_extra_channels) {
for (size_t i = 0; i < 7; ++i) {
JxlPixelFormat ec_format = params.PixelFormat();
ec_format.num_channels = 1;
- PackedImage ec(params.xsize, params.ysize, ec_format);
+ JXL_ASSIGN_OR_DIE(
+ PackedImage ec,
+ PackedImage::Create(params.xsize, params.ysize, ec_format));
FillPackedImage(params.bits_per_sample, &ec);
frame.extra_channels.emplace_back(std::move(ec));
PackedExtraChannel pec;
@@ -432,15 +430,17 @@ TEST(CodecTest, EncodeToPNG) {
ASSERT_TRUE(extras::DecodeBytes(Bytes(original_png), ColorHints(), &ppf));
const JxlPixelFormat& format = ppf.frames.front().color.format;
- ASSERT_THAT(
- png_encoder->AcceptedFormats(),
- Contains(AllOf(Field(&JxlPixelFormat::num_channels, format.num_channels),
- Field(&JxlPixelFormat::data_type, format.data_type),
- Field(&JxlPixelFormat::endianness, format.endianness))));
+ const auto& format_matcher = [&format](const JxlPixelFormat& candidate) {
+ return (candidate.num_channels == format.num_channels) &&
+ (candidate.data_type == format.data_type) &&
+ (candidate.endianness == format.endianness);
+ };
+ const auto formats = png_encoder->AcceptedFormats();
+ ASSERT_TRUE(std::any_of(formats.begin(), formats.end(), format_matcher));
EncodedImage encoded_png;
ASSERT_TRUE(png_encoder->Encode(ppf, &encoded_png, pool));
- EXPECT_THAT(encoded_png.icc, IsEmpty());
- ASSERT_THAT(encoded_png.bitstreams, SizeIs(1));
+ EXPECT_TRUE(encoded_png.icc.empty());
+ ASSERT_EQ(encoded_png.bitstreams.size(), 1);
PackedPixelFile decoded_ppf;
ASSERT_TRUE(extras::DecodeBytes(Bytes(encoded_png.bitstreams.front()),
diff --git a/third_party/jpeg-xl/lib/extras/dec/apng.cc b/third_party/jpeg-xl/lib/extras/dec/apng.cc
index f77dab77d1..8b0da06eb1 100644
--- a/third_party/jpeg-xl/lib/extras/dec/apng.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/apng.cc
@@ -71,9 +71,7 @@ const png_byte kIgnoredPngChunks[] = {
};
// Returns floating-point value from the PNG encoding (times 10^5).
-static double F64FromU32(const uint32_t x) {
- return static_cast<int32_t>(x) * 1E-5;
-}
+double F64FromU32(const uint32_t x) { return static_cast<int32_t>(x) * 1E-5; }
Status DecodeSRGB(const unsigned char* payload, const size_t payload_size,
JxlColorEncoding* color_encoding) {
@@ -402,7 +400,8 @@ class BlobsReaderPNG {
}
if (pos + 2 >= encoded_end) return false; // Truncated base16 2;
- uint32_t nibble0, nibble1;
+ uint32_t nibble0;
+ uint32_t nibble1;
JXL_RETURN_IF_ERROR(DecodeNibble(pos[0], &nibble0));
JXL_RETURN_IF_ERROR(DecodeNibble(pos[1], &nibble1));
bytes->push_back(static_cast<uint8_t>((nibble0 << 4) + nibble1));
@@ -432,9 +431,22 @@ constexpr uint32_t kId_cHRM = 0x4D524863;
constexpr uint32_t kId_eXIf = 0x66495865;
struct APNGFrame {
- std::vector<uint8_t> pixels;
+ APNGFrame() : pixels(nullptr, free) {}
+ std::unique_ptr<void, decltype(free)*> pixels;
+ size_t pixels_size = 0;
std::vector<uint8_t*> rows;
unsigned int w, h, delay_num, delay_den;
+ Status Resize(size_t new_size) {
+ if (new_size > pixels_size) {
+ pixels.reset(malloc(new_size));
+ if (!pixels.get()) {
+ // TODO(szabadka): use specialized OOM error code
+ return JXL_FAILURE("Failed to allocate memory for image buffer");
+ }
+ pixels_size = new_size;
+ }
+ return true;
+ }
};
struct Reader {
@@ -447,7 +459,7 @@ struct Reader {
next += to_copy;
return (len == to_copy);
}
- bool Eof() { return next == last; }
+ bool Eof() const { return next == last; }
};
const unsigned long cMaxPNGSize = 1000000UL;
@@ -463,10 +475,11 @@ void info_fn(png_structp png_ptr, png_infop info_ptr) {
void row_fn(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num,
int pass) {
- APNGFrame* frame = (APNGFrame*)png_get_progressive_ptr(png_ptr);
+ APNGFrame* frame =
+ reinterpret_cast<APNGFrame*>(png_get_progressive_ptr(png_ptr));
JXL_CHECK(frame);
JXL_CHECK(row_num < frame->rows.size());
- JXL_CHECK(frame->rows[row_num] < frame->pixels.data() + frame->pixels.size());
+ JXL_CHECK(frame->rows[row_num] < frame->rows[0] + frame->pixels_size);
png_progressive_combine_row(png_ptr, frame->rows[row_num], new_row);
}
@@ -494,12 +507,13 @@ int processing_start(png_structp& png_ptr, png_infop& info_ptr, void* frame_ptr,
unsigned char header[8] = {137, 80, 78, 71, 13, 10, 26, 10};
// Cleanup prior decoder, if any.
- png_destroy_read_struct(&png_ptr, &info_ptr, 0);
+ png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
// Just in case. Not all versions on libpng wipe-out the pointers.
png_ptr = nullptr;
info_ptr = nullptr;
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ png_ptr =
+ png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
info_ptr = png_create_info_struct(png_ptr);
if (!png_ptr || !info_ptr) return 1;
@@ -508,18 +522,17 @@ int processing_start(png_structp& png_ptr, png_infop& info_ptr, void* frame_ptr,
}
png_set_keep_unknown_chunks(png_ptr, 1, kIgnoredPngChunks,
- (int)sizeof(kIgnoredPngChunks) / 5);
+ static_cast<int>(sizeof(kIgnoredPngChunks) / 5));
png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
- png_set_progressive_read_fn(png_ptr, frame_ptr, info_fn, row_fn, NULL);
+ png_set_progressive_read_fn(png_ptr, frame_ptr, info_fn, row_fn, nullptr);
png_process_data(png_ptr, info_ptr, header, 8);
png_process_data(png_ptr, info_ptr, chunkIHDR.data(), chunkIHDR.size());
if (hasInfo) {
- for (unsigned int i = 0; i < chunksInfo.size(); i++) {
- png_process_data(png_ptr, info_ptr, chunksInfo[i].data(),
- chunksInfo[i].size());
+ for (auto& chunk : chunksInfo) {
+ png_process_data(png_ptr, info_ptr, chunk.data(), chunk.size());
}
}
return 0;
@@ -575,8 +588,6 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
const SizeConstraints* constraints) {
#if JPEGXL_ENABLE_APNG
Reader r;
- unsigned int id, j, w, h, w0, h0, x0, y0;
- unsigned int delay_num, delay_den, dop, bop, rowbytes, imagesize;
unsigned char sig[8];
png_structp png_ptr = nullptr;
png_infop info_ptr = nullptr;
@@ -588,7 +599,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
bool seenFctl = false;
APNGFrame frameRaw = {};
uint32_t num_channels;
- JxlPixelFormat format;
+ JxlPixelFormat format = {};
unsigned int bytes_per_pixel = 0;
struct FrameInfo {
@@ -604,7 +615,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
// Make sure png memory is released in any case.
auto scope_guard = MakeScopeGuard([&]() {
- png_destroy_read_struct(&png_ptr, &info_ptr, 0);
+ png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
// Just in case. Not all versions on libpng wipe-out the pointers.
png_ptr = nullptr;
info_ptr = nullptr;
@@ -616,7 +627,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
if (!r.Read(sig, 8) || memcmp(sig, png_signature, 8) != 0) {
return false;
}
- id = read_chunk(&r, &chunkIHDR);
+ unsigned int id = read_chunk(&r, &chunkIHDR);
ppf->info.exponent_bits_per_sample = 0;
ppf->info.alpha_exponent_bits = 0;
@@ -625,18 +636,22 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
ppf->frames.clear();
bool have_color = false;
- bool have_cicp = false, have_iccp = false, have_srgb = false;
+ bool have_cicp = false;
+ bool have_iccp = false;
+ bool have_srgb = false;
bool errorstate = true;
if (id == kId_IHDR && chunkIHDR.size() == 25) {
- x0 = 0;
- y0 = 0;
- delay_num = 1;
- delay_den = 10;
- dop = 0;
- bop = 0;
-
- w0 = w = png_get_uint_32(chunkIHDR.data() + 8);
- h0 = h = png_get_uint_32(chunkIHDR.data() + 12);
+ unsigned int x0 = 0;
+ unsigned int y0 = 0;
+ unsigned int delay_num = 1;
+ unsigned int delay_den = 10;
+ unsigned int dop = 0;
+ unsigned int bop = 0;
+
+ unsigned int w = png_get_uint_32(chunkIHDR.data() + 8);
+ unsigned int h = png_get_uint_32(chunkIHDR.data() + 12);
+ unsigned int w0 = w;
+ unsigned int h0 = h;
if (w > cMaxPNGSize || h > cMaxPNGSize) {
return false;
}
@@ -648,8 +663,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
ppf->color_encoding.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
ppf->color_encoding.rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
- if (!processing_start(png_ptr, info_ptr, (void*)&frameRaw, hasInfo,
- chunkIHDR, chunksInfo)) {
+ if (!processing_start(png_ptr, info_ptr, static_cast<void*>(&frameRaw),
+ hasInfo, chunkIHDR, chunksInfo)) {
while (!r.Eof()) {
id = read_chunk(&r, &chunk);
if (!id) break;
@@ -657,7 +672,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
if (id == kId_acTL && !hasInfo && !isAnimated) {
isAnimated = true;
- ppf->info.have_animation = true;
+ ppf->info.have_animation = JXL_TRUE;
ppf->info.animation.tps_numerator = 1000;
ppf->info.animation.tps_denominator = 1;
} else if (id == kId_IEND ||
@@ -666,8 +681,10 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
if (!processing_finish(png_ptr, info_ptr, &ppf->metadata)) {
// Allocates the frame buffer.
uint32_t duration = delay_num * 1000 / delay_den;
- frames.push_back(FrameInfo{PackedImage(w0, h0, format), duration,
- x0, w0, y0, h0, dop, bop});
+ JXL_ASSIGN_OR_RETURN(PackedImage image,
+ PackedImage::Create(w0, h0, format));
+ frames.push_back(FrameInfo{std::move(image), duration, x0, w0, y0,
+ h0, dop, bop});
auto& frame = frames.back().data;
for (size_t y = 0; y < h0; ++y) {
memcpy(static_cast<uint8_t*>(frame.pixels()) + frame.stride * y,
@@ -707,7 +724,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
if (hasInfo) {
memcpy(chunkIHDR.data() + 8, chunk.data() + 12, 8);
- if (processing_start(png_ptr, info_ptr, (void*)&frameRaw, hasInfo,
+ if (processing_start(png_ptr, info_ptr,
+ static_cast<void*>(&frameRaw), hasInfo,
chunkIHDR, chunksInfo)) {
break;
}
@@ -724,7 +742,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
int colortype = png_get_color_type(png_ptr, info_ptr);
int png_bit_depth = png_get_bit_depth(png_ptr, info_ptr);
ppf->info.bits_per_sample = png_bit_depth;
- png_color_8p sigbits = NULL;
+ png_color_8p sigbits = nullptr;
png_get_sBIT(png_ptr, info_ptr, &sigbits);
if (colortype & 1) {
// palette will actually be 8-bit regardless of the index bitdepth
@@ -784,12 +802,18 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
}
bytes_per_pixel =
num_channels * (format.data_type == JXL_TYPE_UINT16 ? 2 : 1);
- rowbytes = w * bytes_per_pixel;
- imagesize = h * rowbytes;
- frameRaw.pixels.resize(imagesize);
+ size_t rowbytes = w * bytes_per_pixel;
+ if (h > std::numeric_limits<size_t>::max() / rowbytes) {
+ return JXL_FAILURE("Image too big.");
+ }
+ size_t imagesize = h * rowbytes;
+ JXL_RETURN_IF_ERROR(frameRaw.Resize(imagesize));
frameRaw.rows.resize(h);
- for (j = 0; j < h; j++)
- frameRaw.rows[j] = frameRaw.pixels.data() + j * rowbytes;
+ for (size_t j = 0; j < h; j++) {
+ frameRaw.rows[j] =
+ reinterpret_cast<uint8_t*>(frameRaw.pixels.get()) +
+ j * rowbytes;
+ }
if (processing_data(png_ptr, info_ptr, chunk.data(), chunk.size())) {
break;
@@ -813,6 +837,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
have_cicp = true;
have_color = true;
ppf->icc.clear();
+ ppf->primary_color_representation =
+ PackedPixelFile::kColorEncodingIsPrimary;
}
} else if (!have_cicp && id == kId_iCCP) {
if (processing_data(png_ptr, info_ptr, chunk.data(), chunk.size())) {
@@ -830,6 +856,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
&profile, &proflen);
if (ok && proflen) {
ppf->icc.assign(profile, profile + proflen);
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
have_color = true;
have_iccp = true;
} else {
@@ -922,7 +949,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
py0 + pys >= y0 + ysize && use_for_next_frame) {
// If the new frame is contained within the old frame, we can pad the
// new frame with zeros and not blend.
- PackedImage new_data(pxs, pys, frame.data.format);
+ JXL_ASSIGN_OR_RETURN(PackedImage new_data,
+ PackedImage::Create(pxs, pys, frame.data.format));
memset(new_data.pixels(), 0, new_data.pixels_size);
for (size_t y = 0; y < ysize; y++) {
size_t bytes_per_pixel =
@@ -944,7 +972,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
ppf->frames.emplace_back(std::move(new_data));
} else {
// If all else fails, insert a placeholder blank frame with kReplace.
- PackedImage blank(pxs, pys, frame.data.format);
+ JXL_ASSIGN_OR_RETURN(PackedImage blank,
+ PackedImage::Create(pxs, pys, frame.data.format));
memset(blank.pixels(), 0, blank.pixels_size);
ppf->frames.emplace_back(std::move(blank));
auto& pframe = ppf->frames.back();
@@ -984,7 +1013,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
has_nontrivial_background && frame.dispose_op == DISPOSE_OP_BACKGROUND;
}
if (ppf->frames.empty()) return JXL_FAILURE("No frames decoded");
- ppf->frames.back().frame_info.is_last = true;
+ ppf->frames.back().frame_info.is_last = JXL_TRUE;
return true;
#else
diff --git a/third_party/jpeg-xl/lib/extras/dec/color_description.cc b/third_party/jpeg-xl/lib/extras/dec/color_description.cc
index 54f6aa4206..bf229632d0 100644
--- a/third_party/jpeg-xl/lib/extras/dec/color_description.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/color_description.cc
@@ -9,6 +9,8 @@
#include <cmath>
+#include "lib/jxl/base/common.h"
+
namespace jxl {
namespace {
@@ -19,49 +21,46 @@ struct EnumName {
T value;
};
-const EnumName<JxlColorSpace> kJxlColorSpaceNames[] = {
- {"RGB", JXL_COLOR_SPACE_RGB},
- {"Gra", JXL_COLOR_SPACE_GRAY},
- {"XYB", JXL_COLOR_SPACE_XYB},
- {"CS?", JXL_COLOR_SPACE_UNKNOWN},
-};
-
-const EnumName<JxlWhitePoint> kJxlWhitePointNames[] = {
- {"D65", JXL_WHITE_POINT_D65},
- {"Cst", JXL_WHITE_POINT_CUSTOM},
- {"EER", JXL_WHITE_POINT_E},
- {"DCI", JXL_WHITE_POINT_DCI},
-};
-
-const EnumName<JxlPrimaries> kJxlPrimariesNames[] = {
- {"SRG", JXL_PRIMARIES_SRGB},
- {"Cst", JXL_PRIMARIES_CUSTOM},
- {"202", JXL_PRIMARIES_2100},
- {"DCI", JXL_PRIMARIES_P3},
-};
-
-const EnumName<JxlTransferFunction> kJxlTransferFunctionNames[] = {
- {"709", JXL_TRANSFER_FUNCTION_709},
- {"TF?", JXL_TRANSFER_FUNCTION_UNKNOWN},
- {"Lin", JXL_TRANSFER_FUNCTION_LINEAR},
- {"SRG", JXL_TRANSFER_FUNCTION_SRGB},
- {"PeQ", JXL_TRANSFER_FUNCTION_PQ},
- {"DCI", JXL_TRANSFER_FUNCTION_DCI},
- {"HLG", JXL_TRANSFER_FUNCTION_HLG},
- {"", JXL_TRANSFER_FUNCTION_GAMMA},
-};
-
-const EnumName<JxlRenderingIntent> kJxlRenderingIntentNames[] = {
- {"Per", JXL_RENDERING_INTENT_PERCEPTUAL},
- {"Rel", JXL_RENDERING_INTENT_RELATIVE},
- {"Sat", JXL_RENDERING_INTENT_SATURATION},
- {"Abs", JXL_RENDERING_INTENT_ABSOLUTE},
-};
-
-template <typename T>
-Status ParseEnum(const std::string& token, const EnumName<T>* enum_values,
- size_t enum_len, T* value) {
- for (size_t i = 0; i < enum_len; i++) {
+constexpr auto kJxlColorSpaceNames =
+ to_array<EnumName<JxlColorSpace>>({{"RGB", JXL_COLOR_SPACE_RGB},
+ {"Gra", JXL_COLOR_SPACE_GRAY},
+ {"XYB", JXL_COLOR_SPACE_XYB},
+ {"CS?", JXL_COLOR_SPACE_UNKNOWN}});
+
+constexpr auto kJxlWhitePointNames =
+ to_array<EnumName<JxlWhitePoint>>({{"D65", JXL_WHITE_POINT_D65},
+ {"Cst", JXL_WHITE_POINT_CUSTOM},
+ {"EER", JXL_WHITE_POINT_E},
+ {"DCI", JXL_WHITE_POINT_DCI}});
+
+constexpr auto kJxlPrimariesNames =
+ to_array<EnumName<JxlPrimaries>>({{"SRG", JXL_PRIMARIES_SRGB},
+ {"Cst", JXL_PRIMARIES_CUSTOM},
+ {"202", JXL_PRIMARIES_2100},
+ {"DCI", JXL_PRIMARIES_P3}});
+
+constexpr auto kJxlTransferFunctionNames =
+ to_array<EnumName<JxlTransferFunction>>(
+ {{"709", JXL_TRANSFER_FUNCTION_709},
+ {"TF?", JXL_TRANSFER_FUNCTION_UNKNOWN},
+ {"Lin", JXL_TRANSFER_FUNCTION_LINEAR},
+ {"SRG", JXL_TRANSFER_FUNCTION_SRGB},
+ {"PeQ", JXL_TRANSFER_FUNCTION_PQ},
+ {"DCI", JXL_TRANSFER_FUNCTION_DCI},
+ {"HLG", JXL_TRANSFER_FUNCTION_HLG},
+ {"", JXL_TRANSFER_FUNCTION_GAMMA}});
+
+constexpr auto kJxlRenderingIntentNames =
+ to_array<EnumName<JxlRenderingIntent>>(
+ {{"Per", JXL_RENDERING_INTENT_PERCEPTUAL},
+ {"Rel", JXL_RENDERING_INTENT_RELATIVE},
+ {"Sat", JXL_RENDERING_INTENT_SATURATION},
+ {"Abs", JXL_RENDERING_INTENT_ABSOLUTE}});
+
+template <typename T, size_t N>
+Status ParseEnum(const std::string& token,
+ const std::array<EnumName<T>, N>& enum_values, T* value) {
+ for (size_t i = 0; i < enum_values.size(); i++) {
if (enum_values[i].name == token) {
*value = enum_values[i].value;
return true;
@@ -69,9 +68,6 @@ Status ParseEnum(const std::string& token, const EnumName<T>* enum_values,
}
return false;
}
-#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
-#define PARSE_ENUM(type, token, value) \
- ParseEnum<type>(token, k##type##Names, ARRAY_SIZE(k##type##Names), value)
class Tokenizer {
public:
@@ -122,7 +118,7 @@ Status ParseColorSpace(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
JxlColorSpace cs;
- if (PARSE_ENUM(JxlColorSpace, str, &cs)) {
+ if (ParseEnum(str, kJxlColorSpaceNames, &cs)) {
c->color_space = cs;
return true;
}
@@ -139,7 +135,7 @@ Status ParseWhitePoint(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
- if (PARSE_ENUM(JxlWhitePoint, str, &c->white_point)) return true;
+ if (ParseEnum(str, kJxlWhitePointNames, &c->white_point)) return true;
Tokenizer xy_tokenizer(&str, ';');
c->white_point = JXL_WHITE_POINT_CUSTOM;
@@ -157,7 +153,7 @@ Status ParsePrimaries(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
- if (PARSE_ENUM(JxlPrimaries, str, &c->primaries)) return true;
+ if (ParseEnum(str, kJxlPrimariesNames, &c->primaries)) return true;
Tokenizer xy_tokenizer(&str, ';');
JXL_RETURN_IF_ERROR(ParseDouble(&xy_tokenizer, c->primaries_red_xy + 0));
@@ -174,7 +170,8 @@ Status ParsePrimaries(Tokenizer* tokenizer, JxlColorEncoding* c) {
Status ParseRenderingIntent(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
- if (PARSE_ENUM(JxlRenderingIntent, str, &c->rendering_intent)) return true;
+ if (ParseEnum(str, kJxlRenderingIntentNames, &c->rendering_intent))
+ return true;
return JXL_FAILURE("Invalid RenderingIntent %s\n", str.c_str());
}
@@ -189,7 +186,7 @@ Status ParseTransferFunction(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
- if (PARSE_ENUM(JxlTransferFunction, str, &c->transfer_function)) {
+ if (ParseEnum(str, kJxlTransferFunctionNames, &c->transfer_function)) {
return true;
}
diff --git a/third_party/jpeg-xl/lib/extras/dec/color_hints.cc b/third_party/jpeg-xl/lib/extras/dec/color_hints.cc
index 5c6d7b84a0..b1edd9f6ea 100644
--- a/third_party/jpeg-xl/lib/extras/dec/color_hints.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/color_hints.cc
@@ -43,20 +43,21 @@ Status ApplyColorHints(const ColorHints& color_hints,
} else if (key == "icc") {
const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data());
std::vector<uint8_t> icc(data, data + value.size());
- ppf->icc.swap(icc);
+ ppf->icc = std::move(icc);
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
got_color_space = true;
} else if (key == "exif") {
const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data());
std::vector<uint8_t> blob(data, data + value.size());
- ppf->metadata.exif.swap(blob);
+ ppf->metadata.exif = std::move(blob);
} else if (key == "xmp") {
const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data());
std::vector<uint8_t> blob(data, data + value.size());
- ppf->metadata.xmp.swap(blob);
+ ppf->metadata.xmp = std::move(blob);
} else if (key == "jumbf") {
const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data());
std::vector<uint8_t> blob(data, data + value.size());
- ppf->metadata.jumbf.swap(blob);
+ ppf->metadata.jumbf = std::move(blob);
} else {
JXL_WARNING("Ignoring %s hint", key.c_str());
}
diff --git a/third_party/jpeg-xl/lib/extras/dec/decode.cc b/third_party/jpeg-xl/lib/extras/dec/decode.cc
index b3ca711bb2..3546cb65c0 100644
--- a/third_party/jpeg-xl/lib/extras/dec/decode.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/decode.cc
@@ -35,7 +35,8 @@ std::string GetExtension(const std::string& path) {
} // namespace
-Codec CodecFromPath(std::string path, size_t* JXL_RESTRICT bits_per_sample,
+Codec CodecFromPath(const std::string& path,
+ size_t* JXL_RESTRICT bits_per_sample,
std::string* extension) {
std::string ext = GetExtension(path);
if (extension) {
@@ -98,7 +99,7 @@ Status DecodeBytes(const Span<const uint8_t> bytes,
*ppf = extras::PackedPixelFile();
// Default values when not set by decoders.
- ppf->info.uses_original_profile = true;
+ ppf->info.uses_original_profile = JXL_TRUE;
ppf->info.orientation = JXL_ORIENT_IDENTITY;
const auto choose_codec = [&]() -> Codec {
@@ -116,6 +117,7 @@ Status DecodeBytes(const Span<const uint8_t> bytes,
dparams.accepted_formats.push_back(
{num_channels, JXL_TYPE_FLOAT, JXL_LITTLE_ENDIAN, /*align=*/0});
}
+ dparams.output_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM;
size_t decoded_bytes;
if (DecodeImageJXL(bytes.data(), bytes.size(), dparams, &decoded_bytes,
ppf) &&
diff --git a/third_party/jpeg-xl/lib/extras/dec/decode.h b/third_party/jpeg-xl/lib/extras/dec/decode.h
index 0d7dfcbef2..1a90f4c6a3 100644
--- a/third_party/jpeg-xl/lib/extras/dec/decode.h
+++ b/third_party/jpeg-xl/lib/extras/dec/decode.h
@@ -40,7 +40,7 @@ bool CanDecode(Codec codec);
// If and only if extension is ".pfm", *bits_per_sample is updated to 32 so
// that Encode() would encode to PFM instead of PPM.
-Codec CodecFromPath(std::string path,
+Codec CodecFromPath(const std::string& path,
size_t* JXL_RESTRICT bits_per_sample = nullptr,
std::string* extension = nullptr);
diff --git a/third_party/jpeg-xl/lib/extras/dec/exr.cc b/third_party/jpeg-xl/lib/extras/dec/exr.cc
index 821e0f4b21..d5903155e9 100644
--- a/third_party/jpeg-xl/lib/extras/dec/exr.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/exr.cc
@@ -121,7 +121,12 @@ Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints,
};
ppf->frames.clear();
// Allocates the frame buffer.
- ppf->frames.emplace_back(image_size.x, image_size.y, format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(image_size.x, image_size.y, format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
const auto& frame = ppf->frames.back();
const int row_size = input.dataWindow().size().x + 1;
@@ -188,7 +193,7 @@ Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints,
if (has_alpha) {
ppf->info.alpha_bits = kExrAlphaBits;
ppf->info.alpha_exponent_bits = ppf->info.exponent_bits_per_sample;
- ppf->info.alpha_premultiplied = true;
+ ppf->info.alpha_premultiplied = JXL_TRUE;
}
ppf->info.intensity_target = intensity_target;
return true;
diff --git a/third_party/jpeg-xl/lib/extras/dec/gif.cc b/third_party/jpeg-xl/lib/extras/dec/gif.cc
index 3d963941c0..3f89d460b8 100644
--- a/third_party/jpeg-xl/lib/extras/dec/gif.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/gif.cc
@@ -50,8 +50,10 @@ void ensure_have_alpha(PackedFrame* frame) {
/*endianness=*/JXL_NATIVE_ENDIAN,
/*align=*/0,
};
- frame->extra_channels.emplace_back(frame->color.xsize, frame->color.ysize,
- alpha_format);
+ JXL_ASSIGN_OR_DIE(PackedImage image,
+ PackedImage::Create(frame->color.xsize, frame->color.ysize,
+ alpha_format));
+ frame->extra_channels.emplace_back(std::move(image));
// We need to set opaque-by-default.
std::fill_n(static_cast<uint8_t*>(frame->extra_channels[0].pixels()),
frame->color.xsize * frame->color.ysize, 255u);
@@ -136,7 +138,7 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
if (gif->ImageCount > 1) {
- ppf->info.have_animation = true;
+ ppf->info.have_animation = JXL_TRUE;
// Delays in GIF are specified in 100ths of a second.
ppf->info.animation.tps_numerator = 100;
ppf->info.animation.tps_denominator = 1;
@@ -186,7 +188,9 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
const PackedRgba background_rgba{background_color.Red, background_color.Green,
background_color.Blue, 0};
- PackedFrame canvas(gif->SWidth, gif->SHeight, canvas_format);
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame canvas,
+ PackedFrame::Create(gif->SWidth, gif->SHeight, canvas_format));
std::fill_n(static_cast<PackedRgba*>(canvas.color.pixels()),
canvas.color.xsize * canvas.color.ysize, background_rgba);
Rect canvas_rect{0, 0, canvas.color.xsize, canvas.color.ysize};
@@ -230,8 +234,14 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
// Allocates the frame buffer.
- ppf->frames.emplace_back(total_rect.xsize(), total_rect.ysize(),
- packed_frame_format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(total_rect.xsize(), total_rect.ysize(),
+ packed_frame_format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
+
PackedFrame* frame = &ppf->frames.back();
// We cannot tell right from the start whether there will be a
@@ -301,8 +311,10 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
// Update the canvas by creating a copy first.
- PackedImage new_canvas_image(canvas.color.xsize, canvas.color.ysize,
- canvas.color.format);
+ JXL_ASSIGN_OR_RETURN(
+ PackedImage new_canvas_image,
+ PackedImage::Create(canvas.color.xsize, canvas.color.ysize,
+ canvas.color.format));
memcpy(new_canvas_image.pixels(), canvas.color.pixels(),
new_canvas_image.pixels_size);
for (size_t y = 0, byte_index = 0; y < image_rect.ysize(); ++y) {
diff --git a/third_party/jpeg-xl/lib/extras/dec/jpegli.cc b/third_party/jpeg-xl/lib/extras/dec/jpegli.cc
index ffa1b79c25..443dfe86ba 100644
--- a/third_party/jpeg-xl/lib/extras/dec/jpegli.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/jpegli.cc
@@ -27,7 +27,7 @@ constexpr unsigned char kExifSignature[6] = {0x45, 0x78, 0x69,
constexpr int kExifMarker = JPEG_APP0 + 1;
constexpr int kICCMarker = JPEG_APP0 + 2;
-static inline bool IsJPG(const std::vector<uint8_t>& bytes) {
+inline bool IsJPG(const std::vector<uint8_t>& bytes) {
if (bytes.size() < 2) return false;
if (bytes[0] != 0xFF || bytes[1] != 0xD8) return false;
return true;
@@ -188,7 +188,11 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
} else if (dparams.force_grayscale) {
cinfo.out_color_space = JCS_GRAYSCALE;
}
- if (!ReadICCProfile(&cinfo, &ppf->icc)) {
+ if (ReadICCProfile(&cinfo, &ppf->icc)) {
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
+ } else {
+ ppf->primary_color_representation =
+ PackedPixelFile::kColorEncodingIsPrimary;
ppf->icc.clear();
// Default to SRGB
ppf->color_encoding.color_space =
@@ -214,7 +218,7 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
} else {
return failure("unsupported data type");
}
- ppf->info.uses_original_profile = true;
+ ppf->info.uses_original_profile = JXL_TRUE;
// No alpha in JPG
ppf->info.alpha_bits = 0;
@@ -227,8 +231,8 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
if (dparams.num_colors > 0) {
cinfo.quantize_colors = TRUE;
cinfo.desired_number_of_colors = dparams.num_colors;
- cinfo.two_pass_quantize = dparams.two_pass_quant;
- cinfo.dither_mode = (J_DITHER_MODE)dparams.dither_mode;
+ cinfo.two_pass_quantize = static_cast<boolean>(dparams.two_pass_quant);
+ cinfo.dither_mode = static_cast<J_DITHER_MODE>(dparams.dither_mode);
}
jpegli_start_decompress(&cinfo);
@@ -242,7 +246,12 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
};
ppf->frames.clear();
// Allocates the frame buffer.
- ppf->frames.emplace_back(cinfo.image_width, cinfo.image_height, format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(cinfo.image_width, cinfo.image_height, format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
const auto& frame = ppf->frames.back();
JXL_ASSERT(sizeof(JSAMPLE) * cinfo.out_color_components *
cinfo.image_width <=
diff --git a/third_party/jpeg-xl/lib/extras/dec/jpg.cc b/third_party/jpeg-xl/lib/extras/dec/jpg.cc
index 3c8a4bccfe..4a3e0d3b21 100644
--- a/third_party/jpeg-xl/lib/extras/dec/jpg.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/jpg.cc
@@ -34,7 +34,7 @@ constexpr unsigned char kExifSignature[6] = {0x45, 0x78, 0x69,
0x66, 0x00, 0x00};
constexpr int kExifMarker = JPEG_APP0 + 1;
-static inline bool IsJPG(const Span<const uint8_t> bytes) {
+inline bool IsJPG(const Span<const uint8_t> bytes) {
if (bytes.size() < 2) return false;
if (bytes[0] != 0xFF || bytes[1] != 0xD8) return false;
return true;
@@ -242,7 +242,11 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
if (nbcomp != 1 && nbcomp != 3) {
return failure("unsupported number of components in JPEG");
}
- if (!ReadICCProfile(&cinfo, &ppf->icc)) {
+ if (ReadICCProfile(&cinfo, &ppf->icc)) {
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
+ } else {
+ ppf->primary_color_representation =
+ PackedPixelFile::kColorEncodingIsPrimary;
ppf->icc.clear();
// Default to SRGB
// Actually, (cinfo.output_components == nbcomp) will be checked after
@@ -266,7 +270,7 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
ppf->info.bits_per_sample = BITS_IN_JSAMPLE;
JXL_ASSERT(BITS_IN_JSAMPLE == 8 || BITS_IN_JSAMPLE == 16);
ppf->info.exponent_bits_per_sample = 0;
- ppf->info.uses_original_profile = true;
+ ppf->info.uses_original_profile = JXL_TRUE;
// No alpha in JPG
ppf->info.alpha_bits = 0;
@@ -278,8 +282,8 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
if (dparams && dparams->num_colors > 0) {
cinfo.quantize_colors = TRUE;
cinfo.desired_number_of_colors = dparams->num_colors;
- cinfo.two_pass_quantize = dparams->two_pass_quant;
- cinfo.dither_mode = (J_DITHER_MODE)dparams->dither_mode;
+ cinfo.two_pass_quantize = static_cast<boolean>(dparams->two_pass_quant);
+ cinfo.dither_mode = static_cast<J_DITHER_MODE>(dparams->dither_mode);
}
jpeg_start_decompress(&cinfo);
@@ -295,19 +299,25 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
};
ppf->frames.clear();
// Allocates the frame buffer.
- ppf->frames.emplace_back(cinfo.image_width, cinfo.image_height, format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(cinfo.image_width, cinfo.image_height, format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
const auto& frame = ppf->frames.back();
JXL_ASSERT(sizeof(JSAMPLE) * cinfo.out_color_components *
cinfo.image_width <=
frame.color.stride);
if (cinfo.quantize_colors) {
- jxl::msan::UnpoisonMemory(cinfo.colormap, cinfo.out_color_components *
- sizeof(cinfo.colormap[0]));
+ JSAMPLE** colormap = cinfo.colormap;
+ jxl::msan::UnpoisonMemory(reinterpret_cast<void*>(colormap),
+ cinfo.out_color_components * sizeof(JSAMPLE*));
for (int c = 0; c < cinfo.out_color_components; ++c) {
jxl::msan::UnpoisonMemory(
- cinfo.colormap[c],
- cinfo.actual_number_of_colors * sizeof(cinfo.colormap[c][0]));
+ reinterpret_cast<void*>(colormap[c]),
+ cinfo.actual_number_of_colors * sizeof(JSAMPLE));
}
}
for (size_t y = 0; y < cinfo.image_height; ++y) {
diff --git a/third_party/jpeg-xl/lib/extras/dec/jxl.cc b/third_party/jpeg-xl/lib/extras/dec/jxl.cc
index f3e62c970a..5b7fa03f02 100644
--- a/third_party/jpeg-xl/lib/extras/dec/jxl.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/jxl.cc
@@ -16,20 +16,23 @@
#include "lib/extras/dec/color_description.h"
#include "lib/jxl/base/exif.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/status.h"
namespace jxl {
namespace extras {
namespace {
struct BoxProcessor {
- BoxProcessor(JxlDecoder* dec) : dec_(dec) { Reset(); }
+ explicit BoxProcessor(JxlDecoder* dec) : dec_(dec) { Reset(); }
void InitializeOutput(std::vector<uint8_t>* out) {
+ JXL_ASSERT(out != nullptr);
box_data_ = out;
AddMoreOutput();
}
bool AddMoreOutput() {
+ JXL_ASSERT(box_data_ != nullptr);
Flush();
static const size_t kBoxOutputChunkSize = 1 << 16;
box_data_->resize(box_data_->size() + kBoxOutputChunkSize);
@@ -126,7 +129,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
return false;
}
- JxlPixelFormat format;
+ JxlPixelFormat format = {}; // Initialize to calm down clang-tidy.
std::vector<JxlPixelFormat> accepted_formats = dparams.accepted_formats;
JxlColorEncoding color_encoding;
@@ -177,18 +180,18 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
return false;
}
if (jpeg_bytes == nullptr) {
- if (JXL_DEC_SUCCESS !=
- JxlDecoderSetRenderSpotcolors(dec, dparams.render_spotcolors)) {
+ if (JXL_DEC_SUCCESS != JxlDecoderSetRenderSpotcolors(
+ dec, TO_JXL_BOOL(dparams.render_spotcolors))) {
fprintf(stderr, "JxlDecoderSetRenderSpotColors failed\n");
return false;
}
- if (JXL_DEC_SUCCESS !=
- JxlDecoderSetKeepOrientation(dec, dparams.keep_orientation)) {
+ if (JXL_DEC_SUCCESS != JxlDecoderSetKeepOrientation(
+ dec, TO_JXL_BOOL(dparams.keep_orientation))) {
fprintf(stderr, "JxlDecoderSetKeepOrientation failed\n");
return false;
}
- if (JXL_DEC_SUCCESS !=
- JxlDecoderSetUnpremultiplyAlpha(dec, dparams.unpremultiply_alpha)) {
+ if (JXL_DEC_SUCCESS != JxlDecoderSetUnpremultiplyAlpha(
+ dec, TO_JXL_BOOL(dparams.unpremultiply_alpha))) {
fprintf(stderr, "JxlDecoderSetUnpremultiplyAlpha failed\n");
return false;
}
@@ -267,6 +270,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
return false;
}
} else if (status == JXL_DEC_JPEG_NEED_MORE_OUTPUT) {
+ JXL_ASSERT(jpeg_bytes != nullptr); // Help clang-tidy.
// Decoded a chunk to JPEG.
size_t used_jpeg_output =
jpeg_data_chunk.size() - JxlDecoderReleaseJPEGBuffer(dec);
@@ -309,7 +313,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
} else {
if (dparams.unpremultiply_alpha) {
// Mark in the basic info that alpha was unpremultiplied.
- ppf->info.alpha_premultiplied = false;
+ ppf->info.alpha_premultiplied = JXL_FALSE;
}
}
bool alpha_found = false;
@@ -327,7 +331,8 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
}
std::string name(eci.name_length + 1, 0);
if (JXL_DEC_SUCCESS !=
- JxlDecoderGetExtraChannelName(dec, i, &name[0], name.size())) {
+ JxlDecoderGetExtraChannelName(
+ dec, i, const_cast<char*>(name.data()), name.size())) {
fprintf(stderr, "JxlDecoderGetExtraChannelName failed\n");
return false;
}
@@ -351,24 +356,26 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
}
size_t icc_size = 0;
JxlColorProfileTarget target = JXL_COLOR_PROFILE_TARGET_DATA;
- ppf->color_encoding.color_space = JXL_COLOR_SPACE_UNKNOWN;
- if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsEncodedProfile(
- dec, target, &ppf->color_encoding) ||
- dparams.need_icc) {
- // only get ICC if it is not an Enum color encoding
- if (JXL_DEC_SUCCESS !=
- JxlDecoderGetICCProfileSize(dec, target, &icc_size)) {
- fprintf(stderr, "JxlDecoderGetICCProfileSize failed\n");
- }
- if (icc_size != 0) {
- ppf->icc.resize(icc_size);
- if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsICCProfile(
- dec, target, ppf->icc.data(), icc_size)) {
- fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n");
- return false;
- }
+ if (JXL_DEC_SUCCESS !=
+ JxlDecoderGetICCProfileSize(dec, target, &icc_size)) {
+ fprintf(stderr, "JxlDecoderGetICCProfileSize failed\n");
+ }
+ if (icc_size != 0) {
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
+ ppf->icc.resize(icc_size);
+ if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsICCProfile(
+ dec, target, ppf->icc.data(), icc_size)) {
+ fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n");
+ return false;
}
}
+ if (JXL_DEC_SUCCESS == JxlDecoderGetColorAsEncodedProfile(
+ dec, target, &ppf->color_encoding)) {
+ ppf->primary_color_representation =
+ PackedPixelFile::kColorEncodingIsPrimary;
+ } else {
+ ppf->color_encoding.color_space = JXL_COLOR_SPACE_UNKNOWN;
+ }
icc_size = 0;
target = JXL_COLOR_PROFILE_TARGET_ORIGINAL;
if (JXL_DEC_SUCCESS !=
@@ -385,14 +392,21 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
}
}
} else if (status == JXL_DEC_FRAME) {
- jxl::extras::PackedFrame frame(ppf->info.xsize, ppf->info.ysize, format);
+ auto frame_or = jxl::extras::PackedFrame::Create(ppf->info.xsize,
+ ppf->info.ysize, format);
+ if (!frame_or.status()) {
+ fprintf(stderr, "Failed to create image frame.");
+ return false;
+ }
+ jxl::extras::PackedFrame frame = std::move(frame_or).value();
if (JXL_DEC_SUCCESS != JxlDecoderGetFrameHeader(dec, &frame.frame_info)) {
fprintf(stderr, "JxlDecoderGetFrameHeader failed\n");
return false;
}
frame.name.resize(frame.frame_info.name_length + 1, 0);
if (JXL_DEC_SUCCESS !=
- JxlDecoderGetFrameName(dec, &frame.name[0], frame.name.size())) {
+ JxlDecoderGetFrameName(dec, const_cast<char*>(frame.name.data()),
+ frame.name.size())) {
fprintf(stderr, "JxlDecoderGetFrameName failed\n");
return false;
}
@@ -423,9 +437,16 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
fprintf(stderr, "JxlDecoderPreviewOutBufferSize failed\n");
return false;
}
+ auto preview_image_or = jxl::extras::PackedImage::Create(
+ ppf->info.preview.xsize, ppf->info.preview.ysize, format);
+ if (!preview_image_or.status()) {
+ fprintf(stderr, "Failed to create preview image\n");
+ return false;
+ }
+ jxl::extras::PackedImage preview_image =
+ std::move(preview_image_or).value();
ppf->preview_frame = std::unique_ptr<jxl::extras::PackedFrame>(
- new jxl::extras::PackedFrame(ppf->info.preview.xsize,
- ppf->info.preview.ysize, format));
+ new jxl::extras::PackedFrame(std::move(preview_image)));
if (buffer_size != ppf->preview_frame->color.pixels_size) {
fprintf(stderr, "Invalid out buffer size %" PRIuS " %" PRIuS "\n",
buffer_size, ppf->preview_frame->color.pixels_size);
@@ -492,8 +513,13 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
JxlPixelFormat ec_format = format;
ec_format.num_channels = 1;
for (auto& eci : ppf->extra_channels_info) {
- frame.extra_channels.emplace_back(jxl::extras::PackedImage(
- ppf->info.xsize, ppf->info.ysize, ec_format));
+ auto image = jxl::extras::PackedImage::Create(
+ ppf->info.xsize, ppf->info.ysize, ec_format);
+ if (!image.status()) {
+ fprintf(stderr, "Failed to create extra channel image\n");
+ return false;
+ }
+ frame.extra_channels.emplace_back(std::move(image).value());
auto& ec = frame.extra_channels.back();
size_t buffer_size;
if (JXL_DEC_SUCCESS != JxlDecoderExtraChannelBufferSize(
diff --git a/third_party/jpeg-xl/lib/extras/dec/jxl.h b/third_party/jpeg-xl/lib/extras/dec/jxl.h
index cbada1f6dd..5f4ed7f683 100644
--- a/third_party/jpeg-xl/lib/extras/dec/jxl.h
+++ b/third_party/jpeg-xl/lib/extras/dec/jxl.h
@@ -41,10 +41,6 @@ struct JXLDecompressParams {
// Whether truncated input should be treated as an error.
bool allow_partial_input = false;
- // Set to true if an ICC profile has to be synthesized for Enum color
- // encodings
- bool need_icc = false;
-
// How many passes to decode at most. By default, decode everything.
uint32_t max_passes = std::numeric_limits<uint32_t>::max();
diff --git a/third_party/jpeg-xl/lib/extras/dec/pgx.cc b/third_party/jpeg-xl/lib/extras/dec/pgx.cc
index a99eb0f4ee..4499069d77 100644
--- a/third_party/jpeg-xl/lib/extras/dec/pgx.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/pgx.cc
@@ -150,7 +150,7 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes,
const SizeConstraints* constraints) {
Parser parser(bytes);
HeaderPGX header = {};
- const uint8_t* pos;
+ const uint8_t* pos = nullptr;
if (!parser.ParseHeader(&header, &pos)) return false;
JXL_RETURN_IF_ERROR(
VerifyDimensions(constraints, header.xsize, header.ysize));
@@ -165,7 +165,7 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes,
// Original data is uint, so exponent_bits_per_sample = 0.
ppf->info.bits_per_sample = header.bits_per_sample;
ppf->info.exponent_bits_per_sample = 0;
- ppf->info.uses_original_profile = true;
+ ppf->info.uses_original_profile = JXL_TRUE;
// No alpha in PGX
ppf->info.alpha_bits = 0;
@@ -188,7 +188,12 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes,
};
ppf->frames.clear();
// Allocates the frame buffer.
- ppf->frames.emplace_back(header.xsize, header.ysize, format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(header.xsize, header.ysize, format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
const auto& frame = ppf->frames.back();
size_t pgx_remaining_size = bytes.data() + bytes.size() - pos;
if (pgx_remaining_size < frame.color.pixels_size) {
diff --git a/third_party/jpeg-xl/lib/extras/dec/pnm.cc b/third_party/jpeg-xl/lib/extras/dec/pnm.cc
index 4c4618d41d..040c0bff81 100644
--- a/third_party/jpeg-xl/lib/extras/dec/pnm.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/pnm.cc
@@ -9,6 +9,7 @@
#include <string.h>
#include <cmath>
+#include <cstdint>
#include <mutex>
#include "jxl/encode.h"
@@ -55,8 +56,10 @@ class Parser {
case 'f':
header->is_gray = true;
return ParseHeaderPFM(header, pos);
+
+ default:
+ return false;
}
- return false;
}
// Exposed for testing
@@ -160,11 +163,12 @@ class Parser {
Status MatchString(const char* keyword, bool skipws = true) {
const uint8_t* ppos = pos_;
- while (*keyword) {
+ const uint8_t* kw = reinterpret_cast<const uint8_t*>(keyword);
+ while (*kw) {
if (ppos >= end_) return JXL_FAILURE("PAM: unexpected end of input");
- if (*keyword != *ppos) return false;
+ if (*kw != *ppos) return false;
ppos++;
- keyword++;
+ kw++;
}
pos_ = ppos;
if (skipws) {
@@ -387,8 +391,8 @@ StatusOr<ChunkedPNMDecoder> ChunkedPNMDecoder::Init(const char* path) {
const size_t num_channels = dec.header_.is_gray ? 1 : 3;
const size_t bytes_per_pixel = num_channels * bytes_per_channel;
size_t row_size = dec.header_.xsize * bytes_per_pixel;
- if (header.ysize * row_size + dec.data_start_ < size) {
- return JXL_FAILURE("Invalid ppm");
+ if (size < header.ysize * row_size + dec.data_start_) {
+ return JXL_FAILURE("PNM file too small");
}
return dec;
}
@@ -495,10 +499,18 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes,
};
const JxlPixelFormat ec_format{1, format.data_type, format.endianness, 0};
ppf->frames.clear();
- ppf->frames.emplace_back(header.xsize, header.ysize, format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(header.xsize, header.ysize, format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
auto* frame = &ppf->frames.back();
for (size_t i = 0; i < header.ec_types.size(); ++i) {
- frame->extra_channels.emplace_back(header.xsize, header.ysize, ec_format);
+ JXL_ASSIGN_OR_RETURN(
+ PackedImage ec,
+ PackedImage::Create(header.xsize, header.ysize, ec_format));
+ frame->extra_channels.emplace_back(std::move(ec));
}
size_t pnm_remaining_size = bytes.data() + bytes.size() - pos;
if (pnm_remaining_size < frame->color.pixels_size) {
@@ -533,6 +545,9 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes,
}
}
}
+ if (ppf->info.exponent_bits_per_sample == 0) {
+ ppf->input_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM;
+ }
return true;
}
diff --git a/third_party/jpeg-xl/lib/extras/enc/apng.cc b/third_party/jpeg-xl/lib/extras/enc/apng.cc
index 413a9c8081..40aa876e84 100644
--- a/third_party/jpeg-xl/lib/extras/enc/apng.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/apng.cc
@@ -86,7 +86,7 @@ class APNGEncoder : public Encoder {
std::vector<uint8_t>* bytes) const;
};
-static void PngWrite(png_structp png_ptr, png_bytep data, png_size_t length) {
+void PngWrite(png_structp png_ptr, png_bytep data, png_size_t length) {
std::vector<uint8_t>* bytes =
static_cast<std::vector<uint8_t>*>(png_get_io_ptr(png_ptr));
bytes->insert(bytes->end(), data, data + length);
@@ -137,7 +137,7 @@ class BlobsWriterPNG {
std::vector<std::string>* strings) {
// Encoding: base16 with newline after 72 chars.
const size_t base16_size =
- 2 * bytes.size() + DivCeil(bytes.size(), size_t(36)) + 1;
+ 2 * bytes.size() + DivCeil(bytes.size(), static_cast<size_t>(36)) + 1;
std::string base16;
base16.reserve(base16_size);
for (size_t i = 0; i < bytes.size(); ++i) {
@@ -155,7 +155,7 @@ class BlobsWriterPNG {
snprintf(header, sizeof(header), "\n%s\n%8" PRIuS, type.c_str(),
bytes.size());
- strings->push_back(std::string(key));
+ strings->emplace_back(key);
strings->push_back(std::string(header) + base16);
return true;
}
@@ -303,7 +303,7 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
out[i] = static_cast<uint8_t>(in[i] * mul + 0.5);
}
} else {
- memcpy(&out[0], in, out_size);
+ memcpy(out.data(), in, out_size);
}
} else if (format.data_type == JXL_TYPE_UINT16) {
if (ppf.info.bits_per_sample < 16 ||
@@ -317,20 +317,21 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
StoreBE16(static_cast<uint32_t>(val * mul + 0.5), p_out);
}
} else {
- memcpy(&out[0], in, out_size);
+ memcpy(out.data(), in, out_size);
}
}
png_structp png_ptr;
png_infop info_ptr;
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr,
+ nullptr);
if (!png_ptr) return JXL_FAILURE("Could not init png encoder");
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) return JXL_FAILURE("Could not init png info struct");
- png_set_write_fn(png_ptr, bytes, PngWrite, NULL);
+ png_set_write_fn(png_ptr, bytes, PngWrite, nullptr);
png_set_flush(png_ptr, 0);
int width = xsize;
@@ -344,11 +345,13 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
if (count == 0) {
- if (!ppf.icc.empty()) {
- png_set_benign_errors(png_ptr, 1);
- png_set_iCCP(png_ptr, info_ptr, "1", 0, ppf.icc.data(), ppf.icc.size());
- } else if (!MaybeAddSRGB(ppf.color_encoding, png_ptr, info_ptr)) {
+ if (!MaybeAddSRGB(ppf.color_encoding, png_ptr, info_ptr)) {
MaybeAddCICP(ppf.color_encoding, png_ptr, info_ptr);
+ if (!ppf.icc.empty()) {
+ png_set_benign_errors(png_ptr, 1);
+ png_set_iCCP(png_ptr, info_ptr, "1", 0, ppf.icc.data(),
+ ppf.icc.size());
+ }
MaybeAddCHRM(ppf.color_encoding, png_ptr, info_ptr);
MaybeAddGAMA(ppf.color_encoding, png_ptr, info_ptr);
}
@@ -404,7 +407,7 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
png_write_flush(png_ptr);
const size_t pos = bytes->size();
- png_write_image(png_ptr, &rows[0]);
+ png_write_image(png_ptr, rows.data());
png_write_flush(png_ptr);
if (count > 0) {
std::vector<uint8_t> fdata(4);
@@ -428,7 +431,7 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
count++;
if (count == ppf.frames.size() || !ppf.info.have_animation) {
- png_write_end(png_ptr, NULL);
+ png_write_end(png_ptr, nullptr);
}
png_destroy_write_struct(&png_ptr, &info_ptr);
diff --git a/third_party/jpeg-xl/lib/extras/enc/encode.cc b/third_party/jpeg-xl/lib/extras/enc/encode.cc
index 8c9a148b27..c5e22d8c7e 100644
--- a/third_party/jpeg-xl/lib/extras/enc/encode.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/encode.cc
@@ -54,7 +54,7 @@ Status Encoder::VerifyBitDepth(JxlDataType data_type, uint32_t bits_per_sample,
(bits_per_sample > 16 || exponent_bits > 5))) {
return JXL_FAILURE(
"Incompatible data_type %d and bit depth %u with exponent bits %u",
- (int)data_type, bits_per_sample, exponent_bits);
+ static_cast<int>(data_type), bits_per_sample, exponent_bits);
}
return true;
}
diff --git a/third_party/jpeg-xl/lib/extras/enc/encode.h b/third_party/jpeg-xl/lib/extras/enc/encode.h
index da5f509838..2502d9976b 100644
--- a/third_party/jpeg-xl/lib/extras/enc/encode.h
+++ b/third_party/jpeg-xl/lib/extras/enc/encode.h
@@ -56,7 +56,7 @@ class Encoder {
// Any existing data in encoded_image is discarded.
virtual Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
- ThreadPool* pool = nullptr) const = 0;
+ ThreadPool* pool) const = 0;
void SetOption(std::string name, std::string value) {
options_[std::move(name)] = std::move(value);
diff --git a/third_party/jpeg-xl/lib/extras/enc/exr.cc b/third_party/jpeg-xl/lib/extras/enc/exr.cc
index d4005c3097..5a4f7d768c 100644
--- a/third_party/jpeg-xl/lib/extras/enc/exr.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/exr.cc
@@ -84,7 +84,7 @@ Status EncodeImageEXR(const PackedImage& image, const JxlBasicInfo& info,
const size_t xsize = info.xsize;
const size_t ysize = info.ysize;
const bool has_alpha = info.alpha_bits > 0;
- const bool alpha_is_premultiplied = info.alpha_premultiplied;
+ const bool alpha_is_premultiplied = FROM_JXL_BOOL(info.alpha_premultiplied);
if (info.num_color_channels != 3 ||
c_enc.color_space != JXL_COLOR_SPACE_RGB ||
@@ -177,7 +177,7 @@ class EXREncoder : public Encoder {
return formats;
}
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
- ThreadPool* pool = nullptr) const override {
+ ThreadPool* pool) const override {
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
encoded_image->icc.clear();
encoded_image->bitstreams.clear();
diff --git a/third_party/jpeg-xl/lib/extras/enc/jpegli.cc b/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
index 7e1aa426df..aa10b584d0 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
@@ -34,6 +34,7 @@
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/enc_xyb.h"
#include "lib/jxl/image.h"
+#include "lib/jxl/simd_util.h"
namespace jxl {
namespace extras {
@@ -53,6 +54,10 @@ Status VerifyInput(const PackedPixelFile& ppf) {
if (ppf.frames.size() != 1) {
return JXL_FAILURE("JPEG input must have exactly one frame.");
}
+ if (info.num_color_channels != 1 && info.num_color_channels != 3) {
+ return JXL_FAILURE("Invalid number of color channels %d",
+ info.num_color_channels);
+ }
const PackedImage& image = ppf.frames[0].color;
JXL_RETURN_IF_ERROR(Encoder::VerifyImageSize(image, info));
if (image.format.data_type == JXL_TYPE_FLOAT16) {
@@ -71,7 +76,7 @@ Status VerifyInput(const PackedPixelFile& ppf) {
Status GetColorEncoding(const PackedPixelFile& ppf,
ColorEncoding* color_encoding) {
- if (!ppf.icc.empty()) {
+ if (ppf.primary_color_representation == PackedPixelFile::kIccIsPrimary) {
IccBytes icc = ppf.icc;
JXL_RETURN_IF_ERROR(
color_encoding->SetICC(std::move(icc), JxlGetDefaultCms()));
@@ -122,12 +127,12 @@ Status WriteAppData(j_compress_ptr cinfo,
return true;
}
-static constexpr int kICCMarker = 0xe2;
+constexpr int kICCMarker = 0xe2;
constexpr unsigned char kICCSignature[12] = {
0x49, 0x43, 0x43, 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00};
-static constexpr uint8_t kUnknownTf = 2;
-static constexpr unsigned char kCICPTagSignature[4] = {0x63, 0x69, 0x63, 0x70};
-static constexpr size_t kCICPTagSize = 12;
+constexpr uint8_t kUnknownTf = 2;
+constexpr unsigned char kCICPTagSignature[4] = {0x63, 0x69, 0x63, 0x70};
+constexpr size_t kCICPTagSize = 12;
bool FindCICPTag(const uint8_t* icc_data, size_t len, bool is_first_chunk,
size_t* cicp_offset, size_t* cicp_length, uint8_t* cicp_tag,
@@ -248,32 +253,48 @@ JpegliEndianness ConvertEndianness(JxlEndianness endianness) {
}
}
-void ToFloatRow(const uint8_t* row_in, JxlPixelFormat format, size_t len,
- float* row_out) {
+void ToFloatRow(const uint8_t* row_in, JxlPixelFormat format, size_t xsize,
+ size_t c_out, float* row_out) {
bool is_little_endian =
(format.endianness == JXL_LITTLE_ENDIAN ||
(format.endianness == JXL_NATIVE_ENDIAN && IsLittleEndian()));
static constexpr double kMul8 = 1.0 / 255.0;
static constexpr double kMul16 = 1.0 / 65535.0;
+ const size_t c_in = format.num_channels;
if (format.data_type == JXL_TYPE_UINT8) {
- for (size_t x = 0; x < len; ++x) {
- row_out[x] = row_in[x] * kMul8;
+ for (size_t x = 0; x < xsize; ++x) {
+ for (size_t c = 0; c < c_out; ++c) {
+ const size_t ix = c_in * x + c;
+ row_out[c_out * x + c] = row_in[ix] * kMul8;
+ }
}
} else if (format.data_type == JXL_TYPE_UINT16 && is_little_endian) {
- for (size_t x = 0; x < len; ++x) {
- row_out[x] = LoadLE16(&row_in[2 * x]) * kMul16;
+ for (size_t x = 0; x < xsize; ++x) {
+ for (size_t c = 0; c < c_out; ++c) {
+ const size_t ix = c_in * x + c;
+ row_out[c_out * x + c] = LoadLE16(&row_in[2 * ix]) * kMul16;
+ }
}
} else if (format.data_type == JXL_TYPE_UINT16 && !is_little_endian) {
- for (size_t x = 0; x < len; ++x) {
- row_out[x] = LoadBE16(&row_in[2 * x]) * kMul16;
+ for (size_t x = 0; x < xsize; ++x) {
+ for (size_t c = 0; c < c_out; ++c) {
+ const size_t ix = c_in * x + c;
+ row_out[c_out * x + c] = LoadBE16(&row_in[2 * ix]) * kMul16;
+ }
}
} else if (format.data_type == JXL_TYPE_FLOAT && is_little_endian) {
- for (size_t x = 0; x < len; ++x) {
- row_out[x] = LoadLEFloat(&row_in[4 * x]);
+ for (size_t x = 0; x < xsize; ++x) {
+ for (size_t c = 0; c < c_out; ++c) {
+ const size_t ix = c_in * x + c;
+ row_out[c_out * x + c] = LoadLEFloat(&row_in[4 * ix]);
+ }
}
} else if (format.data_type == JXL_TYPE_FLOAT && !is_little_endian) {
- for (size_t x = 0; x < len; ++x) {
- row_out[x] = LoadBEFloat(&row_in[4 * x]);
+ for (size_t x = 0; x < xsize; ++x) {
+ for (size_t c = 0; c < c_out; ++c) {
+ const size_t ix = c_in * x + c;
+ row_out[c_out * x + c] = LoadBEFloat(&row_in[4 * ix]);
+ }
}
}
}
@@ -352,9 +373,6 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
ColorSpaceTransform c_transform(*JxlGetDefaultCms());
ColorEncoding xyb_encoding;
if (jpeg_settings.xyb) {
- if (ppf.info.num_color_channels != 3) {
- return JXL_FAILURE("Only RGB input is supported in XYB mode.");
- }
if (HasICCProfile(jpeg_settings.app_data)) {
return JXL_FAILURE("APP data ICC profile is not supported in XYB mode.");
}
@@ -374,11 +392,11 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
unsigned char* output_buffer = nullptr;
unsigned long output_size = 0;
std::vector<uint8_t> row_bytes;
- size_t rowlen = RoundUpTo(ppf.info.xsize, VectorSize());
+ size_t rowlen = RoundUpTo(ppf.info.xsize, MaxVectorSize());
hwy::AlignedFreeUniquePtr<float[]> xyb_tmp =
hwy::AllocateAligned<float>(6 * rowlen);
hwy::AlignedFreeUniquePtr<float[]> premul_absorb =
- hwy::AllocateAligned<float>(VectorSize() * 12);
+ hwy::AllocateAligned<float>(MaxVectorSize() * 12);
ComputePremulAbsorb(255.0f, premul_absorb.get());
jpeg_compress_struct cinfo;
@@ -401,6 +419,8 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
cinfo.input_components == 1 ? JCS_GRAYSCALE : JCS_RGB;
if (jpeg_settings.xyb) {
jpegli_set_xyb_mode(&cinfo);
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
} else if (jpeg_settings.use_std_quant_tables) {
jpegli_use_standard_quant_tables(&cinfo);
}
@@ -436,7 +456,7 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
}
}
jpegli_enable_adaptive_quantization(
- &cinfo, jpeg_settings.use_adaptive_quantization);
+ &cinfo, TO_JXL_BOOL(jpeg_settings.use_adaptive_quantization));
if (jpeg_settings.psnr_target > 0.0) {
jpegli_set_psnr(&cinfo, jpeg_settings.psnr_target,
jpeg_settings.search_tolerance,
@@ -448,11 +468,11 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
jpegli_set_distance(&cinfo, jpeg_settings.distance, TRUE);
}
jpegli_set_progressive_level(&cinfo, jpeg_settings.progressive_level);
- cinfo.optimize_coding = jpeg_settings.optimize_coding;
+ cinfo.optimize_coding = TO_JXL_BOOL(jpeg_settings.optimize_coding);
if (!jpeg_settings.app_data.empty()) {
// Make sure jpegli_start_compress() does not write any APP markers.
- cinfo.write_JFIF_header = false;
- cinfo.write_Adobe_marker = false;
+ cinfo.write_JFIF_header = JXL_FALSE;
+ cinfo.write_Adobe_marker = JXL_FALSE;
}
const PackedImage& image = ppf.frames[0].color;
if (jpeg_settings.xyb) {
@@ -476,10 +496,10 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
float* dst_buf = c_transform.BufDst(0);
for (size_t y = 0; y < image.ysize; ++y) {
// convert to float
- ToFloatRow(&pixels[y * image.stride], image.format, 3 * image.xsize,
- src_buf);
+ ToFloatRow(&pixels[y * image.stride], image.format, image.xsize,
+ info.num_color_channels, src_buf);
// convert to linear srgb
- if (!c_transform.Run(0, src_buf, dst_buf)) {
+ if (!c_transform.Run(0, src_buf, dst_buf, image.xsize)) {
return false;
}
// deinterleave channels
@@ -508,9 +528,9 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
}
} else {
row_bytes.resize(image.stride);
- if (cinfo.num_components == (int)image.format.num_channels) {
+ if (cinfo.num_components == static_cast<int>(image.format.num_channels)) {
for (size_t y = 0; y < info.ysize; ++y) {
- memcpy(&row_bytes[0], pixels + y * image.stride, image.stride);
+ memcpy(row_bytes.data(), pixels + y * image.stride, image.stride);
JSAMPROW row[] = {row_bytes.data()};
jpegli_write_scanlines(&cinfo, row, 1);
}
diff --git a/third_party/jpeg-xl/lib/extras/enc/jpg.cc b/third_party/jpeg-xl/lib/extras/enc/jpg.cc
index c34dc6c13f..de0228fc0d 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jpg.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/jpg.cc
@@ -23,6 +23,7 @@
#include <vector>
#include "lib/extras/exif.h"
+#include "lib/jxl/base/common.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
#if JPEGXL_ENABLE_SJPEG
@@ -50,23 +51,21 @@ enum class JpegEncoder {
kSJpeg,
};
-#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
-
// Popular jpeg scan scripts
// The fields of the individual scans are:
// comps_in_scan, component_index[], Ss, Se, Ah, Al
-static constexpr jpeg_scan_info kScanScript1[] = {
+constexpr auto kScanScript1 = to_array<jpeg_scan_info>({
{1, {0}, 0, 0, 0, 0}, //
{1, {1}, 0, 0, 0, 0}, //
{1, {2}, 0, 0, 0, 0}, //
{1, {0}, 1, 8, 0, 0}, //
{1, {0}, 9, 63, 0, 0}, //
{1, {1}, 1, 63, 0, 0}, //
- {1, {2}, 1, 63, 0, 0}, //
-};
-static constexpr size_t kNumScans1 = ARRAY_SIZE(kScanScript1);
+ {1, {2}, 1, 63, 0, 0} //
+});
+constexpr size_t kNumScans1 = kScanScript1.size();
-static constexpr jpeg_scan_info kScanScript2[] = {
+constexpr auto kScanScript2 = to_array<jpeg_scan_info>({
{1, {0}, 0, 0, 0, 0}, //
{1, {1}, 0, 0, 0, 0}, //
{1, {2}, 0, 0, 0, 0}, //
@@ -74,11 +73,11 @@ static constexpr jpeg_scan_info kScanScript2[] = {
{1, {0}, 3, 63, 0, 1}, //
{1, {0}, 1, 63, 1, 0}, //
{1, {1}, 1, 63, 0, 0}, //
- {1, {2}, 1, 63, 0, 0}, //
-};
-static constexpr size_t kNumScans2 = ARRAY_SIZE(kScanScript2);
+ {1, {2}, 1, 63, 0, 0} //
+});
+constexpr size_t kNumScans2 = kScanScript2.size();
-static constexpr jpeg_scan_info kScanScript3[] = {
+constexpr auto kScanScript3 = to_array<jpeg_scan_info>({
{1, {0}, 0, 0, 0, 0}, //
{1, {1}, 0, 0, 0, 0}, //
{1, {2}, 0, 0, 0, 0}, //
@@ -86,11 +85,11 @@ static constexpr jpeg_scan_info kScanScript3[] = {
{1, {0}, 1, 63, 2, 1}, //
{1, {0}, 1, 63, 1, 0}, //
{1, {1}, 1, 63, 0, 0}, //
- {1, {2}, 1, 63, 0, 0}, //
-};
-static constexpr size_t kNumScans3 = ARRAY_SIZE(kScanScript3);
+ {1, {2}, 1, 63, 0, 0} //
+});
+constexpr size_t kNumScans3 = kScanScript3.size();
-static constexpr jpeg_scan_info kScanScript4[] = {
+constexpr auto kScanScript4 = to_array<jpeg_scan_info>({
{3, {0, 1, 2}, 0, 0, 0, 1}, //
{1, {0}, 1, 5, 0, 2}, //
{1, {2}, 1, 63, 0, 1}, //
@@ -100,11 +99,11 @@ static constexpr jpeg_scan_info kScanScript4[] = {
{3, {0, 1, 2}, 0, 0, 1, 0}, //
{1, {2}, 1, 63, 1, 0}, //
{1, {1}, 1, 63, 1, 0}, //
- {1, {0}, 1, 63, 1, 0}, //
-};
-static constexpr size_t kNumScans4 = ARRAY_SIZE(kScanScript4);
+ {1, {0}, 1, 63, 1, 0} //
+});
+constexpr size_t kNumScans4 = kScanScript4.size();
-static constexpr jpeg_scan_info kScanScript5[] = {
+constexpr auto kScanScript5 = to_array<jpeg_scan_info>({
{3, {0, 1, 2}, 0, 0, 0, 1}, //
{1, {0}, 1, 5, 0, 2}, //
{1, {1}, 1, 5, 0, 2}, //
@@ -118,12 +117,12 @@ static constexpr jpeg_scan_info kScanScript5[] = {
{3, {0, 1, 2}, 0, 0, 1, 0}, //
{1, {0}, 1, 63, 1, 0}, //
{1, {1}, 1, 63, 1, 0}, //
- {1, {2}, 1, 63, 1, 0}, //
-};
-static constexpr size_t kNumScans5 = ARRAY_SIZE(kScanScript5);
+ {1, {2}, 1, 63, 1, 0} //
+});
+constexpr size_t kNumScans5 = kScanScript5.size();
// default progressive mode of jpegli
-static constexpr jpeg_scan_info kScanScript6[] = {
+constexpr auto kScanScript6 = to_array<jpeg_scan_info>({
{3, {0, 1, 2}, 0, 0, 0, 0}, //
{1, {0}, 1, 2, 0, 0}, //
{1, {1}, 1, 2, 0, 0}, //
@@ -137,8 +136,8 @@ static constexpr jpeg_scan_info kScanScript6[] = {
{1, {0}, 3, 63, 1, 0}, //
{1, {1}, 3, 63, 1, 0}, //
{1, {2}, 3, 63, 1, 0}, //
-};
-static constexpr size_t kNumScans6 = ARRAY_SIZE(kScanScript6);
+});
+constexpr size_t kNumScans6 = kScanScript6.size();
// Adapt RGB scan info to grayscale jpegs.
void FilterScanComponents(const jpeg_compress_struct* cinfo,
@@ -163,12 +162,12 @@ Status SetJpegProgression(int progressive_id,
jpeg_simple_progression(cinfo);
return true;
}
- constexpr const jpeg_scan_info* kScanScripts[] = {kScanScript1, kScanScript2,
- kScanScript3, kScanScript4,
- kScanScript5, kScanScript6};
- constexpr size_t kNumScans[] = {kNumScans1, kNumScans2, kNumScans3,
- kNumScans4, kNumScans5, kNumScans6};
- if (progressive_id > static_cast<int>(ARRAY_SIZE(kNumScans))) {
+ const jpeg_scan_info* kScanScripts[] = {
+ kScanScript1.data(), kScanScript2.data(), kScanScript3.data(),
+ kScanScript4.data(), kScanScript5.data(), kScanScript6.data()};
+ constexpr auto kNumScans = to_array<size_t>(
+ {kNumScans1, kNumScans2, kNumScans3, kNumScans4, kNumScans5, kNumScans6});
+ if (progressive_id > static_cast<int>(kNumScans.size())) {
return JXL_FAILURE("Unknown jpeg scan script id %d", progressive_id);
}
const jpeg_scan_info* scan_script = kScanScripts[progressive_id - 1];
@@ -178,7 +177,7 @@ Status SetJpegProgression(int progressive_id,
jpeg_scan_info scan_info = scan_script[i];
FilterScanComponents(cinfo, &scan_info);
if (scan_info.comps_in_scan > 0) {
- scan_infos->emplace_back(std::move(scan_info));
+ scan_infos->emplace_back(scan_info);
}
}
cinfo->scan_info = scan_infos->data();
@@ -217,8 +216,8 @@ void WriteExif(jpeg_compress_struct* const cinfo,
for (const unsigned char c : kExifSignature) {
jpeg_write_m_byte(cinfo, c);
}
- for (size_t i = 0; i < exif.size(); ++i) {
- jpeg_write_m_byte(cinfo, exif[i]);
+ for (uint8_t c : exif) {
+ jpeg_write_m_byte(cinfo, c);
}
}
@@ -284,7 +283,7 @@ Status EncodeWithLibJpeg(const PackedImage& image, const JxlBasicInfo& info,
cinfo.input_components = info.num_color_channels;
cinfo.in_color_space = info.num_color_channels == 1 ? JCS_GRAYSCALE : JCS_RGB;
jpeg_set_defaults(&cinfo);
- cinfo.optimize_coding = params.optimize_coding;
+ cinfo.optimize_coding = static_cast<boolean>(params.optimize_coding);
if (cinfo.input_components == 3) {
JXL_RETURN_IF_ERROR(
SetChromaSubsampling(params.chroma_subsampling, &cinfo));
@@ -310,10 +309,10 @@ Status EncodeWithLibJpeg(const PackedImage& image, const JxlBasicInfo& info,
std::vector<uint8_t> row_bytes(image.stride);
const uint8_t* pixels = reinterpret_cast<const uint8_t*>(image.pixels());
- if (cinfo.num_components == (int)image.format.num_channels &&
+ if (cinfo.num_components == static_cast<int>(image.format.num_channels) &&
image.format.data_type == JXL_TYPE_UINT8) {
for (size_t y = 0; y < info.ysize; ++y) {
- memcpy(&row_bytes[0], pixels + y * image.stride, image.stride);
+ memcpy(row_bytes.data(), pixels + y * image.stride, image.stride);
JSAMPROW row[] = {row_bytes.data()};
jpeg_write_scanlines(&cinfo, row, 1);
}
@@ -401,7 +400,7 @@ struct MySearchHook : public sjpeg::SearchHook {
}
bool Update(float result) override {
value = result;
- if (fabs(value - target) < tolerance * target) {
+ if (std::fabs(value - target) < tolerance * target) {
return true;
}
if (value > target) {
@@ -420,9 +419,9 @@ struct MySearchHook : public sjpeg::SearchHook {
} else {
q = (qmin + qmax) / 2.;
}
- return (pass > 0 && fabs(q - last_q) < q_precision);
+ return (pass > 0 && std::fabs(q - last_q) < q_precision);
}
- ~MySearchHook() override {}
+ ~MySearchHook() override = default;
};
#endif
@@ -539,7 +538,7 @@ class JPEGEncoder : public Encoder {
return formats;
}
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
- ThreadPool* pool = nullptr) const override {
+ ThreadPool* pool) const override {
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
JpegEncoder jpeg_encoder = JpegEncoder::kLibJpeg;
JpegParams params;
diff --git a/third_party/jpeg-xl/lib/extras/enc/jxl.cc b/third_party/jpeg-xl/lib/extras/enc/jxl.cc
index 00adbb7dda..d563f298e6 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jxl.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/jxl.cc
@@ -7,6 +7,7 @@
#include <jxl/encode.h>
#include <jxl/encode_cxx.h>
+#include <jxl/types.h>
#include "lib/jxl/base/exif.h"
@@ -132,7 +133,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
return false;
}
- auto settings = JxlEncoderFrameSettingsCreate(enc, nullptr);
+ auto* settings = JxlEncoderFrameSettingsCreate(enc, nullptr);
size_t option_idx = 0;
if (!SetFrameOptions(params.options, 0, &option_idx, settings)) {
return false;
@@ -150,10 +151,11 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
JxlEncoderCollectStats(settings, params.stats);
}
+ bool has_jpeg_bytes = (jpeg_bytes != nullptr);
bool use_boxes = !ppf.metadata.exif.empty() || !ppf.metadata.xmp.empty() ||
!ppf.metadata.jumbf.empty() || !ppf.metadata.iptc.empty();
bool use_container = params.use_container || use_boxes ||
- (jpeg_bytes && params.jpeg_store_metadata);
+ (has_jpeg_bytes && params.jpeg_store_metadata);
if (JXL_ENC_SUCCESS !=
JxlEncoderUseContainer(enc, static_cast<int>(use_container))) {
@@ -161,12 +163,22 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
return false;
}
- if (jpeg_bytes) {
+ if (has_jpeg_bytes) {
if (params.jpeg_store_metadata &&
JXL_ENC_SUCCESS != JxlEncoderStoreJPEGMetadata(enc, JXL_TRUE)) {
fprintf(stderr, "Storing JPEG metadata failed.\n");
return false;
}
+ if (params.jpeg_store_metadata && params.jpeg_strip_exif) {
+ fprintf(stderr,
+ "Cannot store metadata and strip exif at the same time.\n");
+ return false;
+ }
+ if (params.jpeg_store_metadata && params.jpeg_strip_xmp) {
+ fprintf(stderr,
+ "Cannot store metadata and strip xmp at the same time.\n");
+ return false;
+ }
if (!params.jpeg_store_metadata && params.jpeg_strip_exif) {
JxlEncoderFrameSettingsSetOption(settings,
JXL_ENC_FRAME_SETTING_JPEG_KEEP_EXIF, 0);
@@ -210,8 +222,8 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
basic_info.num_extra_channels =
std::max<uint32_t>(num_alpha_channels, ppf.info.num_extra_channels);
basic_info.num_color_channels = ppf.info.num_color_channels;
- const bool lossless = params.distance == 0;
- basic_info.uses_original_profile = lossless;
+ const bool lossless = (params.distance == 0);
+ basic_info.uses_original_profile = TO_JXL_BOOL(lossless);
if (params.override_bitdepth != 0) {
basic_info.bits_per_sample = params.override_bitdepth;
basic_info.exponent_bits_per_sample =
@@ -233,7 +245,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
return false;
}
if (JXL_ENC_SUCCESS !=
- JxlEncoderSetFrameBitDepth(settings, &params.input_bitdepth)) {
+ JxlEncoderSetFrameBitDepth(settings, &ppf.input_bitdepth)) {
fprintf(stderr, "JxlEncoderSetFrameBitDepth() failed.\n");
return false;
}
@@ -248,7 +260,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
fprintf(stderr, "JxlEncoderSetFrameLossless() failed.\n");
return false;
}
- if (!ppf.icc.empty()) {
+ if (ppf.primary_color_representation == PackedPixelFile::kIccIsPrimary) {
if (JXL_ENC_SUCCESS !=
JxlEncoderSetICCProfile(enc, ppf.icc.data(), ppf.icc.size())) {
fprintf(stderr, "JxlEncoderSetICCProfile() failed.\n");
@@ -284,14 +296,15 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
{"jumb", ppf.metadata.jumbf},
{"xml ", ppf.metadata.iptc},
};
- for (size_t i = 0; i < sizeof boxes / sizeof *boxes; ++i) {
- const BoxInfo& box = boxes[i];
- if (!box.bytes.empty() &&
- JXL_ENC_SUCCESS != JxlEncoderAddBox(enc, box.type, box.bytes.data(),
- box.bytes.size(),
- params.compress_boxes)) {
- fprintf(stderr, "JxlEncoderAddBox() failed (%s).\n", box.type);
- return false;
+ for (auto box : boxes) {
+ if (!box.bytes.empty()) {
+ if (JXL_ENC_SUCCESS !=
+ JxlEncoderAddBox(enc, box.type, box.bytes.data(),
+ box.bytes.size(),
+ TO_JXL_BOOL(params.compress_boxes))) {
+ fprintf(stderr, "JxlEncoderAddBox() failed (%s).\n", box.type);
+ return false;
+ }
}
}
JxlEncoderCloseBoxes(enc);
@@ -336,7 +349,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
}
const bool last_frame = fi + 1 == ppf.chunked_frames.size();
if (JXL_ENC_SUCCESS !=
- JxlEncoderAddChunkedFrame(settings, last_frame,
+ JxlEncoderAddChunkedFrame(settings, TO_JXL_BOOL(last_frame),
chunked_frame.GetInputSource())) {
fprintf(stderr, "JxlEncoderAddChunkedFrame() failed.\n");
return false;
diff --git a/third_party/jpeg-xl/lib/extras/enc/jxl.h b/third_party/jpeg-xl/lib/extras/enc/jxl.h
index b8ca5bda2f..2b3793c0c4 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jxl.h
+++ b/third_party/jpeg-xl/lib/extras/enc/jxl.h
@@ -38,7 +38,7 @@ struct JXLCompressParams {
std::vector<JXLOption> options;
// Target butteraugli distance, 0.0 means lossless.
float distance = 1.0f;
- float alpha_distance = 1.0f;
+ float alpha_distance = 0.0f;
// If set to true, forces container mode.
bool use_container = false;
// Whether to enable/disable byte-exact jpeg reconstruction for jpeg inputs.
@@ -57,8 +57,6 @@ struct JXLCompressParams {
size_t override_bitdepth = 0;
int32_t codestream_level = -1;
int32_t premultiply = -1;
- // Override input buffer interpretation.
- JxlBitDepth input_bitdepth = {JXL_BIT_DEPTH_FROM_PIXEL_FORMAT, 0, 0};
// If runner_opaque is set, the decoder uses this parallel runner.
JxlParallelRunner runner = JxlThreadParallelRunner;
void* runner_opaque = nullptr;
@@ -69,10 +67,10 @@ struct JXLCompressParams {
bool allow_expert_options = false;
void AddOption(JxlEncoderFrameSettingId id, int64_t val) {
- options.emplace_back(JXLOption(id, val, 0));
+ options.emplace_back(id, val, 0);
}
void AddFloatOption(JxlEncoderFrameSettingId id, float val) {
- options.emplace_back(JXLOption(id, val, 0));
+ options.emplace_back(id, val, 0);
}
bool HasOutputProcessor() const {
return (output_processor.get_buffer != nullptr &&
diff --git a/third_party/jpeg-xl/lib/extras/enc/npy.cc b/third_party/jpeg-xl/lib/extras/enc/npy.cc
index ae8cf13cc4..8d9954ef31 100644
--- a/third_party/jpeg-xl/lib/extras/enc/npy.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/npy.cc
@@ -7,11 +7,13 @@
#include <jxl/types.h>
+#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include "lib/extras/packed_image.h"
+#include "lib/jxl/base/common.h"
namespace jxl {
namespace extras {
@@ -52,14 +54,17 @@ class JSONDict : public JSONField {
static_assert(std::is_convertible<T*, JSONField*>::value,
"T must be a JSONField");
T* ret = new T();
- values_.emplace_back(
- key, std::unique_ptr<JSONField>(static_cast<JSONField*>(ret)));
+ JSONField* field = static_cast<JSONField*>(ret);
+ auto handle = std::unique_ptr<JSONField>(field);
+ values_.emplace_back(key, std::move(handle));
return ret;
}
template <typename T>
void Add(const std::string& key, const T& value) {
- values_.emplace_back(key, std::unique_ptr<JSONField>(new JSONValue(value)));
+ JSONField* field = static_cast<JSONField*>(new JSONValue(value));
+ auto handle = std::unique_ptr<JSONField>(field);
+ values_.emplace_back(key, std::move(handle));
}
void Write(std::ostream& o, uint32_t indent) const override {
@@ -71,11 +76,11 @@ class JSONDict : public JSONField {
o << ",";
}
is_first = false;
- o << std::endl << indent_str << " \"" << key_value.first << "\": ";
+ o << "\n" << indent_str << " \"" << key_value.first << "\": ";
key_value.second->Write(o, indent + 2);
}
if (!values_.empty()) {
- o << std::endl << indent_str;
+ o << "\n" << indent_str;
}
o << "}";
}
@@ -112,11 +117,11 @@ class JSONArray : public JSONField {
o << ",";
}
is_first = false;
- o << std::endl << indent_str << " ";
+ o << "\n" << indent_str << " ";
value->Write(o, indent + 2);
}
if (!values_.empty()) {
- o << std::endl << indent_str;
+ o << "\n" << indent_str;
}
o << "]";
}
@@ -160,13 +165,13 @@ void GenerateMetadata(const PackedPixelFile& ppf, std::vector<uint8_t>* out) {
}
{
- auto ectype = meta.AddEmpty<JSONArray>("extra_channel_type");
- auto bps = meta.AddEmpty<JSONArray>("bits_per_sample");
- auto ebps = meta.AddEmpty<JSONArray>("exp_bits_per_sample");
+ auto* ectype = meta.AddEmpty<JSONArray>("extra_channel_type");
+ auto* bps = meta.AddEmpty<JSONArray>("bits_per_sample");
+ auto* ebps = meta.AddEmpty<JSONArray>("exp_bits_per_sample");
bps->Add(ppf.info.bits_per_sample);
ebps->Add(ppf.info.exponent_bits_per_sample);
- for (size_t i = 0; i < ppf.extra_channels_info.size(); i++) {
- switch (ppf.extra_channels_info[i].ec_info.type) {
+ for (const auto& eci : ppf.extra_channels_info) {
+ switch (eci.ec_info.type) {
case JXL_CHANNEL_ALPHA: {
ectype->Add(std::string("Alpha"));
break;
@@ -200,8 +205,8 @@ void GenerateMetadata(const PackedPixelFile& ppf, std::vector<uint8_t>* out) {
break;
}
}
- bps->Add(ppf.extra_channels_info[i].ec_info.bits_per_sample);
- ebps->Add(ppf.extra_channels_info[i].ec_info.exponent_bits_per_sample);
+ bps->Add(eci.ec_info.bits_per_sample);
+ ebps->Add(eci.ec_info.exponent_bits_per_sample);
}
}
@@ -282,7 +287,7 @@ bool WriteNPYArray(const PackedPixelFile& ppf, std::vector<uint8_t>* out) {
class NumPyEncoder : public Encoder {
public:
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
- ThreadPool* pool = nullptr) const override {
+ ThreadPool* pool) const override {
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
GenerateMetadata(ppf, &encoded_image->metadata);
encoded_image->bitstreams.emplace_back();
diff --git a/third_party/jpeg-xl/lib/extras/enc/pgx.cc b/third_party/jpeg-xl/lib/extras/enc/pgx.cc
index d4809e38b6..eb8eab4271 100644
--- a/third_party/jpeg-xl/lib/extras/enc/pgx.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/pgx.cc
@@ -60,7 +60,7 @@ Status EncodeImagePGX(const PackedFrame& frame, const JxlBasicInfo& info,
std::vector<uint8_t> pixels(num_samples * bytes_per_sample);
if (format.data_type == JXL_TYPE_UINT8) {
- memcpy(&pixels[0], in, num_samples * bytes_per_sample);
+ memcpy(pixels.data(), in, num_samples * bytes_per_sample);
} else if (format.data_type == JXL_TYPE_UINT16) {
if (format.endianness != JXL_BIG_ENDIAN) {
const uint8_t* p_in = in;
@@ -69,7 +69,7 @@ Status EncodeImagePGX(const PackedFrame& frame, const JxlBasicInfo& info,
StoreBE16(LoadLE16(p_in), p_out);
}
} else {
- memcpy(&pixels[0], in, num_samples * bytes_per_sample);
+ memcpy(pixels.data(), in, num_samples * bytes_per_sample);
}
} else {
return JXL_FAILURE("Unsupported pixel data type");
diff --git a/third_party/jpeg-xl/lib/extras/enc/pnm.cc b/third_party/jpeg-xl/lib/extras/enc/pnm.cc
index 4183900198..966611cfca 100644
--- a/third_party/jpeg-xl/lib/extras/enc/pnm.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/pnm.cc
@@ -31,7 +31,7 @@ constexpr size_t kMaxHeaderSize = 200;
class BasePNMEncoder : public Encoder {
public:
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
- ThreadPool* pool = nullptr) const override {
+ ThreadPool* pool) const override {
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
if (!ppf.metadata.exif.empty() || !ppf.metadata.iptc.empty() ||
!ppf.metadata.jumbf.empty() || !ppf.metadata.xmp.empty()) {
diff --git a/third_party/jpeg-xl/lib/extras/jpegli_test.cc b/third_party/jpeg-xl/lib/extras/jpegli_test.cc
index 66c18617a6..3049049a64 100644
--- a/third_party/jpeg-xl/lib/extras/jpegli_test.cc
+++ b/third_party/jpeg-xl/lib/extras/jpegli_test.cc
@@ -85,7 +85,7 @@ Status EncodeWithLibjpeg(const PackedPixelFile& ppf, int quality,
std::unique_ptr<Encoder> encoder = GetJPEGEncoder();
encoder->SetOption("q", std::to_string(quality));
EncodedImage encoded;
- JXL_RETURN_IF_ERROR(encoder->Encode(ppf, &encoded));
+ JXL_RETURN_IF_ERROR(encoder->Encode(ppf, &encoded, nullptr));
JXL_RETURN_IF_ERROR(!encoded.bitstreams.empty());
*compressed = std::move(encoded.bitstreams[0]);
return true;
@@ -156,8 +156,8 @@ TEST(JpegliTest, JpegliXYBEncodeTest) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
- EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.45f));
- EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.32f));
+ EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.45f);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.32f);
}
TEST(JpegliTest, JpegliDecodeTestLargeSmoothArea) {
@@ -205,8 +205,8 @@ TEST(JpegliTest, JpegliYUVEncodeTest) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
- EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.7f));
- EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.32f));
+ EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.7f);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.32f);
}
TEST(JpegliTest, JpegliYUVChromaSubsamplingEncodeTest) {
@@ -247,8 +247,8 @@ TEST(JpegliTest, JpegliYUVEncodeTestNoAq) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
- EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.85f));
- EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.25f));
+ EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.85f);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.25f);
}
TEST(JpegliTest, JpegliHDRRoundtripTest) {
@@ -267,8 +267,8 @@ TEST(JpegliTest, JpegliHDRRoundtripTest) {
JpegDecompressParams dparams;
dparams.output_data_type = JXL_TYPE_UINT16;
ASSERT_TRUE(DecodeJpeg(compressed, dparams, nullptr, &ppf_out));
- EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(2.95f));
- EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.05f));
+ EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 2.95f);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.05f);
}
TEST(JpegliTest, JpegliSetAppData) {
diff --git a/third_party/jpeg-xl/lib/extras/mmap.cc b/third_party/jpeg-xl/lib/extras/mmap.cc
index 7852831ebd..9f5bba97ed 100644
--- a/third_party/jpeg-xl/lib/extras/mmap.cc
+++ b/third_party/jpeg-xl/lib/extras/mmap.cc
@@ -10,7 +10,8 @@
#include "lib/jxl/base/common.h"
-#if __unix__
+#if defined(__unix__) || defined(__unix) || \
+ defined(__APPLE__) && defined(__MACH__)
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
@@ -54,7 +55,7 @@ struct MemoryMappedFileImpl {
} // namespace jxl
-#elif __WIN32__
+#elif defined(_WIN32)
#include <string.h>
#include <windows.h>
@@ -97,6 +98,8 @@ struct MemoryMappedFileImpl {
return f;
}
+ ~MemoryMappedFileImpl() { UnmapViewOfFile(ptr); }
+
const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(ptr); }
size_t size() const { return fsize.QuadPart; }
diff --git a/third_party/jpeg-xl/lib/extras/packed_image.h b/third_party/jpeg-xl/lib/extras/packed_image.h
index edd5f1be75..a66ddfbd70 100644
--- a/third_party/jpeg-xl/lib/extras/packed_image.h
+++ b/third_party/jpeg-xl/lib/extras/packed_image.h
@@ -37,11 +37,18 @@ namespace extras {
// Class representing an interleaved image with a bunch of channels.
class PackedImage {
public:
- PackedImage(size_t xsize, size_t ysize, const JxlPixelFormat& format)
- : PackedImage(xsize, ysize, format, CalcStride(format, xsize)) {}
+ static StatusOr<PackedImage> Create(size_t xsize, size_t ysize,
+ const JxlPixelFormat& format) {
+ PackedImage image(xsize, ysize, format, CalcStride(format, xsize));
+ if (!image.pixels()) {
+ // TODO(szabadka): use specialized OOM error code
+ return JXL_FAILURE("Failed to allocate memory for image");
+ }
+ return image;
+ }
PackedImage Copy() const {
- PackedImage copy(xsize, ysize, format);
+ PackedImage copy(xsize, ysize, format, CalcStride(format, xsize));
memcpy(reinterpret_cast<uint8_t*>(copy.pixels()),
reinterpret_cast<const uint8_t*>(pixels()), pixels_size);
return copy;
@@ -108,7 +115,7 @@ class PackedImage {
}
}
- void SetPixelValue(size_t y, size_t x, size_t c, float val) {
+ void SetPixelValue(size_t y, size_t x, size_t c, float val) const {
uint8_t* data = pixels(y, x, c);
switch (format.data_type) {
case JXL_TYPE_UINT8:
@@ -169,17 +176,25 @@ class PackedImage {
// as all other frames in the same image.
class PackedFrame {
public:
- template <typename... Args>
- explicit PackedFrame(Args&&... args) : color(std::forward<Args>(args)...) {}
+ explicit PackedFrame(PackedImage&& image) : color(std::move(image)) {}
+
+ static StatusOr<PackedFrame> Create(size_t xsize, size_t ysize,
+ const JxlPixelFormat& format) {
+ JXL_ASSIGN_OR_RETURN(PackedImage image,
+ PackedImage::Create(xsize, ysize, format));
+ PackedFrame frame(std::move(image));
+ return frame;
+ }
- PackedFrame Copy() const {
- PackedFrame copy(color.xsize, color.ysize, color.format);
+ StatusOr<PackedFrame> Copy() const {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame copy,
+ PackedFrame::Create(color.xsize, color.ysize, color.format));
copy.frame_info = frame_info;
copy.name = name;
copy.color = color.Copy();
- for (size_t i = 0; i < extra_channels.size(); ++i) {
- PackedImage ec = extra_channels[i].Copy();
- copy.extra_channels.emplace_back(std::move(ec));
+ for (const auto& ec : extra_channels) {
+ copy.extra_channels.emplace_back(ec.Copy());
}
return copy;
}
@@ -244,12 +259,26 @@ class PackedPixelFile {
std::vector<PackedExtraChannel> extra_channels_info;
// Color information of the decoded pixels.
- // If the icc is empty, the JxlColorEncoding should be used instead.
- std::vector<uint8_t> icc;
+ // `primary_color_representation` indicates whether `color_encoding` or `icc`
+ // is the “authoritative” encoding of the colorspace, as opposed to a fallback
+ // encoding. For example, if `color_encoding` is the primary one, as would
+ // occur when decoding a jxl file with such a representation, then `enc/jxl`
+ // will use it and ignore the ICC profile, whereas `enc/png` will include the
+ // ICC profile for compatibility.
+ // If `icc` is the primary representation, `enc/jxl` will preserve it when
+ // compressing losslessly, but *may* encode it as a color_encoding when
+ // compressing lossily.
+ enum {
+ kColorEncodingIsPrimary,
+ kIccIsPrimary
+ } primary_color_representation = kColorEncodingIsPrimary;
JxlColorEncoding color_encoding = {};
+ std::vector<uint8_t> icc;
// The icc profile of the original image.
std::vector<uint8_t> orig_icc;
+ JxlBitDepth input_bitdepth = {JXL_BIT_DEPTH_FROM_PIXEL_FORMAT, 0, 0};
+
std::unique_ptr<PackedFrame> preview_frame;
std::vector<PackedFrame> frames;
mutable std::vector<ChunkedPackedFrame> chunked_frames;
diff --git a/third_party/jpeg-xl/lib/extras/packed_image_convert.cc b/third_party/jpeg-xl/lib/extras/packed_image_convert.cc
index 56f3b044a4..2ad001bf09 100644
--- a/third_party/jpeg-xl/lib/extras/packed_image_convert.cc
+++ b/third_party/jpeg-xl/lib/extras/packed_image_convert.cc
@@ -22,15 +22,15 @@ namespace jxl {
namespace extras {
Status ConvertPackedFrameToImageBundle(const JxlBasicInfo& info,
+ const JxlBitDepth& input_bitdepth,
const PackedFrame& frame,
const CodecInOut& io, ThreadPool* pool,
ImageBundle* bundle) {
JXL_ASSERT(frame.color.pixels() != nullptr);
- const bool float_in = frame.color.format.data_type == JXL_TYPE_FLOAT16 ||
- frame.color.format.data_type == JXL_TYPE_FLOAT;
size_t frame_bits_per_sample =
- float_in ? PackedImage::BitsPerChannel(frame.color.format.data_type)
- : info.bits_per_sample;
+ input_bitdepth.type == JXL_BIT_DEPTH_FROM_PIXEL_FORMAT
+ ? PackedImage::BitsPerChannel(frame.color.format.data_type)
+ : info.bits_per_sample;
JXL_ASSERT(frame_bits_per_sample != 0);
// It is ok for the frame.color.format.num_channels to not match the
// number of channels on the image.
@@ -64,7 +64,8 @@ Status ConvertPackedFrameToImageBundle(const JxlBasicInfo& info,
bundle->extra_channels().resize(io.metadata.m.extra_channel_info.size());
for (size_t i = 0; i < frame.extra_channels.size(); i++) {
const auto& ppf_ec = frame.extra_channels[i];
- bundle->extra_channels()[i] = ImageF(ppf_ec.xsize, ppf_ec.ysize);
+ JXL_ASSIGN_OR_RETURN(bundle->extra_channels()[i],
+ ImageF::Create(ppf_ec.xsize, ppf_ec.ysize));
JXL_CHECK(BufferToImageF(ppf_ec.format, ppf_ec.xsize, ppf_ec.ysize,
ppf_ec.pixels(), ppf_ec.pixels_size, pool,
&bundle->extra_channels()[i]));
@@ -97,23 +98,23 @@ Status ConvertPackedPixelFileToCodecInOut(const PackedPixelFile& ppf,
ppf.info.exponent_bits_per_sample == 0 && ppf.info.bits_per_sample <= 12;
io->metadata.m.SetAlphaBits(ppf.info.alpha_bits,
- ppf.info.alpha_premultiplied);
+ FROM_JXL_BOOL(ppf.info.alpha_premultiplied));
ExtraChannelInfo* alpha = io->metadata.m.Find(ExtraChannel::kAlpha);
if (alpha) alpha->bit_depth = io->metadata.m.bit_depth;
- io->metadata.m.xyb_encoded = !ppf.info.uses_original_profile;
+ io->metadata.m.xyb_encoded = !FROM_JXL_BOOL(ppf.info.uses_original_profile);
JXL_ASSERT(ppf.info.orientation > 0 && ppf.info.orientation <= 8);
io->metadata.m.orientation = ppf.info.orientation;
// Convert animation metadata
JXL_ASSERT(ppf.frames.size() == 1 || ppf.info.have_animation);
- io->metadata.m.have_animation = ppf.info.have_animation;
+ io->metadata.m.have_animation = FROM_JXL_BOOL(ppf.info.have_animation);
io->metadata.m.animation.tps_numerator = ppf.info.animation.tps_numerator;
io->metadata.m.animation.tps_denominator = ppf.info.animation.tps_denominator;
io->metadata.m.animation.num_loops = ppf.info.animation.num_loops;
// Convert the color encoding.
- if (!ppf.icc.empty()) {
+ if (ppf.primary_color_representation == PackedPixelFile::kIccIsPrimary) {
IccBytes icc = ppf.icc;
if (!io->metadata.m.color_encoding.SetICC(std::move(icc),
JxlGetDefaultCms())) {
@@ -170,15 +171,16 @@ Status ConvertPackedPixelFileToCodecInOut(const PackedPixelFile& ppf,
JXL_RETURN_IF_ERROR(
io->metadata.m.preview_size.Set(preview_xsize, preview_ysize));
JXL_RETURN_IF_ERROR(ConvertPackedFrameToImageBundle(
- ppf.info, *ppf.preview_frame, *io, pool, &io->preview_frame));
+ ppf.info, ppf.input_bitdepth, *ppf.preview_frame, *io, pool,
+ &io->preview_frame));
}
// Convert the pixels
io->frames.clear();
for (const auto& frame : ppf.frames) {
ImageBundle bundle(&io->metadata.m);
- JXL_RETURN_IF_ERROR(
- ConvertPackedFrameToImageBundle(ppf.info, frame, *io, pool, &bundle));
+ JXL_RETURN_IF_ERROR(ConvertPackedFrameToImageBundle(
+ ppf.info, ppf.input_bitdepth, frame, *io, pool, &bundle));
io->frames.push_back(std::move(bundle));
}
@@ -210,7 +212,8 @@ PackedPixelFile ConvertImage3FToPackedPixelFile(const Image3F& image,
: 0;
ppf.color_encoding = c_enc.ToExternal();
ppf.frames.clear();
- PackedFrame frame(image.xsize(), image.ysize(), format);
+ JXL_ASSIGN_OR_DIE(PackedFrame frame,
+ PackedFrame::Create(image.xsize(), image.ysize(), format));
const ImageF* channels[3];
for (int c = 0; c < 3; ++c) {
channels[c] = &image.Plane(c);
@@ -242,7 +245,8 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
ppf->info.alpha_bits = alpha_channel->bit_depth.bits_per_sample;
ppf->info.alpha_exponent_bits =
alpha_channel->bit_depth.exponent_bits_per_sample;
- ppf->info.alpha_premultiplied = alpha_channel->alpha_associated;
+ ppf->info.alpha_premultiplied =
+ TO_JXL_BOOL(alpha_channel->alpha_associated);
}
// Convert the image metadata
@@ -257,9 +261,9 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
ppf->info.linear_below = io.metadata.m.tone_mapping.linear_below;
ppf->info.min_nits = io.metadata.m.tone_mapping.min_nits;
ppf->info.relative_to_max_display =
- io.metadata.m.tone_mapping.relative_to_max_display;
+ TO_JXL_BOOL(io.metadata.m.tone_mapping.relative_to_max_display);
- ppf->info.uses_original_profile = !io.metadata.m.xyb_encoded;
+ ppf->info.uses_original_profile = TO_JXL_BOOL(!io.metadata.m.xyb_encoded);
JXL_ASSERT(0 < io.metadata.m.orientation && io.metadata.m.orientation <= 8);
ppf->info.orientation =
static_cast<JxlOrientation>(io.metadata.m.orientation);
@@ -267,13 +271,16 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
// Convert animation metadata
JXL_ASSERT(io.frames.size() == 1 || io.metadata.m.have_animation);
- ppf->info.have_animation = io.metadata.m.have_animation;
+ ppf->info.have_animation = TO_JXL_BOOL(io.metadata.m.have_animation);
ppf->info.animation.tps_numerator = io.metadata.m.animation.tps_numerator;
ppf->info.animation.tps_denominator = io.metadata.m.animation.tps_denominator;
ppf->info.animation.num_loops = io.metadata.m.animation.num_loops;
// Convert the color encoding
ppf->icc.assign(c_desired.ICC().begin(), c_desired.ICC().end());
+ ppf->primary_color_representation =
+ c_desired.WantICC() ? PackedPixelFile::kIccIsPrimary
+ : PackedPixelFile::kColorEncodingIsPrimary;
ppf->color_encoding = c_desired.ToExternal();
// Convert the extra blobs
@@ -289,22 +296,24 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
JXL_ASSERT(frame.metadata()->bit_depth.bits_per_sample != 0);
// It is ok for the frame.color().kNumPlanes to not match the
// number of channels on the image.
+ const uint32_t alpha_channels = has_alpha ? 1 : 0;
const uint32_t num_channels =
- frame.metadata()->color_encoding.Channels() + has_alpha;
+ frame.metadata()->color_encoding.Channels() + alpha_channels;
JxlPixelFormat format{/*num_channels=*/num_channels,
/*data_type=*/pixel_format.data_type,
/*endianness=*/pixel_format.endianness,
/*align=*/pixel_format.align};
- PackedFrame packed_frame(frame.oriented_xsize(), frame.oriented_ysize(),
- format);
+ JXL_ASSIGN_OR_RETURN(PackedFrame packed_frame,
+ PackedFrame::Create(frame.oriented_xsize(),
+ frame.oriented_ysize(), format));
const size_t bits_per_sample =
float_out ? packed_frame.color.BitsPerChannel(pixel_format.data_type)
: ppf->info.bits_per_sample;
packed_frame.name = frame.name;
packed_frame.frame_info.name_length = frame.name.size();
// Color transform
- ImageBundle ib = frame.Copy();
+ JXL_ASSIGN_OR_RETURN(ImageBundle ib, frame.Copy());
const ImageBundle* to_color_transform = &ib;
ImageMetadata metadata = io.metadata.m;
ImageBundle store(&metadata);
diff --git a/third_party/jpeg-xl/lib/extras/tone_mapping.cc b/third_party/jpeg-xl/lib/extras/tone_mapping.cc
index 3d0269524b..39df304501 100644
--- a/third_party/jpeg-xl/lib/extras/tone_mapping.cc
+++ b/third_party/jpeg-xl/lib/extras/tone_mapping.cc
@@ -19,7 +19,7 @@ HWY_BEFORE_NAMESPACE();
namespace jxl {
namespace HWY_NAMESPACE {
-static constexpr float rec2020_luminances[3] = {0.2627f, 0.6780f, 0.0593f};
+static constexpr Vector3 rec2020_luminances{0.2627f, 0.6780f, 0.0593f};
Status ToneMapFrame(const std::pair<float, float> display_nits,
ImageBundle* const ib, ThreadPool* const pool) {
diff --git a/third_party/jpeg-xl/lib/extras/tone_mapping_gbench.cc b/third_party/jpeg-xl/lib/extras/tone_mapping_gbench.cc
index 34cbdde781..8fc928a4fd 100644
--- a/third_party/jpeg-xl/lib/extras/tone_mapping_gbench.cc
+++ b/third_party/jpeg-xl/lib/extras/tone_mapping_gbench.cc
@@ -6,11 +6,12 @@
#include "benchmark/benchmark.h"
#include "lib/extras/codec.h"
#include "lib/extras/tone_mapping.h"
+#include "lib/jxl/image.h"
namespace jxl {
static void BM_ToneMapping(benchmark::State& state) {
- Image3F color(2268, 1512);
+ JXL_ASSIGN_OR_DIE(Image3F color, Image3F::Create(2268, 1512));
FillImage(0.5f, &color);
// Use linear Rec. 2020 so that `ToneMapTo` doesn't have to convert to it and
@@ -25,7 +26,8 @@ static void BM_ToneMapping(benchmark::State& state) {
for (auto _ : state) {
state.PauseTiming();
CodecInOut tone_mapping_input;
- Image3F color2(color.xsize(), color.ysize());
+ JXL_ASSIGN_OR_DIE(Image3F color2,
+ Image3F::Create(color.xsize(), color.ysize()));
CopyImageTo(color, &color2);
tone_mapping_input.SetFromImage(std::move(color2), linear_rec2020);
tone_mapping_input.metadata.m.SetIntensityTarget(255);
diff --git a/third_party/jpeg-xl/lib/include/jxl/cms_interface.h b/third_party/jpeg-xl/lib/include/jxl/cms_interface.h
index c164eaccb5..25c700867a 100644
--- a/third_party/jpeg-xl/lib/include/jxl/cms_interface.h
+++ b/third_party/jpeg-xl/lib/include/jxl/cms_interface.h
@@ -29,10 +29,10 @@ extern "C" {
/** Parses an ICC profile and populates @p c and @p cmyk with the data.
*
- * @param user_data JxlCmsInterface::set_fields_data passed as-is.
+ * @param user_data @ref JxlCmsInterface::set_fields_data passed as-is.
* @param icc_data the ICC data to parse.
* @param icc_size how many bytes of icc_data are valid.
- * @param c a JxlColorEncoding to populate if applicable.
+ * @param c a @ref JxlColorEncoding to populate if applicable.
* @param cmyk a boolean to set to whether the colorspace is a CMYK colorspace.
* @return Whether the relevant fields in @p c were successfully populated.
*/
@@ -66,22 +66,23 @@ typedef struct {
/** Allocates and returns the data needed for @p num_threads parallel transforms
* from the @p input colorspace to @p output, with up to @p pixels_per_thread
- * pixels to transform per call to JxlCmsInterface::run. @p init_data comes
- * directly from the JxlCmsInterface instance. Since @c run only receives the
- * data returned by @c init, a reference to @p init_data should be kept there
- * if access to it is desired in @c run. Likewise for JxlCmsInterface::destroy.
+ * pixels to transform per call to @ref JxlCmsInterface::run. @p init_data comes
+ * directly from the @ref JxlCmsInterface instance. Since @c run only receives
+ * the data returned by @c init, a reference to @p init_data should be kept
+ * there if access to it is desired in @c run. Likewise for @ref
+ * JxlCmsInterface::destroy.
*
* The ICC data in @p input and @p output is guaranteed to outlive the @c init /
* @c run / @c destroy cycle.
*
- * @param init_data JxlCmsInterface::init_data passed as-is.
+ * @param init_data @ref JxlCmsInterface::init_data passed as-is.
* @param num_threads the maximum number of threads from which
- * JxlCmsInterface::run will be called.
+ * @ref JxlCmsInterface::run will be called.
* @param pixels_per_thread the maximum number of pixels that each call to
- * JxlCmsInterface::run will have to transform.
+ * @ref JxlCmsInterface::run will have to transform.
* @param input_profile the input colorspace for the transform.
- * @param output_profile the colorspace to which JxlCmsInterface::run should
- * convert the input data.
+ * @param output_profile the colorspace to which @ref JxlCmsInterface::run
+ * should convert the input data.
* @param intensity_target for colorspaces where luminance is relative
* (essentially: not PQ), indicates the luminance at which (1, 1, 1) will
* be displayed. This is useful for conversions between PQ and a relative
@@ -135,7 +136,7 @@ typedef float* (*jpegxl_cms_get_buffer_func)(void* user_data, size_t thread);
* @param output_buffer the buffer receiving the transformed pixel data.
* @param num_pixels the number of pixels to transform from @p input to
* @p output.
- * @return JXL_TRUE on success, JXL_FALSE on failure.
+ * @return ::JXL_TRUE on success, ::JXL_FALSE on failure.
*/
typedef JXL_BOOL (*jpegxl_cms_run_func)(void* user_data, size_t thread,
const float* input_buffer,
@@ -226,7 +227,7 @@ typedef void (*jpegxl_cms_destroy_func)(void*);
typedef struct {
/** CMS-specific data that will be passed to @ref set_fields_from_icc. */
void* set_fields_data;
- /** Populates a JxlColorEncoding from an ICC profile. */
+ /** Populates a @ref JxlColorEncoding from an ICC profile. */
jpegxl_cms_set_fields_from_icc_func set_fields_from_icc;
/** CMS-specific data that will be passed to @ref init. */
diff --git a/third_party/jpeg-xl/lib/include/jxl/codestream_header.h b/third_party/jpeg-xl/lib/include/jxl/codestream_header.h
index fb71484233..e60eb03355 100644
--- a/third_party/jpeg-xl/lib/include/jxl/codestream_header.h
+++ b/third_party/jpeg-xl/lib/include/jxl/codestream_header.h
@@ -71,7 +71,7 @@ typedef struct {
} JxlPreviewHeader;
/** The codestream animation header, optionally present in the beginning of
- * the codestream, and if it is it applies to all animation frames, unlike
+ * the codestream, and if it is it applies to all animation frames, unlike @ref
* JxlFrameHeader which applies to an individual frame.
*/
typedef struct {
@@ -166,12 +166,12 @@ typedef struct {
* it to to the original color profile. The decoder also does not convert to
* the target display color profile. To convert the pixel data produced by
* the decoder to the original color profile, one of the JxlDecoderGetColor*
- * functions needs to be called with @ref JXL_COLOR_PROFILE_TARGET_DATA to get
- * the color profile of the decoder output, and then an external CMS can be
- * used for conversion.
- * Note that for lossy compression, this should be set to false for most use
- * cases, and if needed, the image should be converted to the original color
- * profile after decoding, as described above.
+ * functions needs to be called with
+ * ::JXL_COLOR_PROFILE_TARGET_DATA to get the color profile of the decoder
+ * output, and then an external CMS can be used for conversion. Note that for
+ * lossy compression, this should be set to false for most use cases, and if
+ * needed, the image should be converted to the original color profile after
+ * decoding, as described above.
*/
JXL_BOOL uses_original_profile;
@@ -194,17 +194,19 @@ typedef struct {
* grayscale data, or 3 for colored data. This count does not include
* the alpha channel or other extra channels. To check presence of an alpha
* channel, such as in the case of RGBA color, check alpha_bits != 0.
- * If and only if this is 1, the JxlColorSpace in the JxlColorEncoding is
- * JXL_COLOR_SPACE_GRAY.
+ * If and only if this is 1, the @ref JxlColorSpace in the @ref
+ * JxlColorEncoding is
+ * ::JXL_COLOR_SPACE_GRAY.
*/
uint32_t num_color_channels;
/** Number of additional image channels. This includes the main alpha channel,
* but can also include additional channels such as depth, additional alpha
* channels, spot colors, and so on. Information about the extra channels
- * can be queried with JxlDecoderGetExtraChannelInfo. The main alpha channel,
- * if it exists, also has its information available in the alpha_bits,
- * alpha_exponent_bits and alpha_premultiplied fields in this JxlBasicInfo.
+ * can be queried with @ref JxlDecoderGetExtraChannelInfo. The main alpha
+ * channel, if it exists, also has its information available in the
+ * alpha_bits, alpha_exponent_bits and alpha_premultiplied fields in this @ref
+ * JxlBasicInfo.
*/
uint32_t num_extra_channels;
@@ -388,7 +390,8 @@ typedef struct {
/** The header of one displayed frame or non-coalesced layer. */
typedef struct {
/** How long to wait after rendering in ticks. The duration in seconds of a
- * tick is given by tps_numerator and tps_denominator in JxlAnimationHeader.
+ * tick is given by tps_numerator and tps_denominator in @ref
+ * JxlAnimationHeader.
*/
uint32_t duration;
@@ -396,9 +399,9 @@ typedef struct {
* interpreted from most-significant to least-significant as hour, minute,
* second, and frame. If timecode is nonzero, it is strictly larger than that
* of a previous frame with nonzero duration. These values are only available
- * if have_timecodes in JxlAnimationHeader is JXL_TRUE.
- * This value is only used if have_timecodes in JxlAnimationHeader is
- * JXL_TRUE.
+ * if have_timecodes in @ref JxlAnimationHeader is ::JXL_TRUE.
+ * This value is only used if have_timecodes in @ref JxlAnimationHeader is
+ * ::JXL_TRUE.
*/
uint32_t timecode;
diff --git a/third_party/jpeg-xl/lib/include/jxl/color_encoding.h b/third_party/jpeg-xl/lib/include/jxl/color_encoding.h
index 928117e8dd..e6325dcb30 100644
--- a/third_party/jpeg-xl/lib/include/jxl/color_encoding.h
+++ b/third_party/jpeg-xl/lib/include/jxl/color_encoding.h
@@ -24,9 +24,9 @@ extern "C" {
typedef enum {
/** Tristimulus RGB */
JXL_COLOR_SPACE_RGB,
- /** Luminance based, the primaries in JxlColorEncoding must be ignored. This
- * value implies that num_color_channels in JxlBasicInfo is 1, any other value
- * implies num_color_channels is 3. */
+ /** Luminance based, the primaries in @ref JxlColorEncoding must be ignored.
+ * This value implies that num_color_channels in @ref JxlBasicInfo is 1, any
+ * other value implies num_color_channels is 3. */
JXL_COLOR_SPACE_GRAY,
/** XYB (opsin) color space */
JXL_COLOR_SPACE_XYB,
@@ -35,18 +35,18 @@ typedef enum {
} JxlColorSpace;
/** Built-in whitepoints for color encoding. When decoding, the numerical xy
- * whitepoint value can be read from the JxlColorEncoding white_point field
+ * whitepoint value can be read from the @ref JxlColorEncoding white_point field
* regardless of the enum value. When encoding, enum values except
- * JXL_WHITE_POINT_CUSTOM override the numerical fields. Some enum values match
- * a subset of CICP (Rec. ITU-T H.273 | ISO/IEC 23091-2:2019(E)), however the
- * white point and RGB primaries are separate enums here.
+ * ::JXL_WHITE_POINT_CUSTOM override the numerical fields. Some enum values
+ * match a subset of CICP (Rec. ITU-T H.273 | ISO/IEC 23091-2:2019(E)), however
+ * the white point and RGB primaries are separate enums here.
*/
typedef enum {
/** CIE Standard Illuminant D65: 0.3127, 0.3290 */
JXL_WHITE_POINT_D65 = 1,
- /** White point must be read from the JxlColorEncoding white_point field, or
- * as ICC profile. This enum value is not an exact match of the corresponding
- * CICP value. */
+ /** White point must be read from the @ref JxlColorEncoding white_point field,
+ * or as ICC profile. This enum value is not an exact match of the
+ * corresponding CICP value. */
JXL_WHITE_POINT_CUSTOM = 2,
/** CIE Standard Illuminant E (equal-energy): 1/3, 1/3 */
JXL_WHITE_POINT_E = 10,
@@ -55,10 +55,10 @@ typedef enum {
} JxlWhitePoint;
/** Built-in primaries for color encoding. When decoding, the primaries can be
- * read from the JxlColorEncoding primaries_red_xy, primaries_green_xy and
+ * read from the @ref JxlColorEncoding primaries_red_xy, primaries_green_xy and
* primaries_blue_xy fields regardless of the enum value. When encoding, the
- * enum values except JXL_PRIMARIES_CUSTOM override the numerical fields. Some
- * enum values match a subset of CICP (Rec. ITU-T H.273 | ISO/IEC
+ * enum values except ::JXL_PRIMARIES_CUSTOM override the numerical fields.
+ * Some enum values match a subset of CICP (Rec. ITU-T H.273 | ISO/IEC
* 23091-2:2019(E)), however the white point and RGB primaries are separate
* enums here.
*/
@@ -66,7 +66,7 @@ typedef enum {
/** The CIE xy values of the red, green and blue primaries are: 0.639998686,
0.330010138; 0.300003784, 0.600003357; 0.150002046, 0.059997204 */
JXL_PRIMARIES_SRGB = 1,
- /** Primaries must be read from the JxlColorEncoding primaries_red_xy,
+ /** Primaries must be read from the @ref JxlColorEncoding primaries_red_xy,
* primaries_green_xy and primaries_blue_xy fields, or as ICC profile. This
* enum value is not an exact match of the corresponding CICP value. */
JXL_PRIMARIES_CUSTOM = 2,
@@ -94,7 +94,7 @@ typedef enum {
JXL_TRANSFER_FUNCTION_DCI = 17,
/** As specified in Rec. ITU-R BT.2100-1 (HLG) */
JXL_TRANSFER_FUNCTION_HLG = 18,
- /** Transfer function follows power law given by the gamma value in
+ /** Transfer function follows power law given by the gamma value in @ref
JxlColorEncoding. Not a CICP value. */
JXL_TRANSFER_FUNCTION_GAMMA = 65535,
} JxlTransferFunction;
@@ -118,7 +118,7 @@ typedef struct {
*/
JxlColorSpace color_space;
- /** Built-in white point. If this value is JXL_WHITE_POINT_CUSTOM, must
+ /** Built-in white point. If this value is ::JXL_WHITE_POINT_CUSTOM, must
* use the numerical whitepoint values from white_point_xy.
*/
JxlWhitePoint white_point;
@@ -126,10 +126,10 @@ typedef struct {
/** Numerical whitepoint values in CIE xy space. */
double white_point_xy[2];
- /** Built-in RGB primaries. If this value is JXL_PRIMARIES_CUSTOM, must
+ /** Built-in RGB primaries. If this value is ::JXL_PRIMARIES_CUSTOM, must
* use the numerical primaries values below. This field and the custom values
* below are unused and must be ignored if the color space is
- * JXL_COLOR_SPACE_GRAY or JXL_COLOR_SPACE_XYB.
+ * ::JXL_COLOR_SPACE_GRAY or ::JXL_COLOR_SPACE_XYB.
*/
JxlPrimaries primaries;
@@ -145,7 +145,8 @@ typedef struct {
/** Transfer function if have_gamma is 0 */
JxlTransferFunction transfer_function;
- /** Gamma value used when transfer_function is JXL_TRANSFER_FUNCTION_GAMMA
+ /** Gamma value used when transfer_function is @ref
+ * JXL_TRANSFER_FUNCTION_GAMMA
*/
double gamma;
diff --git a/third_party/jpeg-xl/lib/include/jxl/decode.h b/third_party/jpeg-xl/lib/include/jxl/decode.h
index eaee70fa61..599b8336f3 100644
--- a/third_party/jpeg-xl/lib/include/jxl/decode.h
+++ b/third_party/jpeg-xl/lib/include/jxl/decode.h
@@ -66,12 +66,12 @@ typedef enum {
* @p size doesn't need to be a full image, only the beginning of the file.
*
* @return a flag indicating if a JPEG XL signature was found and what type.
- * - @ref JXL_SIG_NOT_ENOUGH_BYTES if not enough bytes were passed to
+ * - ::JXL_SIG_NOT_ENOUGH_BYTES if not enough bytes were passed to
* determine if a valid signature is there.
- * - @ref JXL_SIG_INVALID if no valid signature found for JPEG XL decoding.
- * - @ref JXL_SIG_CODESTREAM if a valid JPEG XL codestream signature was
+ * - ::JXL_SIG_INVALID if no valid signature found for JPEG XL decoding.
+ * - ::JXL_SIG_CODESTREAM if a valid JPEG XL codestream signature was
* found.
- * - @ref JXL_SIG_CONTAINER if a valid JPEG XL container signature was found.
+ * - ::JXL_SIG_CONTAINER if a valid JPEG XL container signature was found.
*/
JXL_EXPORT JxlSignature JxlSignatureCheck(const uint8_t* buf, size_t len);
@@ -115,7 +115,7 @@ JXL_EXPORT void JxlDecoderDestroy(JxlDecoder* dec);
/**
* Return value for @ref JxlDecoderProcessInput.
- * The values from @ref JXL_DEC_BASIC_INFO onwards are optional informative
+ * The values from ::JXL_DEC_BASIC_INFO onwards are optional informative
* events that can be subscribed to, they are never returned if they
* have not been registered with @ref JxlDecoderSubscribeEvents.
*/
@@ -123,12 +123,12 @@ typedef enum {
/** Function call finished successfully, or decoding is finished and there is
* nothing more to be done.
*
- * Note that @ref JxlDecoderProcessInput will return JXL_DEC_SUCCESS if all
- * events that were registered with @ref JxlDecoderSubscribeEvents were
+ * Note that @ref JxlDecoderProcessInput will return ::JXL_DEC_SUCCESS if
+ * all events that were registered with @ref JxlDecoderSubscribeEvents were
* processed, even before the end of the JPEG XL codestream.
*
* In this case, the return value @ref JxlDecoderReleaseInput will be the same
- * as it was at the last signaled event. E.g. if JXL_DEC_FULL_IMAGE was
+ * as it was at the last signaled event. E.g. if ::JXL_DEC_FULL_IMAGE was
* subscribed to, then all bytes from the end of the JPEG XL codestream
* (including possible boxes needed for jpeg reconstruction) will be returned
* as unprocessed.
@@ -151,14 +151,14 @@ typedef enum {
* In most cases, @ref JxlDecoderReleaseInput will return no unprocessed bytes
* at this event, the only exceptions are if the previously set input ended
* within (a) the raw codestream signature, (b) the signature box, (c) a box
- * header, or (d) the first 4 bytes of a brob, ftyp, or jxlp box. In any of
- * these cases the number of unprocessed bytes is less than 20.
+ * header, or (d) the first 4 bytes of a `brob`, `ftyp`, or `jxlp` box. In any
+ * of these cases the number of unprocessed bytes is less than 20.
*/
JXL_DEC_NEED_MORE_INPUT = 2,
/** The decoder is able to decode a preview image and requests setting a
* preview output buffer using @ref JxlDecoderSetPreviewOutBuffer. This occurs
- * if @ref JXL_DEC_PREVIEW_IMAGE is requested and it is possible to decode a
+ * if ::JXL_DEC_PREVIEW_IMAGE is requested and it is possible to decode a
* preview image from the codestream and the preview out buffer was not yet
* set. There is maximum one preview image in a codestream.
* In this case, @ref JxlDecoderReleaseInput will return all bytes from the
@@ -179,13 +179,13 @@ typedef enum {
/** The JPEG reconstruction buffer is too small for reconstructed JPEG
* codestream to fit. @ref JxlDecoderSetJPEGBuffer must be called again to
* make room for remaining bytes. This event may occur multiple times
- * after @ref JXL_DEC_JPEG_RECONSTRUCTION.
+ * after ::JXL_DEC_JPEG_RECONSTRUCTION.
*/
JXL_DEC_JPEG_NEED_MORE_OUTPUT = 6,
/** The box contents output buffer is too small. @ref JxlDecoderSetBoxBuffer
* must be called again to make room for remaining bytes. This event may occur
- * multiple times after @ref JXL_DEC_BOX.
+ * multiple times after ::JXL_DEC_BOX.
*/
JXL_DEC_BOX_NEED_MORE_OUTPUT = 7,
@@ -201,7 +201,7 @@ typedef enum {
/** Informative event by @ref JxlDecoderProcessInput
* "JxlDecoderProcessInput": Color encoding or ICC profile from the
* codestream header. This event occurs max once per image and always later
- * than @ref JXL_DEC_BASIC_INFO and earlier than any pixel data.
+ * than ::JXL_DEC_BASIC_INFO and earlier than any pixel data.
* In this case, @ref JxlDecoderReleaseInput will return all bytes from the
* end of the image header (which is the start of the first frame) as
* unprocessed.
@@ -212,7 +212,7 @@ typedef enum {
* "JxlDecoderProcessInput": Preview image, a small frame, decoded. This
* event can only happen if the image has a preview frame encoded. This event
* occurs max once for the codestream and always later than @ref
- * JXL_DEC_COLOR_ENCODING and before @ref JXL_DEC_FRAME.
+ * JXL_DEC_COLOR_ENCODING and before ::JXL_DEC_FRAME.
* In this case, @ref JxlDecoderReleaseInput will return all bytes from the
* end of the preview frame as unprocessed.
*/
@@ -223,19 +223,19 @@ typedef enum {
* JxlDecoderGetFrameHeader can be used at this point. A note on frames:
* a JPEG XL image can have internal frames that are not intended to be
* displayed (e.g. used for compositing a final frame), but this only returns
- * displayed frames, unless @ref JxlDecoderSetCoalescing was set to JXL_FALSE:
- * in that case, the individual layers are returned, without blending. Note
- * that even when coalescing is disabled, only frames of type kRegularFrame
- * are returned; frames of type kReferenceOnly and kLfFrame are always for
- * internal purposes only and cannot be accessed. A displayed frame either has
- * an animation duration or is the only or last frame in the image. This event
- * occurs max once per displayed frame, always later than @ref
- * JXL_DEC_COLOR_ENCODING, and always earlier than any pixel data. While
- * JPEG XL supports encoding a single frame as the composition of multiple
- * internal sub-frames also called frames, this event is not indicated for the
- * internal frames.
- * In this case, @ref JxlDecoderReleaseInput will return all bytes from the
- * end of the frame header (including ToC) as unprocessed.
+ * displayed frames, unless @ref JxlDecoderSetCoalescing was set to @ref
+ * JXL_FALSE "JXL_FALSE": in that case, the individual layers are returned,
+ * without blending. Note that even when coalescing is disabled, only frames
+ * of type kRegularFrame are returned; frames of type kReferenceOnly
+ * and kLfFrame are always for internal purposes only and cannot be accessed.
+ * A displayed frame either has an animation duration or is the only or last
+ * frame in the image. This event occurs max once per displayed frame, always
+ * later than ::JXL_DEC_COLOR_ENCODING, and always earlier than any pixel
+ * data. While JPEG XL supports encoding a single frame as the composition of
+ * multiple internal sub-frames also called frames, this event is not
+ * indicated for the internal frames. In this case, @ref
+ * JxlDecoderReleaseInput will return all bytes from the end of the frame
+ * header (including ToC) as unprocessed.
*/
JXL_DEC_FRAME = 0x400,
@@ -246,7 +246,7 @@ typedef enum {
* not this return status only indicates we're past this point in the
* codestream. This event occurs max once per frame.
* In this case, @ref JxlDecoderReleaseInput will return all bytes from the
- * end of the frame (or if @ref JXL_DEC_JPEG_RECONSTRUCTION is subscribed to,
+ * end of the frame (or if ::JXL_DEC_JPEG_RECONSTRUCTION is subscribed to,
* from the end of the last box that is needed for jpeg reconstruction) as
* unprocessed.
*/
@@ -259,9 +259,9 @@ typedef enum {
* is set a byte stream identical to the JPEG codestream used to encode the
* image will be written to the JPEG reconstruction buffer instead of pixels
* to the image out buffer. This event occurs max once per image and always
- * before @ref JXL_DEC_FULL_IMAGE.
+ * before ::JXL_DEC_FULL_IMAGE.
* In this case, @ref JxlDecoderReleaseInput will return all bytes from the
- * end of the 'jbrd' box as unprocessed.
+ * end of the `jbrd` box as unprocessed.
*/
JXL_DEC_JPEG_RECONSTRUCTION = 0x2000,
@@ -290,8 +290,8 @@ typedef enum {
*
* The buffer set with @ref JxlDecoderSetBoxBuffer must be set again for each
* next box to be obtained, or can be left unset to skip outputting this box.
- * The output buffer contains the full box data when the next @ref JXL_DEC_BOX
- * event or @ref JXL_DEC_SUCCESS occurs. @ref JXL_DEC_BOX occurs for all
+ * The output buffer contains the full box data when the next ::JXL_DEC_BOX
+ * event or ::JXL_DEC_SUCCESS occurs. ::JXL_DEC_BOX occurs for all
* boxes, including non-metadata boxes such as the signature box or codestream
* boxes. To check whether the box is a metadata type for respectively EXIF,
* XMP or JUMBF, use @ref JxlDecoderGetBoxType and check for types "Exif",
@@ -324,26 +324,40 @@ typedef enum {
* Setting a progressive detail with value N implies all progressive details
* with smaller or equal value. Currently only the following level of
* progressive detail is implemented:
- * - kDC (which implies kFrames)
- * - kLastPasses (which implies kDC and kFrames)
- * - kPasses (which implies kLastPasses, kDC and kFrames)
+ * - @ref kDC (which implies kFrames)
+ * - @ref kLastPasses (which implies @ref kDC and @ref kFrames)
+ * - @ref kPasses (which implies @ref kLastPasses, kDC and @ref kFrames)
*/
typedef enum {
- // after completed kRegularFrames
+ /**
+ * after completed kRegularFrames
+ */
kFrames = 0,
- // after completed DC (1:8)
+ /**
+ * after completed DC (1:8)
+ */
kDC = 1,
- // after completed AC passes that are the last pass for their resolution
- // target.
+ /**
+ * after completed AC passes that are the last pass for their resolution
+ * target.
+ */
kLastPasses = 2,
- // after completed AC passes that are not the last pass for their resolution
- // target.
+ /**
+ * after completed AC passes that are not the last pass for their resolution
+ * target.
+ */
kPasses = 3,
- // during DC frame when lower resolution are completed (1:32, 1:16)
+ /**
+ * during DC frame when lower resolution are completed (1:32, 1:16)
+ */
kDCProgressive = 4,
- // after completed groups
+ /**
+ * after completed groups
+ */
kDCGroups = 5,
- // after completed groups
+ /**
+ * after completed groups
+ */
kGroups = 6,
} JxlProgressiveDetail;
@@ -354,8 +368,8 @@ typedef enum {
* more efficiently with @ref JxlDecoderSkipFrames. Settings such as parallel
* runner or subscribed events are kept. After rewind, @ref
* JxlDecoderSubscribeEvents can be used again, and it is feasible to leave out
- * events that were already handled before, such as @ref JXL_DEC_BASIC_INFO
- * and @ref JXL_DEC_COLOR_ENCODING, since they will provide the same information
+ * events that were already handled before, such as ::JXL_DEC_BASIC_INFO
+ * and ::JXL_DEC_COLOR_ENCODING, since they will provide the same information
* as before.
* The difference to @ref JxlDecoderReset is that some state is kept, namely
* settings set by a call to
@@ -376,14 +390,14 @@ JXL_EXPORT void JxlDecoderRewind(JxlDecoder* dec);
* the input, but will not output the frame events. It can be more efficient
* when skipping frames, and even more so when using this after @ref
* JxlDecoderRewind. If the decoder is already processing a frame (could
- * have emitted @ref JXL_DEC_FRAME but not yet @ref JXL_DEC_FULL_IMAGE), it
+ * have emitted ::JXL_DEC_FRAME but not yet ::JXL_DEC_FULL_IMAGE), it
* starts skipping from the next frame. If the amount is larger than the amount
* of frames remaining in the image, all remaining frames are skipped. Calling
* this function multiple times adds the amount to skip to the already existing
* amount.
*
* A frame here is defined as a frame that without skipping emits events such
- * as @ref JXL_DEC_FRAME and @ref JXL_DEC_FULL_IMAGE, frames that are internal
+ * as ::JXL_DEC_FRAME and ::JXL_DEC_FULL_IMAGE, frames that are internal
* to the file format but are not rendered as part of an animation, or are not
* the final still frame of a still image, are not counted.
*
@@ -394,14 +408,14 @@ JXL_EXPORT void JxlDecoderSkipFrames(JxlDecoder* dec, size_t amount);
/**
* Skips processing the current frame. Can be called after frame processing
- * already started, signaled by a @ref JXL_DEC_NEED_IMAGE_OUT_BUFFER event,
- * but before the corresponding @ref JXL_DEC_FULL_IMAGE event. The next signaled
- * event will be another @ref JXL_DEC_FRAME, or @ref JXL_DEC_SUCCESS if there
+ * already started, signaled by a ::JXL_DEC_NEED_IMAGE_OUT_BUFFER event,
+ * but before the corresponding ::JXL_DEC_FULL_IMAGE event. The next signaled
+ * event will be another ::JXL_DEC_FRAME, or ::JXL_DEC_SUCCESS if there
* are no more frames. If pixel data is required from the already processed part
* of the frame, @ref JxlDecoderFlushImage must be called before this.
*
* @param dec decoder object
- * @return @ref JXL_DEC_SUCCESS if there is a frame to skip, and @ref
+ * @return ::JXL_DEC_SUCCESS if there is a frame to skip, and @ref
* JXL_DEC_ERROR if the function was not called during frame processing.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSkipCurrentFrame(JxlDecoder* dec);
@@ -415,7 +429,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSkipCurrentFrame(JxlDecoder* dec);
* be NULL to use the default, single-threaded, runner. A multithreaded
* runner should be set to reach fast performance.
* @param parallel_runner_opaque opaque pointer for parallel_runner.
- * @return @ref JXL_DEC_SUCCESS if the runner was set, @ref JXL_DEC_ERROR
+ * @return ::JXL_DEC_SUCCESS if the runner was set, ::JXL_DEC_ERROR
* otherwise (the previous runner remains set).
*/
JXL_EXPORT JxlDecoderStatus
@@ -439,7 +453,7 @@ JxlDecoderSetParallelRunner(JxlDecoder* dec, JxlParallelRunner parallel_runner,
*/
JXL_EXPORT size_t JxlDecoderSizeHintBasicInfo(const JxlDecoder* dec);
-/** Select for which informative events, i.e. @ref JXL_DEC_BASIC_INFO, etc., the
+/** Select for which informative events, i.e. ::JXL_DEC_BASIC_INFO, etc., the
* decoder should return with a status. It is not required to subscribe to any
* events, data can still be requested from the decoder as soon as it available.
* By default, the decoder is subscribed to no events (events_wanted == 0), and
@@ -449,7 +463,7 @@ JXL_EXPORT size_t JxlDecoderSizeHintBasicInfo(const JxlDecoder* dec);
*
* @param dec decoder object
* @param events_wanted bitfield of desired events.
- * @return @ref JXL_DEC_SUCCESS if no error, @ref JXL_DEC_ERROR otherwise.
+ * @return ::JXL_DEC_SUCCESS if no error, ::JXL_DEC_ERROR otherwise.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSubscribeEvents(JxlDecoder* dec,
int events_wanted);
@@ -459,14 +473,14 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSubscribeEvents(JxlDecoder* dec,
* indicating that the decoder must perform a rotation and/or
* mirroring to the encoded image data.
*
- * - If skip_reorientation is JXL_FALSE (the default): the decoder
+ * - If skip_reorientation is ::JXL_FALSE (the default): the decoder
* will apply the transformation from the orientation setting, hence
* rendering the image according to its specified intent. When
- * producing a JxlBasicInfo, the decoder will always set the
+ * producing a @ref JxlBasicInfo, the decoder will always set the
* orientation field to JXL_ORIENT_IDENTITY (matching the returned
* pixel data) and also align xsize and ysize so that they correspond
* to the width and the height of the returned pixel data.
- * - If skip_reorientation is JXL_TRUE: the decoder will skip
+ * - If skip_reorientation is ::JXL_TRUE "JXL_TRUE": the decoder will skip
* applying the transformation from the orientation setting, returning
* the image in the as-in-bitstream pixeldata orientation.
* This may be faster to decode since the decoder doesn't have to apply the
@@ -483,17 +497,18 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSubscribeEvents(JxlDecoder* dec,
*
* @param dec decoder object
* @param skip_reorientation JXL_TRUE to enable, JXL_FALSE to disable.
- * @return @ref JXL_DEC_SUCCESS if no error, @ref JXL_DEC_ERROR otherwise.
+ * @return ::JXL_DEC_SUCCESS if no error, ::JXL_DEC_ERROR otherwise.
*/
JXL_EXPORT JxlDecoderStatus
JxlDecoderSetKeepOrientation(JxlDecoder* dec, JXL_BOOL skip_reorientation);
/**
* Enables or disables preserving of associated alpha channels. If
- * unpremul_alpha is set to JXL_FALSE then for associated alpha channel, the
- * pixel data is returned with premultiplied colors. If it is set to JXL_TRUE,
- * The colors will be unpremultiplied based on the alpha channel. This function
- * has no effect if the image does not have an associated alpha channel.
+ * unpremul_alpha is set to ::JXL_FALSE then for associated alpha channel,
+ * the pixel data is returned with premultiplied colors. If it is set to @ref
+ * JXL_TRUE, The colors will be unpremultiplied based on the alpha channel. This
+ * function has no effect if the image does not have an associated alpha
+ * channel.
*
* By default, this option is disabled, and the returned pixel data "as is".
*
@@ -501,20 +516,20 @@ JxlDecoderSetKeepOrientation(JxlDecoder* dec, JXL_BOOL skip_reorientation);
*
* @param dec decoder object
* @param unpremul_alpha JXL_TRUE to enable, JXL_FALSE to disable.
- * @return @ref JXL_DEC_SUCCESS if no error, @ref JXL_DEC_ERROR otherwise.
+ * @return ::JXL_DEC_SUCCESS if no error, ::JXL_DEC_ERROR otherwise.
*/
JXL_EXPORT JxlDecoderStatus
JxlDecoderSetUnpremultiplyAlpha(JxlDecoder* dec, JXL_BOOL unpremul_alpha);
/** Enables or disables rendering spot colors. By default, spot colors
* are rendered, which is OK for viewing the decoded image. If render_spotcolors
- * is JXL_FALSE, then spot colors are not rendered, and have to be retrieved
- * separately using @ref JxlDecoderSetExtraChannelBuffer. This is useful for
- * e.g. printing applications.
+ * is ::JXL_FALSE, then spot colors are not rendered, and have to be
+ * retrieved separately using @ref JxlDecoderSetExtraChannelBuffer. This is
+ * useful for e.g. printing applications.
*
* @param dec decoder object
* @param render_spotcolors JXL_TRUE to enable (default), JXL_FALSE to disable.
- * @return @ref JXL_DEC_SUCCESS if no error, @ref JXL_DEC_ERROR otherwise.
+ * @return ::JXL_DEC_SUCCESS if no error, ::JXL_DEC_ERROR otherwise.
*/
JXL_EXPORT JxlDecoderStatus
JxlDecoderSetRenderSpotcolors(JxlDecoder* dec, JXL_BOOL render_spotcolors);
@@ -530,7 +545,7 @@ JxlDecoderSetRenderSpotcolors(JxlDecoder* dec, JXL_BOOL render_spotcolors);
* @param dec decoder object
* @param coalescing JXL_TRUE to enable coalescing (default), JXL_FALSE to
* disable it.
- * @return @ref JXL_DEC_SUCCESS if no error, @ref JXL_DEC_ERROR otherwise.
+ * @return ::JXL_DEC_SUCCESS if no error, ::JXL_DEC_ERROR otherwise.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetCoalescing(JxlDecoder* dec,
JXL_BOOL coalescing);
@@ -547,32 +562,32 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetCoalescing(JxlDecoder* dec,
*
* The returned status indicates whether the decoder needs more input bytes, or
* more output buffer for a certain type of output data. No matter what the
- * returned status is (other than @ref JXL_DEC_ERROR), new information, such
+ * returned status is (other than ::JXL_DEC_ERROR), new information, such
* as @ref JxlDecoderGetBasicInfo, may have become available after this call.
- * When the return value is not @ref JXL_DEC_ERROR or @ref JXL_DEC_SUCCESS, the
+ * When the return value is not ::JXL_DEC_ERROR or ::JXL_DEC_SUCCESS, the
* decoding requires more @ref JxlDecoderProcessInput calls to continue.
*
* @param dec decoder object
- * @return @ref JXL_DEC_SUCCESS when decoding finished and all events handled.
+ * @return ::JXL_DEC_SUCCESS when decoding finished and all events handled.
* If you still have more unprocessed input data anyway, then you can still
* continue by using @ref JxlDecoderSetInput and calling @ref
* JxlDecoderProcessInput again, similar to handling @ref
- * JXL_DEC_NEED_MORE_INPUT. @ref JXL_DEC_SUCCESS can occur instead of @ref
+ * JXL_DEC_NEED_MORE_INPUT. ::JXL_DEC_SUCCESS can occur instead of @ref
* JXL_DEC_NEED_MORE_INPUT when, for example, the input data ended right at
* the boundary of a box of the container format, all essential codestream
* boxes were already decoded, but extra metadata boxes are still present in
* the next data. @ref JxlDecoderProcessInput cannot return success if all
* codestream boxes have not been seen yet.
- * @return @ref JXL_DEC_ERROR when decoding failed, e.g. invalid codestream.
+ * @return ::JXL_DEC_ERROR when decoding failed, e.g. invalid codestream.
* TODO(lode): document the input data mechanism
- * @return @ref JXL_DEC_NEED_MORE_INPUT when more input data is necessary.
- * @return @ref JXL_DEC_BASIC_INFO when basic info such as image dimensions is
+ * @return ::JXL_DEC_NEED_MORE_INPUT when more input data is necessary.
+ * @return ::JXL_DEC_BASIC_INFO when basic info such as image dimensions is
* available and this informative event is subscribed to.
- * @return @ref JXL_DEC_COLOR_ENCODING when color profile information is
+ * @return ::JXL_DEC_COLOR_ENCODING when color profile information is
* available and this informative event is subscribed to.
- * @return @ref JXL_DEC_PREVIEW_IMAGE when preview pixel information is
+ * @return ::JXL_DEC_PREVIEW_IMAGE when preview pixel information is
* available and output in the preview buffer.
- * @return @ref JXL_DEC_FULL_IMAGE when all pixel information at highest detail
+ * @return ::JXL_DEC_FULL_IMAGE when all pixel information at highest detail
* is available and has been output in the pixel buffer.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderProcessInput(JxlDecoder* dec);
@@ -588,8 +603,8 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderProcessInput(JxlDecoder* dec);
* @param dec decoder object
* @param data pointer to next bytes to read from
* @param size amount of bytes available starting from data
- * @return @ref JXL_DEC_ERROR if input was already set without releasing or @ref
- * JxlDecoderCloseInput was already called, @ref JXL_DEC_SUCCESS otherwise.
+ * @return ::JXL_DEC_ERROR if input was already set without releasing or @ref
+ * JxlDecoderCloseInput was already called, ::JXL_DEC_SUCCESS otherwise.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetInput(JxlDecoder* dec,
const uint8_t* data,
@@ -602,17 +617,17 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetInput(JxlDecoder* dec,
* whenever any input is already set and new input needs to be added with @ref
* JxlDecoderSetInput, but is not required before @ref JxlDecoderDestroy or @ref
* JxlDecoderReset. Calling @ref JxlDecoderReleaseInput when no input is set is
- * not an error and returns 0.
+ * not an error and returns `0`.
*
* @param dec decoder object
* @return The amount of bytes the decoder has not yet processed that are still
- * remaining in the data set by @ref JxlDecoderSetInput, or 0 if no input is
- * set or @ref JxlDecoderReleaseInput was already called. For a next call
- * to @ref JxlDecoderProcessInput, the buffer must start with these
- * unprocessed bytes. From this value it is possible to infer the position
- * of certain JPEG XL codestream elements (e.g. end of headers, frame
- * start/end). See the documentation of individual values of @ref
- * JxlDecoderStatus for more information.
+ * remaining in the data set by @ref JxlDecoderSetInput, or `0` if no input
+ * is set or @ref JxlDecoderReleaseInput was already called. For a next call to
+ * @ref JxlDecoderProcessInput, the buffer must start with these unprocessed
+ * bytes. From this value it is possible to infer the position of certain JPEG
+ * XL codestream elements (e.g. end of headers, frame start/end). See the
+ * documentation of individual values of @ref JxlDecoderStatus for more
+ * information.
*/
JXL_EXPORT size_t JxlDecoderReleaseInput(JxlDecoder* dec);
@@ -621,9 +636,9 @@ JXL_EXPORT size_t JxlDecoderReleaseInput(JxlDecoder* dec);
* will be called. This function allows the decoder to determine correctly if it
* should return success, need more input or error in certain cases. For
* backwards compatibility with a previous version of the API, using this
- * function is optional when not using the @ref JXL_DEC_BOX event (the decoder
+ * function is optional when not using the ::JXL_DEC_BOX event (the decoder
* is able to determine the end of the image frames without marking the end),
- * but using this function is required when using @ref JXL_DEC_BOX for getting
+ * but using this function is required when using ::JXL_DEC_BOX for getting
* metadata box contents. This function does not replace @ref
* JxlDecoderReleaseInput, that function should still be called if its return
* value is needed.
@@ -643,8 +658,8 @@ JXL_EXPORT void JxlDecoderCloseInput(JxlDecoder* dec);
* @param dec decoder object
* @param info struct to copy the information into, or NULL to only check
* whether the information is available through the return value.
- * @return @ref JXL_DEC_SUCCESS if the value is available, @ref
- * JXL_DEC_NEED_MORE_INPUT if not yet available, @ref JXL_DEC_ERROR
+ * @return ::JXL_DEC_SUCCESS if the value is available, @ref
+ * JXL_DEC_NEED_MORE_INPUT if not yet available, ::JXL_DEC_ERROR
* in case of other error conditions.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetBasicInfo(const JxlDecoder* dec,
@@ -652,14 +667,14 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetBasicInfo(const JxlDecoder* dec,
/**
* Outputs information for extra channel at the given index. The index must be
- * smaller than num_extra_channels in the associated JxlBasicInfo.
+ * smaller than num_extra_channels in the associated @ref JxlBasicInfo.
*
* @param dec decoder object
* @param index index of the extra channel to query.
* @param info struct to copy the information into, or NULL to only check
* whether the information is available through the return value.
- * @return @ref JXL_DEC_SUCCESS if the value is available, @ref
- * JXL_DEC_NEED_MORE_INPUT if not yet available, @ref JXL_DEC_ERROR
+ * @return ::JXL_DEC_SUCCESS if the value is available, @ref
+ * JXL_DEC_NEED_MORE_INPUT if not yet available, ::JXL_DEC_ERROR
* in case of other error conditions.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetExtraChannelInfo(
@@ -667,16 +682,16 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetExtraChannelInfo(
/**
* Outputs name for extra channel at the given index in UTF-8. The index must be
- * smaller than num_extra_channels in the associated JxlBasicInfo. The buffer
- * for name must have at least name_length + 1 bytes allocated, gotten from
- * the associated JxlExtraChannelInfo.
+ * smaller than `num_extra_channels` in the associated @ref JxlBasicInfo. The
+ * buffer for name must have at least `name_length + 1` bytes allocated, gotten
+ * from the associated @ref JxlExtraChannelInfo.
*
* @param dec decoder object
* @param index index of the extra channel to query.
* @param name buffer to copy the name into
* @param size size of the name buffer in bytes
- * @return @ref JXL_DEC_SUCCESS if the value is available, @ref
- * JXL_DEC_NEED_MORE_INPUT if not yet available, @ref JXL_DEC_ERROR
+ * @return ::JXL_DEC_SUCCESS if the value is available, @ref
+ * JXL_DEC_NEED_MORE_INPUT if not yet available, ::JXL_DEC_ERROR
* in case of other error conditions.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetExtraChannelName(const JxlDecoder* dec,
@@ -719,7 +734,7 @@ typedef enum {
* problematic, in that: while ICC profiles can encode a transfer function
* that happens to approximate those of PQ and HLG (HLG for only one given
* system gamma at a time, and necessitating a 3D LUT if gamma is to be
- * different from 1), they cannot (before ICCv4.4) semantically signal that
+ * different from `1`), they cannot (before ICCv4.4) semantically signal that
* this is the color space that they represent. Therefore, they will
* typically not actually be interpreted as representing an HDR color space.
* This is especially detrimental to PQ which will then be interpreted as if
@@ -741,8 +756,8 @@ typedef enum {
* or the color profile of the decoded pixels.
* @param color_encoding struct to copy the information into, or NULL to only
* check whether the information is available through the return value.
- * @return @ref JXL_DEC_SUCCESS if the data is available and returned, @ref
- * JXL_DEC_NEED_MORE_INPUT if not yet available, @ref JXL_DEC_ERROR in
+ * @return ::JXL_DEC_SUCCESS if the data is available and returned, @ref
+ * JXL_DEC_NEED_MORE_INPUT if not yet available, ::JXL_DEC_ERROR in
* case the encoded structured color profile does not exist in the
* codestream.
*/
@@ -766,10 +781,10 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetColorAsEncodedProfile(
* or the color profile of the decoded pixels.
* @param size variable to output the size into, or NULL to only check the
* return status.
- * @return @ref JXL_DEC_SUCCESS if the ICC profile is available, @ref
+ * @return ::JXL_DEC_SUCCESS if the ICC profile is available, @ref
* JXL_DEC_NEED_MORE_INPUT if the decoder has not yet received enough
* input data to determine whether an ICC profile is available or what its
- * size is, @ref JXL_DEC_ERROR in case the ICC profile is not available and
+ * size is, ::JXL_DEC_ERROR in case the ICC profile is not available and
* cannot be generated.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetICCProfileSize(
@@ -785,8 +800,8 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetICCProfileSize(
* or the color profile of the decoded pixels.
* @param icc_profile buffer to copy the ICC profile into
* @param size size of the icc_profile buffer in bytes
- * @return @ref JXL_DEC_SUCCESS if the profile was successfully returned is
- * available, @ref JXL_DEC_NEED_MORE_INPUT if not yet available, @ref
+ * @return ::JXL_DEC_SUCCESS if the profile was successfully returned is
+ * available, ::JXL_DEC_NEED_MORE_INPUT if not yet available, @ref
* JXL_DEC_ERROR if the profile doesn't exist or the output size is not
* large enough.
*/
@@ -801,7 +816,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetColorAsICCProfile(
*
* @param dec decoder object
* @param color_encoding the default color encoding to set
- * @return @ref JXL_DEC_SUCCESS if the preference was set successfully, @ref
+ * @return ::JXL_DEC_SUCCESS if the preference was set successfully, @ref
* JXL_DEC_ERROR otherwise.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetPreferredColorProfile(
@@ -814,7 +829,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetPreferredColorProfile(
* change from version to version.
* @param dec decoder object
* @param desired_intensity_target the intended target peak luminance
- * @return @ref JXL_DEC_SUCCESS if the preference was set successfully, @ref
+ * @return ::JXL_DEC_SUCCESS if the preference was set successfully, @ref
* JXL_DEC_ERROR otherwise.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetDesiredIntensityTarget(
@@ -823,7 +838,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetDesiredIntensityTarget(
/**
* Sets the desired output color profile of the decoded image either from a
* color encoding or an ICC profile. Valid calls of this function have either @c
- * color_encoding or @c icc_data set to NULL and @c icc_size must be 0 if and
+ * color_encoding or @c icc_data set to NULL and @c icc_size must be `0` if and
* only if @c icc_data is NULL.
*
* Depending on whether a color management system (CMS) has been set the
@@ -848,17 +863,17 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetDesiredIntensityTarget(
* If called with an ICC profile (after a call to @ref JxlDecoderSetCms), the
* ICC profile has to be a valid RGB or grayscale color profile.
*
- * Can only be set after the @ref JXL_DEC_COLOR_ENCODING event occurred and
+ * Can only be set after the ::JXL_DEC_COLOR_ENCODING event occurred and
* before any other event occurred, and should be used before getting
- * JXL_COLOR_PROFILE_TARGET_DATA.
+ * ::JXL_COLOR_PROFILE_TARGET_DATA.
*
- * This function must not be called before JxlDecoderSetCms.
+ * This function must not be called before @ref JxlDecoderSetCms.
*
* @param dec decoder orbject
* @param color_encoding the output color encoding
* @param icc_data bytes of the icc profile
* @param icc_size size of the icc profile in bytes
- * @return @ref JXL_DEC_SUCCESS if the color profile was set successfully, @ref
+ * @return ::JXL_DEC_SUCCESS if the color profile was set successfully, @ref
* JXL_DEC_ERROR otherwise.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetOutputColorProfile(
@@ -891,7 +906,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetCms(JxlDecoder* dec,
* @param dec decoder object
* @param format format of pixels
* @param size output value, buffer size in bytes
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error, such as
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error, such as
* information not available yet.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderPreviewOutBufferSize(
@@ -901,15 +916,15 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderPreviewOutBufferSize(
* Sets the buffer to write the small resolution preview image
* to. The size of the buffer must be at least as large as given by @ref
* JxlDecoderPreviewOutBufferSize. The buffer follows the format described
- * by JxlPixelFormat. The preview image dimensions are given by the
- * JxlPreviewHeader. The buffer is owned by the caller.
+ * by @ref JxlPixelFormat. The preview image dimensions are given by the
+ * @ref JxlPreviewHeader. The buffer is owned by the caller.
*
* @param dec decoder object
* @param format format of pixels. Object owned by user and its contents are
* copied internally.
* @param buffer buffer type to output the pixel data to
* @param size size of buffer in bytes
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error, such as
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error, such as
* size too small.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetPreviewOutBuffer(
@@ -917,14 +932,14 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetPreviewOutBuffer(
/**
* Outputs the information from the frame, such as duration when have_animation.
- * This function can be called when @ref JXL_DEC_FRAME occurred for the current
+ * This function can be called when ::JXL_DEC_FRAME occurred for the current
* frame, even when have_animation in the JxlBasicInfo is JXL_FALSE.
*
* @param dec decoder object
* @param header struct to copy the information into, or NULL to only check
* whether the information is available through the return value.
- * @return @ref JXL_DEC_SUCCESS if the value is available, @ref
- * JXL_DEC_NEED_MORE_INPUT if not yet available, @ref JXL_DEC_ERROR in
+ * @return ::JXL_DEC_SUCCESS if the value is available, @ref
+ * JXL_DEC_NEED_MORE_INPUT if not yet available, ::JXL_DEC_ERROR in
* case of other error conditions.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetFrameHeader(const JxlDecoder* dec,
@@ -932,14 +947,14 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetFrameHeader(const JxlDecoder* dec,
/**
* Outputs name for the current frame. The buffer for name must have at least
- * name_length + 1 bytes allocated, gotten from the associated JxlFrameHeader.
+ * `name_length + 1` bytes allocated, gotten from the associated JxlFrameHeader.
*
* @param dec decoder object
* @param name buffer to copy the name into
* @param size size of the name buffer in bytes, including zero termination
- * character, so this must be at least JxlFrameHeader.name_length + 1.
- * @return @ref JXL_DEC_SUCCESS if the value is available, @ref
- * JXL_DEC_NEED_MORE_INPUT if not yet available, @ref JXL_DEC_ERROR in
+ * character, so this must be at least @ref JxlFrameHeader.name_length + 1.
+ * @return ::JXL_DEC_SUCCESS if the value is available, @ref
+ * JXL_DEC_NEED_MORE_INPUT if not yet available, ::JXL_DEC_ERROR in
* case of other error conditions.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetFrameName(const JxlDecoder* dec,
@@ -947,15 +962,15 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetFrameName(const JxlDecoder* dec,
/**
* Outputs the blend information for the current frame for a specific extra
- * channel. This function can be called when @ref JXL_DEC_FRAME occurred for the
- * current frame, even when have_animation in the JxlBasicInfo is JXL_FALSE.
- * This information is only useful if coalescing is disabled; otherwise the
- * decoder will have performed blending already.
+ * channel. This function can be called when ::JXL_DEC_FRAME occurred for the
+ * current frame, even when have_animation in the @ref JxlBasicInfo is @ref
+ * JXL_FALSE. This information is only useful if coalescing is disabled;
+ * otherwise the decoder will have performed blending already.
*
* @param dec decoder object
* @param index the index of the extra channel
* @param blend_info struct to copy the information into
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetExtraChannelBlendInfo(
const JxlDecoder* dec, size_t index, JxlBlendInfo* blend_info);
@@ -965,14 +980,14 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetExtraChannelBlendInfo(
* given format. This is the buffer for @ref JxlDecoderSetImageOutBuffer.
* Requires that the basic image information is available in the decoder in the
* case of coalescing enabled (default). In case coalescing is disabled, this
- * can only be called after the @ref JXL_DEC_FRAME event occurs. In that case,
+ * can only be called after the ::JXL_DEC_FRAME event occurs. In that case,
* it will return the size required to store the possibly cropped frame (which
* can be larger or smaller than the image dimensions).
*
* @param dec decoder object
* @param format format of the pixels.
* @param size output value, buffer size in bytes
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error, such as
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error, such as
* information not available yet.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderImageOutBufferSize(
@@ -980,18 +995,18 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderImageOutBufferSize(
/**
* Sets the buffer to write the full resolution image to. This can be set when
- * the @ref JXL_DEC_FRAME event occurs, must be set when the @ref
+ * the ::JXL_DEC_FRAME event occurs, must be set when the @ref
* JXL_DEC_NEED_IMAGE_OUT_BUFFER event occurs, and applies only for the
* current frame. The size of the buffer must be at least as large as given
* by @ref JxlDecoderImageOutBufferSize. The buffer follows the format described
- * by JxlPixelFormat. The buffer is owned by the caller.
+ * by @ref JxlPixelFormat. The buffer is owned by the caller.
*
* @param dec decoder object
* @param format format of the pixels. Object owned by user and its contents
* are copied internally.
* @param buffer buffer type to output the pixel data to
* @param size size of buffer in bytes
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error, such as
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error, such as
* size too small.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetImageOutBuffer(
@@ -1062,15 +1077,15 @@ typedef void (*JxlImageOutDestroyCallback)(void* run_opaque);
/**
* Sets pixel output callback. This is an alternative to @ref
- * JxlDecoderSetImageOutBuffer. This can be set when the @ref JXL_DEC_FRAME
- * event occurs, must be set when the @ref JXL_DEC_NEED_IMAGE_OUT_BUFFER event
+ * JxlDecoderSetImageOutBuffer. This can be set when the ::JXL_DEC_FRAME
+ * event occurs, must be set when the ::JXL_DEC_NEED_IMAGE_OUT_BUFFER event
* occurs, and applies only for the current frame. Only one of @ref
* JxlDecoderSetImageOutBuffer or @ref JxlDecoderSetImageOutCallback may be used
* for the same frame, not both at the same time.
*
* The callback will be called multiple times, to receive the image
* data in small chunks. The callback receives a horizontal stripe of pixel
- * data, 1 pixel high, xsize pixels wide, called a scanline. The xsize here is
+ * data, `1` pixel high, xsize pixels wide, called a scanline. The xsize here is
* not the same as the full image width, the scanline may be a partial section,
* and xsize may differ between calls. The user can then process and/or copy the
* partial scanline to an image buffer. The callback may be called
@@ -1099,7 +1114,7 @@ typedef void (*JxlImageOutDestroyCallback)(void* run_opaque);
* data.
* @param opaque optional user data, which will be passed on to the callback,
* may be NULL.
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error, such
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error, such
* as @ref JxlDecoderSetImageOutBuffer already set.
*/
JXL_EXPORT JxlDecoderStatus
@@ -1122,7 +1137,7 @@ JxlDecoderSetImageOutCallback(JxlDecoder* dec, const JxlPixelFormat* format,
* @param init_opaque optional user data passed to @c init_callback, may be NULL
* (unlike the return value from @c init_callback which may only be NULL if
* initialization failed).
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error, such
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error, such
* as @ref JxlDecoderSetImageOutBuffer having already been called.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetMultithreadedImageOutCallback(
@@ -1137,12 +1152,12 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetMultithreadedImageOutCallback(
*
* @param dec decoder object
* @param format format of the pixels. The num_channels value is ignored and is
- * always treated to be 1.
+ * always treated to be `1`.
* @param size output value, buffer size in bytes
* @param index which extra channel to get, matching the index used in @ref
* JxlDecoderGetExtraChannelInfo. Must be smaller than num_extra_channels in
- * the associated JxlBasicInfo.
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error, such as
+ * the associated @ref JxlBasicInfo.
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error, such as
* information not available yet or invalid index.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderExtraChannelBufferSize(
@@ -1151,13 +1166,13 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderExtraChannelBufferSize(
/**
* Sets the buffer to write an extra channel to. This can be set when
- * the @ref JXL_DEC_FRAME or @ref JXL_DEC_NEED_IMAGE_OUT_BUFFER event occurs,
+ * the ::JXL_DEC_FRAME or ::JXL_DEC_NEED_IMAGE_OUT_BUFFER event occurs,
* and applies only for the current frame. The size of the buffer must be at
* least as large as given by @ref JxlDecoderExtraChannelBufferSize. The buffer
- * follows the format described by JxlPixelFormat, but where num_channels is 1.
- * The buffer is owned by the caller. The amount of extra channels is given by
- * the num_extra_channels field in the associated JxlBasicInfo, and the
- * information of individual extra channels can be queried with @ref
+ * follows the format described by @ref JxlPixelFormat, but where num_channels
+ * is `1`. The buffer is owned by the caller. The amount of extra channels is
+ * given by the num_extra_channels field in the associated @ref JxlBasicInfo,
+ * and the information of individual extra channels can be queried with @ref
* JxlDecoderGetExtraChannelInfo. To get multiple extra channels, this function
* must be called multiple times, once for each wanted index. Not all images
* have extra channels. The alpha channel is an extra channel and can be gotten
@@ -1170,13 +1185,13 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderExtraChannelBufferSize(
* @param dec decoder object
* @param format format of the pixels. Object owned by user and its contents
* are copied internally. The num_channels value is ignored and is always
- * treated to be 1.
+ * treated to be `1`.
* @param buffer buffer type to output the pixel data to
* @param size size of buffer in bytes
* @param index which extra channel to get, matching the index used in @ref
* JxlDecoderGetExtraChannelInfo. Must be smaller than num_extra_channels in
- * the associated JxlBasicInfo.
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error, such as
+ * the associated @ref JxlBasicInfo.
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error, such as
* size too small or invalid index.
*/
JXL_EXPORT JxlDecoderStatus
@@ -1197,8 +1212,8 @@ JxlDecoderSetExtraChannelBuffer(JxlDecoder* dec, const JxlPixelFormat* format,
* @param dec decoder object
* @param data pointer to next bytes to write to
* @param size amount of bytes available starting from data
- * @return @ref JXL_DEC_ERROR if output buffer was already set and @ref
- * JxlDecoderReleaseJPEGBuffer was not called on it, @ref JXL_DEC_SUCCESS
+ * @return ::JXL_DEC_ERROR if output buffer was already set and @ref
+ * JxlDecoderReleaseJPEGBuffer was not called on it, ::JXL_DEC_SUCCESS
* otherwise
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetJPEGBuffer(JxlDecoder* dec,
@@ -1213,11 +1228,11 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetJPEGBuffer(JxlDecoder* dec,
* JxlDecoderDestroy or @ref JxlDecoderReset.
*
* Calling @ref JxlDecoderReleaseJPEGBuffer when no buffer is set is
- * not an error and returns 0.
+ * not an error and returns `0`.
*
* @param dec decoder object
* @return the amount of bytes the decoder has not yet written to of the data
- * set by @ref JxlDecoderSetJPEGBuffer, or 0 if no buffer is set or @ref
+ * set by @ref JxlDecoderSetJPEGBuffer, or `0` if no buffer is set or @ref
* JxlDecoderReleaseJPEGBuffer was already called.
*/
JXL_EXPORT size_t JxlDecoderReleaseJPEGBuffer(JxlDecoder* dec);
@@ -1233,15 +1248,15 @@ JXL_EXPORT size_t JxlDecoderReleaseJPEGBuffer(JxlDecoder* dec);
* JxlDecoderReleaseBoxBuffer, bytes that the decoder has already output
* should not be included, only the remaining bytes output must be set.
*
- * The @ref JxlDecoderReleaseBoxBuffer must be used at the next @ref JXL_DEC_BOX
- * event or final @ref JXL_DEC_SUCCESS event to compute the size of the output
+ * The @ref JxlDecoderReleaseBoxBuffer must be used at the next ::JXL_DEC_BOX
+ * event or final ::JXL_DEC_SUCCESS event to compute the size of the output
* box bytes.
*
* @param dec decoder object
* @param data pointer to next bytes to write to
* @param size amount of bytes available starting from data
- * @return @ref JXL_DEC_ERROR if output buffer was already set and @ref
- * JxlDecoderReleaseBoxBuffer was not called on it, @ref JXL_DEC_SUCCESS
+ * @return ::JXL_DEC_ERROR if output buffer was already set and @ref
+ * JxlDecoderReleaseBoxBuffer was not called on it, ::JXL_DEC_SUCCESS
* otherwise
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetBoxBuffer(JxlDecoder* dec,
@@ -1256,11 +1271,11 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetBoxBuffer(JxlDecoder* dec,
* JxlDecoderDestroy or @ref JxlDecoderReset.
*
* Calling @ref JxlDecoderReleaseBoxBuffer when no buffer is set is
- * not an error and returns 0.
+ * not an error and returns `0`.
*
* @param dec decoder object
* @return the amount of bytes the decoder has not yet written to of the data
- * set by @ref JxlDecoderSetBoxBuffer, or 0 if no buffer is set or @ref
+ * set by @ref JxlDecoderSetBoxBuffer, or `0` if no buffer is set or @ref
* JxlDecoderReleaseBoxBuffer was already called.
*/
JXL_EXPORT size_t JxlDecoderReleaseBoxBuffer(JxlDecoder* dec);
@@ -1274,23 +1289,23 @@ JXL_EXPORT size_t JxlDecoderReleaseBoxBuffer(JxlDecoder* dec);
* finished.
*
* The default mode is raw. This setting can only be changed before decoding, or
- * directly after a @ref JXL_DEC_BOX event, and is remembered until the decoder
+ * directly after a ::JXL_DEC_BOX event, and is remembered until the decoder
* is reset or destroyed.
*
* Enabling decompressed mode requires Brotli support from the library.
*
* @param dec decoder object
- * @param decompress JXL_TRUE to transparently decompress, JXL_FALSE to get
- * boxes in raw mode.
- * @return @ref JXL_DEC_ERROR if decompressed mode is set and Brotli is not
- * available, @ref JXL_DEC_SUCCESS otherwise.
+ * @param decompress ::JXL_TRUE to transparently decompress, ::JXL_FALSE
+ * to get boxes in raw mode.
+ * @return ::JXL_DEC_ERROR if decompressed mode is set and Brotli is not
+ * available, ::JXL_DEC_SUCCESS otherwise.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetDecompressBoxes(JxlDecoder* dec,
JXL_BOOL decompress);
/**
- * Outputs the type of the current box, after a @ref JXL_DEC_BOX event occurred,
- * as 4 characters without null termination character. In case of a compressed
+ * Outputs the type of the current box, after a ::JXL_DEC_BOX event occurred,
+ * as `4` characters without null termination character. In case of a compressed
* "brob" box, this will return "brob" if the decompressed argument is
* JXL_FALSE, or the underlying box type if the decompressed argument is
* JXL_TRUE.
@@ -1306,15 +1321,15 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetDecompressBoxes(JxlDecoder* dec,
* - "xml ": a box with XML data, in particular XMP metadata.
* - "jumb": a JUMBF superbox (JPEG Universal Metadata Box Format, ISO/IEC
* 19566-5).
- * - "JXL ": mandatory signature box, must come first, 12 bytes long including
- * the box header
- * - "ftyp": a second mandatory signature box, must come second, 20 bytes long
- * including the box header
- * - "jxll": a JXL level box. This indicates if the codestream is level 5 or
- * level 10 compatible. If not present, it is level 5. Level 10 allows more
- * features such as very high image resolution and bit-depths above 16 bits
- * per channel. Added automatically by the encoder when
- * JxlEncoderSetCodestreamLevel is used
+ * - "JXL ": mandatory signature box, must come first, `12` bytes long
+ * including the box header
+ * - "ftyp": a second mandatory signature box, must come second, `20` bytes
+ * long including the box header
+ * - "jxll": a JXL level box. This indicates if the codestream is level `5` or
+ * level `10` compatible. If not present, it is level `5`. Level `10` allows
+ * more features such as very high image resolution and bit-depths above `16`
+ * bits per channel. Added automatically by the encoder when
+ * @ref JxlEncoderSetCodestreamLevel is used
* - "jxlc": a box with the image codestream, in case the codestream is not
* split across multiple boxes. The codestream contains the JPEG XL image
* itself, including the basic info such as image dimensions, ICC color
@@ -1350,7 +1365,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetDecompressBoxes(JxlDecoder* dec,
* @param type buffer to copy the type into
* @param decompressed which box type to get: JXL_FALSE to get the raw box type,
* which can be "brob", JXL_TRUE, get the underlying box type.
- * @return @ref JXL_DEC_SUCCESS if the value is available, @ref JXL_DEC_ERROR if
+ * @return ::JXL_DEC_SUCCESS if the value is available, ::JXL_DEC_ERROR if
* not, for example the JXL file does not use the container format.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetBoxType(JxlDecoder* dec,
@@ -1363,13 +1378,29 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetBoxType(JxlDecoder* dec,
*
* @param dec decoder object
* @param size raw size of the box in bytes
- * @return @ref JXL_DEC_ERROR if no box size is available, @ref JXL_DEC_SUCCESS
+ * @return ::JXL_DEC_ERROR if no box size is available, ::JXL_DEC_SUCCESS
* otherwise.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetBoxSizeRaw(const JxlDecoder* dec,
uint64_t* size);
/**
+ * Returns the size of the contents of a box, after the @ref
+ * JXL_DEC_BOX event. This does not include any of the headers of the box. For
+ * compressed "brob" boxes, this is the size of the compressed content. Even
+ * when @ref JxlDecoderSetDecompressBoxes is enabled, the return value of
+ * function does not change, and the decompressed size is not known before it
+ * has already been decompressed and output.
+ *
+ * @param dec decoder object
+ * @param size size of the payload of the box in bytes
+ * @return @ref JXL_DEC_ERROR if no box size is available, @ref JXL_DEC_SUCCESS
+ * otherwise.
+ */
+JXL_EXPORT JxlDecoderStatus JxlDecoderGetBoxSizeContents(const JxlDecoder* dec,
+ uint64_t* size);
+
+/**
* Configures at which progressive steps in frame decoding these @ref
* JXL_DEC_FRAME_PROGRESSION event occurs. The default value for the level
* of detail if this function is never called is `kDC`.
@@ -1377,7 +1408,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetBoxSizeRaw(const JxlDecoder* dec,
* @param dec decoder object
* @param detail at which level of detail to trigger @ref
* JXL_DEC_FRAME_PROGRESSION
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error, such as
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error, such as
* an invalid value for the progressive detail.
*/
JXL_EXPORT JxlDecoderStatus
@@ -1385,11 +1416,11 @@ JxlDecoderSetProgressiveDetail(JxlDecoder* dec, JxlProgressiveDetail detail);
/**
* Returns the intended downsampling ratio for the progressive frame produced
- * by @ref JxlDecoderFlushImage after the latest @ref JXL_DEC_FRAME_PROGRESSION
+ * by @ref JxlDecoderFlushImage after the latest ::JXL_DEC_FRAME_PROGRESSION
* event.
*
* @param dec decoder object
- * @return The intended downsampling ratio, can be 1, 2, 4 or 8.
+ * @return The intended downsampling ratio, can be `1`, `2`, `4` or `8`.
*/
JXL_EXPORT size_t JxlDecoderGetIntendedDownsamplingRatio(JxlDecoder* dec);
@@ -1399,12 +1430,12 @@ JXL_EXPORT size_t JxlDecoderGetIntendedDownsamplingRatio(JxlDecoder* dec);
* JxlDecoderSetImageOutBuffer will contain partial image data.
*
* Can be called when @ref JxlDecoderProcessInput returns @ref
- * JXL_DEC_NEED_MORE_INPUT, after the @ref JXL_DEC_FRAME event already occurred
- * and before the @ref JXL_DEC_FULL_IMAGE event occurred for a frame.
+ * JXL_DEC_NEED_MORE_INPUT, after the ::JXL_DEC_FRAME event already occurred
+ * and before the ::JXL_DEC_FULL_IMAGE event occurred for a frame.
*
* @param dec decoder object
- * @return @ref JXL_DEC_SUCCESS if image data was flushed to the output buffer,
- * or @ref JXL_DEC_ERROR when no flush was done, e.g. if not enough image
+ * @return ::JXL_DEC_SUCCESS if image data was flushed to the output buffer,
+ * or ::JXL_DEC_ERROR when no flush was done, e.g. if not enough image
* data was available yet even for flush, or no output buffer was set yet.
* This error is not fatal, it only indicates no flushed image is available
* right now. Regular decoding can still be performed.
@@ -1416,11 +1447,11 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderFlushImage(JxlDecoder* dec);
*
* Can be called after @ref JxlDecoderSetImageOutBuffer or @ref
* JxlDecoderSetImageOutCallback. For float pixel data types, only the default
- * @ref JXL_BIT_DEPTH_FROM_PIXEL_FORMAT setting is supported.
+ * ::JXL_BIT_DEPTH_FROM_PIXEL_FORMAT setting is supported.
*
* @param dec decoder object
* @param bit_depth the bit depth setting of the pixel output
- * @return @ref JXL_DEC_SUCCESS on success, @ref JXL_DEC_ERROR on error, such as
+ * @return ::JXL_DEC_SUCCESS on success, ::JXL_DEC_ERROR on error, such as
* incompatible custom bit depth and pixel data type.
*/
JXL_EXPORT JxlDecoderStatus
diff --git a/third_party/jpeg-xl/lib/include/jxl/encode.h b/third_party/jpeg-xl/lib/include/jxl/encode.h
index 2a87821f06..bb11dd7572 100644
--- a/third_party/jpeg-xl/lib/include/jxl/encode.h
+++ b/third_party/jpeg-xl/lib/include/jxl/encode.h
@@ -41,8 +41,8 @@ JXL_EXPORT uint32_t JxlEncoderVersion(void);
/**
* Opaque structure that holds the JPEG XL encoder.
*
- * Allocated and initialized with JxlEncoderCreate().
- * Cleaned up and deallocated with JxlEncoderDestroy().
+ * Allocated and initialized with @ref JxlEncoderCreate().
+ * Cleaned up and deallocated with @ref JxlEncoderDestroy().
*/
typedef struct JxlEncoderStruct JxlEncoder;
@@ -50,9 +50,9 @@ typedef struct JxlEncoderStruct JxlEncoder;
* Settings and metadata for a single image frame. This includes encoder options
* for a frame such as compression quality and speed.
*
- * Allocated and initialized with JxlEncoderFrameSettingsCreate().
+ * Allocated and initialized with @ref JxlEncoderFrameSettingsCreate().
* Cleaned up and deallocated when the encoder is destroyed with
- * JxlEncoderDestroy().
+ * @ref JxlEncoderDestroy().
*/
typedef struct JxlEncoderFrameSettingsStruct JxlEncoderFrameSettings;
@@ -126,7 +126,7 @@ typedef enum {
typedef enum {
/** Sets encoder effort/speed level without affecting decoding speed. Valid
* values are, from faster to slower speed: 1:lightning 2:thunder 3:falcon
- * 4:cheetah 5:hare 6:wombat 7:squirrel 8:kitten 9:tortoise.
+ * 4:cheetah 5:hare 6:wombat 7:squirrel 8:kitten 9:tortoise 10:glacier.
* Default: squirrel (7).
*/
JXL_ENC_FRAME_SETTING_EFFORT = 0,
@@ -145,7 +145,7 @@ typedef enum {
*/
JXL_ENC_FRAME_SETTING_RESAMPLING = 2,
- /** Similar to JXL_ENC_FRAME_SETTING_RESAMPLING, but for extra channels.
+ /** Similar to ::JXL_ENC_FRAME_SETTING_RESAMPLING, but for extra channels.
* Integer option, use -1 for the default behavior (depends on encoder
* implementation), 1 for no downsampling (1x1), 2 for 2x2 downsampling, 4 for
* 4x4 downsampling, 8 for 8x8 downsampling.
@@ -158,7 +158,7 @@ typedef enum {
* downsampled resolution, not the full image resolution. The downsampled
* resolution is given by ceil(xsize / resampling), ceil(ysize / resampling)
* with xsize and ysize the dimensions given in the basic info, and resampling
- * the factor set with @ref JXL_ENC_FRAME_SETTING_RESAMPLING.
+ * the factor set with ::JXL_ENC_FRAME_SETTING_RESAMPLING.
* Use 0 to disable, 1 to enable. Default value is 0.
*/
JXL_ENC_FRAME_SETTING_ALREADY_DOWNSAMPLED = 4,
@@ -171,8 +171,8 @@ typedef enum {
JXL_ENC_FRAME_SETTING_PHOTON_NOISE = 5,
/** Enables adaptive noise generation. This setting is not recommended for
- * use, please use JXL_ENC_FRAME_SETTING_PHOTON_NOISE instead. Use -1 for the
- * default (encoder chooses), 0 to disable, 1 to enable.
+ * use, please use ::JXL_ENC_FRAME_SETTING_PHOTON_NOISE instead. Use -1 for
+ * the default (encoder chooses), 0 to disable, 1 to enable.
*/
JXL_ENC_FRAME_SETTING_NOISE = 6,
@@ -320,27 +320,28 @@ typedef enum {
* 1 = index this frame within the Frame Index Box.
* If any frames are indexed, the first frame needs to
* be indexed, too. If the first frame is not indexed, and
- * a later frame is attempted to be indexed, JXL_ENC_ERROR will occur.
+ * a later frame is attempted to be indexed, ::JXL_ENC_ERROR will occur.
* If non-keyframes, i.e., frames with cropping, blending or patches are
- * attempted to be indexed, JXL_ENC_ERROR will occur.
+ * attempted to be indexed, ::JXL_ENC_ERROR will occur.
*/
JXL_ENC_FRAME_INDEX_BOX = 31,
- /** Sets brotli encode effort for use in JPEG recompression and compressed
- * metadata boxes (brob). Can be -1 (default) or 0 (fastest) to 11 (slowest).
- * Default is based on the general encode effort in case of JPEG
+ /** Sets brotli encode effort for use in JPEG recompression and
+ * compressed metadata boxes (brob). Can be -1 (default) or 0 (fastest) to 11
+ * (slowest). Default is based on the general encode effort in case of JPEG
* recompression, and 4 for brob boxes.
*/
JXL_ENC_FRAME_SETTING_BROTLI_EFFORT = 32,
/** Enables or disables brotli compression of metadata boxes derived from
- * a JPEG frame when using JxlEncoderAddJPEGFrame. This has no effect on boxes
- * added using JxlEncoderAddBox.
- * -1 = default, 0 = disable compression, 1 = enable compression.
+ * a JPEG frame when using @ref JxlEncoderAddJPEGFrame. This has no effect on
+ * boxes added using @ref JxlEncoderAddBox. -1 = default, 0 = disable
+ * compression, 1 = enable compression.
*/
JXL_ENC_FRAME_SETTING_JPEG_COMPRESS_BOXES = 33,
/** Control what kind of buffering is used, when using chunked image frames.
+ * -1 = default (let the encoder decide)
* 0 = buffers everything, basically the same as non-streamed code path
(mainly for testing)
* 1 = buffers everything for images that are smaller than 2048 x 2048, and
@@ -351,30 +352,30 @@ typedef enum {
*
* When using streaming input and output the encoder minimizes memory usage at
* the cost of compression density. Also note that images produced with
- * streaming mode might can not be decoded progressively.
+ * streaming mode might not be progressively decodeable.
*/
JXL_ENC_FRAME_SETTING_BUFFERING = 34,
/** Keep or discard Exif metadata boxes derived from a JPEG frame when using
- * JxlEncoderAddJPEGFrame. This has no effect on boxes added using
- * JxlEncoderAddBox. When JxlEncoderStoreJPEGMetadata is set to 1, this option
- * cannot be set to 0. Even when Exif metadata is discarded, the orientation
- * will still be applied. 0 = discard Exif metadata, 1 = keep Exif metadata
- * (default).
+ * @ref JxlEncoderAddJPEGFrame. This has no effect on boxes added using
+ * @ref JxlEncoderAddBox. When @ref JxlEncoderStoreJPEGMetadata is set to 1,
+ * this option cannot be set to 0. Even when Exif metadata is discarded, the
+ * orientation will still be applied. 0 = discard Exif metadata, 1 = keep Exif
+ * metadata (default).
*/
JXL_ENC_FRAME_SETTING_JPEG_KEEP_EXIF = 35,
/** Keep or discard XMP metadata boxes derived from a JPEG frame when using
- * JxlEncoderAddJPEGFrame. This has no effect on boxes added using
- * JxlEncoderAddBox. When JxlEncoderStoreJPEGMetadata is set to 1, this option
- * cannot be set to 0. 0 = discard XMP metadata, 1 = keep XMP metadata
- * (default).
+ * @ref JxlEncoderAddJPEGFrame. This has no effect on boxes added using
+ * @ref JxlEncoderAddBox. When @ref JxlEncoderStoreJPEGMetadata is set to 1,
+ * this option cannot be set to 0. 0 = discard XMP metadata, 1 = keep XMP
+ * metadata (default).
*/
JXL_ENC_FRAME_SETTING_JPEG_KEEP_XMP = 36,
/** Keep or discard JUMBF metadata boxes derived from a JPEG frame when using
- * JxlEncoderAddJPEGFrame. This has no effect on boxes added using
- * JxlEncoderAddBox. 0 = discard JUMBF metadata, 1 = keep JUMBF metadata
+ * @ref JxlEncoderAddJPEGFrame. This has no effect on boxes added using
+ * @ref JxlEncoderAddBox. 0 = discard JUMBF metadata, 1 = keep JUMBF metadata
* (default).
*/
JXL_ENC_FRAME_SETTING_JPEG_KEEP_JUMBF = 37,
@@ -395,7 +396,7 @@ typedef enum {
} JxlEncoderFrameSettingId;
/**
- * Creates an instance of JxlEncoder and initializes it.
+ * Creates an instance of @ref JxlEncoder and initializes it.
*
* @p memory_manager will be used for all the library dynamic allocations made
* from this instance. The parameter may be NULL, in which case the default
@@ -404,21 +405,21 @@ typedef enum {
* @param memory_manager custom allocator function. It may be NULL. The memory
* manager will be copied internally.
* @return @c NULL if the instance can not be allocated or initialized
- * @return pointer to initialized JxlEncoder otherwise
+ * @return pointer to initialized @ref JxlEncoder otherwise
*/
JXL_EXPORT JxlEncoder* JxlEncoderCreate(const JxlMemoryManager* memory_manager);
/**
- * Re-initializes a JxlEncoder instance, so it can be re-used for encoding
+ * Re-initializes a @ref JxlEncoder instance, so it can be re-used for encoding
* another image. All state and settings are reset as if the object was
- * newly created with JxlEncoderCreate, but the memory manager is kept.
+ * newly created with @ref JxlEncoderCreate, but the memory manager is kept.
*
* @param enc instance to be re-initialized.
*/
JXL_EXPORT void JxlEncoderReset(JxlEncoder* enc);
/**
- * Deinitializes and frees JxlEncoder instance.
+ * Deinitializes and frees a @ref JxlEncoder instance.
*
* @param enc instance to be cleaned up and deallocated.
*/
@@ -430,8 +431,8 @@ JXL_EXPORT void JxlEncoderDestroy(JxlEncoder* enc);
* left unset, the default CMS implementation will be used.
*
* @param enc encoder object.
- * @param cms structure representing a CMS implementation. See JxlCmsInterface
- * for more details.
+ * @param cms structure representing a CMS implementation. See @ref
+ * JxlCmsInterface for more details.
*/
JXL_EXPORT void JxlEncoderSetCms(JxlEncoder* enc, JxlCmsInterface cms);
@@ -444,7 +445,7 @@ JXL_EXPORT void JxlEncoderSetCms(JxlEncoder* enc, JxlCmsInterface cms);
* be NULL to use the default, single-threaded, runner. A multithreaded
* runner should be set to reach fast performance.
* @param parallel_runner_opaque opaque pointer for parallel_runner.
- * @return JXL_ENC_SUCCESS if the runner was set, JXL_ENC_ERROR
+ * @return ::JXL_ENC_SUCCESS if the runner was set, ::JXL_ENC_ERROR
* otherwise (the previous runner remains set).
*/
JXL_EXPORT JxlEncoderStatus
@@ -452,16 +453,16 @@ JxlEncoderSetParallelRunner(JxlEncoder* enc, JxlParallelRunner parallel_runner,
void* parallel_runner_opaque);
/**
- * Get the (last) error code in case JXL_ENC_ERROR was returned.
+ * Get the (last) error code in case ::JXL_ENC_ERROR was returned.
*
* @param enc encoder object.
- * @return the JxlEncoderError that caused the (last) JXL_ENC_ERROR to be
- * returned.
+ * @return the @ref JxlEncoderError that caused the (last) ::JXL_ENC_ERROR to
+ * be returned.
*/
JXL_EXPORT JxlEncoderError JxlEncoderGetError(JxlEncoder* enc);
/**
- * Encodes JPEG XL file using the available bytes. @p *avail_out indicates how
+ * Encodes a JPEG XL file using the available bytes. @p *avail_out indicates how
* many output bytes are available, and @p *next_out points to the input bytes.
* *avail_out will be decremented by the amount of bytes that have been
* processed by the encoder and *next_out will be incremented by the same
@@ -469,12 +470,12 @@ JXL_EXPORT JxlEncoderError JxlEncoderGetError(JxlEncoder* enc);
* bytes.
*
* The returned status indicates whether the encoder needs more output bytes.
- * When the return value is not JXL_ENC_ERROR or JXL_ENC_SUCCESS, the encoding
- * requires more JxlEncoderProcessOutput calls to continue.
+ * When the return value is not ::JXL_ENC_ERROR or ::JXL_ENC_SUCCESS, the
+ * encoding requires more @ref JxlEncoderProcessOutput calls to continue.
*
* The caller must guarantee that *avail_out >= 32 when calling
- * JxlEncoderProcessOutput; otherwise, JXL_ENC_NEED_MORE_OUTPUT will be
- * returned. It is guaranteed that, if *avail_out >= 32, at least one byte of
+ * @ref JxlEncoderProcessOutput; otherwise, ::JXL_ENC_NEED_MORE_OUTPUT will
+ * be returned. It is guaranteed that, if *avail_out >= 32, at least one byte of
* output will be written.
*
* This encodes the frames and/or boxes added so far. If the last frame or last
@@ -486,9 +487,9 @@ JXL_EXPORT JxlEncoderError JxlEncoderGetError(JxlEncoder* enc);
* @param enc encoder object.
* @param next_out pointer to next bytes to write to.
* @param avail_out amount of bytes available starting from *next_out.
- * @return JXL_ENC_SUCCESS when encoding finished and all events handled.
- * @return JXL_ENC_ERROR when encoding failed, e.g. invalid input.
- * @return JXL_ENC_NEED_MORE_OUTPUT more output buffer is necessary.
+ * @return ::JXL_ENC_SUCCESS when encoding finished and all events handled.
+ * @return ::JXL_ENC_ERROR when encoding failed, e.g. invalid input.
+ * @return ::JXL_ENC_NEED_MORE_OUTPUT more output buffer is necessary.
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderProcessOutput(JxlEncoder* enc,
uint8_t** next_out,
@@ -509,13 +510,14 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderProcessOutput(JxlEncoder* enc,
* time duration of 0, making them form a composite still. See @ref
* JxlFrameHeader for more information.
*
- * This information is stored in the JxlEncoderFrameSettings and so is used for
- * any frame encoded with these JxlEncoderFrameSettings. It is ok to change
- * between @ref JxlEncoderAddImageFrame calls, each added image frame will have
- * the frame header that was set in the options at the time of calling
- * JxlEncoderAddImageFrame.
+ * This information is stored in the @ref JxlEncoderFrameSettings and so is used
+ * for any frame encoded with these @ref JxlEncoderFrameSettings. It is ok to
+ * change between @ref JxlEncoderAddImageFrame calls, each added image frame
+ * will have the frame header that was set in the options at the time of calling
+ * @ref JxlEncoderAddImageFrame.
*
- * The is_last and name_length fields of the JxlFrameHeader are ignored, use
+ * The is_last and name_length fields of the @ref JxlFrameHeader are ignored,
+ * use
* @ref JxlEncoderCloseFrames to indicate last frame, and @ref
* JxlEncoderSetFrameName to indicate the name and its length instead.
* Calling this function will clear any name that was previously set with @ref
@@ -525,7 +527,7 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderProcessOutput(JxlEncoder* enc,
* includes reference to the encoder object.
* @param frame_header frame header data to set. Object owned by the caller and
* does not need to be kept in memory, its information is copied internally.
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error
*/
JXL_EXPORT JxlEncoderStatus
JxlEncoderSetFrameHeader(JxlEncoderFrameSettings* frame_settings,
@@ -540,7 +542,7 @@ JxlEncoderSetFrameHeader(JxlEncoderFrameSettings* frame_settings,
* includes reference to the encoder object.
* @param index index of the extra channel to use.
* @param blend_info blend info to set for the extra channel
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelBlendInfo(
JxlEncoderFrameSettings* frame_settings, size_t index,
@@ -550,8 +552,9 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelBlendInfo(
* Sets the name of the animation frame. This function is optional, frames are
* not required to have a name. This setting is a part of the frame header, and
* the same principles as for @ref JxlEncoderSetFrameHeader apply. The
- * name_length field of JxlFrameHeader is ignored by the encoder, this function
- * determines the name length instead as the length in bytes of the C string.
+ * name_length field of @ref JxlFrameHeader is ignored by the encoder, this
+ * function determines the name length instead as the length in bytes of the C
+ * string.
*
* The maximum possible name length is 1071 bytes (excluding terminating null
* character).
@@ -563,7 +566,7 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelBlendInfo(
* includes reference to the encoder object.
* @param frame_name name of the next frame to be encoded, as a UTF-8 encoded C
* string (zero terminated). Owned by the caller, and copied internally.
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetFrameName(
JxlEncoderFrameSettings* frame_settings, const char* frame_name);
@@ -571,15 +574,17 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetFrameName(
/**
* Sets the bit depth of the input buffer.
*
- * For float pixel formats, only the default JXL_BIT_DEPTH_FROM_PIXEL_FORMAT
+ * For float pixel formats, only the default @ref
+ JXL_BIT_DEPTH_FROM_PIXEL_FORMAT
* setting is allowed, while for unsigned pixel formats,
- * JXL_BIT_DEPTH_FROM_CODESTREAM setting is also allowed. See the comment on
+ * ::JXL_BIT_DEPTH_FROM_CODESTREAM setting is also allowed. See the comment
+ on
* @ref JxlEncoderAddImageFrame for the effects of the bit depth setting.
* @param frame_settings set of options and metadata for this frame. Also
* includes reference to the encoder object.
* @param bit_depth the bit depth setting of the pixel input
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetFrameBitDepth(
JxlEncoderFrameSettings* frame_settings, const JxlBitDepth* bit_depth);
@@ -587,13 +592,13 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetFrameBitDepth(
/**
* Sets the buffer to read JPEG encoded bytes from for the next frame to encode.
*
- * If JxlEncoderSetBasicInfo has not yet been called, calling
- * JxlEncoderAddJPEGFrame will implicitly call it with the parameters of the
- * added JPEG frame.
+ * If @ref JxlEncoderSetBasicInfo has not yet been called, calling
+ * @ref JxlEncoderAddJPEGFrame will implicitly call it with the parameters of
+ * the added JPEG frame.
*
- * If JxlEncoderSetColorEncoding or JxlEncoderSetICCProfile has not yet been
- * called, calling JxlEncoderAddJPEGFrame will implicitly call it with the
- * parameters of the added JPEG frame.
+ * If @ref JxlEncoderSetColorEncoding or @ref JxlEncoderSetICCProfile has not
+ * yet been called, calling @ref JxlEncoderAddJPEGFrame will implicitly call it
+ * with the parameters of the added JPEG frame.
*
* If the encoder is set to store JPEG reconstruction metadata using @ref
* JxlEncoderStoreJPEGMetadata and a single JPEG frame is added, it will be
@@ -603,12 +608,16 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetFrameBitDepth(
* JxlEncoderCloseFrames must be called before the next
* @ref JxlEncoderProcessOutput call.
*
+ * Note, this can only be used to add JPEG frames for lossless compression. To
+ * encode with lossy compression, the JPEG must be decoded manually and a pixel
+ * buffer added using JxlEncoderAddImageFrame.
+ *
* @param frame_settings set of options and metadata for this frame. Also
* includes reference to the encoder object.
* @param buffer bytes to read JPEG from. Owned by the caller and its contents
* are copied internally.
* @param size size of buffer in bytes.
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error
*/
JXL_EXPORT JxlEncoderStatus
JxlEncoderAddJPEGFrame(const JxlEncoderFrameSettings* frame_settings,
@@ -616,33 +625,36 @@ JxlEncoderAddJPEGFrame(const JxlEncoderFrameSettings* frame_settings,
/**
* Sets the buffer to read pixels from for the next image to encode. Must call
- * JxlEncoderSetBasicInfo before JxlEncoderAddImageFrame.
+ * @ref JxlEncoderSetBasicInfo before @ref JxlEncoderAddImageFrame.
*
* Currently only some data types for pixel formats are supported:
- * - JXL_TYPE_UINT8, with range 0..255
- * - JXL_TYPE_UINT16, with range 0..65535
- * - JXL_TYPE_FLOAT16, with nominal range 0..1
- * - JXL_TYPE_FLOAT, with nominal range 0..1
+ * - ::JXL_TYPE_UINT8, with range 0..255
+ * - ::JXL_TYPE_UINT16, with range 0..65535
+ * - ::JXL_TYPE_FLOAT16, with nominal range 0..1
+ * - ::JXL_TYPE_FLOAT, with nominal range 0..1
*
* Note: the sample data type in pixel_format is allowed to be different from
- * what is described in the JxlBasicInfo. The type in pixel_format, together
- * with an optional @ref JxlBitDepth parameter set by @ref
+ * what is described in the @ref JxlBasicInfo. The type in pixel_format,
+ * together with an optional @ref JxlBitDepth parameter set by @ref
* JxlEncoderSetFrameBitDepth describes the format of the uncompressed pixel
- * buffer. The bits_per_sample and exponent_bits_per_sample in the JxlBasicInfo
- * describes what will actually be encoded in the JPEG XL codestream.
- * For example, to encode a 12-bit image, you would set bits_per_sample to 12,
- * while the input frame buffer can be in the following formats:
- * - if pixel format is in JXL_TYPE_UINT16 with default bit depth setting
- * (i.e. JXL_BIT_DEPTH_FROM_PIXEL_FORMAT), input sample values are rescaled
- * to 16-bit, i.e. multiplied by 65535/4095;
- * - if pixel format is in JXL_TYPE_UINT16 with JXL_BIT_DEPTH_FROM_CODESTREAM
- * bit depth setting, input sample values are provided unscaled;
- * - if pixel format is in JXL_TYPE_FLOAT, input sample values are rescaled
- * to 0..1, i.e. multiplied by 1.f/4095.f.
- * While it is allowed, it is obviously not recommended to use a pixel_format
- * with lower precision than what is specified in the JxlBasicInfo.
- *
- * We support interleaved channels as described by the JxlPixelFormat:
+ * buffer. The bits_per_sample and exponent_bits_per_sample in the @ref
+ * JxlBasicInfo describes what will actually be encoded in the JPEG XL
+ * codestream. For example, to encode a 12-bit image, you would set
+ * bits_per_sample to 12, while the input frame buffer can be in the following
+ * formats:
+ * - if pixel format is in ::JXL_TYPE_UINT16 with default bit depth setting
+ * (i.e. ::JXL_BIT_DEPTH_FROM_PIXEL_FORMAT), input sample values are
+ * rescaled to 16-bit, i.e. multiplied by 65535/4095;
+ * - if pixel format is in ::JXL_TYPE_UINT16 with @ref
+ * JXL_BIT_DEPTH_FROM_CODESTREAM bit depth setting, input sample values are
+ * provided unscaled;
+ * - if pixel format is in ::JXL_TYPE_FLOAT, input sample values are
+ * rescaled to 0..1, i.e. multiplied by 1.f/4095.f. While it is allowed, it is
+ * obviously not recommended to use a pixel_format with lower precision than
+ * what is specified in the @ref JxlBasicInfo.
+ *
+ * We support interleaved channels as described by the @ref JxlPixelFormat
+ * "JxlPixelFormat":
* - single-channel data, e.g. grayscale
* - single-channel + alpha
* - trichromatic, e.g. RGB
@@ -654,10 +666,11 @@ JxlEncoderAddJPEGFrame(const JxlEncoderFrameSettings* frame_settings,
* set to all-opaque (an alpha value of 1.0 everywhere).
*
* The pixels are assumed to be encoded in the original profile that is set with
- * JxlEncoderSetColorEncoding or JxlEncoderSetICCProfile. If none of these
- * functions were used, the pixels are assumed to be nonlinear sRGB for integer
- * data types (JXL_TYPE_UINT8, JXL_TYPE_UINT16), and linear sRGB for floating
- * point data types (JXL_TYPE_FLOAT16, JXL_TYPE_FLOAT).
+ * @ref JxlEncoderSetColorEncoding or @ref JxlEncoderSetICCProfile. If none of
+ * these functions were used, the pixels are assumed to be nonlinear sRGB for
+ * integer data types (::JXL_TYPE_UINT8, ::JXL_TYPE_UINT16), and linear
+ * sRGB for floating point data types (::JXL_TYPE_FLOAT16, @ref
+ * JXL_TYPE_FLOAT).
*
* Sample values in floating-point pixel formats are allowed to be outside the
* nominal range, e.g. to represent out-of-sRGB-gamut colors in the
@@ -676,14 +689,14 @@ JxlEncoderAddJPEGFrame(const JxlEncoderFrameSettings* frame_settings,
* and its contents are copied internally.
* @param size size of buffer in bytes. This size should match what is implied
* by the frame dimensions and the pixel format.
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderAddImageFrame(
const JxlEncoderFrameSettings* frame_settings,
const JxlPixelFormat* pixel_format, const void* buffer, size_t size);
/**
- * The JxlEncoderOutputProcessor structure provides an interface for the
+ * The @ref JxlEncoderOutputProcessor structure provides an interface for the
* encoder's output processing. Users of the library, who want to do streaming
* encoding, should implement the required callbacks for buffering, writing,
* seeking (if supported), and setting a finalized position during the encoding
@@ -785,7 +798,7 @@ struct JxlEncoderOutputProcessor {
* @param enc encoder object.
* @param output_processor the struct containing the callbacks for managing
* output.
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error.
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error.
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetOutputProcessor(
JxlEncoder* enc, struct JxlEncoderOutputProcessor output_processor);
@@ -801,7 +814,7 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetOutputProcessor(
* This should not be used when using @ref JxlEncoderProcessOutput.
*
* @param enc encoder object.
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error.
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error.
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderFlushInput(JxlEncoder* enc);
@@ -923,9 +936,9 @@ struct JxlChunkedFrameInputSource {
* chunked or streaming manner, which can be especially useful when dealing with
* large images that may not fit entirely in memory or when trying to optimize
* memory usage. The input data is provided through callbacks defined in the
- * `JxlChunkedFrameInputSource` struct. Once the frame data has been completely
- * retrieved, this function will flush the input and close it if it is the last
- * frame.
+ * @ref JxlChunkedFrameInputSource struct. Once the frame data has been
+ * completely retrieved, this function will flush the input and close it if it
+ * is the last frame.
*
* @param frame_settings set of options and metadata for this frame. Also
* includes reference to the encoder object.
@@ -943,7 +956,7 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderAddChunkedFrame(
/**
* Sets the buffer to read pixels from for an extra channel at a given index.
* The index must be smaller than the num_extra_channels in the associated
- * JxlBasicInfo. Must call @ref JxlEncoderSetExtraChannelInfo before
+ * @ref JxlBasicInfo. Must call @ref JxlEncoderSetExtraChannelInfo before @ref
* JxlEncoderSetExtraChannelBuffer.
*
* TODO(firsching): mention what data types in pixel formats are supported.
@@ -961,15 +974,15 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderAddChunkedFrame(
* @param size size of buffer in bytes. This size should match what is implied
* by the frame dimensions and the pixel format.
* @param index index of the extra channel to use.
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelBuffer(
const JxlEncoderFrameSettings* frame_settings,
const JxlPixelFormat* pixel_format, const void* buffer, size_t size,
uint32_t index);
-/** Adds a metadata box to the file format. JxlEncoderProcessOutput must be used
- * to effectively write the box to the output. @ref JxlEncoderUseBoxes must
+/** Adds a metadata box to the file format. @ref JxlEncoderProcessOutput must be
+ * used to effectively write the box to the output. @ref JxlEncoderUseBoxes must
* be enabled before using this function.
*
* Boxes allow inserting application-specific data and metadata (Exif, XML/XMP,
@@ -996,10 +1009,10 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelBuffer(
* the encoder encodes the size header itself. Most boxes are written
* automatically by the encoder as needed ("JXL ", "ftyp", "jxll", "jxlc",
* "jxlp", "jxli", "jbrd"), and this function only needs to be called to add
- * optional metadata when encoding from pixels (using JxlEncoderAddImageFrame).
- * When recompressing JPEG files (using JxlEncoderAddJPEGFrame), if the input
- * JPEG contains EXIF, XMP or JUMBF metadata, the corresponding boxes are
- * already added automatically.
+ * optional metadata when encoding from pixels (using @ref
+ * JxlEncoderAddImageFrame). When recompressing JPEG files (using @ref
+ * JxlEncoderAddJPEGFrame), if the input JPEG contains EXIF, XMP or JUMBF
+ * metadata, the corresponding boxes are already added automatically.
*
* Box types are given by 4 characters. The following boxes can be added with
* this function:
@@ -1032,9 +1045,9 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelBuffer(
* @param size size of the box contents.
* @param compress_box Whether to compress this box as a "brob" box. Requires
* Brotli support.
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error, such as when
- * using this function without JxlEncoderUseContainer, or adding a box type
- * that would result in an invalid file format.
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error, such as
+ * when using this function without @ref JxlEncoderUseContainer, or adding a box
+ * type that would result in an invalid file format.
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderAddBox(JxlEncoder* enc,
const JxlBoxType type,
@@ -1061,9 +1074,9 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderUseBoxes(JxlEncoder* enc);
* the stream will be finished. It is not necessary to use this function if
* @ref JxlEncoderUseBoxes is not used. Further frames may still be added.
*
- * Must be called between JxlEncoderAddBox of the last box
- * and the next call to JxlEncoderProcessOutput, or @ref JxlEncoderProcessOutput
- * won't output the last box correctly.
+ * Must be called between @ref JxlEncoderAddBox of the last box
+ * and the next call to @ref JxlEncoderProcessOutput, or @ref
+ * JxlEncoderProcessOutput won't output the last box correctly.
*
* NOTE: if you don't need to close frames and boxes at separate times, you can
* use @ref JxlEncoderCloseInput instead to close both at once.
@@ -1087,10 +1100,10 @@ JXL_EXPORT void JxlEncoderCloseBoxes(JxlEncoder* enc);
JXL_EXPORT void JxlEncoderCloseFrames(JxlEncoder* enc);
/**
- * Closes any input to the encoder, equivalent to calling JxlEncoderCloseFrames
- * as well as calling JxlEncoderCloseBoxes if needed. No further input of any
- * kind may be given to the encoder, but further @ref JxlEncoderProcessOutput
- * calls should be done to create the final output.
+ * Closes any input to the encoder, equivalent to calling @ref
+ * JxlEncoderCloseFrames as well as calling @ref JxlEncoderCloseBoxes if needed.
+ * No further input of any kind may be given to the encoder, but further @ref
+ * JxlEncoderProcessOutput calls should be done to create the final output.
*
* The requirements of both @ref JxlEncoderCloseFrames and @ref
* JxlEncoderCloseBoxes apply to this function. Either this function or the
@@ -1104,39 +1117,39 @@ JXL_EXPORT void JxlEncoderCloseInput(JxlEncoder* enc);
/**
* Sets the original color encoding of the image encoded by this encoder. This
- * is an alternative to JxlEncoderSetICCProfile and only one of these two must
- * be used. This one sets the color encoding as a @ref JxlColorEncoding, while
- * the other sets it as ICC binary data.
- * Must be called after JxlEncoderSetBasicInfo.
+ * is an alternative to @ref JxlEncoderSetICCProfile and only one of these two
+ * must be used. This one sets the color encoding as a @ref JxlColorEncoding,
+ * while the other sets it as ICC binary data. Must be called after @ref
+ * JxlEncoderSetBasicInfo.
*
* @param enc encoder object.
* @param color color encoding. Object owned by the caller and its contents are
* copied internally.
- * @return JXL_ENC_SUCCESS if the operation was successful, JXL_ENC_ERROR or
- * JXL_ENC_NOT_SUPPORTED otherwise
+ * @return ::JXL_ENC_SUCCESS if the operation was successful, @ref
+ * JXL_ENC_ERROR otherwise
*/
JXL_EXPORT JxlEncoderStatus
JxlEncoderSetColorEncoding(JxlEncoder* enc, const JxlColorEncoding* color);
/**
* Sets the original color encoding of the image encoded by this encoder as an
- * ICC color profile. This is an alternative to JxlEncoderSetColorEncoding and
- * only one of these two must be used. This one sets the color encoding as ICC
- * binary data, while the other defines it as a @ref JxlColorEncoding.
- * Must be called after JxlEncoderSetBasicInfo.
+ * ICC color profile. This is an alternative to @ref JxlEncoderSetColorEncoding
+ * and only one of these two must be used. This one sets the color encoding as
+ * ICC binary data, while the other defines it as a @ref JxlColorEncoding. Must
+ * be called after @ref JxlEncoderSetBasicInfo.
*
* @param enc encoder object.
* @param icc_profile bytes of the original ICC profile
* @param size size of the icc_profile buffer in bytes
- * @return JXL_ENC_SUCCESS if the operation was successful, JXL_ENC_ERROR or
- * JXL_ENC_NOT_SUPPORTED otherwise
+ * @return ::JXL_ENC_SUCCESS if the operation was successful, @ref
+ * JXL_ENC_ERROR otherwise
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetICCProfile(JxlEncoder* enc,
const uint8_t* icc_profile,
size_t size);
/**
- * Initializes a JxlBasicInfo struct to default values.
+ * Initializes a @ref JxlBasicInfo struct to default values.
* For forwards-compatibility, this function has to be called before values
* are assigned to the struct fields.
* The default values correspond to an 8-bit RGB image, no alpha or any
@@ -1147,7 +1160,7 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetICCProfile(JxlEncoder* enc,
JXL_EXPORT void JxlEncoderInitBasicInfo(JxlBasicInfo* info);
/**
- * Initializes a JxlFrameHeader struct to default values.
+ * Initializes a @ref JxlFrameHeader struct to default values.
* For forwards-compatibility, this function has to be called before values
* are assigned to the struct fields.
* The default values correspond to a frame with no animation duration and the
@@ -1159,7 +1172,7 @@ JXL_EXPORT void JxlEncoderInitBasicInfo(JxlBasicInfo* info);
JXL_EXPORT void JxlEncoderInitFrameHeader(JxlFrameHeader* frame_header);
/**
- * Initializes a JxlBlendInfo struct to default values.
+ * Initializes a @ref JxlBlendInfo struct to default values.
* For forwards-compatibility, this function has to be called before values
* are assigned to the struct fields.
*
@@ -1170,26 +1183,26 @@ JXL_EXPORT void JxlEncoderInitBlendInfo(JxlBlendInfo* blend_info);
/**
* Sets the global metadata of the image encoded by this encoder.
*
- * If the JxlBasicInfo contains information of extra channels beyond an alpha
- * channel, then @ref JxlEncoderSetExtraChannelInfo must be called between
- * JxlEncoderSetBasicInfo and @ref JxlEncoderAddImageFrame. In order to indicate
- * extra channels, the value of `info.num_extra_channels` should be set to the
- * number of extra channels, also counting the alpha channel if present.
+ * If the @ref JxlBasicInfo contains information of extra channels beyond an
+ * alpha channel, then @ref JxlEncoderSetExtraChannelInfo must be called between
+ * @ref JxlEncoderSetBasicInfo and @ref JxlEncoderAddImageFrame. In order to
+ * indicate extra channels, the value of `info.num_extra_channels` should be set
+ * to the number of extra channels, also counting the alpha channel if present.
*
* @param enc encoder object.
* @param info global image metadata. Object owned by the caller and its
* contents are copied internally.
- * @return JXL_ENC_SUCCESS if the operation was successful,
- * JXL_ENC_ERROR or JXL_ENC_NOT_SUPPORTED otherwise
+ * @return ::JXL_ENC_SUCCESS if the operation was successful,
+ * ::JXL_ENC_ERROR otherwise
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetBasicInfo(JxlEncoder* enc,
const JxlBasicInfo* info);
/**
* Sets the upsampling method the decoder will use in case there are frames
- * with JXL_ENC_FRAME_SETTING_RESAMPLING set. This is useful in combination
- * with the JXL_ENC_FRAME_SETTING_ALREADY_DOWNSAMPLED option, to control the
- * type of upsampling that will be used.
+ * with ::JXL_ENC_FRAME_SETTING_RESAMPLING set. This is useful in combination
+ * with the ::JXL_ENC_FRAME_SETTING_ALREADY_DOWNSAMPLED option, to control
+ * the type of upsampling that will be used.
*
* @param enc encoder object.
* @param factor upsampling factor to configure (1, 2, 4 or 8; for 1 this
@@ -1198,15 +1211,15 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetBasicInfo(JxlEncoder* enc,
* -1: default (good for photographic images, no signaling overhead)
* 0: nearest neighbor (good for pixel art)
* 1: 'pixel dots' (same as NN for 2x, diamond-shaped 'pixel dots' for 4x/8x)
- * @return JXL_ENC_SUCCESS if the operation was successful,
- * JXL_ENC_ERROR or JXL_ENC_NOT_SUPPORTED otherwise
+ * @return ::JXL_ENC_SUCCESS if the operation was successful,
+ * ::JXL_ENC_ERROR otherwise
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetUpsamplingMode(JxlEncoder* enc,
int64_t factor,
int64_t mode);
/**
- * Initializes a JxlExtraChannelInfo struct to default values.
+ * Initializes a @ref JxlExtraChannelInfo struct to default values.
* For forwards-compatibility, this function has to be called before values
* are assigned to the struct fields.
* The default values correspond to an 8-bit channel of the provided type.
@@ -1220,23 +1233,24 @@ JXL_EXPORT void JxlEncoderInitExtraChannelInfo(JxlExtraChannelType type,
/**
* Sets information for the extra channel at the given index. The index
- * must be smaller than num_extra_channels in the associated JxlBasicInfo.
+ * must be smaller than num_extra_channels in the associated @ref JxlBasicInfo.
*
* @param enc encoder object
* @param index index of the extra channel to set.
* @param info global extra channel metadata. Object owned by the caller and its
* contents are copied internally.
- * @return JXL_ENC_SUCCESS on success, JXL_ENC_ERROR on error
+ * @return ::JXL_ENC_SUCCESS on success, ::JXL_ENC_ERROR on error
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelInfo(
JxlEncoder* enc, size_t index, const JxlExtraChannelInfo* info);
/**
* Sets the name for the extra channel at the given index in UTF-8. The index
- * must be smaller than the num_extra_channels in the associated JxlBasicInfo.
+ * must be smaller than the num_extra_channels in the associated @ref
+ * JxlBasicInfo.
*
* TODO(lode): remove size parameter for consistency with
- * JxlEncoderSetFrameName
+ * @ref JxlEncoderSetFrameName
*
* @param enc encoder object
* @param index index of the extra channel to set.
@@ -1252,17 +1266,18 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelName(JxlEncoder* enc,
/**
* Sets a frame-specific option of integer type to the encoder options.
- * The JxlEncoderFrameSettingId argument determines which option is set.
+ * The @ref JxlEncoderFrameSettingId argument determines which option is set.
*
* @param frame_settings set of options and metadata for this frame. Also
* includes reference to the encoder object.
* @param option ID of the option to set.
* @param value Integer value to set for this option.
- * @return JXL_ENC_SUCCESS if the operation was successful, JXL_ENC_ERROR in
- * case of an error, such as invalid or unknown option id, or invalid integer
- * value for the given option. If an error is returned, the state of the
- * JxlEncoderFrameSettings object is still valid and is the same as before this
- * function was called.
+ * @return ::JXL_ENC_SUCCESS if the operation was successful, @ref
+ * JXL_ENC_ERROR in case of an error, such as invalid or unknown option id, or
+ * invalid integer value for the given option. If an error is returned, the
+ * state of the
+ * @ref JxlEncoderFrameSettings object is still valid and is the same as before
+ * this function was called.
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderFrameSettingsSetOption(
JxlEncoderFrameSettings* frame_settings, JxlEncoderFrameSettingId option,
@@ -1270,17 +1285,18 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderFrameSettingsSetOption(
/**
* Sets a frame-specific option of float type to the encoder options.
- * The JxlEncoderFrameSettingId argument determines which option is set.
+ * The @ref JxlEncoderFrameSettingId argument determines which option is set.
*
* @param frame_settings set of options and metadata for this frame. Also
* includes reference to the encoder object.
* @param option ID of the option to set.
* @param value Float value to set for this option.
- * @return JXL_ENC_SUCCESS if the operation was successful, JXL_ENC_ERROR in
- * case of an error, such as invalid or unknown option id, or invalid integer
- * value for the given option. If an error is returned, the state of the
- * JxlEncoderFrameSettings object is still valid and is the same as before this
- * function was called.
+ * @return ::JXL_ENC_SUCCESS if the operation was successful, @ref
+ * JXL_ENC_ERROR in case of an error, such as invalid or unknown option id, or
+ * invalid integer value for the given option. If an error is returned, the
+ * state of the
+ * @ref JxlEncoderFrameSettings object is still valid and is the same as before
+ * this function was called.
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderFrameSettingsSetFloatOption(
JxlEncoderFrameSettings* frame_settings, JxlEncoderFrameSettingId option,
@@ -1292,7 +1308,7 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderFrameSettingsSetFloatOption(
* When using @ref JxlEncoderUseBoxes, @ref JxlEncoderStoreJPEGMetadata or @ref
* JxlEncoderSetCodestreamLevel with level 10, the encoder will automatically
* also use the container format, it is not necessary to use
- * JxlEncoderUseContainer for those use cases.
+ * @ref JxlEncoderUseContainer for those use cases.
*
* By default this setting is disabled.
*
@@ -1318,8 +1334,8 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderUseContainer(JxlEncoder* enc,
*
* @param enc encoder object.
* @param store_jpeg_metadata true if the encoder should store JPEG metadata.
- * @return JXL_ENC_SUCCESS if the operation was successful, JXL_ENC_ERROR
- * otherwise.
+ * @return ::JXL_ENC_SUCCESS if the operation was successful, @ref
+ * JXL_ENC_ERROR otherwise.
*/
JXL_EXPORT JxlEncoderStatus
JxlEncoderStoreJPEGMetadata(JxlEncoder* enc, JXL_BOOL store_jpeg_metadata);
@@ -1334,8 +1350,8 @@ JxlEncoderStoreJPEGMetadata(JxlEncoder* enc, JXL_BOOL store_jpeg_metadata);
* 268435456 pixels total with a maximum width or height of 262144 pixels,
* maximum 16-bit color channel depth, maximum 120 frames per second for
* animation, maximum ICC color profile size of 4 MiB, it allows all color
- * models and extra channel types except CMYK and the JXL_CHANNEL_BLACK extra
- * channel, and a maximum of 4 extra channels in addition to the 3 color
+ * models and extra channel types except CMYK and the JXL_CHANNEL_BLACK
+ * extra channel, and a maximum of 4 extra channels in addition to the 3 color
* channels. It also sets boundaries to certain internally used coding tools.
*
* Level 10: this level removes or increases the bounds of most of the level
@@ -1355,8 +1371,8 @@ JxlEncoderStoreJPEGMetadata(JxlEncoder* enc, JXL_BOOL store_jpeg_metadata);
*
* @param enc encoder object.
* @param level the level value to set, must be -1, 5, or 10.
- * @return JXL_ENC_SUCCESS if the operation was successful, JXL_ENC_ERROR
- * otherwise.
+ * @return ::JXL_ENC_SUCCESS if the operation was successful, @ref
+ * JXL_ENC_ERROR otherwise.
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetCodestreamLevel(JxlEncoder* enc,
int level);
@@ -1370,9 +1386,10 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetCodestreamLevel(JxlEncoder* enc,
* the JPEG XL file.
*
* If this returns 5, nothing needs to be done and the codestream can be
- * compatible with any decoder. If this returns 10, JxlEncoderSetCodestreamLevel
- * has to be used to set the codestream level to 10, or the encoder can be
- * configured differently to allow using the more compatible level 5.
+ * compatible with any decoder. If this returns 10, @ref
+ * JxlEncoderSetCodestreamLevel has to be used to set the codestream level to
+ * 10, or the encoder can be configured differently to allow using the more
+ * compatible level 5.
*
* @param enc encoder object.
* @return -1 if no level can support the configuration (e.g. image dimensions
@@ -1391,14 +1408,14 @@ JXL_EXPORT int JxlEncoderGetRequiredCodestreamLevel(const JxlEncoder* enc);
*
* When disabled, those options are not overridden, but since those options
* could still have been manually set to a combination that operates losslessly,
- * using this function with lossless set to JXL_DEC_FALSE does not guarantee
- * lossy encoding, though the default set of options is lossy.
+ * using this function with lossless set to ::JXL_FALSE does not
+ * guarantee lossy encoding, though the default set of options is lossy.
*
* @param frame_settings set of options and metadata for this frame. Also
* includes reference to the encoder object.
* @param lossless whether to override options for lossless mode
- * @return JXL_ENC_SUCCESS if the operation was successful, JXL_ENC_ERROR
- * otherwise.
+ * @return ::JXL_ENC_SUCCESS if the operation was successful, @ref
+ * JXL_ENC_ERROR otherwise.
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetFrameLossless(
JxlEncoderFrameSettings* frame_settings, JXL_BOOL lossless);
@@ -1406,7 +1423,7 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetFrameLossless(
/**
* Sets the distance level for lossy compression: target max butteraugli
* distance, lower = higher quality. Range: 0 .. 25.
- * 0.0 = mathematically lossless (however, use JxlEncoderSetFrameLossless
+ * 0.0 = mathematically lossless (however, use @ref JxlEncoderSetFrameLossless
* instead to use true lossless, as setting distance to 0 alone is not the only
* requirement). 1.0 = visually lossless. Recommended range: 0.5 .. 3.0. Default
* value: 1.0.
@@ -1414,24 +1431,25 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetFrameLossless(
* @param frame_settings set of options and metadata for this frame. Also
* includes reference to the encoder object.
* @param distance the distance value to set.
- * @return JXL_ENC_SUCCESS if the operation was successful, JXL_ENC_ERROR
- * otherwise.
+ * @return ::JXL_ENC_SUCCESS if the operation was successful, @ref
+ * JXL_ENC_ERROR otherwise.
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetFrameDistance(
JxlEncoderFrameSettings* frame_settings, float distance);
/**
* Sets the distance level for lossy compression of extra channels.
- * The distance is as in JxlEncoderSetFrameDistance (lower = higher quality).
- * If not set, or if set to the special value -1, the distance that was set with
- * JxlEncoderSetFrameDistance will be used.
+ * The distance is as in @ref JxlEncoderSetFrameDistance (lower = higher
+ * quality). If not set, or if set to the special value -1, the distance that
+ * was set with
+ * @ref JxlEncoderSetFrameDistance will be used.
*
* @param frame_settings set of options and metadata for this frame. Also
* includes reference to the encoder object.
* @param index index of the extra channel to set a distance value for.
* @param distance the distance value to set.
- * @return JXL_ENC_SUCCESS if the operation was successful, JXL_ENC_ERROR
- * otherwise.
+ * @return ::JXL_ENC_SUCCESS if the operation was successful, @ref
+ * JXL_ENC_ERROR otherwise.
*/
JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelDistance(
JxlEncoderFrameSettings* frame_settings, size_t index, float distance);
@@ -1441,8 +1459,7 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelDistance(
*
* This function takes in input a JPEG-style quality factor `quality` and
* produces as output a `distance` value suitable to be used with @ref
- * JxlEncoderSetFrameDistance and
- * @ref JxlEncoderSetExtraChannelDistance.
+ * JxlEncoderSetFrameDistance and @ref JxlEncoderSetExtraChannelDistance.
*
* The `distance` value influences the level of compression, with lower values
* indicating higher quality:
@@ -1479,10 +1496,10 @@ JXL_EXPORT float JxlEncoderDistanceFromQuality(float quality);
* the @p source options, or set to default if @p source is NULL.
*
* The returned pointer is an opaque struct tied to the encoder and it will be
- * deallocated by the encoder when JxlEncoderDestroy() is called. For functions
- * taking both a @ref JxlEncoder and a @ref JxlEncoderFrameSettings, only
- * JxlEncoderFrameSettings created with this function for the same encoder
- * instance can be used.
+ * deallocated by the encoder when @ref JxlEncoderDestroy() is called. For
+ * functions taking both a @ref JxlEncoder and a @ref JxlEncoderFrameSettings,
+ * only @ref JxlEncoderFrameSettings created with this function for the same
+ * encoder instance can be used.
*
* @param enc encoder object.
* @param source source options to copy initial values from, or NULL to get
@@ -1513,7 +1530,7 @@ JXL_EXPORT void JxlColorEncodingSetToLinearSRGB(
/**
* Enables usage of expert options.
*
- * At the moment, the only expert option is setting an effort value of 10,
+ * At the moment, the only expert option is setting an effort value of 11,
* which gives the best compression for pixel-lossless modes but is very slow.
*
* @param enc encoder object.
diff --git a/third_party/jpeg-xl/lib/include/jxl/parallel_runner.h b/third_party/jpeg-xl/lib/include/jxl/parallel_runner.h
index e71e0aa926..ea66685dbc 100644
--- a/third_party/jpeg-xl/lib/include/jxl/parallel_runner.h
+++ b/third_party/jpeg-xl/lib/include/jxl/parallel_runner.h
@@ -46,39 +46,41 @@ extern "C" {
/** Return code used in the JxlParallel* functions as return value. A value
* of 0 means success and any other value means error. The special value
- * JXL_PARALLEL_RET_RUNNER_ERROR can be used by the runner to indicate any
+ * ::JXL_PARALLEL_RET_RUNNER_ERROR can be used by the runner to indicate any
* other error.
*/
typedef int JxlParallelRetCode;
/**
- * General error returned by the JxlParallelRunInit function to indicate
+ * General error returned by the @ref JxlParallelRunInit function to indicate
* an error.
*/
#define JXL_PARALLEL_RET_RUNNER_ERROR (-1)
/**
- * Parallel run initialization callback. See JxlParallelRunner for details.
+ * Parallel run initialization callback. See @ref JxlParallelRunner for details.
*
* This function MUST be called by the JxlParallelRunner only once, on the
- * same thread that called JxlParallelRunner, before any parallel execution.
- * The purpose of this call is to provide the maximum number of threads that the
- * JxlParallelRunner will use, which can be used by JPEG XL to allocate
+ * same thread that called @ref JxlParallelRunner, before any parallel
+ * execution. The purpose of this call is to provide the maximum number of
+ * threads that the
+ * @ref JxlParallelRunner will use, which can be used by JPEG XL to allocate
* per-thread storage if needed.
*
* @param jpegxl_opaque the @p jpegxl_opaque handle provided to
- * JxlParallelRunner() must be passed here.
+ * @ref JxlParallelRunner() must be passed here.
* @param num_threads the maximum number of threads. This value must be
* positive.
* @return 0 if the initialization process was successful.
* @return an error code if there was an error, which should be returned by
- * JxlParallelRunner().
+ * @ref JxlParallelRunner().
*/
typedef JxlParallelRetCode (*JxlParallelRunInit)(void* jpegxl_opaque,
size_t num_threads);
/**
- * Parallel run data processing callback. See JxlParallelRunner for details.
+ * Parallel run data processing callback. See @ref JxlParallelRunner for
+ * details.
*
* This function MUST be called once for every number in the range [start_range,
* end_range) (including start_range but not including end_range) passing this
@@ -86,11 +88,11 @@ typedef JxlParallelRetCode (*JxlParallelRunInit)(void* jpegxl_opaque,
* different threads in parallel.
*
* @param jpegxl_opaque the @p jpegxl_opaque handle provided to
- * JxlParallelRunner() must be passed here.
+ * @ref JxlParallelRunner() must be passed here.
* @param value the number in the range [start_range, end_range) of the call.
* @param thread_id the thread number where this function is being called from.
* This must be lower than the @p num_threads value passed to
- * JxlParallelRunInit.
+ * @ref JxlParallelRunInit.
*/
typedef void (*JxlParallelRunFunction)(void* jpegxl_opaque, uint32_t value,
size_t thread_id);
@@ -103,11 +105,12 @@ typedef void (*JxlParallelRunFunction)(void* jpegxl_opaque, uint32_t value,
* number in the range [start_range, end_range) (including start_range but not
* including end_range) possibly from different multiple threads in parallel.
*
- * The JxlParallelRunner function does not need to be re-entrant. This means
- * that the same JxlParallelRunner function with the same runner_opaque
- * provided parameter will not be called from the library from either @p init or
+ * The @ref JxlParallelRunner function does not need to be re-entrant. This
+ * means that the same @ref JxlParallelRunner function with the same
+ * runner_opaque provided parameter will not be called from the library from
+ * either @p init or
* @p func in the same decoder or encoder instance. However, a single decoding
- * or encoding instance may call the provided JxlParallelRunner multiple
+ * or encoding instance may call the provided @ref JxlParallelRunner multiple
* times for different parts of the decoding or encoding process.
*
* @return 0 if the @p init call succeeded (returned 0) and no other error
@@ -120,7 +123,7 @@ typedef JxlParallelRetCode (*JxlParallelRunner)(
void* runner_opaque, void* jpegxl_opaque, JxlParallelRunInit init,
JxlParallelRunFunction func, uint32_t start_range, uint32_t end_range);
-/* The following is an example of a JxlParallelRunner that doesn't use any
+/* The following is an example of a @ref JxlParallelRunner that doesn't use any
* multi-threading. Note that this implementation doesn't store any state
* between multiple calls of the ExampleSequentialRunner function, so the
* runner_opaque value is not used.
diff --git a/third_party/jpeg-xl/lib/include/jxl/resizable_parallel_runner.h b/third_party/jpeg-xl/lib/include/jxl/resizable_parallel_runner.h
index a65015d861..c82b0bc23b 100644
--- a/third_party/jpeg-xl/lib/include/jxl/resizable_parallel_runner.h
+++ b/third_party/jpeg-xl/lib/include/jxl/resizable_parallel_runner.h
@@ -16,7 +16,7 @@
* created can be changed after creation of the thread pool; the threads
* (including the main thread) are re-used for every
* ResizableParallelRunner::Runner call. Only one concurrent
- * JxlResizableParallelRunner call per instance is allowed at a time.
+ * @ref JxlResizableParallelRunner call per instance is allowed at a time.
*
* This is a scalable, lower-overhead thread pool runner, especially suitable
* for data-parallel computations in the fork-join model, where clients need to
@@ -41,20 +41,20 @@
extern "C" {
#endif
-/** Parallel runner internally using std::thread. Use as JxlParallelRunner.
+/** Parallel runner internally using std::thread. Use as @ref JxlParallelRunner.
*/
JXL_THREADS_EXPORT JxlParallelRetCode JxlResizableParallelRunner(
void* runner_opaque, void* jpegxl_opaque, JxlParallelRunInit init,
JxlParallelRunFunction func, uint32_t start_range, uint32_t end_range);
-/** Creates the runner for JxlResizableParallelRunner. Use as the opaque
+/** Creates the runner for @ref JxlResizableParallelRunner. Use as the opaque
* runner. The runner will execute tasks on the calling thread until
* @ref JxlResizableParallelRunnerSetThreads is called.
*/
JXL_THREADS_EXPORT void* JxlResizableParallelRunnerCreate(
const JxlMemoryManager* memory_manager);
-/** Changes the number of threads for JxlResizableParallelRunner.
+/** Changes the number of threads for @ref JxlResizableParallelRunner.
*/
JXL_THREADS_EXPORT void JxlResizableParallelRunnerSetThreads(
void* runner_opaque, size_t num_threads);
@@ -64,7 +64,7 @@ JXL_THREADS_EXPORT void JxlResizableParallelRunnerSetThreads(
JXL_THREADS_EXPORT uint32_t
JxlResizableParallelRunnerSuggestThreads(uint64_t xsize, uint64_t ysize);
-/** Destroys the runner created by JxlResizableParallelRunnerCreate.
+/** Destroys the runner created by @ref JxlResizableParallelRunnerCreate.
*/
JXL_THREADS_EXPORT void JxlResizableParallelRunnerDestroy(void* runner_opaque);
diff --git a/third_party/jpeg-xl/lib/include/jxl/stats.h b/third_party/jpeg-xl/lib/include/jxl/stats.h
index c9359dc870..5ed440636f 100644
--- a/third_party/jpeg-xl/lib/include/jxl/stats.h
+++ b/third_party/jpeg-xl/lib/include/jxl/stats.h
@@ -23,15 +23,15 @@ extern "C" {
/**
* Opaque structure that holds the encoder statistics.
*
- * Allocated and initialized with JxlEncoderStatsCreate().
- * Cleaned up and deallocated with JxlEncoderStatsDestroy().
+ * Allocated and initialized with @ref JxlEncoderStatsCreate().
+ * Cleaned up and deallocated with @ref JxlEncoderStatsDestroy().
*/
typedef struct JxlEncoderStatsStruct JxlEncoderStats;
/**
* Creates an instance of JxlEncoderStats and initializes it.
*
- * @return pointer to initialized JxlEncoderStats instance
+ * @return pointer to initialized @ref JxlEncoderStats instance
*/
JXL_EXPORT JxlEncoderStats* JxlEncoderStatsCreate(void);
@@ -43,7 +43,7 @@ JXL_EXPORT JxlEncoderStats* JxlEncoderStatsCreate(void);
*/
JXL_EXPORT void JxlEncoderStatsDestroy(JxlEncoderStats* stats);
-/** Data type for querying JxlEncoderStats object
+/** Data type for querying @ref JxlEncoderStats object
*/
typedef enum {
JXL_ENC_STAT_HEADER_BITS,
diff --git a/third_party/jpeg-xl/lib/include/jxl/thread_parallel_runner.h b/third_party/jpeg-xl/lib/include/jxl/thread_parallel_runner.h
index 6166fe7d36..933f373ce9 100644
--- a/third_party/jpeg-xl/lib/include/jxl/thread_parallel_runner.h
+++ b/third_party/jpeg-xl/lib/include/jxl/thread_parallel_runner.h
@@ -41,24 +41,24 @@
extern "C" {
#endif
-/** Parallel runner internally using std::thread. Use as JxlParallelRunner.
+/** Parallel runner internally using std::thread. Use as @ref JxlParallelRunner.
*/
JXL_THREADS_EXPORT JxlParallelRetCode JxlThreadParallelRunner(
void* runner_opaque, void* jpegxl_opaque, JxlParallelRunInit init,
JxlParallelRunFunction func, uint32_t start_range, uint32_t end_range);
-/** Creates the runner for JxlThreadParallelRunner. Use as the opaque
+/** Creates the runner for @ref JxlThreadParallelRunner. Use as the opaque
* runner.
*/
JXL_THREADS_EXPORT void* JxlThreadParallelRunnerCreate(
const JxlMemoryManager* memory_manager, size_t num_worker_threads);
-/** Destroys the runner created by JxlThreadParallelRunnerCreate.
+/** Destroys the runner created by @ref JxlThreadParallelRunnerCreate.
*/
JXL_THREADS_EXPORT void JxlThreadParallelRunnerDestroy(void* runner_opaque);
/** Returns a default num_worker_threads value for
- * JxlThreadParallelRunnerCreate.
+ * @ref JxlThreadParallelRunnerCreate.
*/
JXL_THREADS_EXPORT size_t JxlThreadParallelRunnerDefaultNumWorkerThreads(void);
diff --git a/third_party/jpeg-xl/lib/include/jxl/types.h b/third_party/jpeg-xl/lib/include/jxl/types.h
index a47216f878..2538dbaa82 100644
--- a/third_party/jpeg-xl/lib/include/jxl/types.h
+++ b/third_party/jpeg-xl/lib/include/jxl/types.h
@@ -13,7 +13,6 @@
#ifndef JXL_TYPES_H_
#define JXL_TYPES_H_
-#include <jxl/jxl_export.h>
#include <stddef.h>
#include <stdint.h>
@@ -32,15 +31,17 @@ extern "C" {
#define JXL_TRUE 1
/** Portable @c false replacement. */
#define JXL_FALSE 0
-/** Converts of bool-like value to either JXL_TRUE or JXL_FALSE. */
+/** Converts of bool-like value to either ::JXL_TRUE or ::JXL_FALSE. */
#define TO_JXL_BOOL(C) (!!(C) ? JXL_TRUE : JXL_FALSE)
+/** Converts JXL_BOOL to C++ bool. */
+#define FROM_JXL_BOOL(C) (static_cast<bool>(C))
/** Data type for the sample values per channel per pixel.
*/
typedef enum {
/** Use 32-bit single-precision floating point values, with range 0.0-1.0
* (within gamut, may go outside this range for wide color gamut). Floating
- * point output, either JXL_TYPE_FLOAT or JXL_TYPE_FLOAT16, is recommended
+ * point output, either ::JXL_TYPE_FLOAT or ::JXL_TYPE_FLOAT16, is recommended
* for HDR and wide gamut images when color profile conversion is required. */
JXL_TYPE_FLOAT = 0,
@@ -92,8 +93,7 @@ typedef struct {
JxlDataType data_type;
/** Whether multi-byte data types are represented in big endian or little
- * endian format. This applies to JXL_TYPE_UINT16, JXL_TYPE_UINT32
- * and JXL_TYPE_FLOAT.
+ * endian format. This applies to ::JXL_TYPE_UINT16 and ::JXL_TYPE_FLOAT.
*/
JxlEndianness endianness;
diff --git a/third_party/jpeg-xl/lib/jpegli.cmake b/third_party/jpeg-xl/lib/jpegli.cmake
index f06912f438..a471c8b2ab 100644
--- a/third_party/jpeg-xl/lib/jpegli.cmake
+++ b/third_party/jpeg-xl/lib/jpegli.cmake
@@ -88,7 +88,6 @@ foreach (TESTFILE IN LISTS JPEGXL_INTERNAL_JPEGLI_TESTS)
target_link_libraries(${TESTNAME}
hwy
jpegli-static
- gmock
GTest::GTest
GTest::Main
${JPEG_LIBRARIES}
diff --git a/third_party/jpeg-xl/lib/jpegli/adaptive_quantization.cc b/third_party/jpeg-xl/lib/jpegli/adaptive_quantization.cc
index 6a8c4d3128..2039326cbd 100644
--- a/third_party/jpeg-xl/lib/jpegli/adaptive_quantization.cc
+++ b/third_party/jpeg-xl/lib/jpegli/adaptive_quantization.cc
@@ -5,6 +5,7 @@
#include "lib/jpegli/adaptive_quantization.h"
+#include <jxl/types.h>
#include <stddef.h>
#include <stdlib.h>
@@ -46,7 +47,7 @@ using hwy::HWY_NAMESPACE::Sqrt;
using hwy::HWY_NAMESPACE::Sub;
using hwy::HWY_NAMESPACE::ZeroIfNegative;
-static constexpr float kInputScaling = 1.0f / 255.0f;
+constexpr float kInputScaling = 1.0f / 255.0f;
// Primary template: default to actual division.
template <typename T, class V>
@@ -65,7 +66,7 @@ struct FastDivision<float, V> {
}
V operator()(const V n, const V d) const {
-#if 1 // Faster on SKX
+#if JXL_TRUE // Faster on SKX
return Div(n, d);
#else
return n * ReciprocalNR(d);
@@ -191,12 +192,12 @@ V ComputeMask(const D d, const V out_val) {
}
// mul and mul2 represent a scaling difference between jxl and butteraugli.
-static const float kSGmul = 226.0480446705883f;
-static const float kSGmul2 = 1.0f / 73.377132366608819f;
-static const float kLog2 = 0.693147181f;
+const float kSGmul = 226.0480446705883f;
+const float kSGmul2 = 1.0f / 73.377132366608819f;
+const float kLog2 = 0.693147181f;
// Includes correction factor for std::log -> log2.
-static const float kSGRetMul = kSGmul2 * 18.6580932135f * kLog2;
-static const float kSGVOffset = 7.14672470003f;
+const float kSGRetMul = kSGmul2 * 18.6580932135f * kLog2;
+const float kSGVOffset = 7.14672470003f;
template <bool invert, typename D, typename V>
V RatioOfDerivativesOfCubicRootToSimpleGamma(const D d, V v) {
@@ -226,7 +227,7 @@ V RatioOfDerivativesOfCubicRootToSimpleGamma(const D d, V v) {
}
template <bool invert = false>
-static float RatioOfDerivativesOfCubicRootToSimpleGamma(float v) {
+float RatioOfDerivativesOfCubicRootToSimpleGamma(float v) {
using DScalar = HWY_CAPPED(float, 1);
auto vscalar = Load(DScalar(), &v);
return GetLane(
@@ -503,7 +504,7 @@ HWY_EXPORT(PerBlockModulations);
namespace {
-static constexpr int kPreErosionBorder = 1;
+constexpr int kPreErosionBorder = 1;
} // namespace
diff --git a/third_party/jpeg-xl/lib/jpegli/bitstream.cc b/third_party/jpeg-xl/lib/jpegli/bitstream.cc
index 3448367dde..4dbeb738bb 100644
--- a/third_party/jpeg-xl/lib/jpegli/bitstream.cc
+++ b/third_party/jpeg-xl/lib/jpegli/bitstream.cc
@@ -90,8 +90,8 @@ bool EncodeDQT(j_compress_ptr cinfo, bool write_all_tables) {
JPEGLI_ERROR("Missing quant table %d", i);
}
int precision = 0;
- for (size_t k = 0; k < DCTSIZE2; ++k) {
- if (quant_table->quantval[k] > 255) {
+ for (UINT16 q : quant_table->quantval) {
+ if (q > 255) {
precision = 1;
is_baseline = false;
}
@@ -123,7 +123,6 @@ bool EncodeDQT(j_compress_ptr cinfo, bool write_all_tables) {
void EncodeSOF(j_compress_ptr cinfo, bool is_baseline) {
if (cinfo->data_precision != kJpegPrecision) {
- is_baseline = false;
JPEGLI_ERROR("Unsupported data precision %d", cinfo->data_precision);
}
const uint8_t marker = cinfo->progressive_mode ? 0xc2
@@ -302,7 +301,7 @@ void WriteBlock(const int32_t* JXL_RESTRICT symbols,
namespace {
-static JXL_INLINE void EmitMarker(JpegBitWriter* bw, int marker) {
+JXL_INLINE void EmitMarker(JpegBitWriter* bw, int marker) {
bw->data[bw->pos++] = 0xFF;
bw->data[bw->pos++] = marker;
}
diff --git a/third_party/jpeg-xl/lib/jpegli/bitstream.h b/third_party/jpeg-xl/lib/jpegli/bitstream.h
index aa54c73d7e..bed441aefe 100644
--- a/third_party/jpeg-xl/lib/jpegli/bitstream.h
+++ b/third_party/jpeg-xl/lib/jpegli/bitstream.h
@@ -32,9 +32,8 @@ void EncodeSOS(j_compress_ptr cinfo, int scan_index);
void WriteScanHeader(j_compress_ptr cinfo, int scan_index);
void WriteBlock(const int32_t* JXL_RESTRICT symbols,
- const int32_t* JXL_RESTRICT extra_bits, const int num_nonzeros,
- const bool emit_eob,
- const HuffmanCodeTable* JXL_RESTRICT dc_code,
+ const int32_t* JXL_RESTRICT extra_bits, int num_nonzeros,
+ bool emit_eob, const HuffmanCodeTable* JXL_RESTRICT dc_code,
const HuffmanCodeTable* JXL_RESTRICT ac_code,
JpegBitWriter* JXL_RESTRICT bw);
void WriteScanData(j_compress_ptr cinfo, int scan_index);
diff --git a/third_party/jpeg-xl/lib/jpegli/color_quantize.cc b/third_party/jpeg-xl/lib/jpegli/color_quantize.cc
index e8357e2160..c4f32bf439 100644
--- a/third_party/jpeg-xl/lib/jpegli/color_quantize.cc
+++ b/third_party/jpeg-xl/lib/jpegli/color_quantize.cc
@@ -11,13 +11,14 @@
#include "lib/jpegli/decode_internal.h"
#include "lib/jpegli/error.h"
+#include "lib/jxl/base/status.h"
namespace jpegli {
namespace {
-static constexpr int kNumColorCellBits[kMaxComponents] = {3, 4, 3, 3};
-static constexpr int kCompW[kMaxComponents] = {2, 3, 1, 1};
+constexpr int kNumColorCellBits[kMaxComponents] = {3, 4, 3, 3};
+constexpr int kCompW[kMaxComponents] = {2, 3, 1, 1};
int Pow(int a, int b) {
int r = 1;
@@ -102,8 +103,8 @@ namespace {
// 2^13 priority levels for the PQ seems to be a good compromise between
// accuracy, running time and stack space usage.
-static const int kMaxPriority = 1 << 13;
-static const int kMaxLevel = 3;
+const int kMaxPriority = 1 << 13;
+const int kMaxLevel = 3;
// This function is used in the multi-resolution grid to be able to compute
// the keys for the different resolutions by just shifting the first key.
@@ -153,7 +154,7 @@ inline int ColorIntQuadDistanceRGB(uint8_t r1, uint8_t g1, uint8_t b1,
}
inline int ScaleQuadDistanceRGB(int d) {
- return static_cast<int>(sqrt(d * 0.25) + 0.5);
+ return static_cast<int>(std::lround(sqrt(d * 0.25)));
}
// The function updates the minimal distances, the clustering and the
@@ -216,9 +217,9 @@ struct WangHasher {
// to a unique integer index assigned to the different colors in order of
// appearance in the image. Return the number of unique colors found.
// The colors are pre-quantized to 3 * 6 bits precision.
-static int BuildRGBColorIndex(const uint8_t* const image, int const num_pixels,
- int* const count, uint8_t* const red,
- uint8_t* const green, uint8_t* const blue) {
+int BuildRGBColorIndex(const uint8_t* const image, int const num_pixels,
+ int* const count, uint8_t* const red,
+ uint8_t* const green, uint8_t* const blue) {
// Impossible because rgb are in the low 24 bits, and the upper 8 bits is 0.
const uint32_t impossible_pixel_value = 0x10000000;
std::unordered_map<uint32_t, int, RGBPixelHasher> index_map(1 << 12);
@@ -264,7 +265,7 @@ void ChooseColorMap2Pass(j_decompress_ptr cinfo) {
std::unique_ptr<uint8_t[]> blue(new uint8_t[max_color_count]);
std::vector<int> count(max_color_count, 0);
// number of colors
- int n = BuildRGBColorIndex(m->pixels_, num_pixels, &count[0], &red[0],
+ int n = BuildRGBColorIndex(m->pixels_, num_pixels, count.data(), &red[0],
&green[0], &blue[0]);
std::vector<int> dist(n, std::numeric_limits<int>::max());
@@ -285,14 +286,14 @@ void ChooseColorMap2Pass(j_decompress_ptr cinfo) {
winner = i;
}
if (!in_palette[i] && count[i] > count_threshold) {
- AddToRGBPalette(&red[0], &green[0], &blue[0], &count[0], i, k++, n,
- &dist[0], &cluster[0], &center[0], &error);
+ AddToRGBPalette(&red[0], &green[0], &blue[0], count.data(), i, k++, n,
+ dist.data(), cluster.data(), &center[0], &error);
in_palette[i] = true;
}
}
if (k == 0) {
- AddToRGBPalette(&red[0], &green[0], &blue[0], &count[0], winner, k++, n,
- &dist[0], &cluster[0], &center[0], &error);
+ AddToRGBPalette(&red[0], &green[0], &blue[0], count.data(), winner, k++, n,
+ dist.data(), cluster.data(), &center[0], &error);
in_palette[winner] = true;
}
@@ -365,8 +366,8 @@ void ChooseColorMap2Pass(j_decompress_ptr cinfo) {
if (priority < top_priority) {
bucket_array[priority].push_back(i);
} else {
- AddToRGBPalette(&red[0], &green[0], &blue[0], &count[0], i, k++, n,
- &dist[0], &cluster[0], &center[0], &error);
+ AddToRGBPalette(&red[0], &green[0], &blue[0], count.data(), i, k++, n,
+ dist.data(), cluster.data(), &center[0], &error);
}
bucket_array[top_priority].pop_back();
while (top_priority >= 0 && bucket_array[top_priority].empty()) {
@@ -387,7 +388,7 @@ void ChooseColorMap2Pass(j_decompress_ptr cinfo) {
namespace {
-void FindCandidatesForCell(j_decompress_ptr cinfo, int ncomp, int cell[],
+void FindCandidatesForCell(j_decompress_ptr cinfo, int ncomp, const int cell[],
std::vector<uint8_t>* candidates) {
int cell_min[kMaxComponents];
int cell_max[kMaxComponents];
@@ -404,7 +405,8 @@ void FindCandidatesForCell(j_decompress_ptr cinfo, int ncomp, int cell[],
int dmax = 0;
for (int c = 0; c < ncomp; ++c) {
int palette_c = cinfo->colormap[c][i];
- int dminc = 0, dmaxc;
+ int dminc = 0;
+ int dmaxc;
if (palette_c < cell_min[c]) {
dminc = cell_min[c] - palette_c;
dmaxc = cell_max[c] - palette_c;
@@ -436,6 +438,8 @@ void FindCandidatesForCell(j_decompress_ptr cinfo, int ncomp, int cell[],
void CreateInverseColorMap(j_decompress_ptr cinfo) {
jpeg_decomp_master* m = cinfo->master;
int ncomp = cinfo->out_color_components;
+ JXL_ASSERT(ncomp > 0);
+ JXL_ASSERT(ncomp <= kMaxComponents);
int num_cells = 1;
for (int c = 0; c < ncomp; ++c) {
num_cells *= (1 << kNumColorCellBits[c]);
@@ -455,7 +459,7 @@ void CreateInverseColorMap(j_decompress_ptr cinfo) {
m->regenerate_inverse_colormap_ = false;
}
-int LookupColorIndex(j_decompress_ptr cinfo, JSAMPLE* pixel) {
+int LookupColorIndex(j_decompress_ptr cinfo, const JSAMPLE* pixel) {
jpeg_decomp_master* m = cinfo->master;
int num_channels = cinfo->out_color_components;
int index = 0;
diff --git a/third_party/jpeg-xl/lib/jpegli/color_quantize.h b/third_party/jpeg-xl/lib/jpegli/color_quantize.h
index 3dda1d8713..92b922f756 100644
--- a/third_party/jpeg-xl/lib/jpegli/color_quantize.h
+++ b/third_party/jpeg-xl/lib/jpegli/color_quantize.h
@@ -20,7 +20,7 @@ void CreateOrderedDitherTables(j_decompress_ptr cinfo);
void InitFSDitherState(j_decompress_ptr cinfo);
-int LookupColorIndex(j_decompress_ptr cinfo, JSAMPLE* pixel);
+int LookupColorIndex(j_decompress_ptr cinfo, const JSAMPLE* pixel);
} // namespace jpegli
diff --git a/third_party/jpeg-xl/lib/jpegli/dct-inl.h b/third_party/jpeg-xl/lib/jpegli/dct-inl.h
index 1cbe704002..66cc3b6b53 100644
--- a/third_party/jpeg-xl/lib/jpegli/dct-inl.h
+++ b/third_party/jpeg-xl/lib/jpegli/dct-inl.h
@@ -187,7 +187,7 @@ void DCT1D(const float* JXL_RESTRICT pixels, size_t pixels_stride,
}
}
-static JXL_INLINE JXL_MAYBE_UNUSED void TransformFromPixels(
+JXL_INLINE JXL_MAYBE_UNUSED void TransformFromPixels(
const float* JXL_RESTRICT pixels, size_t pixels_stride,
float* JXL_RESTRICT coefficients, float* JXL_RESTRICT scratch_space) {
DCT1D(pixels, pixels_stride, scratch_space);
@@ -196,14 +196,14 @@ static JXL_INLINE JXL_MAYBE_UNUSED void TransformFromPixels(
Transpose8x8Block(scratch_space, coefficients);
}
-static JXL_INLINE JXL_MAYBE_UNUSED void StoreQuantizedValue(const Vec<DI>& ival,
- int16_t* out) {
+JXL_INLINE JXL_MAYBE_UNUSED void StoreQuantizedValue(const Vec<DI>& ival,
+ int16_t* out) {
Rebind<int16_t, DI> di16;
Store(DemoteTo(di16, ival), di16, out);
}
-static JXL_INLINE JXL_MAYBE_UNUSED void StoreQuantizedValue(const Vec<DI>& ival,
- int32_t* out) {
+JXL_INLINE JXL_MAYBE_UNUSED void StoreQuantizedValue(const Vec<DI>& ival,
+ int32_t* out) {
DI di;
Store(ival, di, out);
}
diff --git a/third_party/jpeg-xl/lib/jpegli/decode.cc b/third_party/jpeg-xl/lib/jpegli/decode.cc
index 758babeb5e..9fdf68dd18 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode.cc
+++ b/third_party/jpeg-xl/lib/jpegli/decode.cc
@@ -115,8 +115,10 @@ void InitProgressMonitor(j_decompress_ptr cinfo, bool coef_only) {
cinfo->progress->total_passes = 1;
} else {
int input_passes = !cinfo->buffered_image && m->is_multiscan_ ? 1 : 0;
- bool two_pass_quant = cinfo->quantize_colors && !cinfo->colormap &&
- cinfo->two_pass_quantize && cinfo->enable_2pass_quant;
+ bool two_pass_quant = FROM_JXL_BOOL(cinfo->quantize_colors) &&
+ (cinfo->colormap != nullptr) &&
+ FROM_JXL_BOOL(cinfo->two_pass_quantize) &&
+ FROM_JXL_BOOL(cinfo->enable_2pass_quant);
cinfo->progress->total_passes = input_passes + (two_pass_quant ? 2 : 1);
}
cinfo->progress->completed_passes = 0;
@@ -175,7 +177,7 @@ void BuildHuffmanLookupTable(j_decompress_ptr cinfo, JHUFF_TBL* table,
for (int i = 0; i < total_count; ++i) {
int value = table->huffval[i];
if (values_seen[value]) {
- return JPEGLI_ERROR("Duplicate Huffman code value %d", value);
+ JPEGLI_ERROR("Duplicate Huffman code value %d", value);
}
values_seen[value] = 1;
values[i] = value;
@@ -223,7 +225,7 @@ void PrepareForScan(j_decompress_ptr cinfo) {
HuffmanTableEntry* huff_lut =
&m->dc_huff_lut_[dc_tbl_idx * kJpegHuffmanLutSize];
if (!table) {
- return JPEGLI_ERROR("DC Huffman table %d not found", dc_tbl_idx);
+ JPEGLI_ERROR("DC Huffman table %d not found", dc_tbl_idx);
}
BuildHuffmanLookupTable(cinfo, table, huff_lut);
}
@@ -233,7 +235,7 @@ void PrepareForScan(j_decompress_ptr cinfo) {
HuffmanTableEntry* huff_lut =
&m->ac_huff_lut_[ac_tbl_idx * kJpegHuffmanLutSize];
if (!table) {
- return JPEGLI_ERROR("AC Huffman table %d not found", ac_tbl_idx);
+ JPEGLI_ERROR("AC Huffman table %d not found", ac_tbl_idx);
}
BuildHuffmanLookupTable(cinfo, table, huff_lut);
}
@@ -543,8 +545,8 @@ void jpegli_CreateDecompress(j_decompress_ptr cinfo, int version,
cinfo->is_decompressor = TRUE;
cinfo->progress = nullptr;
cinfo->src = nullptr;
- for (int i = 0; i < NUM_QUANT_TBLS; i++) {
- cinfo->quant_tbl_ptrs[i] = nullptr;
+ for (auto& quant_tbl_ptr : cinfo->quant_tbl_ptrs) {
+ quant_tbl_ptr = nullptr;
}
for (int i = 0; i < NUM_HUFF_TBLS; i++) {
cinfo->dc_huff_tbl_ptrs[i] = nullptr;
@@ -555,8 +557,8 @@ void jpegli_CreateDecompress(j_decompress_ptr cinfo, int version,
cinfo->rec_outbuf_height = 1; // output works with any buffer height
cinfo->master = new jpeg_decomp_master;
jpeg_decomp_master* m = cinfo->master;
- for (int i = 0; i < 16; ++i) {
- m->app_marker_parsers[i] = nullptr;
+ for (auto& app_marker_parser : m->app_marker_parsers) {
+ app_marker_parser = nullptr;
}
m->com_marker_parser = nullptr;
memset(m->markers_to_save_, 0, sizeof(m->markers_to_save_));
@@ -661,7 +663,7 @@ boolean jpegli_read_icc_profile(j_decompress_ptr cinfo, JOCTET** icc_data_ptr,
return FALSE;
}
*icc_data_len = m->icc_profile_.size();
- *icc_data_ptr = (JOCTET*)malloc(*icc_data_len);
+ *icc_data_ptr = static_cast<JOCTET*>(malloc(*icc_data_len));
if (*icc_data_ptr == nullptr) {
JPEGLI_ERROR("jpegli_read_icc_profile: Out of memory");
}
@@ -738,21 +740,26 @@ void jpegli_calc_output_dimensions(j_decompress_ptr cinfo) {
}
boolean jpegli_has_multiple_scans(j_decompress_ptr cinfo) {
- if (cinfo->input_scan_number == 0) {
- JPEGLI_ERROR("No SOS marker found.");
+ if (cinfo->global_state != jpegli::kDecHeaderDone &&
+ cinfo->global_state != jpegli::kDecProcessScan &&
+ cinfo->global_state != jpegli::kDecProcessMarkers) {
+ JPEGLI_ERROR("jpegli_has_multiple_scans: unexpected state %d",
+ cinfo->global_state);
}
- return cinfo->master->is_multiscan_;
+ return TO_JXL_BOOL(cinfo->master->is_multiscan_);
}
boolean jpegli_input_complete(j_decompress_ptr cinfo) {
- return cinfo->master->found_eoi_;
+ return TO_JXL_BOOL(cinfo->master->found_eoi_);
}
boolean jpegli_start_decompress(j_decompress_ptr cinfo) {
jpeg_decomp_master* m = cinfo->master;
if (cinfo->global_state == jpegli::kDecHeaderDone) {
- m->streaming_mode_ = !m->is_multiscan_ && !cinfo->buffered_image &&
- (!cinfo->quantize_colors || !cinfo->two_pass_quantize);
+ m->streaming_mode_ = !m->is_multiscan_ &&
+ !FROM_JXL_BOOL(cinfo->buffered_image) &&
+ (!FROM_JXL_BOOL(cinfo->quantize_colors) ||
+ !FROM_JXL_BOOL(cinfo->two_pass_quantize));
jpegli::AllocateCoefficientBuffer(cinfo);
jpegli_calc_output_dimensions(cinfo);
jpegli::PrepareForScan(cinfo);
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc b/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc
index c48b9377c3..0cc5a194d7 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc
@@ -18,8 +18,8 @@
namespace jpegli {
namespace {
-static constexpr uint8_t kFakeEoiMarker[2] = {0xff, 0xd9};
-static constexpr size_t kNumSourceBuffers = 4;
+constexpr uint8_t kFakeEoiMarker[2] = {0xff, 0xd9};
+constexpr size_t kNumSourceBuffers = 4;
// Custom source manager that refills the input buffer in chunks, simulating
// a file reader with a fixed buffer size.
@@ -61,7 +61,7 @@ class SourceManager {
static void init_source(j_decompress_ptr cinfo) {}
static boolean fill_input_buffer(j_decompress_ptr cinfo) {
- auto src = reinterpret_cast<SourceManager*>(cinfo->src);
+ auto* src = reinterpret_cast<SourceManager*>(cinfo->src);
if (src->pos_ < src->len_) {
size_t chunk_size = std::min(src->len_ - src->pos_, src->max_chunk_size_);
size_t next_idx = ++src->chunk_idx_ % kNumSourceBuffers;
@@ -79,7 +79,7 @@ class SourceManager {
}
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
- auto src = reinterpret_cast<SourceManager*>(cinfo->src);
+ auto* src = reinterpret_cast<SourceManager*>(cinfo->src);
if (num_bytes <= 0) {
return;
}
@@ -166,9 +166,9 @@ void ReadOutputImage(const DecompressParams& dparams, j_decompress_ptr cinfo,
rowdata[c][i] =
y0 + i < ysize ? &output->raw_data[c][(y0 + i) * xsize] : nullptr;
}
- data[c] = &rowdata[c][0];
+ data[c] = rowdata[c].data();
}
- num_output_lines = jpegli_read_raw_data(cinfo, &data[0], max_lines);
+ num_output_lines = jpegli_read_raw_data(cinfo, data.data(), max_lines);
} else {
size_t max_output_lines = dparams.max_output_lines;
if (max_output_lines == 0) max_output_lines = cinfo->output_height;
@@ -189,7 +189,7 @@ void ReadOutputImage(const DecompressParams& dparams, j_decompress_ptr cinfo,
scanlines[i] = &output->pixels[yidx * stride];
}
num_output_lines =
- jpegli_read_scanlines(cinfo, &scanlines[0], max_lines);
+ jpegli_read_scanlines(cinfo, scanlines.data(), max_lines);
if (cinfo->quantize_colors) {
for (size_t i = 0; i < num_output_lines; ++i) {
UnmapColors(scanlines[i], cinfo->output_width,
@@ -222,7 +222,7 @@ struct TestConfig {
std::vector<uint8_t> GetTestJpegData(TestConfig& config) {
std::vector<uint8_t> compressed;
if (!config.fn.empty()) {
- compressed = ReadTestData(config.fn.c_str());
+ compressed = ReadTestData(config.fn);
} else {
GeneratePixels(&config.input);
JXL_CHECK(EncodeWithJpegli(config.input, config.jparams, &compressed));
@@ -297,10 +297,10 @@ void TestAPIBuffered(const CompressParams& jparams,
SetDecompressParams(dparams, cinfo);
jpegli_set_output_format(cinfo, dparams.data_type, dparams.endianness);
VerifyHeader(jparams, cinfo);
+ bool has_multiple_scans = FROM_JXL_BOOL(jpegli_has_multiple_scans(cinfo));
EXPECT_TRUE(jpegli_start_decompress(cinfo));
// start decompress should not read the whole input in buffered image mode
EXPECT_FALSE(jpegli_input_complete(cinfo));
- bool has_multiple_scans = jpegli_has_multiple_scans(cinfo);
EXPECT_EQ(0, cinfo->output_scan_number);
int sos_marker_cnt = 1; // read_header reads the first SOS marker
while (!jpegli_input_complete(cinfo)) {
@@ -341,8 +341,11 @@ void TestAPIBuffered(const CompressParams& jparams,
}
TEST(DecodeAPITest, ReuseCinfo) {
- TestImage input, output, expected;
- std::vector<TestImage> output_progression, expected_output_progression;
+ TestImage input;
+ TestImage output;
+ TestImage expected;
+ std::vector<TestImage> output_progression;
+ std::vector<TestImage> expected_output_progression;
CompressParams jparams;
DecompressParams dparams;
std::vector<uint8_t> compressed;
@@ -383,8 +386,8 @@ TEST(DecodeAPITest, ReuseCinfo) {
expected.Clear();
DecodeWithLibjpeg(jparams, dparams, compressed, &expected);
output.Clear();
- cinfo.buffered_image = false;
- cinfo.raw_data_out = false;
+ cinfo.buffered_image = JXL_FALSE;
+ cinfo.raw_data_out = JXL_FALSE;
cinfo.scale_num = cinfo.scale_denom = 1;
SourceManager src(compressed.data(), compressed.size(),
1u << 12);
@@ -1245,7 +1248,8 @@ std::ostream& operator<<(std::ostream& os, const DecompressParams& dparams) {
}
os << IOMethodName(dparams.data_type, dparams.endianness);
if (dparams.set_out_color_space) {
- os << "OutColor" << ColorSpaceName((J_COLOR_SPACE)dparams.out_color_space);
+ os << "OutColor"
+ << ColorSpaceName(static_cast<J_COLOR_SPACE>(dparams.out_color_space));
}
if (dparams.crop_output) {
os << "Crop";
@@ -1265,7 +1269,8 @@ std::ostream& operator<<(std::ostream& os, const DecompressParams& dparams) {
if (i > 0) os << "_";
const auto& sparam = dparams.scan_params[i];
os << QuantMode(sparam.color_quant_mode);
- os << DitherMode((J_DITHER_MODE)sparam.dither_mode) << "Dither";
+ os << DitherMode(static_cast<J_DITHER_MODE>(sparam.dither_mode))
+ << "Dither";
}
}
if (dparams.skip_scans) {
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_internal.h b/third_party/jpeg-xl/lib/jpegli/decode_internal.h
index ed7baa39e9..37dfcc4526 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_internal.h
+++ b/third_party/jpeg-xl/lib/jpegli/decode_internal.h
@@ -45,12 +45,13 @@ struct jpeg_decomp_master {
size_t input_buffer_pos_;
// Number of bits after codestream_pos_ that were already processed.
size_t codestream_bits_ahead_;
- bool streaming_mode_;
// Coefficient buffers
jvirt_barray_ptr* coef_arrays;
JBLOCKARRAY coeff_rows[jpegli::kMaxComponents];
+ bool streaming_mode_;
+
//
// Marker data processing state.
//
@@ -58,6 +59,11 @@ struct jpeg_decomp_master {
bool found_dri_;
bool found_sof_;
bool found_eoi_;
+
+ // Whether this jpeg has multiple scans (progressive or non-interleaved
+ // sequential).
+ bool is_multiscan_;
+
size_t icc_index_;
size_t icc_total_;
std::vector<uint8_t> icc_profile_;
@@ -66,9 +72,6 @@ struct jpeg_decomp_master {
uint8_t markers_to_save_[32];
jpeg_marker_parser_method app_marker_parsers[16];
jpeg_marker_parser_method com_marker_parser;
- // Whether this jpeg has multiple scans (progressive or non-interleaved
- // sequential).
- bool is_multiscan_;
// Fields defined by SOF marker.
size_t iMCU_cols_;
@@ -96,9 +99,11 @@ struct jpeg_decomp_master {
//
int output_passes_done_;
JpegliDataType output_data_type_ = JPEGLI_TYPE_UINT8;
- bool swap_endianness_ = false;
size_t xoffset_;
+ bool swap_endianness_ = false;
bool need_context_rows_;
+ bool regenerate_inverse_colormap_;
+ bool apply_smoothing;
int min_scaled_dct_size;
int scaled_dct_size[jpegli::kMaxComponents];
@@ -127,7 +132,6 @@ struct jpeg_decomp_master {
uint8_t* pixels_;
JSAMPARRAY scanlines_;
std::vector<std::vector<uint8_t>> candidate_lists_;
- bool regenerate_inverse_colormap_;
float* dither_[jpegli::kMaxComponents];
float* error_row_[2 * jpegli::kMaxComponents];
size_t dither_size_;
@@ -145,7 +149,6 @@ struct jpeg_decomp_master {
// i.e. the bottom half when rendering incomplete scans.
int (*coef_bits_latch)[SAVED_COEFS];
int (*prev_coef_bits_latch)[SAVED_COEFS];
- bool apply_smoothing;
};
#endif // LIB_JPEGLI_DECODE_INTERNAL_H_
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_marker.cc b/third_party/jpeg-xl/lib/jpegli/decode_marker.cc
index c5c5790cdf..a9ed4df329 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_marker.cc
+++ b/third_party/jpeg-xl/lib/jpegli/decode_marker.cc
@@ -5,6 +5,7 @@
#include "lib/jpegli/decode_marker.h"
+#include <jxl/types.h>
#include <string.h>
#include "lib/jpegli/common.h"
@@ -22,23 +23,22 @@ constexpr uint8_t kIccProfileTag[12] = "ICC_PROFILE";
// Macros for commonly used error conditions.
-#define JPEG_VERIFY_LEN(n) \
- if (pos + (n) > len) { \
- return JPEGLI_ERROR("Unexpected end of marker: pos=%" PRIuS \
- " need=%d len=%" PRIuS, \
- pos, static_cast<int>(n), len); \
+#define JPEG_VERIFY_LEN(n) \
+ if (pos + (n) > len) { \
+ JPEGLI_ERROR("Unexpected end of marker: pos=%" PRIuS \
+ " need=%d len=%" PRIuS, \
+ pos, static_cast<int>(n), len); \
}
-#define JPEG_VERIFY_INPUT(var, low, high) \
- if ((var) < (low) || (var) > (high)) { \
- return JPEGLI_ERROR("Invalid " #var ": %d", static_cast<int>(var)); \
+#define JPEG_VERIFY_INPUT(var, low, high) \
+ if ((var) < (low) || (var) > (high)) { \
+ JPEGLI_ERROR("Invalid " #var ": %d", static_cast<int>(var)); \
}
-#define JPEG_VERIFY_MARKER_END() \
- if (pos != len) { \
- return JPEGLI_ERROR("Invalid marker length: declared=%" PRIuS \
- " actual=%" PRIuS, \
- len, pos); \
+#define JPEG_VERIFY_MARKER_END() \
+ if (pos != len) { \
+ JPEGLI_ERROR("Invalid marker length: declared=%" PRIuS " actual=%" PRIuS, \
+ len, pos); \
}
inline int ReadUint8(const uint8_t* data, size_t* pos) {
@@ -60,7 +60,7 @@ void ProcessSOF(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
JPEGLI_ERROR("Duplicate SOF marker.");
}
m->found_sof_ = true;
- cinfo->progressive_mode = (cinfo->unread_marker == 0xc2);
+ cinfo->progressive_mode = TO_JXL_BOOL(cinfo->unread_marker == 0xc2);
cinfo->arith_code = 0;
size_t pos = 2;
JPEG_VERIFY_LEN(6);
@@ -181,7 +181,7 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
for (int i = 0; i < cinfo->comps_in_scan; ++i) {
int id = ReadUint8(data, &pos);
if (ids_seen[id]) { // (cf. section B.2.3, regarding CSj)
- return JPEGLI_ERROR("Duplicate ID %d in SOS.", id);
+ JPEGLI_ERROR("Duplicate ID %d in SOS.", id);
}
ids_seen[id] = 1;
jpeg_component_info* comp = nullptr;
@@ -192,8 +192,7 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
}
}
if (!comp) {
- return JPEGLI_ERROR("SOS marker: Could not find component with id %d",
- id);
+ JPEGLI_ERROR("SOS marker: Could not find component with id %d", id);
}
int c = ReadUint8(data, &pos);
comp->dc_tbl_no = c >> 4;
@@ -222,7 +221,7 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
if (cinfo->input_scan_number == 0) {
m->is_multiscan_ = (cinfo->comps_in_scan < cinfo->num_components ||
- cinfo->progressive_mode);
+ FROM_JXL_BOOL(cinfo->progressive_mode));
}
if (cinfo->Ah != 0 && cinfo->Al != cinfo->Ah - 1) {
// section G.1.1.1.2 : Successive approximation control only improves
@@ -261,12 +260,12 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
int comp_idx = cinfo->cur_comp_info[i]->component_index;
for (int k = cinfo->Ss; k <= cinfo->Se; ++k) {
if (m->scan_progression_[comp_idx][k] & scan_bitmask) {
- return JPEGLI_ERROR(
+ JPEGLI_ERROR(
"Overlapping scans: component=%d k=%d prev_mask: %u cur_mask %u",
comp_idx, k, m->scan_progression_[i][k], scan_bitmask);
}
if (m->scan_progression_[comp_idx][k] & refinement_bitmask) {
- return JPEGLI_ERROR(
+ JPEGLI_ERROR(
"Invalid scan order, a more refined scan was already done: "
"component=%d k=%d prev_mask=%u cur_mask=%u",
comp_idx, k, m->scan_progression_[i][k], scan_bitmask);
@@ -275,7 +274,7 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
}
}
if (cinfo->Al > 10) {
- return JPEGLI_ERROR("Scan parameter Al=%d is not supported.", cinfo->Al);
+ JPEGLI_ERROR("Scan parameter Al=%d is not supported.", cinfo->Al);
}
}
@@ -285,7 +284,7 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
void ProcessDHT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
size_t pos = 2;
if (pos == len) {
- return JPEGLI_ERROR("DHT marker: no Huffman table found");
+ JPEGLI_ERROR("DHT marker: no Huffman table found");
}
while (pos < len) {
JPEG_VERIFY_LEN(1 + kJpegHuffmanMaxBitLength);
@@ -293,7 +292,7 @@ void ProcessDHT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
// component Huffman codes, 0x10 is added to the index.
int slot_id = ReadUint8(data, &pos);
int huffman_index = slot_id;
- int is_ac_table = (slot_id & 0x10) != 0;
+ bool is_ac_table = ((slot_id & 0x10) != 0);
JHUFF_TBL** table;
if (is_ac_table) {
huffman_index -= 0x10;
@@ -343,7 +342,7 @@ void ProcessDQT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
}
size_t pos = 2;
if (pos == len) {
- return JPEGLI_ERROR("DQT marker: no quantization table found");
+ JPEGLI_ERROR("DQT marker: no quantization table found");
}
while (pos < len) {
JPEG_VERIFY_LEN(1);
@@ -377,7 +376,7 @@ void ProcessDNL(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
void ProcessDRI(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
jpeg_decomp_master* m = cinfo->master;
if (m->found_dri_) {
- return JPEGLI_ERROR("Duplicate DRI marker.");
+ JPEGLI_ERROR("Duplicate DRI marker.");
}
m->found_dri_ = true;
size_t pos = 2;
@@ -411,24 +410,24 @@ void ProcessAPP(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
payload += sizeof(kIccProfileTag);
payload_size -= sizeof(kIccProfileTag);
if (payload_size < 2) {
- return JPEGLI_ERROR("ICC chunk is too small.");
+ JPEGLI_ERROR("ICC chunk is too small.");
}
uint8_t index = payload[0];
uint8_t total = payload[1];
++m->icc_index_;
if (m->icc_index_ != index) {
- return JPEGLI_ERROR("Invalid ICC chunk order.");
+ JPEGLI_ERROR("Invalid ICC chunk order.");
}
if (total == 0) {
- return JPEGLI_ERROR("Invalid ICC chunk total.");
+ JPEGLI_ERROR("Invalid ICC chunk total.");
}
if (m->icc_total_ == 0) {
m->icc_total_ = total;
} else if (m->icc_total_ != total) {
- return JPEGLI_ERROR("Invalid ICC chunk total.");
+ JPEGLI_ERROR("Invalid ICC chunk total.");
}
if (m->icc_index_ > m->icc_total_) {
- return JPEGLI_ERROR("Invalid ICC chunk index.");
+ JPEGLI_ERROR("Invalid ICC chunk index.");
}
m->icc_profile_.insert(m->icc_profile_.end(), payload + 2,
payload + payload_size);
@@ -494,8 +493,8 @@ uint8_t ProcessNextMarker(j_decompress_ptr cinfo, const uint8_t* const data,
marker = data[*pos + 1];
if (num_skipped > 0) {
if (m->found_soi_) {
- JPEGLI_WARN("Skipped %d bytes before marker 0x%02x", (int)num_skipped,
- marker);
+ JPEGLI_WARN("Skipped %d bytes before marker 0x%02x",
+ static_cast<int>(num_skipped), marker);
} else {
JPEGLI_ERROR("Did not find SOI marker.");
}
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_marker.h b/third_party/jpeg-xl/lib/jpegli/decode_marker.h
index fb24b3ee87..f3d47f6ad2 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_marker.h
+++ b/third_party/jpeg-xl/lib/jpegli/decode_marker.h
@@ -22,8 +22,8 @@ namespace jpegli {
// EOI marker. Input buffer refill is handled by the caller;
// * JPEG_REACHED_SOS, if the next SOS marker is found;
// * JPEG_REACHED_EOR, if the end of the input is found.
-int ProcessMarkers(j_decompress_ptr cinfo, const uint8_t* const data,
- const size_t len, size_t* pos);
+int ProcessMarkers(j_decompress_ptr cinfo, const uint8_t* data, size_t len,
+ size_t* pos);
jpeg_marker_parser_method GetMarkerProcessor(j_decompress_ptr cinfo);
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_scan.cc b/third_party/jpeg-xl/lib/jpegli/decode_scan.cc
index 05b1f37220..1b50792f0a 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_scan.cc
+++ b/third_party/jpeg-xl/lib/jpegli/decode_scan.cc
@@ -61,7 +61,7 @@ struct BitReaderState {
if (bits_left_ <= 16) {
while (bits_left_ <= 56) {
val_ <<= 8;
- val_ |= (uint64_t)GetNextByte();
+ val_ |= static_cast<uint64_t>(GetNextByte());
bits_left_ += 8;
}
}
@@ -427,7 +427,7 @@ void PrepareForiMCURow(j_decompress_ptr cinfo) {
int offset = m->streaming_mode_ ? 0 : by0;
m->coeff_rows[c] = (*cinfo->mem->access_virt_barray)(
reinterpret_cast<j_common_ptr>(cinfo), m->coef_arrays[c], offset,
- max_block_rows, true);
+ max_block_rows, TRUE);
}
}
@@ -451,7 +451,8 @@ int ProcessScan(j_decompress_ptr cinfo, const uint8_t* const data,
++num_skipped;
}
if (num_skipped > 0) {
- JPEGLI_WARN("Skipped %d bytes before restart marker", (int)num_skipped);
+ JPEGLI_WARN("Skipped %d bytes before restart marker",
+ static_cast<int>(num_skipped));
}
if (*pos + 2 > len) {
return kNeedMoreInput;
@@ -471,7 +472,7 @@ int ProcessScan(j_decompress_ptr cinfo, const uint8_t* const data,
}
// Decode one MCU.
- HWY_ALIGN_MAX coeff_t sink_block[DCTSIZE2];
+ HWY_ALIGN_MAX static coeff_t sink_block[DCTSIZE2] = {0};
bool scan_ok = true;
for (int i = 0; i < cinfo->comps_in_scan; ++i) {
const jpeg_component_info* comp = cinfo->cur_comp_info[i];
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_scan.h b/third_party/jpeg-xl/lib/jpegli/decode_scan.h
index 1d7b18fc1a..dd1bfcd110 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_scan.h
+++ b/third_party/jpeg-xl/lib/jpegli/decode_scan.h
@@ -21,8 +21,8 @@ namespace jpegli {
// * JPEG_SUSPENDED, if the input buffer ends before the end of an iMCU row;
// * JPEG_ROW_COMPLETED, if the next iMCU row (but not the scan) is reached;
// * JPEG_SCAN_COMPLETED, if the end of the scan is reached.
-int ProcessScan(j_decompress_ptr cinfo, const uint8_t* const data,
- const size_t len, size_t* pos, size_t* bit_pos);
+int ProcessScan(j_decompress_ptr cinfo, const uint8_t* data, size_t len,
+ size_t* pos, size_t* bit_pos);
void PrepareForiMCURow(j_decompress_ptr cinfo);
diff --git a/third_party/jpeg-xl/lib/jpegli/destination_manager.cc b/third_party/jpeg-xl/lib/jpegli/destination_manager.cc
index 9bc269f0c9..6548130866 100644
--- a/third_party/jpeg-xl/lib/jpegli/destination_manager.cc
+++ b/third_party/jpeg-xl/lib/jpegli/destination_manager.cc
@@ -19,13 +19,13 @@ struct StdioDestinationManager {
uint8_t* buffer;
static void init_destination(j_compress_ptr cinfo) {
- auto dest = reinterpret_cast<StdioDestinationManager*>(cinfo->dest);
+ auto* dest = reinterpret_cast<StdioDestinationManager*>(cinfo->dest);
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = kDestBufferSize;
}
static boolean empty_output_buffer(j_compress_ptr cinfo) {
- auto dest = reinterpret_cast<StdioDestinationManager*>(cinfo->dest);
+ auto* dest = reinterpret_cast<StdioDestinationManager*>(cinfo->dest);
if (fwrite(dest->buffer, 1, kDestBufferSize, dest->f) != kDestBufferSize) {
JPEGLI_ERROR("Failed to write to output stream.");
}
@@ -35,7 +35,7 @@ struct StdioDestinationManager {
}
static void term_destination(j_compress_ptr cinfo) {
- auto dest = reinterpret_cast<StdioDestinationManager*>(cinfo->dest);
+ auto* dest = reinterpret_cast<StdioDestinationManager*>(cinfo->dest);
size_t bytes_left = kDestBufferSize - dest->pub.free_in_buffer;
if (bytes_left &&
fwrite(dest->buffer, 1, bytes_left, dest->f) != bytes_left) {
@@ -62,7 +62,7 @@ struct MemoryDestinationManager {
static void init_destination(j_compress_ptr cinfo) {}
static boolean empty_output_buffer(j_compress_ptr cinfo) {
- auto dest = reinterpret_cast<MemoryDestinationManager*>(cinfo->dest);
+ auto* dest = reinterpret_cast<MemoryDestinationManager*>(cinfo->dest);
uint8_t* next_buffer =
reinterpret_cast<uint8_t*>(malloc(dest->buffer_size * 2));
memcpy(next_buffer, dest->current_buffer, dest->buffer_size);
@@ -80,7 +80,7 @@ struct MemoryDestinationManager {
}
static void term_destination(j_compress_ptr cinfo) {
- auto dest = reinterpret_cast<MemoryDestinationManager*>(cinfo->dest);
+ auto* dest = reinterpret_cast<MemoryDestinationManager*>(cinfo->dest);
*dest->output_size = dest->buffer_size - dest->pub.free_in_buffer;
}
};
@@ -99,7 +99,7 @@ void jpegli_stdio_dest(j_compress_ptr cinfo, FILE* outfile) {
cinfo->dest = reinterpret_cast<jpeg_destination_mgr*>(
jpegli::Allocate<jpegli::StdioDestinationManager>(cinfo, 1));
}
- auto dest = reinterpret_cast<jpegli::StdioDestinationManager*>(cinfo->dest);
+ auto* dest = reinterpret_cast<jpegli::StdioDestinationManager*>(cinfo->dest);
dest->f = outfile;
dest->buffer = jpegli::Allocate<uint8_t>(cinfo, jpegli::kDestBufferSize);
dest->pub.next_output_byte = dest->buffer;
@@ -122,11 +122,11 @@ void jpegli_mem_dest(j_compress_ptr cinfo, unsigned char** outbuffer,
JPEGLI_ERROR("jpegli_mem_dest: a different dest manager was already set");
}
if (!cinfo->dest) {
- auto dest = jpegli::Allocate<jpegli::MemoryDestinationManager>(cinfo, 1);
+ auto* dest = jpegli::Allocate<jpegli::MemoryDestinationManager>(cinfo, 1);
dest->temp_buffer = nullptr;
cinfo->dest = reinterpret_cast<jpeg_destination_mgr*>(dest);
}
- auto dest = reinterpret_cast<jpegli::MemoryDestinationManager*>(cinfo->dest);
+ auto* dest = reinterpret_cast<jpegli::MemoryDestinationManager*>(cinfo->dest);
dest->pub.init_destination =
jpegli::MemoryDestinationManager::init_destination;
dest->pub.empty_output_buffer =
diff --git a/third_party/jpeg-xl/lib/jpegli/downsample.cc b/third_party/jpeg-xl/lib/jpegli/downsample.cc
index df2c156972..f1e945d509 100644
--- a/third_party/jpeg-xl/lib/jpegli/downsample.cc
+++ b/third_party/jpeg-xl/lib/jpegli/downsample.cc
@@ -29,7 +29,7 @@ void DownsampleRow2x1(const float* row_in, size_t len, float* row_out) {
const size_t N = Lanes(d);
const size_t len_out = len / 2;
const auto mul = Set(d, 0.5f);
- Vec<D> v0, v1;
+ Vec<D> v0, v1; // NOLINT
for (size_t x = 0; x < len_out; x += N) {
LoadInterleaved2(d, row_in + 2 * x, v0, v1);
Store(Mul(mul, Add(v0, v1)), d, row_out + x);
@@ -40,7 +40,7 @@ void DownsampleRow3x1(const float* row_in, size_t len, float* row_out) {
const size_t N = Lanes(d);
const size_t len_out = len / 3;
const auto mul = Set(d, 1.0f / 3);
- Vec<D> v0, v1, v2;
+ Vec<D> v0, v1, v2; // NOLINT
for (size_t x = 0; x < len_out; x += N) {
LoadInterleaved3(d, row_in + 3 * x, v0, v1, v2);
Store(Mul(mul, Add(Add(v0, v1), v2)), d, row_out + x);
@@ -51,7 +51,7 @@ void DownsampleRow4x1(const float* row_in, size_t len, float* row_out) {
const size_t N = Lanes(d);
const size_t len_out = len / 4;
const auto mul = Set(d, 0.25f);
- Vec<D> v0, v1, v2, v3;
+ Vec<D> v0, v1, v2, v3; // NOLINT
for (size_t x = 0; x < len_out; x += N) {
LoadInterleaved4(d, row_in + 4 * x, v0, v1, v2, v3);
Store(Mul(mul, Add(Add(v0, v1), Add(v2, v3))), d, row_out + x);
@@ -91,7 +91,7 @@ void Downsample2x2(float* rows_in[MAX_SAMP_FACTOR], size_t len,
const auto mul = Set(d, 0.25f);
float* row0 = rows_in[0];
float* row1 = rows_in[1];
- Vec<D> v0, v1, v2, v3;
+ Vec<D> v0, v1, v2, v3; // NOLINT
for (size_t x = 0; x < len_out; x += N) {
LoadInterleaved2(d, row0 + 2 * x, v0, v1);
LoadInterleaved2(d, row1 + 2 * x, v2, v3);
diff --git a/third_party/jpeg-xl/lib/jpegli/encode.cc b/third_party/jpeg-xl/lib/jpegli/encode.cc
index 8a106e239a..5326f2cb0f 100644
--- a/third_party/jpeg-xl/lib/jpegli/encode.cc
+++ b/third_party/jpeg-xl/lib/jpegli/encode.cc
@@ -5,6 +5,8 @@
#include "lib/jpegli/encode.h"
+#include <jxl/types.h>
+
#include <cmath>
#include <initializer_list>
#include <vector>
@@ -323,8 +325,8 @@ void ProcessCompressionParams(j_compress_ptr cinfo) {
if (cinfo->scan_info == nullptr) {
SetDefaultScanScript(cinfo);
}
- cinfo->progressive_mode =
- cinfo->scan_info->Ss != 0 || cinfo->scan_info->Se != DCTSIZE2 - 1;
+ cinfo->progressive_mode = TO_JXL_BOOL(cinfo->scan_info->Ss != 0 ||
+ cinfo->scan_info->Se != DCTSIZE2 - 1);
ValidateScanScript(cinfo);
m->scan_token_info =
Allocate<ScanTokenInfo>(cinfo, cinfo->num_scans, JPOOL_IMAGE);
@@ -449,7 +451,7 @@ void AllocateBuffers(j_compress_ptr cinfo) {
const size_t ysize_blocks = comp->height_in_blocks;
m->coeff_buffers[c] = (*cinfo->mem->request_virt_barray)(
reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE,
- /*pre_zero=*/false, xsize_blocks, ysize_blocks, comp->v_samp_factor);
+ /*pre_zero=*/FALSE, xsize_blocks, ysize_blocks, comp->v_samp_factor);
}
}
if (m->use_adaptive_quantization) {
@@ -663,8 +665,8 @@ void jpegli_CreateCompress(j_compress_ptr cinfo, int version,
cinfo->num_components = 0;
cinfo->jpeg_color_space = JCS_UNKNOWN;
cinfo->comp_info = nullptr;
- for (int i = 0; i < NUM_QUANT_TBLS; ++i) {
- cinfo->quant_tbl_ptrs[i] = nullptr;
+ for (auto& quant_tbl_ptr : cinfo->quant_tbl_ptrs) {
+ quant_tbl_ptr = nullptr;
}
for (int i = 0; i < NUM_HUFF_TBLS; ++i) {
cinfo->dc_huff_tbl_ptrs[i] = nullptr;
@@ -673,7 +675,7 @@ void jpegli_CreateCompress(j_compress_ptr cinfo, int version,
memset(cinfo->arith_dc_L, 0, sizeof(cinfo->arith_dc_L));
memset(cinfo->arith_dc_U, 0, sizeof(cinfo->arith_dc_U));
memset(cinfo->arith_ac_K, 0, sizeof(cinfo->arith_ac_K));
- cinfo->write_Adobe_marker = false;
+ cinfo->write_Adobe_marker = FALSE;
cinfo->master = jpegli::Allocate<jpeg_comp_master>(cinfo, 1);
jpegli::InitializeCompressParams(cinfo);
cinfo->master->force_baseline = true;
@@ -763,7 +765,7 @@ void jpegli_set_colorspace(j_compress_ptr cinfo, J_COLOR_SPACE colorspace) {
JPEGLI_ERROR("Unsupported jpeg colorspace %d", colorspace);
}
// Adobe marker is only needed to distinguish CMYK and YCCK JPEGs.
- cinfo->write_Adobe_marker = (cinfo->jpeg_color_space == JCS_YCCK);
+ cinfo->write_Adobe_marker = TO_JXL_BOOL(cinfo->jpeg_color_space == JCS_YCCK);
if (cinfo->comp_info == nullptr) {
cinfo->comp_info =
jpegli::Allocate<jpeg_component_info>(cinfo, MAX_COMPONENTS);
@@ -810,7 +812,7 @@ void jpegli_set_colorspace(j_compress_ptr cinfo, J_COLOR_SPACE colorspace) {
void jpegli_set_distance(j_compress_ptr cinfo, float distance,
boolean force_baseline) {
CheckState(cinfo, jpegli::kEncStart);
- cinfo->master->force_baseline = force_baseline;
+ cinfo->master->force_baseline = FROM_JXL_BOOL(force_baseline);
float distances[NUM_QUANT_TBLS] = {distance, distance, distance};
jpegli::SetQuantMatrices(cinfo, distances, /*add_two_chroma_tables=*/true);
}
@@ -834,7 +836,7 @@ void jpegli_set_psnr(j_compress_ptr cinfo, float psnr, float tolerance,
void jpegli_set_quality(j_compress_ptr cinfo, int quality,
boolean force_baseline) {
CheckState(cinfo, jpegli::kEncStart);
- cinfo->master->force_baseline = force_baseline;
+ cinfo->master->force_baseline = FROM_JXL_BOOL(force_baseline);
float distance = jpegli_quality_to_distance(quality);
float distances[NUM_QUANT_TBLS] = {distance, distance, distance};
jpegli::SetQuantMatrices(cinfo, distances, /*add_two_chroma_tables=*/false);
@@ -843,7 +845,7 @@ void jpegli_set_quality(j_compress_ptr cinfo, int quality,
void jpegli_set_linear_quality(j_compress_ptr cinfo, int scale_factor,
boolean force_baseline) {
CheckState(cinfo, jpegli::kEncStart);
- cinfo->master->force_baseline = force_baseline;
+ cinfo->master->force_baseline = FROM_JXL_BOOL(force_baseline);
float distance = jpegli::LinearQualityToDistance(scale_factor);
float distances[NUM_QUANT_TBLS] = {distance, distance, distance};
jpegli::SetQuantMatrices(cinfo, distances, /*add_two_chroma_tables=*/false);
@@ -894,7 +896,7 @@ void jpegli_add_quant_table(j_compress_ptr cinfo, int which_tbl,
void jpegli_enable_adaptive_quantization(j_compress_ptr cinfo, boolean value) {
CheckState(cinfo, jpegli::kEncStart);
- cinfo->master->use_adaptive_quantization = value;
+ cinfo->master->use_adaptive_quantization = FROM_JXL_BOOL(value);
}
void jpegli_simple_progression(j_compress_ptr cinfo) {
@@ -955,7 +957,7 @@ void jpegli_copy_critical_parameters(j_decompress_ptr srcinfo,
jpegli_set_colorspace(dstinfo, srcinfo->jpeg_color_space);
if (dstinfo->num_components != srcinfo->num_components) {
const auto& cinfo = dstinfo;
- return JPEGLI_ERROR("Mismatch between src colorspace and components");
+ JPEGLI_ERROR("Mismatch between src colorspace and components");
}
dstinfo->data_precision = srcinfo->data_precision;
dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling;
@@ -1005,7 +1007,7 @@ void jpegli_write_coefficients(j_compress_ptr cinfo,
jvirt_barray_ptr* coef_arrays) {
CheckState(cinfo, jpegli::kEncStart);
cinfo->global_state = jpegli::kEncWriteCoeffs;
- jpegli::InitCompress(cinfo, /*write_all_tables=*/true);
+ jpegli::InitCompress(cinfo, /*write_all_tables=*/TRUE);
cinfo->master->coeff_buffers = coef_arrays;
cinfo->next_scanline = cinfo->image_height;
cinfo->master->next_input_row = cinfo->image_height;
@@ -1047,7 +1049,7 @@ void jpegli_write_m_header(j_compress_ptr cinfo, int marker,
marker_data[1] = marker;
marker_data[2] = (datalen + 2) >> 8;
marker_data[3] = (datalen + 2) & 0xff;
- jpegli::WriteOutput(cinfo, &marker_data[0], 4);
+ jpegli::WriteOutput(cinfo, marker_data.data(), 4);
}
void jpegli_write_m_byte(j_compress_ptr cinfo, int val) {
@@ -1213,7 +1215,8 @@ void jpegli_finish_compress(j_compress_ptr cinfo) {
}
const bool tokens_done = jpegli::IsStreamingSupported(cinfo);
- const bool bitstream_done = tokens_done && !cinfo->optimize_coding;
+ const bool bitstream_done =
+ tokens_done && !FROM_JXL_BOOL(cinfo->optimize_coding);
if (!tokens_done) {
jpegli::TokenizeJpeg(cinfo);
diff --git a/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc b/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc
index 8d53557567..1afdcf610d 100644
--- a/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc
@@ -133,12 +133,11 @@ TEST(EncodeAPITest, ReuseCinfoSameMemOutput) {
jpegli_destroy_compress(&cinfo);
}
size_t pos = 0;
- for (size_t i = 0; i < all_configs.size(); ++i) {
+ for (auto& config : all_configs) {
TestImage output;
- pos +=
- DecodeWithLibjpeg(all_configs[i].jparams, DecompressParams(), nullptr,
- 0, buffer + pos, buffer_size - pos, &output);
- VerifyOutputImage(all_configs[i].input, output, all_configs[i].max_dist);
+ pos += DecodeWithLibjpeg(config.jparams, DecompressParams(), nullptr, 0,
+ buffer + pos, buffer_size - pos, &output);
+ VerifyOutputImage(config.input, output, config.max_dist);
}
if (buffer) free(buffer);
}
@@ -164,20 +163,21 @@ TEST(EncodeAPITest, ReuseCinfoSameStdOutput) {
size_t total_size = ftell(tmpf);
rewind(tmpf);
std::vector<uint8_t> compressed(total_size);
- JXL_CHECK(total_size == fread(&compressed[0], 1, total_size, tmpf));
+ JXL_CHECK(total_size == fread(compressed.data(), 1, total_size, tmpf));
fclose(tmpf);
size_t pos = 0;
- for (size_t i = 0; i < all_configs.size(); ++i) {
+ for (auto& config : all_configs) {
TestImage output;
- pos += DecodeWithLibjpeg(all_configs[i].jparams, DecompressParams(),
- nullptr, 0, &compressed[pos],
- compressed.size() - pos, &output);
- VerifyOutputImage(all_configs[i].input, output, all_configs[i].max_dist);
+ pos +=
+ DecodeWithLibjpeg(config.jparams, DecompressParams(), nullptr, 0,
+ &compressed[pos], compressed.size() - pos, &output);
+ VerifyOutputImage(config.input, output, config.max_dist);
}
}
TEST(EncodeAPITest, ReuseCinfoChangeParams) {
- TestImage input, output;
+ TestImage input;
+ TestImage output;
CompressParams jparams;
DecompressParams dparams;
uint8_t* buffer = nullptr;
diff --git a/third_party/jpeg-xl/lib/jpegli/encode_finish.cc b/third_party/jpeg-xl/lib/jpegli/encode_finish.cc
index 955676bdee..767a6532c5 100644
--- a/third_party/jpeg-xl/lib/jpegli/encode_finish.cc
+++ b/third_party/jpeg-xl/lib/jpegli/encode_finish.cc
@@ -213,6 +213,8 @@ float FindDistanceForPSNR(j_compress_ptr cinfo) {
d = best_distance;
if (sampling == 1 && PSNR_SEARCH_DBG) {
printf("Final PSNR %.2f at distance %.4f\n", best_psnr, d);
+ } else {
+ (void)best_psnr;
}
}
return d;
diff --git a/third_party/jpeg-xl/lib/jpegli/entropy_coding.cc b/third_party/jpeg-xl/lib/jpegli/entropy_coding.cc
index 7e50bbc3a7..515996a43d 100644
--- a/third_party/jpeg-xl/lib/jpegli/entropy_coding.cc
+++ b/third_party/jpeg-xl/lib/jpegli/entropy_coding.cc
@@ -99,10 +99,16 @@ void TokenizeACProgressiveScan(j_compress_ptr cinfo, int scan_index,
TokenArray* ta = &m->token_arrays[m->cur_token_array];
sti->token_offset = m->total_num_tokens + ta->num_tokens;
sti->restarts = Allocate<size_t>(cinfo, num_restarts, JPOOL_IMAGE);
+ const auto emit_eob_run = [&]() {
+ int nbits = jxl::FloorLog2Nonzero<uint32_t>(eob_run);
+ int symbol = nbits << 4u;
+ *m->next_token++ = Token(context, symbol, eob_run & ((1 << nbits) - 1));
+ eob_run = 0;
+ };
for (JDIMENSION by = 0; by < comp->height_in_blocks; ++by) {
JBLOCKARRAY ba = (*cinfo->mem->access_virt_barray)(
reinterpret_cast<j_common_ptr>(cinfo), m->coeff_buffers[comp_idx], by,
- 1, false);
+ 1, FALSE);
// Each coefficient can appear in at most one token, but we have to reserve
// one extra EOBrun token that was rolled over from the previous block-row
// and has to be flushed at the end.
@@ -121,13 +127,7 @@ void TokenizeACProgressiveScan(j_compress_ptr cinfo, int scan_index,
}
for (JDIMENSION bx = 0; bx < comp->width_in_blocks; ++bx) {
if (restart_interval > 0 && restarts_to_go == 0) {
- if (eob_run > 0) {
- int nbits = jxl::FloorLog2Nonzero<uint32_t>(eob_run);
- int symbol = nbits << 4u;
- *m->next_token++ =
- Token(context, symbol, eob_run & ((1 << nbits) - 1));
- eob_run = 0;
- }
+ if (eob_run > 0) emit_eob_run();
ta->num_tokens = m->next_token - ta->tokens;
sti->restarts[restart_idx++] = m->total_num_tokens + ta->num_tokens;
restarts_to_go = restart_interval;
@@ -139,7 +139,8 @@ void TokenizeACProgressiveScan(j_compress_ptr cinfo, int scan_index,
int num_nzeros = 0;
int num_future_nzeros = 0;
for (int k = Ss; k <= Se; ++k) {
- if ((temp = block[k]) == 0) {
+ temp = block[k];
+ if (temp == 0) {
r++;
continue;
}
@@ -156,13 +157,7 @@ void TokenizeACProgressiveScan(j_compress_ptr cinfo, int scan_index,
num_future_nzeros++;
continue;
}
- if (eob_run > 0) {
- int nbits = jxl::FloorLog2Nonzero<uint32_t>(eob_run);
- int symbol = nbits << 4u;
- *m->next_token++ =
- Token(context, symbol, eob_run & ((1 << nbits) - 1));
- eob_run = 0;
- }
+ if (eob_run > 0) emit_eob_run();
while (r > 15) {
*m->next_token++ = Token(context, 0xf0, 0);
r -= 16;
@@ -175,13 +170,7 @@ void TokenizeACProgressiveScan(j_compress_ptr cinfo, int scan_index,
}
if (r > 0) {
++eob_run;
- if (eob_run == 0x7FFF) {
- int nbits = jxl::FloorLog2Nonzero<uint32_t>(eob_run);
- int symbol = nbits << 4u;
- *m->next_token++ =
- Token(context, symbol, eob_run & ((1 << nbits) - 1));
- eob_run = 0;
- }
+ if (eob_run == 0x7FFF) emit_eob_run();
}
sti->num_nonzeros += num_nzeros;
sti->num_future_nonzeros += num_future_nzeros;
@@ -190,11 +179,8 @@ void TokenizeACProgressiveScan(j_compress_ptr cinfo, int scan_index,
ta->num_tokens = m->next_token - ta->tokens;
}
if (eob_run > 0) {
- int nbits = jxl::FloorLog2Nonzero<uint32_t>(eob_run);
- int symbol = nbits << 4u;
- *m->next_token++ = Token(context, symbol, eob_run & ((1 << nbits) - 1));
+ emit_eob_run();
++ta->num_tokens;
- eob_run = 0;
}
sti->num_tokens = m->total_num_tokens + ta->num_tokens - sti->token_offset;
sti->restarts[restart_idx++] = m->total_num_tokens + ta->num_tokens;
@@ -229,7 +215,7 @@ void TokenizeACRefinementScan(j_compress_ptr cinfo, int scan_index,
for (JDIMENSION by = 0; by < comp->height_in_blocks; ++by) {
JBLOCKARRAY ba = (*cinfo->mem->access_virt_barray)(
reinterpret_cast<j_common_ptr>(cinfo), m->coeff_buffers[comp_idx], by,
- 1, false);
+ 1, FALSE);
for (JDIMENSION bx = 0; bx < comp->width_in_blocks; ++bx) {
if (restart_interval > 0 && restarts_to_go == 0) {
sti->restarts[restart_idx++] = next_token - sti->tokens;
@@ -337,7 +323,7 @@ void TokenizeScan(j_compress_ptr cinfo, size_t scan_index, int ac_ctx_offset,
// "Non-interleaved" means color data comes in separate scans, in other words
// each scan can contain only one color component.
const bool is_interleaved = (scan_info->comps_in_scan > 1);
- const bool is_progressive = cinfo->progressive_mode;
+ const bool is_progressive = FROM_JXL_BOOL(cinfo->progressive_mode);
const int Ah = scan_info->Ah;
const int Al = scan_info->Al;
HWY_ALIGN constexpr coeff_t kSinkBlock[DCTSIZE2] = {0};
@@ -373,7 +359,7 @@ void TokenizeScan(j_compress_ptr cinfo, size_t scan_index, int ac_ctx_offset,
int max_block_rows = std::min(n_blocks_y, block_rows_left);
ba[i] = (*cinfo->mem->access_virt_barray)(
reinterpret_cast<j_common_ptr>(cinfo), m->coeff_buffers[comp_idx],
- by0, max_block_rows, false);
+ by0, max_block_rows, FALSE);
}
if (!cinfo->progressive_mode) {
int max_tokens_per_mcu_row = MaxNumTokensPerMCURow(cinfo);
@@ -557,7 +543,7 @@ float HistogramCost(const Histogram& histo) {
}
counts[kJpegHuffmanAlphabetSize] = 1;
CreateHuffmanTree(counts.data(), counts.size(), kJpegHuffmanMaxBitLength,
- &depths[0]);
+ depths.data());
size_t header_bits = (1 + kJpegHuffmanMaxBitLength) * 8;
size_t data_bits = 0;
for (size_t i = 0; i < kJpegHuffmanAlphabetSize; ++i) {
@@ -576,8 +562,8 @@ void AddHistograms(const Histogram& a, const Histogram& b, Histogram* c) {
}
bool IsEmptyHistogram(const Histogram& histo) {
- for (size_t i = 0; i < kJpegHuffmanAlphabetSize; ++i) {
- if (histo.count[i]) return false;
+ for (int count : histo.count) {
+ if (count) return false;
}
return true;
}
@@ -668,7 +654,7 @@ void BuildJpegHuffmanTable(const Histogram& histo, JHUFF_TBL* table) {
}
counts[kJpegHuffmanAlphabetSize] = 1;
CreateHuffmanTree(counts.data(), counts.size(), kJpegHuffmanMaxBitLength,
- &depths[0]);
+ depths.data());
memset(table, 0, sizeof(JHUFF_TBL));
for (size_t i = 0; i < kJpegHuffmanAlphabetSize; ++i) {
if (depths[i] > 0) {
@@ -726,7 +712,7 @@ void OptimizeHuffmanCodes(j_compress_ptr cinfo) {
jpeg_comp_master* m = cinfo->master;
// Build DC and AC histograms.
std::vector<Histogram> histograms(m->num_contexts);
- BuildHistograms(cinfo, &histograms[0]);
+ BuildHistograms(cinfo, histograms.data());
// Cluster DC histograms.
JpegClusteredHistograms dc_clusters;
@@ -760,7 +746,7 @@ void OptimizeHuffmanCodes(j_compress_ptr cinfo) {
m->context_map = Allocate<uint8_t>(cinfo, m->num_contexts, JPOOL_IMAGE);
memset(m->context_map, 0, m->num_contexts);
for (size_t i = 0; i < m->num_contexts; ++i) {
- if (i < (size_t)cinfo->num_components) {
+ if (i < static_cast<size_t>(cinfo->num_components)) {
m->context_map[i] = dc_clusters.histogram_indexes[i];
} else if (i >= 4) {
m->context_map[i] = num_dc_huff + ac_clusters.histogram_indexes[i - 4];
diff --git a/third_party/jpeg-xl/lib/jpegli/error.h b/third_party/jpeg-xl/lib/jpegli/error.h
index 4451abd416..5f266baee1 100644
--- a/third_party/jpeg-xl/lib/jpegli/error.h
+++ b/third_party/jpeg-xl/lib/jpegli/error.h
@@ -10,6 +10,7 @@
#include <stdint.h>
#include "lib/jpegli/common.h"
+#include "lib/jxl/base/status.h"
namespace jpegli {
@@ -17,10 +18,12 @@ bool FormatString(char* buffer, const char* format, ...);
} // namespace jpegli
+// `error_exit` should be no-return; but let's add some guarantees on our side.
#define JPEGLI_ERROR(format, ...) \
jpegli::FormatString(cinfo->err->msg_parm.s, ("%s:%d: " format), __FILE__, \
__LINE__, ##__VA_ARGS__), \
- (*cinfo->err->error_exit)(reinterpret_cast<j_common_ptr>(cinfo))
+ (*cinfo->err->error_exit)(reinterpret_cast<j_common_ptr>(cinfo)), \
+ (void)jxl::Abort()
#define JPEGLI_WARN(format, ...) \
jpegli::FormatString(cinfo->err->msg_parm.s, ("%s:%d: " format), __FILE__, \
diff --git a/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc b/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc
index 0d481c572a..3eaf6a313b 100644
--- a/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc
@@ -241,9 +241,10 @@ TEST(EncoderErrorHandlingTest, InvalidQuantValue) {
cinfo.image_height = 1;
cinfo.input_components = 1;
jpegli_set_defaults(&cinfo);
- cinfo.quant_tbl_ptrs[0] = jpegli_alloc_quant_table((j_common_ptr)&cinfo);
- for (size_t k = 0; k < DCTSIZE2; ++k) {
- cinfo.quant_tbl_ptrs[0]->quantval[k] = 0;
+ cinfo.quant_tbl_ptrs[0] =
+ jpegli_alloc_quant_table(reinterpret_cast<j_common_ptr>(&cinfo));
+ for (UINT16& q : cinfo.quant_tbl_ptrs[0]->quantval) {
+ q = 0;
}
jpegli_start_compress(&cinfo, TRUE);
JSAMPLE image[1] = {0};
@@ -992,7 +993,7 @@ TEST(EncoderErrorHandlingTest, AddOnTableNoStringParam) {
jpegli_destroy_compress(&cinfo);
}
-static const uint8_t kCompressed0[] = {
+const uint8_t kCompressed0[] = {
// SOI
0xff, 0xd8, //
// DQT
@@ -1036,12 +1037,12 @@ static const uint8_t kCompressed0[] = {
// EOI
0xff, 0xd9, //
};
-static const size_t kLen0 = sizeof(kCompressed0);
+const size_t kLen0 = sizeof(kCompressed0);
-static const size_t kDQTOffset = 2;
-static const size_t kSOFOffset = 71;
-static const size_t kDHTOffset = 84;
-static const size_t kSOSOffset = 296;
+const size_t kDQTOffset = 2;
+const size_t kSOFOffset = 71;
+const size_t kDHTOffset = 84;
+const size_t kSOSOffset = 296;
TEST(DecoderErrorHandlingTest, MinimalSuccess) {
JXL_CHECK(kCompressed0[kDQTOffset] == 0xff);
@@ -1130,7 +1131,7 @@ TEST(DecoderErrorHandlingTest, NoReadScanlines) {
jpegli_destroy_decompress(&cinfo);
}
-static const size_t kMaxImageWidth = 0xffff;
+const size_t kMaxImageWidth = 0xffff;
JSAMPLE kOutputBuffer[MAX_COMPONENTS * kMaxImageWidth];
bool ParseCompressed(const std::vector<uint8_t>& compressed) {
diff --git a/third_party/jpeg-xl/lib/jpegli/huffman.cc b/third_party/jpeg-xl/lib/jpegli/huffman.cc
index 1cf88a5536..5391030213 100644
--- a/third_party/jpeg-xl/lib/jpegli/huffman.cc
+++ b/third_party/jpeg-xl/lib/jpegli/huffman.cc
@@ -183,7 +183,8 @@ void CreateHuffmanTree(const uint32_t* data, const size_t length,
size_t i = 0; // Points to the next leaf node.
size_t j = n + 1; // Points to the next non-leaf node.
for (size_t k = n - 1; k != 0; --k) {
- size_t left, right;
+ size_t left;
+ size_t right;
if (tree[i].total_count <= tree[j].total_count) {
left = i;
++i;
@@ -210,7 +211,7 @@ void CreateHuffmanTree(const uint32_t* data, const size_t length,
tree.push_back(sentinel);
}
JXL_DASSERT(tree.size() == 2 * n + 1);
- SetDepth(tree[2 * n - 1], &tree[0], depth, 0);
+ SetDepth(tree[2 * n - 1], tree.data(), depth, 0);
// We need to pack the Huffman tree in tree_limit bits.
// If this was not successful, add fake entities to the lowest values
diff --git a/third_party/jpeg-xl/lib/jpegli/idct.cc b/third_party/jpeg-xl/lib/jpegli/idct.cc
index 4d10563583..9859e8ef85 100644
--- a/third_party/jpeg-xl/lib/jpegli/idct.cc
+++ b/third_party/jpeg-xl/lib/jpegli/idct.cc
@@ -197,7 +197,7 @@ void InverseTransformBlock8x8(const int16_t* JXL_RESTRICT qblock,
// Computes the N-point IDCT of in[], and stores the result in out[]. The in[]
// array is at most 8 values long, values in[8:N-1] are assumed to be 0.
-void Compute1dIDCT(float* in, float* out, size_t N) {
+void Compute1dIDCT(const float* in, float* out, size_t N) {
switch (N) {
case 3: {
static constexpr float kC3[3] = {
@@ -608,6 +608,9 @@ void Compute1dIDCT(float* in, float* out, size_t N) {
out[8] = even7 - odd7;
break;
}
+ default:
+ JXL_ABORT("Compute1dIDCT does not support N=%d", static_cast<int>(N));
+ break;
}
}
diff --git a/third_party/jpeg-xl/lib/jpegli/input.cc b/third_party/jpeg-xl/lib/jpegli/input.cc
index 765bf98946..16299477f7 100644
--- a/third_party/jpeg-xl/lib/jpegli/input.cc
+++ b/third_party/jpeg-xl/lib/jpegli/input.cc
@@ -89,7 +89,7 @@ void ReadUint8RowInterleaved2(const uint8_t* row_in, size_t len,
const size_t simd_len = len & (~(N - 1));
float* JXL_RESTRICT const row0 = row_out[0];
float* JXL_RESTRICT const row1 = row_out[1];
- Vec<DU8> out0, out1;
+ Vec<DU8> out0, out1; // NOLINT
for (size_t x = 0; x < simd_len; x += N) {
LoadInterleaved2(du8, row_in + 2 * x, out0, out1);
Store(ConvertTo(d, PromoteTo(du, out0)), d, row0 + x);
@@ -105,7 +105,7 @@ void ReadUint8RowInterleaved3(const uint8_t* row_in, size_t len,
float* JXL_RESTRICT const row0 = row_out[0];
float* JXL_RESTRICT const row1 = row_out[1];
float* JXL_RESTRICT const row2 = row_out[2];
- Vec<DU8> out0, out1, out2;
+ Vec<DU8> out0, out1, out2; // NOLINT
for (size_t x = 0; x < simd_len; x += N) {
LoadInterleaved3(du8, row_in + 3 * x, out0, out1, out2);
Store(ConvertTo(d, PromoteTo(du, out0)), d, row0 + x);
@@ -123,7 +123,7 @@ void ReadUint8RowInterleaved4(const uint8_t* row_in, size_t len,
float* JXL_RESTRICT const row1 = row_out[1];
float* JXL_RESTRICT const row2 = row_out[2];
float* JXL_RESTRICT const row3 = row_out[3];
- Vec<DU8> out0, out1, out2, out3;
+ Vec<DU8> out0, out1, out2, out3; // NOLINT
for (size_t x = 0; x < simd_len; x += N) {
LoadInterleaved4(du8, row_in + 4 * x, out0, out1, out2, out3);
Store(ConvertTo(d, PromoteTo(du, out0)), d, row0 + x);
@@ -158,7 +158,7 @@ void ReadUint16RowInterleaved2(const uint8_t* row_in, size_t len,
reinterpret_cast<const uint16_t*>(row_in);
float* JXL_RESTRICT const row0 = row_out[0];
float* JXL_RESTRICT const row1 = row_out[1];
- Vec<DU16> out0, out1;
+ Vec<DU16> out0, out1; // NOLINT
for (size_t x = 0; x < simd_len; x += N) {
LoadInterleaved2(du16, row + 2 * x, out0, out1);
Store(Mul(mul, ConvertTo(d, PromoteTo(du, out0))), d, row0 + x);
@@ -177,7 +177,7 @@ void ReadUint16RowInterleaved3(const uint8_t* row_in, size_t len,
float* JXL_RESTRICT const row0 = row_out[0];
float* JXL_RESTRICT const row1 = row_out[1];
float* JXL_RESTRICT const row2 = row_out[2];
- Vec<DU16> out0, out1, out2;
+ Vec<DU16> out0, out1, out2; // NOLINT
for (size_t x = 0; x < simd_len; x += N) {
LoadInterleaved3(du16, row + 3 * x, out0, out1, out2);
Store(Mul(mul, ConvertTo(d, PromoteTo(du, out0))), d, row0 + x);
@@ -198,7 +198,7 @@ void ReadUint16RowInterleaved4(const uint8_t* row_in, size_t len,
float* JXL_RESTRICT const row1 = row_out[1];
float* JXL_RESTRICT const row2 = row_out[2];
float* JXL_RESTRICT const row3 = row_out[3];
- Vec<DU16> out0, out1, out2, out3;
+ Vec<DU16> out0, out1, out2, out3; // NOLINT
for (size_t x = 0; x < simd_len; x += N) {
LoadInterleaved4(du16, row + 4 * x, out0, out1, out2, out3);
Store(Mul(mul, ConvertTo(d, PromoteTo(du, out0))), d, row0 + x);
@@ -250,7 +250,7 @@ void ReadFloatRowInterleaved2(const uint8_t* row_in, size_t len,
const float* JXL_RESTRICT const row = reinterpret_cast<const float*>(row_in);
float* JXL_RESTRICT const row0 = row_out[0];
float* JXL_RESTRICT const row1 = row_out[1];
- Vec<D> out0, out1;
+ Vec<D> out0, out1; // NOLINT
for (size_t x = 0; x < simd_len; x += N) {
LoadInterleaved2(d, row + 2 * x, out0, out1);
Store(Mul(mul, out0), d, row0 + x);
@@ -268,7 +268,7 @@ void ReadFloatRowInterleaved3(const uint8_t* row_in, size_t len,
float* JXL_RESTRICT const row0 = row_out[0];
float* JXL_RESTRICT const row1 = row_out[1];
float* JXL_RESTRICT const row2 = row_out[2];
- Vec<D> out0, out1, out2;
+ Vec<D> out0, out1, out2; // NOLINT
for (size_t x = 0; x < simd_len; x += N) {
LoadInterleaved3(d, row + 3 * x, out0, out1, out2);
Store(Mul(mul, out0), d, row0 + x);
@@ -288,7 +288,7 @@ void ReadFloatRowInterleaved4(const uint8_t* row_in, size_t len,
float* JXL_RESTRICT const row1 = row_out[1];
float* JXL_RESTRICT const row2 = row_out[2];
float* JXL_RESTRICT const row3 = row_out[3];
- Vec<D> out0, out1, out2, out3;
+ Vec<D> out0, out1, out2, out3; // NOLINT
for (size_t x = 0; x < simd_len; x += N) {
LoadInterleaved4(d, row + 4 * x, out0, out1, out2, out3);
Store(Mul(mul, out0), d, row0 + x);
diff --git a/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc b/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc
index 09bafd9188..eb8b7ebc26 100644
--- a/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc
@@ -17,7 +17,7 @@
namespace jpegli {
namespace {
-static constexpr uint8_t kFakeEoiMarker[2] = {0xff, 0xd9};
+constexpr uint8_t kFakeEoiMarker[2] = {0xff, 0xd9};
struct SourceManager {
SourceManager(const uint8_t* data, size_t len, size_t max_chunk_size,
@@ -50,14 +50,14 @@ struct SourceManager {
}
if (pub_.bytes_in_buffer > 0) {
EXPECT_LE(pub_.bytes_in_buffer, buffer_.size());
- memmove(&buffer_[0], pub_.next_input_byte, pub_.bytes_in_buffer);
+ memmove(buffer_.data(), pub_.next_input_byte, pub_.bytes_in_buffer);
}
size_t chunk_size =
pos_ < len_ ? std::min(len_ - pos_, max_chunk_size_) : 2;
buffer_.resize(pub_.bytes_in_buffer + chunk_size);
memcpy(&buffer_[pub_.bytes_in_buffer],
pos_ < len_ ? data_ + pos_ : kFakeEoiMarker, chunk_size);
- pub_.next_input_byte = &buffer_[0];
+ pub_.next_input_byte = buffer_.data();
pub_.bytes_in_buffer += chunk_size;
pos_ += chunk_size;
return true;
@@ -73,7 +73,7 @@ struct SourceManager {
bool is_partial_file_;
static void init_source(j_decompress_ptr cinfo) {
- auto src = reinterpret_cast<SourceManager*>(cinfo->src);
+ auto* src = reinterpret_cast<SourceManager*>(cinfo->src);
src->pub_.next_input_byte = nullptr;
src->pub_.bytes_in_buffer = 0;
}
@@ -81,7 +81,7 @@ struct SourceManager {
static boolean fill_input_buffer(j_decompress_ptr cinfo) { return FALSE; }
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
- auto src = reinterpret_cast<SourceManager*>(cinfo->src);
+ auto* src = reinterpret_cast<SourceManager*>(cinfo->src);
if (num_bytes <= 0) {
return;
}
@@ -156,10 +156,10 @@ void ReadOutputImage(const DecompressParams& dparams, j_decompress_ptr cinfo,
rowdata[c][i] =
y0 + i < ysize ? &output->raw_data[c][(y0 + i) * xsize] : nullptr;
}
- data[c] = &rowdata[c][0];
+ data[c] = rowdata[c].data();
}
while ((num_output_lines =
- jpegli_read_raw_data(cinfo, &data[0], max_lines)) == 0) {
+ jpegli_read_raw_data(cinfo, data.data(), max_lines)) == 0) {
JXL_CHECK(src && src->LoadNextChunk());
}
} else {
@@ -173,7 +173,7 @@ void ReadOutputImage(const DecompressParams& dparams, j_decompress_ptr cinfo,
size_t yidx = cinfo->output_scanline + i;
scanlines[i] = &output->pixels[yidx * stride];
}
- while ((num_output_lines = jpegli_read_scanlines(cinfo, &scanlines[0],
+ while ((num_output_lines = jpegli_read_scanlines(cinfo, scanlines.data(),
max_lines)) == 0) {
JXL_CHECK(src && src->LoadNextChunk());
}
@@ -197,7 +197,7 @@ struct TestConfig {
std::vector<uint8_t> GetTestJpegData(TestConfig& config) {
if (!config.fn.empty()) {
- return ReadTestData(config.fn.c_str());
+ return ReadTestData(config.fn);
}
GeneratePixels(&config.input);
std::vector<uint8_t> compressed;
@@ -249,7 +249,7 @@ TEST_P(InputSuspensionTestParam, InputOutputLockStepNonBuffered) {
EXPECT_EQ(0, memcmp(markers_seen, kMarkerSequence, num_markers_seen));
}
VerifyHeader(config.jparams, &cinfo);
- cinfo.raw_data_out = dparams.output_mode == RAW_DATA;
+ cinfo.raw_data_out = TO_JXL_BOOL(dparams.output_mode == RAW_DATA);
if (dparams.output_mode == COEFFICIENTS) {
jvirt_barray_ptr* coef_arrays;
@@ -303,7 +303,7 @@ TEST_P(InputSuspensionTestParam, InputOutputLockStepBuffered) {
jpegli_set_output_format(&cinfo, dparams.data_type, dparams.endianness);
cinfo.buffered_image = TRUE;
- cinfo.raw_data_out = dparams.output_mode == RAW_DATA;
+ cinfo.raw_data_out = TO_JXL_BOOL(dparams.output_mode == RAW_DATA);
EXPECT_TRUE(jpegli_start_decompress(&cinfo));
EXPECT_FALSE(jpegli_input_complete(&cinfo));
@@ -380,8 +380,8 @@ TEST_P(InputSuspensionTestParam, PreConsumeInputBuffered) {
}
EXPECT_EQ(JPEG_REACHED_SOS, jpegli_consume_input(&cinfo));
cinfo.buffered_image = TRUE;
- cinfo.raw_data_out = dparams.output_mode == RAW_DATA;
- cinfo.do_block_smoothing = dparams.do_block_smoothing;
+ cinfo.raw_data_out = TO_JXL_BOOL(dparams.output_mode == RAW_DATA);
+ cinfo.do_block_smoothing = TO_JXL_BOOL(dparams.do_block_smoothing);
EXPECT_TRUE(jpegli_start_decompress(&cinfo));
EXPECT_FALSE(jpegli_input_complete(&cinfo));
@@ -446,8 +446,8 @@ TEST_P(InputSuspensionTestParam, PreConsumeInputNonBuffered) {
}
}
EXPECT_EQ(JPEG_REACHED_SOS, jpegli_consume_input(&cinfo));
- cinfo.raw_data_out = dparams.output_mode == RAW_DATA;
- cinfo.do_block_smoothing = dparams.do_block_smoothing;
+ cinfo.raw_data_out = TO_JXL_BOOL(dparams.output_mode == RAW_DATA);
+ cinfo.do_block_smoothing = TO_JXL_BOOL(dparams.do_block_smoothing);
if (dparams.output_mode == COEFFICIENTS) {
jpegli_read_coefficients(&cinfo);
diff --git a/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc b/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc
index de2303756e..020adf5e9e 100644
--- a/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc
+++ b/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc
@@ -37,12 +37,13 @@ void ReadOutputPass(j_decompress_ptr cinfo, const DecompressParams& dparams,
output->ysize = ysize_cropped;
output->components = cinfo->out_color_components;
if (cinfo->quantize_colors) {
- jxl::msan::UnpoisonMemory(cinfo->colormap, cinfo->out_color_components *
- sizeof(cinfo->colormap[0]));
+ JSAMPLE** colormap = cinfo->colormap;
+ jxl::msan::UnpoisonMemory(reinterpret_cast<void*>(colormap),
+ cinfo->out_color_components * sizeof(JSAMPLE*));
for (int c = 0; c < cinfo->out_color_components; ++c) {
jxl::msan::UnpoisonMemory(
- cinfo->colormap[c],
- cinfo->actual_number_of_colors * sizeof(cinfo->colormap[c][0]));
+ reinterpret_cast<void*>(colormap[c]),
+ cinfo->actual_number_of_colors * sizeof(JSAMPLE));
}
}
if (!cinfo->raw_data_out) {
@@ -89,10 +90,10 @@ void ReadOutputPass(j_decompress_ptr cinfo, const DecompressParams& dparams,
rowdata[c][i] =
y0 + i < ysize ? &output->raw_data[c][(y0 + i) * xsize] : nullptr;
}
- data[c] = &rowdata[c][0];
+ data[c] = rowdata[c].data();
}
JXL_CHECK(iMCU_height ==
- jpeg_read_raw_data(cinfo, &data[0], iMCU_height));
+ jpeg_read_raw_data(cinfo, data.data(), iMCU_height));
}
}
JXL_CHECK(cinfo->total_iMCU_rows ==
@@ -113,7 +114,7 @@ void DecodeWithLibjpeg(const CompressParams& jparams,
jpeg_read_header(cinfo, /*require_image=*/TRUE));
if (!jparams.icc.empty()) {
uint8_t* icc_data = nullptr;
- unsigned int icc_len;
+ unsigned int icc_len = 0; // "unpoison" via initialization
JXL_CHECK(jpeg_read_icc_profile(cinfo, &icc_data, &icc_len));
JXL_CHECK(icc_data);
jxl::msan::UnpoisonMemory(icc_data, icc_len);
diff --git a/third_party/jpeg-xl/lib/jpegli/libjpeg_wrapper.cc b/third_party/jpeg-xl/lib/jpegli/libjpeg_wrapper.cc
index b38d16f255..471b7c7192 100644
--- a/third_party/jpeg-xl/lib/jpegli/libjpeg_wrapper.cc
+++ b/third_party/jpeg-xl/lib/jpegli/libjpeg_wrapper.cc
@@ -122,11 +122,11 @@ boolean jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr,
}
void jpeg_abort_decompress(j_decompress_ptr cinfo) {
- return jpegli_abort_decompress(cinfo);
+ jpegli_abort_decompress(cinfo);
}
void jpeg_destroy_decompress(j_decompress_ptr cinfo) {
- return jpegli_destroy_decompress(cinfo);
+ jpegli_destroy_decompress(cinfo);
}
void jpeg_CreateCompress(j_compress_ptr cinfo, int version, size_t structsize) {
diff --git a/third_party/jpeg-xl/lib/jpegli/memory_manager.h b/third_party/jpeg-xl/lib/jpegli/memory_manager.h
index 3e2bdabe06..c650caad49 100644
--- a/third_party/jpeg-xl/lib/jpegli/memory_manager.h
+++ b/third_party/jpeg-xl/lib/jpegli/memory_manager.h
@@ -19,7 +19,8 @@ void InitMemoryManager(j_common_ptr cinfo);
template <typename T>
T* Allocate(j_common_ptr cinfo, size_t len, int pool_id = JPOOL_PERMANENT) {
- void* p = (*cinfo->mem->alloc_small)(cinfo, pool_id, len * sizeof(T));
+ const size_t size = len * sizeof(T); // NOLINT
+ void* p = (*cinfo->mem->alloc_small)(cinfo, pool_id, size);
return reinterpret_cast<T*>(p);
}
diff --git a/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc b/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc
index 73db791727..3cb2fd3ee4 100644
--- a/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc
@@ -10,8 +10,8 @@
namespace jpegli {
namespace {
-static constexpr size_t kInitialBufferSize = 1024;
-static constexpr size_t kFinalBufferSize = 18;
+constexpr size_t kInitialBufferSize = 1024;
+constexpr size_t kFinalBufferSize = 18;
struct DestinationManager {
jpeg_destination_mgr pub;
@@ -37,7 +37,7 @@ struct DestinationManager {
}
static void init_destination(j_compress_ptr cinfo) {
- auto us = reinterpret_cast<DestinationManager*>(cinfo->dest);
+ auto* us = reinterpret_cast<DestinationManager*>(cinfo->dest);
us->buffer.resize(kInitialBufferSize);
us->Rewind();
}
@@ -84,7 +84,7 @@ TEST_P(OutputSuspensionTestParam, PixelData) {
while (cinfo.next_scanline < cinfo.image_height) {
size_t lines_left = cinfo.image_height - cinfo.next_scanline;
size_t num_lines = std::min(config.lines_batch_size, lines_left);
- memcpy(&row_bytes[0], &input.pixels[cinfo.next_scanline * stride],
+ memcpy(row_bytes.data(), &input.pixels[cinfo.next_scanline * stride],
num_lines * stride);
std::vector<JSAMPROW> rows(num_lines);
for (size_t i = 0; i < num_lines; ++i) {
@@ -142,7 +142,7 @@ TEST_P(OutputSuspensionTestParam, RawData) {
std::vector<JSAMPARRAY> data(cinfo.num_components);
for (int c = 0; c < cinfo.num_components; ++c) {
rowdata[c].resize(config.jparams.v_samp(c) * DCTSIZE);
- data[c] = &rowdata[c][0];
+ data[c] = rowdata[c].data();
}
while (cinfo.next_scanline < cinfo.image_height) {
for (int c = 0; c < cinfo.num_components; ++c) {
@@ -155,7 +155,7 @@ TEST_P(OutputSuspensionTestParam, RawData) {
(y0 + i < cheight ? &raw_data[c][(y0 + i) * cwidth] : nullptr);
}
}
- while (jpegli_write_raw_data(&cinfo, &data[0], max_lines) == 0) {
+ while (jpegli_write_raw_data(&cinfo, data.data(), max_lines) == 0) {
dest.EmptyTo(&compressed, config.buffer_size);
}
}
diff --git a/third_party/jpeg-xl/lib/jpegli/quant.cc b/third_party/jpeg-xl/lib/jpegli/quant.cc
index 36f1df4cdd..14db6701b2 100644
--- a/third_party/jpeg-xl/lib/jpegli/quant.cc
+++ b/third_party/jpeg-xl/lib/jpegli/quant.cc
@@ -26,7 +26,7 @@ namespace {
constexpr float kGlobalScaleXYB = 1.43951668f;
constexpr float kGlobalScaleYCbCr = 1.73966010f;
-static constexpr float kBaseQuantMatrixXYB[] = {
+constexpr float kBaseQuantMatrixXYB[] = {
// c = 0
7.5629935265f,
19.8247814178f,
@@ -224,7 +224,7 @@ static constexpr float kBaseQuantMatrixXYB[] = {
63.6065597534f,
};
-static const float kBaseQuantMatrixYCbCr[] = {
+const float kBaseQuantMatrixYCbCr[] = {
// c = 0
1.2397409345866273f, //
1.7227115097630963f, //
@@ -422,8 +422,8 @@ static const float kBaseQuantMatrixYCbCr[] = {
114.89202448569779f, //
};
-static const float k420GlobalScale = 1.22;
-static const float k420Rescale[64] = {
+const float k420GlobalScale = 1.22;
+const float k420Rescale[64] = {
0.4093, 0.3209, 0.3477, 0.3333, 0.3144, 0.2823, 0.3214, 0.3354, //
0.3209, 0.3111, 0.3489, 0.2801, 0.3059, 0.3119, 0.4135, 0.3445, //
0.3477, 0.3489, 0.3586, 0.3257, 0.2727, 0.3754, 0.3369, 0.3484, //
@@ -434,7 +434,7 @@ static const float k420Rescale[64] = {
0.3354, 0.3445, 0.3484, 0.3839, 0.3836, 0.0726, 0.0553, 0.3368, //
};
-static const float kBaseQuantMatrixStd[] = {
+const float kBaseQuantMatrixStd[] = {
// c = 0
16.0f, 11.0f, 10.0f, 16.0f, 24.0f, 40.0f, 51.0f, 61.0f, //
12.0f, 12.0f, 14.0f, 19.0f, 26.0f, 58.0f, 60.0f, 55.0f, //
@@ -455,7 +455,7 @@ static const float kBaseQuantMatrixStd[] = {
99.0f, 99.0f, 99.0f, 99.0f, 99.0f, 99.0f, 99.0f, 99.0f, //
};
-static const float kZeroBiasMulYCbCrLQ[] = {
+const float kZeroBiasMulYCbCrLQ[] = {
// c = 0
0.0000f, 0.0568f, 0.3880f, 0.6190f, 0.6190f, 0.4490f, 0.4490f, 0.6187f, //
0.0568f, 0.5829f, 0.6189f, 0.6190f, 0.6190f, 0.7190f, 0.6190f, 0.6189f, //
@@ -485,7 +485,7 @@ static const float kZeroBiasMulYCbCrLQ[] = {
0.2960f, 0.2113f, 0.2426f, 0.1590f, 0.5403f, 0.3060f, 0.3060f, 0.3060f, //
};
-static const float kZeroBiasMulYCbCrHQ[] = {
+const float kZeroBiasMulYCbCrHQ[] = {
// c = 0
0.0000f, 0.0044f, 0.2521f, 0.6547f, 0.8161f, 0.6130f, 0.8841f, 0.8155f, //
0.0044f, 0.6831f, 0.6553f, 0.6295f, 0.7848f, 0.7843f, 0.8474f, 0.7836f, //
@@ -515,9 +515,9 @@ static const float kZeroBiasMulYCbCrHQ[] = {
0.4836f, 0.4897f, 0.2583f, 0.3565f, 0.5949f, 0.6629f, 0.6644f, 0.6644f, //
};
-static const float kZeroBiasOffsetYCbCrDC[] = {0.0f, 0.0f, 0.0f};
+const float kZeroBiasOffsetYCbCrDC[] = {0.0f, 0.0f, 0.0f};
-static const float kZeroBiasOffsetYCbCrAC[] = {
+const float kZeroBiasOffsetYCbCrAC[] = {
0.59082f,
0.58146f,
0.57988f,
diff --git a/third_party/jpeg-xl/lib/jpegli/render.cc b/third_party/jpeg-xl/lib/jpegli/render.cc
index 24e7e99618..c550f9a575 100644
--- a/third_party/jpeg-xl/lib/jpegli/render.cc
+++ b/third_party/jpeg-xl/lib/jpegli/render.cc
@@ -8,7 +8,6 @@
#include <string.h>
#include <array>
-#include <atomic>
#include <cmath>
#include <cstddef>
#include <cstdint>
@@ -203,12 +202,13 @@ void WriteToOutput(j_decompress_ptr cinfo, float* JXL_RESTRICT rows[],
if (cinfo->quantize_colors && m->quant_pass_ == 1) {
float* error_row[kMaxComponents];
float* next_error_row[kMaxComponents];
- if (cinfo->dither_mode == JDITHER_ORDERED) {
+ J_DITHER_MODE dither_mode = cinfo->dither_mode;
+ if (dither_mode == JDITHER_ORDERED) {
for (size_t c = 0; c < num_channels; ++c) {
DitherRow(cinfo, &rows[c][xoffset], c, cinfo->output_scanline,
cinfo->output_width);
}
- } else if (cinfo->dither_mode == JDITHER_FS) {
+ } else if (dither_mode == JDITHER_FS) {
for (size_t c = 0; c < num_channels; ++c) {
if (cinfo->output_scanline % 2 == 0) {
error_row[c] = m->error_row_[c];
@@ -221,12 +221,12 @@ void WriteToOutput(j_decompress_ptr cinfo, float* JXL_RESTRICT rows[],
}
}
const float mul = 255.0f;
- if (cinfo->dither_mode != JDITHER_FS) {
+ if (dither_mode != JDITHER_FS) {
StoreUnsignedRow(rows, xoffset, len, num_channels, mul, scratch_space);
}
for (size_t i = 0; i < len; ++i) {
uint8_t* pixel = &scratch_space[num_channels * i];
- if (cinfo->dither_mode == JDITHER_FS) {
+ if (dither_mode == JDITHER_FS) {
for (size_t c = 0; c < num_channels; ++c) {
float val = rows[c][i] * mul + LimitError(error_row[c][i]);
pixel[c] = std::round(std::min(255.0f, std::max(0.0f, val)));
@@ -234,7 +234,7 @@ void WriteToOutput(j_decompress_ptr cinfo, float* JXL_RESTRICT rows[],
}
int index = LookupColorIndex(cinfo, pixel);
output[i] = index;
- if (cinfo->dither_mode == JDITHER_FS) {
+ if (dither_mode == JDITHER_FS) {
size_t prev_i = i > 0 ? i - 1 : 0;
size_t next_i = i + 1 < len ? i + 1 : len - 1;
for (size_t c = 0; c < num_channels; ++c) {
@@ -293,19 +293,18 @@ HWY_EXPORT(DecenterRow);
void GatherBlockStats(const int16_t* JXL_RESTRICT coeffs,
const size_t coeffs_size, int32_t* JXL_RESTRICT nonzeros,
int32_t* JXL_RESTRICT sumabs) {
- return HWY_DYNAMIC_DISPATCH(GatherBlockStats)(coeffs, coeffs_size, nonzeros,
- sumabs);
+ HWY_DYNAMIC_DISPATCH(GatherBlockStats)(coeffs, coeffs_size, nonzeros, sumabs);
}
void WriteToOutput(j_decompress_ptr cinfo, float* JXL_RESTRICT rows[],
size_t xoffset, size_t len, size_t num_channels,
uint8_t* JXL_RESTRICT output) {
- return HWY_DYNAMIC_DISPATCH(WriteToOutput)(cinfo, rows, xoffset, len,
- num_channels, output);
+ HWY_DYNAMIC_DISPATCH(WriteToOutput)
+ (cinfo, rows, xoffset, len, num_channels, output);
}
void DecenterRow(float* row, size_t xsize) {
- return HWY_DYNAMIC_DISPATCH(DecenterRow)(row, xsize);
+ HWY_DYNAMIC_DISPATCH(DecenterRow)(row, xsize);
}
bool ShouldApplyDequantBiases(j_decompress_ptr cinfo, int ci) {
@@ -360,8 +359,8 @@ bool do_smoothing(j_decompress_ptr cinfo) {
if (!cinfo->progressive_mode || cinfo->coef_bits == nullptr) {
return false;
}
- auto coef_bits_latch = m->coef_bits_latch;
- auto prev_coef_bits_latch = m->prev_coef_bits_latch;
+ auto* coef_bits_latch = m->coef_bits_latch;
+ auto* prev_coef_bits_latch = m->prev_coef_bits_latch;
for (int ci = 0; ci < cinfo->num_components; ci++) {
jpeg_component_info* compptr = &cinfo->comp_info[ci];
@@ -468,6 +467,7 @@ void PredictSmooth(j_decompress_ptr cinfo, JBLOCKARRAY blocks, int component,
return swap_indices ? dc_values[j][i] : dc_values[i][j];
};
Al = coef_bits[coef_index];
+ JXL_ASSERT(coef_index >= 0 && coef_index < 10);
switch (coef_index) {
case 0:
// set the DC
@@ -520,6 +520,7 @@ void PredictSmooth(j_decompress_ptr cinfo, JBLOCKARRAY blocks, int component,
break;
case 7:
case 8:
+ default:
// set Q12 and Q21
num = (dc(1, 1) - 3 * dc(1, 2) + dc(1, 3) - dc(3, 1) + 3 * dc(3, 2) -
dc(3, 3));
@@ -551,7 +552,7 @@ void PredictSmooth(j_decompress_ptr cinfo, JBLOCKARRAY blocks, int component,
void PrepareForOutput(j_decompress_ptr cinfo) {
jpeg_decomp_master* m = cinfo->master;
bool smoothing = do_smoothing(cinfo);
- m->apply_smoothing = smoothing && cinfo->do_block_smoothing;
+ m->apply_smoothing = smoothing && FROM_JXL_BOOL(cinfo->do_block_smoothing);
size_t coeffs_per_block = cinfo->num_components * DCTSIZE2;
memset(m->nonzeros_, 0, coeffs_per_block * sizeof(m->nonzeros_[0]));
memset(m->sumabs_, 0, coeffs_per_block * sizeof(m->sumabs_[0]));
@@ -584,7 +585,7 @@ void DecodeCurrentiMCURow(j_decompress_ptr cinfo) {
int offset = m->streaming_mode_ ? 0 : by0;
ba[c] = (*cinfo->mem->access_virt_barray)(
reinterpret_cast<j_common_ptr>(cinfo), m->coef_arrays[c], offset,
- max_block_rows, false);
+ max_block_rows, FALSE);
}
for (int c = 0; c < cinfo->num_components; ++c) {
size_t k0 = c * DCTSIZE2;
diff --git a/third_party/jpeg-xl/lib/jpegli/source_manager.cc b/third_party/jpeg-xl/lib/jpegli/source_manager.cc
index 0b8e0a5c8c..58adf803b1 100644
--- a/third_party/jpeg-xl/lib/jpegli/source_manager.cc
+++ b/third_party/jpeg-xl/lib/jpegli/source_manager.cc
@@ -39,7 +39,7 @@ struct StdioSourceManager {
uint8_t* buffer;
static boolean fill_input_buffer(j_decompress_ptr cinfo) {
- auto src = reinterpret_cast<StdioSourceManager*>(cinfo->src);
+ auto* src = reinterpret_cast<StdioSourceManager*>(cinfo->src);
size_t num_bytes_read = fread(src->buffer, 1, kStdioBufferSize, src->f);
if (num_bytes_read == 0) {
return EmitFakeEoiMarker(cinfo);
@@ -77,7 +77,7 @@ void jpegli_stdio_src(j_decompress_ptr cinfo, FILE* infile) {
cinfo->src = reinterpret_cast<jpeg_source_mgr*>(
jpegli::Allocate<jpegli::StdioSourceManager>(cinfo, 1));
}
- auto src = reinterpret_cast<jpegli::StdioSourceManager*>(cinfo->src);
+ auto* src = reinterpret_cast<jpegli::StdioSourceManager*>(cinfo->src);
src->f = infile;
src->buffer = jpegli::Allocate<uint8_t>(cinfo, jpegli::kStdioBufferSize);
src->pub.next_input_byte = src->buffer;
diff --git a/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc b/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc
index 4e137876c9..59d12b001b 100644
--- a/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc
@@ -50,7 +50,7 @@ FILE* MemOpen(const std::vector<uint8_t>& data) {
TEST_P(SourceManagerTestParam, TestStdioSourceManager) {
TestConfig config = GetParam();
- std::vector<uint8_t> compressed = ReadTestData(config.fn.c_str());
+ std::vector<uint8_t> compressed = ReadTestData(config.fn);
if (config.dparams.size_factor < 1.0) {
compressed.resize(compressed.size() * config.dparams.size_factor);
}
@@ -77,7 +77,7 @@ TEST_P(SourceManagerTestParam, TestStdioSourceManager) {
TEST_P(SourceManagerTestParam, TestMemSourceManager) {
TestConfig config = GetParam();
- std::vector<uint8_t> compressed = ReadTestData(config.fn.c_str());
+ std::vector<uint8_t> compressed = ReadTestData(config.fn);
if (config.dparams.size_factor < 1.0f) {
compressed.resize(compressed.size() * config.dparams.size_factor);
}
diff --git a/third_party/jpeg-xl/lib/jpegli/streaming_test.cc b/third_party/jpeg-xl/lib/jpegli/streaming_test.cc
index 8d2e3577f3..2e6f7029b0 100644
--- a/third_party/jpeg-xl/lib/jpegli/streaming_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/streaming_test.cc
@@ -36,13 +36,13 @@ struct SourceManager {
// input buffer. The buffer size is kept short because empty_output_buffer() is
// called only when the output buffer is full, and we want to update the decoder
// input frequently to demonstrate that streaming works.
-static constexpr size_t kOutputBufferSize = 1024;
+constexpr size_t kOutputBufferSize = 1024;
struct DestinationManager {
jpeg_destination_mgr pub;
std::vector<uint8_t> buffer;
SourceManager* dest;
- DestinationManager(SourceManager* src)
+ explicit DestinationManager(SourceManager* src)
: buffer(kOutputBufferSize), dest(src) {
pub.next_output_byte = buffer.data();
pub.free_in_buffer = buffer.size();
@@ -54,7 +54,7 @@ struct DestinationManager {
static void init_destination(j_compress_ptr cinfo) {}
static boolean empty_output_buffer(j_compress_ptr cinfo) {
- auto us = reinterpret_cast<DestinationManager*>(cinfo->dest);
+ auto* us = reinterpret_cast<DestinationManager*>(cinfo->dest);
jpeg_destination_mgr* src = &us->pub;
jpeg_source_mgr* dst = &us->dest->pub;
std::vector<uint8_t>& src_buf = us->buffer;
@@ -69,7 +69,7 @@ struct DestinationManager {
dst->bytes_in_buffer = dst_buf.size();
src->next_output_byte = src_buf.data();
src->free_in_buffer = src_buf.size();
- return true;
+ return TRUE;
}
static void term_destination(j_compress_ptr cinfo) {
@@ -87,6 +87,7 @@ class StreamingTestParam : public ::testing::TestWithParam<TestConfig> {};
TEST_P(StreamingTestParam, TestStreaming) {
jpeg_decompress_struct dinfo = {};
jpeg_compress_struct cinfo = {};
+ SourceManager src;
TestConfig config = GetParam();
TestImage& input = config.input;
TestImage output;
@@ -99,7 +100,6 @@ TEST_P(StreamingTestParam, TestStreaming) {
// compressor's output is connected to the decompressor's input.
jpegli_create_decompress(&dinfo);
jpegli_create_compress(&cinfo);
- SourceManager src;
dinfo.src = reinterpret_cast<jpeg_source_mgr*>(&src);
DestinationManager dest(&src);
cinfo.dest = reinterpret_cast<jpeg_destination_mgr*>(&dest);
@@ -107,7 +107,7 @@ TEST_P(StreamingTestParam, TestStreaming) {
cinfo.image_width = input.xsize;
cinfo.image_height = input.ysize;
cinfo.input_components = input.components;
- cinfo.in_color_space = (J_COLOR_SPACE)input.color_space;
+ cinfo.in_color_space = static_cast<J_COLOR_SPACE>(input.color_space);
jpegli_set_defaults(&cinfo);
cinfo.comp_info[0].v_samp_factor = config.jparams.v_sampling[0];
jpegli_set_progressive_level(&cinfo, 0);
@@ -122,13 +122,13 @@ TEST_P(StreamingTestParam, TestStreaming) {
while (yin < cinfo.image_height) {
// Feed one iMCU row at a time to the compressor.
size_t lines_in = std::min(iMCU_height, cinfo.image_height - yin);
- memcpy(&row_bytes[0], &input.pixels[yin * stride], lines_in * stride);
+ memcpy(row_bytes.data(), &input.pixels[yin * stride], lines_in * stride);
std::vector<JSAMPROW> rows_in(lines_in);
for (size_t i = 0; i < lines_in; ++i) {
rows_in[i] = &row_bytes[i * stride];
}
EXPECT_EQ(lines_in,
- jpegli_write_scanlines(&cinfo, &rows_in[0], lines_in));
+ jpegli_write_scanlines(&cinfo, rows_in.data(), lines_in));
yin += lines_in;
if (yin == cinfo.image_height) {
jpegli_finish_compress(&cinfo);
@@ -180,7 +180,7 @@ TEST_P(StreamingTestParam, TestStreaming) {
reinterpret_cast<JSAMPLE*>(&output.pixels[(yout + i) * stride]);
}
EXPECT_EQ(lines_out,
- jpegli_read_scanlines(&dinfo, &rows_out[0], lines_out));
+ jpegli_read_scanlines(&dinfo, rows_out.data(), lines_out));
VerifyOutputImage(input, output, yout, lines_out, 3.8f);
yout += lines_out;
diff --git a/third_party/jpeg-xl/lib/jpegli/test_utils-inl.h b/third_party/jpeg-xl/lib/jpegli/test_utils-inl.h
index a454917187..4fbcb721e4 100644
--- a/third_party/jpeg-xl/lib/jpegli/test_utils-inl.h
+++ b/third_party/jpeg-xl/lib/jpegli/test_utils-inl.h
@@ -8,20 +8,20 @@
// include paths for the jpeg headers.
// Sequential non-interleaved.
-static constexpr jpeg_scan_info kScript1[] = {
+constexpr jpeg_scan_info kScript1[] = {
{1, {0}, 0, 63, 0, 0},
{1, {1}, 0, 63, 0, 0},
{1, {2}, 0, 63, 0, 0},
};
// Sequential partially interleaved, chroma first.
-static constexpr jpeg_scan_info kScript2[] = {
+constexpr jpeg_scan_info kScript2[] = {
{2, {1, 2}, 0, 63, 0, 0},
{1, {0}, 0, 63, 0, 0},
};
// Rest of the scan scripts are progressive.
-static constexpr jpeg_scan_info kScript3[] = {
+constexpr jpeg_scan_info kScript3[] = {
// Interleaved full DC.
{3, {0, 1, 2}, 0, 0, 0, 0},
// Full AC scans.
@@ -29,7 +29,7 @@ static constexpr jpeg_scan_info kScript3[] = {
{1, {1}, 1, 63, 0, 0},
{1, {2}, 1, 63, 0, 0},
};
-static constexpr jpeg_scan_info kScript4[] = {
+constexpr jpeg_scan_info kScript4[] = {
// Non-interleaved full DC.
{1, {0}, 0, 0, 0, 0},
{1, {1}, 0, 0, 0, 0},
@@ -39,7 +39,7 @@ static constexpr jpeg_scan_info kScript4[] = {
{1, {1}, 1, 63, 0, 0},
{1, {2}, 1, 63, 0, 0},
};
-static constexpr jpeg_scan_info kScript5[] = {
+constexpr jpeg_scan_info kScript5[] = {
// Partially interleaved full DC, chroma first.
{2, {1, 2}, 0, 0, 0, 0},
{1, {0}, 0, 0, 0, 0},
@@ -52,7 +52,7 @@ static constexpr jpeg_scan_info kScript5[] = {
{1, {1}, 1, 63, 1, 0},
{1, {2}, 1, 63, 1, 0},
};
-static constexpr jpeg_scan_info kScript6[] = {
+constexpr jpeg_scan_info kScript6[] = {
// Interleaved DC shifted by 2 bits.
{3, {0, 1, 2}, 0, 0, 0, 2},
// Interleaved DC refinement scans.
@@ -64,7 +64,7 @@ static constexpr jpeg_scan_info kScript6[] = {
{1, {2}, 1, 63, 0, 0},
};
-static constexpr jpeg_scan_info kScript7[] = {
+constexpr jpeg_scan_info kScript7[] = {
// Non-interleaved DC shifted by 2 bits.
{1, {0}, 0, 0, 0, 2},
{1, {1}, 0, 0, 0, 2},
@@ -83,7 +83,7 @@ static constexpr jpeg_scan_info kScript7[] = {
{1, {2}, 1, 63, 0, 0},
};
-static constexpr jpeg_scan_info kScript8[] = {
+constexpr jpeg_scan_info kScript8[] = {
// Partially interleaved DC shifted by 2 bits, chroma first
{2, {1, 2}, 0, 0, 0, 2},
{1, {0}, 0, 0, 0, 2},
@@ -99,7 +99,7 @@ static constexpr jpeg_scan_info kScript8[] = {
{1, {2}, 1, 63, 0, 0},
};
-static constexpr jpeg_scan_info kScript9[] = {
+constexpr jpeg_scan_info kScript9[] = {
// Interleaved full DC.
{3, {0, 1, 2}, 0, 0, 0, 0},
// AC scans for component 0
@@ -123,7 +123,7 @@ static constexpr jpeg_scan_info kScript9[] = {
{1, {2}, 17, 63, 1, 0},
};
-static constexpr jpeg_scan_info kScript10[] = {
+constexpr jpeg_scan_info kScript10[] = {
// Interleaved full DC.
{3, {0, 1, 2}, 0, 0, 0, 0},
// AC scans for spectral range 1..16
@@ -156,14 +156,14 @@ struct ScanScript {
const jpeg_scan_info* scans;
};
-static constexpr ScanScript kTestScript[] = {
+constexpr ScanScript kTestScript[] = {
{ARRAY_SIZE(kScript1), kScript1}, {ARRAY_SIZE(kScript2), kScript2},
{ARRAY_SIZE(kScript3), kScript3}, {ARRAY_SIZE(kScript4), kScript4},
{ARRAY_SIZE(kScript5), kScript5}, {ARRAY_SIZE(kScript6), kScript6},
{ARRAY_SIZE(kScript7), kScript7}, {ARRAY_SIZE(kScript8), kScript8},
{ARRAY_SIZE(kScript9), kScript9}, {ARRAY_SIZE(kScript10), kScript10},
};
-static constexpr int kNumTestScripts = ARRAY_SIZE(kTestScript);
+constexpr int kNumTestScripts = ARRAY_SIZE(kTestScript);
void SetScanDecompressParams(const DecompressParams& dparams,
j_decompress_ptr cinfo, int scan_number) {
@@ -178,7 +178,7 @@ void SetScanDecompressParams(const DecompressParams& dparams,
return;
}
if (dparams.quantize_colors) {
- cinfo->dither_mode = (J_DITHER_MODE)sparams->dither_mode;
+ cinfo->dither_mode = static_cast<J_DITHER_MODE>(sparams->dither_mode);
if (sparams->color_quant_mode == CQUANT_1PASS) {
cinfo->two_pass_quantize = FALSE;
cinfo->colormap = nullptr;
@@ -194,7 +194,8 @@ void SetScanDecompressParams(const DecompressParams& dparams,
cinfo->colormap = (*cinfo->mem->alloc_sarray)(
reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE,
cinfo->actual_number_of_colors, 3);
- jxl::msan::UnpoisonMemory(cinfo->colormap, 3 * sizeof(JSAMPROW));
+ jxl::msan::UnpoisonMemory(reinterpret_cast<void*>(cinfo->colormap),
+ 3 * sizeof(JSAMPLE*));
for (int i = 0; i < kTestColorMapNumColors; ++i) {
cinfo->colormap[0][i] = (kTestColorMap[i] >> 16) & 0xff;
cinfo->colormap[1][i] = (kTestColorMap[i] >> 8) & 0xff;
@@ -212,20 +213,21 @@ void SetScanDecompressParams(const DecompressParams& dparams,
void SetDecompressParams(const DecompressParams& dparams,
j_decompress_ptr cinfo) {
- cinfo->do_block_smoothing = dparams.do_block_smoothing;
- cinfo->do_fancy_upsampling = dparams.do_fancy_upsampling;
+ cinfo->do_block_smoothing = dparams.do_block_smoothing ? 1 : 0;
+ cinfo->do_fancy_upsampling = dparams.do_fancy_upsampling ? 1 : 0;
if (dparams.output_mode == RAW_DATA) {
cinfo->raw_data_out = TRUE;
}
if (dparams.set_out_color_space) {
- cinfo->out_color_space = (J_COLOR_SPACE)dparams.out_color_space;
+ cinfo->out_color_space =
+ static_cast<J_COLOR_SPACE>(dparams.out_color_space);
if (dparams.out_color_space == JCS_UNKNOWN) {
cinfo->jpeg_color_space = JCS_UNKNOWN;
}
}
cinfo->scale_num = dparams.scale_num;
cinfo->scale_denom = dparams.scale_denom;
- cinfo->quantize_colors = dparams.quantize_colors;
+ cinfo->quantize_colors = dparams.quantize_colors ? 1 : 0;
cinfo->desired_number_of_colors = dparams.desired_number_of_colors;
if (!dparams.scan_params.empty()) {
if (cinfo->buffered_image) {
@@ -420,7 +422,7 @@ void CopyCoefficients(j_decompress_ptr cinfo, jvirt_barray_ptr* coef_arrays,
DCTSIZE2);
for (size_t by = 0; by < comp->height_in_blocks; ++by) {
JBLOCKARRAY ba = (*cinfo->mem->access_virt_barray)(comptr, coef_arrays[c],
- by, 1, true);
+ by, 1, TRUE);
size_t stride = comp->width_in_blocks * sizeof(JBLOCK);
size_t offset = by * comp->width_in_blocks * DCTSIZE2;
memcpy(&coeffs[offset], ba[0], stride);
diff --git a/third_party/jpeg-xl/lib/jpegli/test_utils.cc b/third_party/jpeg-xl/lib/jpegli/test_utils.cc
index 232b937496..4e675070cf 100644
--- a/third_party/jpeg-xl/lib/jpegli/test_utils.cc
+++ b/third_party/jpeg-xl/lib/jpegli/test_utils.cc
@@ -153,7 +153,7 @@ bool ReadPNM(const std::vector<uint8_t>& data, size_t* xsize, size_t* ysize,
return false;
}
pixels->resize(data.data() + data.size() - pos);
- memcpy(&(*pixels)[0], pos, pixels->size());
+ memcpy(pixels->data(), pos, pixels->size());
return true;
}
@@ -216,7 +216,8 @@ std::ostream& operator<<(std::ostream& os, const TestImage& input) {
os << input.xsize << "x" << input.ysize;
os << IOMethodName(input.data_type, input.endianness);
if (input.color_space != JCS_RGB) {
- os << "InputColor" << ColorSpaceName((J_COLOR_SPACE)input.color_space);
+ os << "InputColor"
+ << ColorSpaceName(static_cast<J_COLOR_SPACE>(input.color_space));
}
if (input.color_space == JCS_UNKNOWN) {
os << input.components;
@@ -229,18 +230,18 @@ std::ostream& operator<<(std::ostream& os, const CompressParams& jparams) {
os << SamplingId(jparams);
if (jparams.set_jpeg_colorspace) {
os << "JpegColor"
- << ColorSpaceName((J_COLOR_SPACE)jparams.jpeg_color_space);
+ << ColorSpaceName(static_cast<J_COLOR_SPACE>(jparams.jpeg_color_space));
}
if (!jparams.comp_ids.empty()) {
os << "CID";
- for (size_t i = 0; i < jparams.comp_ids.size(); ++i) {
- os << jparams.comp_ids[i];
+ for (int cid : jparams.comp_ids) {
+ os << cid;
}
}
if (!jparams.quant_indexes.empty()) {
os << "QIDX";
- for (size_t i = 0; i < jparams.quant_indexes.size(); ++i) {
- os << jparams.quant_indexes[i];
+ for (int qi : jparams.quant_indexes) {
+ os << qi;
}
for (const auto& table : jparams.quant_tables) {
os << "TABLE" << table.slot_idx << "T" << table.table_type << "F"
@@ -320,7 +321,7 @@ void RGBToYCbCr(float r, float g, float b, float* y, float* cb, float* cr) {
void ConvertPixel(const uint8_t* input_rgb, uint8_t* out,
J_COLOR_SPACE colorspace, size_t num_channels,
JpegliDataType data_type = JPEGLI_TYPE_UINT8,
- bool swap_endianness = JPEGLI_NATIVE_ENDIAN) {
+ JXL_BOOL swap_endianness = JPEGLI_NATIVE_ENDIAN) {
const float kMul = 255.0f;
float r = input_rgb[0] / kMul;
float g = input_rgb[1] / kMul;
@@ -334,7 +335,9 @@ void ConvertPixel(const uint8_t* input_rgb, uint8_t* out,
out8[c] = input_rgb[std::min<size_t>(2, c)];
}
} else if (colorspace == JCS_YCbCr) {
- float Y, Cb, Cr;
+ float Y;
+ float Cb;
+ float Cr;
RGBToYCbCr(r, g, b, &Y, &Cb, &Cr);
out8[0] = static_cast<uint8_t>(std::round(Y * kMul));
out8[1] = static_cast<uint8_t>(std::round(Cb * kMul));
@@ -350,7 +353,9 @@ void ConvertPixel(const uint8_t* input_rgb, uint8_t* out,
out8[1] = static_cast<uint8_t>(std::round((1.0f - g) * kMul));
out8[2] = static_cast<uint8_t>(std::round((1.0f - b) * kMul));
} else if (colorspace == JCS_YCCK) {
- float Y, Cb, Cr;
+ float Y;
+ float Cb;
+ float Cr;
RGBToYCbCr(r, g, b, &Y, &Cb, &Cr);
out8[0] = static_cast<uint8_t>(std::round(Y * kMul));
out8[1] = static_cast<uint8_t>(std::round(Cb * kMul));
@@ -399,7 +404,10 @@ void ConvertToGrayscale(TestImage* img) {
void GeneratePixels(TestImage* img) {
const std::vector<uint8_t> imgdata = ReadTestData("jxl/flower/flower.pnm");
- size_t xsize, ysize, channels, bitdepth;
+ size_t xsize;
+ size_t ysize;
+ size_t channels;
+ size_t bitdepth;
std::vector<uint8_t> pixels;
JXL_CHECK(ReadPNM(imgdata, &xsize, &ysize, &channels, &bitdepth, &pixels));
if (img->xsize == 0) img->xsize = xsize;
@@ -412,7 +420,8 @@ void GeneratePixels(TestImage* img) {
size_t in_stride = xsize * in_bytes_per_pixel;
size_t x0 = (xsize - img->xsize) / 2;
size_t y0 = (ysize - img->ysize) / 2;
- SetNumChannels((J_COLOR_SPACE)img->color_space, &img->components);
+ SetNumChannels(static_cast<J_COLOR_SPACE>(img->color_space),
+ &img->components);
size_t out_bytes_per_pixel =
jpegli_bytes_per_sample(img->data_type) * img->components;
size_t out_stride = img->xsize * out_bytes_per_pixel;
@@ -427,8 +436,9 @@ void GeneratePixels(TestImage* img) {
size_t idx_in = y * in_stride + x * in_bytes_per_pixel;
size_t idx_out = iy * out_stride + ix * out_bytes_per_pixel;
ConvertPixel(&pixels[idx_in], &img->pixels[idx_out],
- (J_COLOR_SPACE)img->color_space, img->components,
- img->data_type, swap_endianness);
+ static_cast<J_COLOR_SPACE>(img->color_space),
+ img->components, img->data_type,
+ TO_JXL_BOOL(swap_endianness));
}
}
}
@@ -492,7 +502,7 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
jpegli_set_progressive_level(cinfo, 0);
}
jpegli_set_defaults(cinfo);
- cinfo->in_color_space = (J_COLOR_SPACE)input.color_space;
+ cinfo->in_color_space = static_cast<J_COLOR_SPACE>(input.color_space);
jpegli_default_colorspace(cinfo);
if (jparams.override_JFIF >= 0) {
cinfo->write_JFIF_header = jparams.override_JFIF;
@@ -501,7 +511,8 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
cinfo->write_Adobe_marker = jparams.override_Adobe;
}
if (jparams.set_jpeg_colorspace) {
- jpegli_set_colorspace(cinfo, (J_COLOR_SPACE)jparams.jpeg_color_space);
+ jpegli_set_colorspace(cinfo,
+ static_cast<J_COLOR_SPACE>(jparams.jpeg_color_space));
}
if (!jparams.comp_ids.empty()) {
for (int c = 0; c < cinfo->num_components; ++c) {
@@ -522,15 +533,16 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
for (const auto& table : jparams.quant_tables) {
if (table.add_raw) {
cinfo->quant_tbl_ptrs[table.slot_idx] =
- jpegli_alloc_quant_table((j_common_ptr)cinfo);
+ jpegli_alloc_quant_table(reinterpret_cast<j_common_ptr>(cinfo));
for (int k = 0; k < DCTSIZE2; ++k) {
cinfo->quant_tbl_ptrs[table.slot_idx]->quantval[k] =
table.quantval[k];
}
cinfo->quant_tbl_ptrs[table.slot_idx]->sent_table = FALSE;
} else {
- jpegli_add_quant_table(cinfo, table.slot_idx, &table.basic_table[0],
- table.scale_factor, table.force_baseline);
+ jpegli_add_quant_table(cinfo, table.slot_idx, table.basic_table.data(),
+ table.scale_factor,
+ TO_JXL_BOOL(table.force_baseline));
}
}
}
@@ -546,7 +558,8 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
jpegli_set_progressive_level(cinfo, jparams.progressive_mode);
}
jpegli_set_input_format(cinfo, input.data_type, input.endianness);
- jpegli_enable_adaptive_quantization(cinfo, jparams.use_adaptive_quantization);
+ jpegli_enable_adaptive_quantization(
+ cinfo, TO_JXL_BOOL(jparams.use_adaptive_quantization));
cinfo->restart_interval = jparams.restart_interval;
cinfo->restart_in_rows = jparams.restart_in_rows;
cinfo->smoothing_factor = jparams.smoothing_factor;
@@ -555,7 +568,7 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
} else if (jparams.optimize_coding == 0) {
cinfo->optimize_coding = FALSE;
}
- cinfo->raw_data_in = !input.raw_data.empty();
+ cinfo->raw_data_in = TO_JXL_BOOL(!input.raw_data.empty());
if (jparams.optimize_coding == 0 && jparams.use_flat_dc_luma_code) {
JHUFF_TBL* tbl = cinfo->dc_huff_tbl_ptrs[0];
memset(tbl, 0, sizeof(*tbl));
@@ -572,13 +585,13 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
cinfo->ac_huff_tbl_ptrs[0]->sent_table = TRUE;
cinfo->ac_huff_tbl_ptrs[1]->sent_table = TRUE;
}
- jpegli_start_compress(cinfo, write_all_tables);
+ jpegli_start_compress(cinfo, TO_JXL_BOOL(write_all_tables));
if (jparams.add_marker) {
jpegli_write_marker(cinfo, kSpecialMarker0, kMarkerData,
sizeof(kMarkerData));
jpegli_write_m_header(cinfo, kSpecialMarker1, sizeof(kMarkerData));
- for (size_t p = 0; p < sizeof(kMarkerData); ++p) {
- jpegli_write_m_byte(cinfo, kMarkerData[p]);
+ for (uint8_t c : kMarkerData) {
+ jpegli_write_m_byte(cinfo, c);
}
for (size_t i = 0; i < kMarkerSequenceLen; ++i) {
jpegli_write_marker(cinfo, kMarkerSequence[i], kMarkerData,
@@ -597,7 +610,7 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
std::vector<JSAMPARRAY> data(cinfo->num_components);
for (int c = 0; c < cinfo->num_components; ++c) {
rowdata[c].resize(jparams.v_samp(c) * DCTSIZE);
- data[c] = &rowdata[c][0];
+ data[c] = rowdata[c].data();
}
while (cinfo->next_scanline < cinfo->image_height) {
for (int c = 0; c < cinfo->num_components; ++c) {
@@ -610,7 +623,7 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
(y0 + i < cheight ? &raw_data[c][(y0 + i) * cwidth] : nullptr);
}
}
- size_t num_lines = jpegli_write_raw_data(cinfo, &data[0], max_lines);
+ size_t num_lines = jpegli_write_raw_data(cinfo, data.data(), max_lines);
JXL_CHECK(num_lines == max_lines);
}
} else if (!input.coeffs.empty()) {
@@ -630,15 +643,15 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
jpegli_write_marker(cinfo, kSpecialMarker0, kMarkerData,
sizeof(kMarkerData));
jpegli_write_m_header(cinfo, kSpecialMarker1, sizeof(kMarkerData));
- for (size_t p = 0; p < sizeof(kMarkerData); ++p) {
- jpegli_write_m_byte(cinfo, kMarkerData[p]);
+ for (uint8_t c : kMarkerData) {
+ jpegli_write_m_byte(cinfo, c);
}
}
for (int c = 0; c < cinfo->num_components; ++c) {
jpeg_component_info* comp = &cinfo->comp_info[c];
for (size_t by = 0; by < comp->height_in_blocks; ++by) {
JBLOCKARRAY ba = (*cinfo->mem->access_virt_barray)(
- comptr, coef_arrays[c], by, 1, true);
+ comptr, coef_arrays[c], by, 1, TRUE);
size_t stride = comp->width_in_blocks * sizeof(JBLOCK);
size_t offset = by * comp->width_in_blocks * DCTSIZE2;
memcpy(ba[0], &input.coeffs[c][offset], stride);
@@ -649,7 +662,7 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
jpegli_bytes_per_sample(input.data_type);
std::vector<uint8_t> row_bytes(stride);
for (size_t y = 0; y < cinfo->image_height; ++y) {
- memcpy(&row_bytes[0], &input.pixels[y * stride], stride);
+ memcpy(row_bytes.data(), &input.pixels[y * stride], stride);
JSAMPROW row[] = {row_bytes.data()};
jpegli_write_scanlines(cinfo, row, 1);
}
@@ -681,15 +694,15 @@ bool EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
int NumTestScanScripts() { return kNumTestScripts; }
-void DumpImage(const TestImage& image, const std::string fn) {
+void DumpImage(const TestImage& image, const std::string& fn) {
JXL_CHECK(image.components == 1 || image.components == 3);
size_t bytes_per_sample = jpegli_bytes_per_sample(image.data_type);
uint32_t maxval = (1u << (8 * bytes_per_sample)) - 1;
char type = image.components == 1 ? '5' : '6';
std::ofstream out(fn.c_str(), std::ofstream::binary);
- out << "P" << type << std::endl
- << image.xsize << " " << image.ysize << std::endl
- << maxval << std::endl;
+ out << "P" << type << "\n"
+ << image.xsize << " " << image.ysize << "\n"
+ << maxval << "\n";
out.write(reinterpret_cast<const char*>(image.pixels.data()),
image.pixels.size());
out.close();
diff --git a/third_party/jpeg-xl/lib/jpegli/testing.h b/third_party/jpeg-xl/lib/jpegli/testing.h
index 873a0171e7..6a6e0ca638 100644
--- a/third_party/jpeg-xl/lib/jpegli/testing.h
+++ b/third_party/jpeg-xl/lib/jpegli/testing.h
@@ -6,15 +6,7 @@
#ifndef LIB_JPEGLI_TESTING_H_
#define LIB_JPEGLI_TESTING_H_
-// GTest/GMock specific macros / wrappers.
-
-// gmock unconditionally redefines those macros (to wrong values).
-// Lets include it only here and mitigate the problem.
-#pragma push_macro("PRIdS")
-#pragma push_macro("PRIuS")
-#include "gmock/gmock.h"
-#pragma pop_macro("PRIuS")
-#pragma pop_macro("PRIdS")
+// GTest specific macros / wrappers.
#include "gtest/gtest.h"
@@ -28,8 +20,12 @@
// Ensures that we don't make our test bounds too lax, effectively disabling the
// tests.
-MATCHER_P(IsSlightlyBelow, max, "") {
- return max * 0.75 <= arg && arg <= max * 1.0;
-}
+#define EXPECT_SLIGHTLY_BELOW(A, E) \
+ { \
+ double _actual = (A); \
+ double _expected = (E); \
+ EXPECT_LE(_actual, _expected); \
+ EXPECT_GE(_actual, 0.75 * _expected); \
+ }
#endif // LIB_JPEGLI_TESTING_H_
diff --git a/third_party/jpeg-xl/lib/jpegli/transpose-inl.h b/third_party/jpeg-xl/lib/jpegli/transpose-inl.h
index 9fdd222f4e..cdc289f96c 100644
--- a/third_party/jpeg-xl/lib/jpegli/transpose-inl.h
+++ b/third_party/jpeg-xl/lib/jpegli/transpose-inl.h
@@ -18,8 +18,8 @@ namespace HWY_NAMESPACE {
namespace {
#if HWY_CAP_GE256
-static JXL_INLINE void Transpose8x8Block(const float* JXL_RESTRICT from,
- float* JXL_RESTRICT to) {
+JXL_INLINE void Transpose8x8Block(const float* JXL_RESTRICT from,
+ float* JXL_RESTRICT to) {
const HWY_CAPPED(float, 8) d;
auto i0 = Load(d, from);
auto i1 = Load(d, from + 1 * 8);
@@ -67,8 +67,8 @@ static JXL_INLINE void Transpose8x8Block(const float* JXL_RESTRICT from,
Store(i7, d, to + 7 * 8);
}
#elif HWY_TARGET != HWY_SCALAR
-static JXL_INLINE void Transpose8x8Block(const float* JXL_RESTRICT from,
- float* JXL_RESTRICT to) {
+JXL_INLINE void Transpose8x8Block(const float* JXL_RESTRICT from,
+ float* JXL_RESTRICT to) {
const HWY_CAPPED(float, 4) d;
for (size_t n = 0; n < 8; n += 4) {
for (size_t m = 0; m < 8; m += 4) {
diff --git a/third_party/jpeg-xl/lib/jpegli/upsample.cc b/third_party/jpeg-xl/lib/jpegli/upsample.cc
index 5559aa78a6..7dae841b8a 100644
--- a/third_party/jpeg-xl/lib/jpegli/upsample.cc
+++ b/third_party/jpeg-xl/lib/jpegli/upsample.cc
@@ -122,7 +122,7 @@ HWY_EXPORT(Upsample2Vertical);
void Upsample2Horizontal(float* JXL_RESTRICT row,
float* JXL_RESTRICT scratch_space, size_t len_out) {
- return HWY_DYNAMIC_DISPATCH(Upsample2Horizontal)(row, scratch_space, len_out);
+ HWY_DYNAMIC_DISPATCH(Upsample2Horizontal)(row, scratch_space, len_out);
}
void Upsample2Vertical(const float* JXL_RESTRICT row_top,
@@ -130,8 +130,8 @@ void Upsample2Vertical(const float* JXL_RESTRICT row_top,
const float* JXL_RESTRICT row_bot,
float* JXL_RESTRICT row_out0,
float* JXL_RESTRICT row_out1, size_t len) {
- return HWY_DYNAMIC_DISPATCH(Upsample2Vertical)(row_top, row_mid, row_bot,
- row_out0, row_out1, len);
+ HWY_DYNAMIC_DISPATCH(Upsample2Vertical)
+ (row_top, row_mid, row_bot, row_out0, row_out1, len);
}
} // namespace jpegli
#endif // HWY_ONCE
diff --git a/third_party/jpeg-xl/lib/jxl.cmake b/third_party/jpeg-xl/lib/jxl.cmake
index 8c7e711f52..86fa37151d 100644
--- a/third_party/jpeg-xl/lib/jxl.cmake
+++ b/third_party/jpeg-xl/lib/jxl.cmake
@@ -60,7 +60,7 @@ include(GenerateExportHeader)
# CMake does not allow generate_export_header for INTERFACE library, so we
# add this stub library just for file generation.
-add_library(jxl_export OBJECT ${JPEGXL_INTERNAL_PUBLIC_HEADERS})
+add_library(jxl_export OBJECT ${JPEGXL_INTERNAL_PUBLIC_HEADERS} nothing.cc)
set_target_properties(jxl_export PROPERTIES
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN 1
@@ -269,8 +269,10 @@ set(JPEGXL_LIBRARY_REQUIRES
if (BUILD_SHARED_LIBS)
set(JPEGXL_REQUIRES_TYPE "Requires.private")
+ set(JPEGXL_PRIVATE_LIBS "-lm ${PKGCONFIG_CXX_LIB}")
else()
set(JPEGXL_REQUIRES_TYPE "Requires")
+ set(JPEGXL_PUBLIC_LIBS "-lm ${PKGCONFIG_CXX_LIB}")
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/jxl/libjxl.pc.in"
diff --git a/third_party/jpeg-xl/lib/jxl/ac_strategy.cc b/third_party/jpeg-xl/lib/jxl/ac_strategy.cc
index 3de477f71c..e7a72f5a33 100644
--- a/third_party/jpeg-xl/lib/jxl/ac_strategy.cc
+++ b/third_party/jpeg-xl/lib/jxl/ac_strategy.cc
@@ -8,12 +8,9 @@
#include <string.h>
#include <algorithm>
-#include <numeric> // iota
-#include <type_traits>
#include <utility>
#include "lib/jxl/base/bits.h"
-#include "lib/jxl/image_ops.h"
namespace jxl {
@@ -86,10 +83,12 @@ constexpr size_t AcStrategy::kMaxCoeffBlocks;
constexpr size_t AcStrategy::kMaxBlockDim;
constexpr size_t AcStrategy::kMaxCoeffArea;
-AcStrategyImage::AcStrategyImage(size_t xsize, size_t ysize)
- : layers_(xsize, ysize) {
- row_ = layers_.Row(0);
- stride_ = layers_.PixelsPerRow();
+StatusOr<AcStrategyImage> AcStrategyImage::Create(size_t xsize, size_t ysize) {
+ AcStrategyImage img;
+ JXL_ASSIGN_OR_RETURN(img.layers_, ImageB::Create(xsize, ysize));
+ img.row_ = img.layers_.Row(0);
+ img.stride_ = img.layers_.PixelsPerRow();
+ return img;
}
size_t AcStrategyImage::CountBlocks(AcStrategy::Type type) const {
diff --git a/third_party/jpeg-xl/lib/jxl/ac_strategy.h b/third_party/jpeg-xl/lib/jxl/ac_strategy.h
index ecdcbbbd32..9e5917ff1b 100644
--- a/third_party/jpeg-xl/lib/jxl/ac_strategy.h
+++ b/third_party/jpeg-xl/lib/jxl/ac_strategy.h
@@ -144,7 +144,7 @@ class AcStrategy {
8, 4, 8, 16, 8, 16, 32, 16, 32};
static_assert(sizeof(kLut) / sizeof(*kLut) == kNumValidStrategies,
"Update LUT");
- return kLut[size_t(strategy_)];
+ return kLut[static_cast<size_t>(strategy_)];
}
JXL_INLINE size_t covered_blocks_y() const {
@@ -153,7 +153,7 @@ class AcStrategy {
8, 8, 4, 16, 16, 8, 32, 32, 16};
static_assert(sizeof(kLut) / sizeof(*kLut) == kNumValidStrategies,
"Update LUT");
- return kLut[size_t(strategy_)];
+ return kLut[static_cast<size_t>(strategy_)];
}
JXL_INLINE size_t log2_covered_blocks() const {
@@ -162,7 +162,7 @@ class AcStrategy {
6, 5, 5, 8, 7, 7, 10, 9, 9};
static_assert(sizeof(kLut) / sizeof(*kLut) == kNumValidStrategies,
"Update LUT");
- return kLut[size_t(strategy_)];
+ return kLut[static_cast<size_t>(strategy_)];
}
private:
@@ -181,7 +181,9 @@ class AcStrategyRow {
public:
explicit AcStrategyRow(const uint8_t* row) : row_(row) {}
AcStrategy operator[](size_t x) const {
- return AcStrategy(static_cast<AcStrategy::Type>(row_[x] >> 1), row_[x] & 1);
+ AcStrategy::Type strategy = static_cast<AcStrategy::Type>(row_[x] >> 1);
+ bool is_first = static_cast<bool>(row_[x] & 1);
+ return AcStrategy(strategy, is_first);
}
private:
@@ -191,7 +193,8 @@ class AcStrategyRow {
class AcStrategyImage {
public:
AcStrategyImage() = default;
- AcStrategyImage(size_t xsize, size_t ysize);
+ static StatusOr<AcStrategyImage> Create(size_t xsize, size_t ysize);
+
AcStrategyImage(AcStrategyImage&&) = default;
AcStrategyImage& operator=(AcStrategyImage&&) = default;
diff --git a/third_party/jpeg-xl/lib/jxl/ac_strategy_test.cc b/third_party/jpeg-xl/lib/jxl/ac_strategy_test.cc
index 3745db2b32..b1d9103466 100644
--- a/third_party/jpeg-xl/lib/jxl/ac_strategy_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/ac_strategy_test.cc
@@ -81,7 +81,8 @@ class AcStrategyRoundtrip : public ::hwy::TestWithParamTargetAndT<int> {
HWY_TARGET_INSTANTIATE_TEST_SUITE_P_T(
AcStrategyRoundtrip,
- ::testing::Range(0, int(AcStrategy::Type::kNumValidStrategies)));
+ ::testing::Range(0,
+ static_cast<int>(AcStrategy::Type::kNumValidStrategies)));
TEST_P(AcStrategyRoundtrip, Test) { Run(); }
@@ -141,7 +142,8 @@ class AcStrategyRoundtripDownsample
HWY_TARGET_INSTANTIATE_TEST_SUITE_P_T(
AcStrategyRoundtripDownsample,
- ::testing::Range(0, int(AcStrategy::Type::kNumValidStrategies)));
+ ::testing::Range(0,
+ static_cast<int>(AcStrategy::Type::kNumValidStrategies)));
TEST_P(AcStrategyRoundtripDownsample, Test) { Run(); }
@@ -205,7 +207,8 @@ class AcStrategyDownsample : public ::hwy::TestWithParamTargetAndT<int> {
HWY_TARGET_INSTANTIATE_TEST_SUITE_P_T(
AcStrategyDownsample,
- ::testing::Range(0, int(AcStrategy::Type::kNumValidStrategies)));
+ ::testing::Range(0,
+ static_cast<int>(AcStrategy::Type::kNumValidStrategies)));
TEST_P(AcStrategyDownsample, Test) { Run(); }
diff --git a/third_party/jpeg-xl/lib/jxl/alpha_test.cc b/third_party/jpeg-xl/lib/jxl/alpha_test.cc
index ddafd829ec..a93254f3dd 100644
--- a/third_party/jpeg-xl/lib/jxl/alpha_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/alpha_test.cc
@@ -5,69 +5,59 @@
#include "lib/jxl/alpha.h"
-#include "lib/jxl/test_utils.h"
+#include <array>
+
+#include "lib/jxl/base/common.h"
#include "lib/jxl/testing.h"
namespace jxl {
namespace {
-using ::testing::_;
-using ::testing::ElementsAre;
-using ::testing::FloatNear;
-
TEST(AlphaTest, BlendingWithNonPremultiplied) {
- const float bg_rgb[3] = {100, 110, 120};
+ const Color bg_rgb{100, 110, 120};
const float bg_a = 180.f / 255;
- const float fg_rgb[3] = {25, 21, 23};
+ const Color fg_rgb{25, 21, 23};
const float fg_a = 15420.f / 65535;
const float fg_a2 = 2.0f;
- float out_rgb[3];
+ Color out_rgb;
float out_a;
PerformAlphaBlending(
/*bg=*/{&bg_rgb[0], &bg_rgb[1], &bg_rgb[2], &bg_a},
/*fg=*/{&fg_rgb[0], &fg_rgb[1], &fg_rgb[2], &fg_a},
/*out=*/{&out_rgb[0], &out_rgb[1], &out_rgb[2], &out_a}, 1,
/*alpha_is_premultiplied=*/false, /*clamp=*/false);
- EXPECT_THAT(out_rgb,
- ElementsAre(FloatNear(77.2f, .05f), FloatNear(83.0f, .05f),
- FloatNear(90.6f, .05f)));
+ EXPECT_ARRAY_NEAR(out_rgb, (Color{77.2f, 83.0f, 90.6f}), 0.05f);
EXPECT_NEAR(out_a, 3174.f / 4095, 1e-5);
PerformAlphaBlending(
/*bg=*/{&bg_rgb[0], &bg_rgb[1], &bg_rgb[2], &bg_a},
/*fg=*/{&fg_rgb[0], &fg_rgb[1], &fg_rgb[2], &fg_a2},
/*out=*/{&out_rgb[0], &out_rgb[1], &out_rgb[2], &out_a}, 1,
/*alpha_is_premultiplied=*/false, /*clamp=*/true);
- EXPECT_THAT(out_rgb, ElementsAre(FloatNear(fg_rgb[0], .05f),
- FloatNear(fg_rgb[1], .05f),
- FloatNear(fg_rgb[2], .05f)));
+ EXPECT_ARRAY_NEAR(out_rgb, fg_rgb, 0.05f);
EXPECT_NEAR(out_a, 1.0f, 1e-5);
}
TEST(AlphaTest, BlendingWithPremultiplied) {
- const float bg_rgb[3] = {100, 110, 120};
+ const Color bg_rgb{100, 110, 120};
const float bg_a = 180.f / 255;
- const float fg_rgb[3] = {25, 21, 23};
+ const Color fg_rgb{25, 21, 23};
const float fg_a = 15420.f / 65535;
const float fg_a2 = 2.0f;
- float out_rgb[3];
+ Color out_rgb;
float out_a;
PerformAlphaBlending(
/*bg=*/{&bg_rgb[0], &bg_rgb[1], &bg_rgb[2], &bg_a},
/*fg=*/{&fg_rgb[0], &fg_rgb[1], &fg_rgb[2], &fg_a},
/*out=*/{&out_rgb[0], &out_rgb[1], &out_rgb[2], &out_a}, 1,
/*alpha_is_premultiplied=*/true, /*clamp=*/false);
- EXPECT_THAT(out_rgb,
- ElementsAre(FloatNear(101.5f, .05f), FloatNear(105.1f, .05f),
- FloatNear(114.8f, .05f)));
+ EXPECT_ARRAY_NEAR(out_rgb, (Color{101.5f, 105.1f, 114.8f}), 0.05f);
EXPECT_NEAR(out_a, 3174.f / 4095, 1e-5);
PerformAlphaBlending(
/*bg=*/{&bg_rgb[0], &bg_rgb[1], &bg_rgb[2], &bg_a},
/*fg=*/{&fg_rgb[0], &fg_rgb[1], &fg_rgb[2], &fg_a2},
/*out=*/{&out_rgb[0], &out_rgb[1], &out_rgb[2], &out_a}, 1,
/*alpha_is_premultiplied=*/true, /*clamp=*/true);
- EXPECT_THAT(out_rgb, ElementsAre(FloatNear(fg_rgb[0], .05f),
- FloatNear(fg_rgb[1], .05f),
- FloatNear(fg_rgb[2], .05f)));
+ EXPECT_ARRAY_NEAR(out_rgb, fg_rgb, 0.05f);
EXPECT_NEAR(out_a, 1.0f, 1e-5);
}
@@ -76,58 +66,51 @@ TEST(AlphaTest, Mul) {
const float fg = 25;
float out;
PerformMulBlending(&bg, &fg, &out, 1, /*clamp=*/false);
- EXPECT_THAT(out, FloatNear(fg * bg, .05f));
+ EXPECT_NEAR(out, fg * bg, .05f);
PerformMulBlending(&bg, &fg, &out, 1, /*clamp=*/true);
- EXPECT_THAT(out, FloatNear(bg, .05f));
+ EXPECT_NEAR(out, bg, .05f);
}
TEST(AlphaTest, PremultiplyAndUnpremultiply) {
- const float alpha[] = {0.f, 63.f / 255, 127.f / 255, 1.f};
- float r[] = {120, 130, 140, 150};
- float g[] = {124, 134, 144, 154};
- float b[] = {127, 137, 147, 157};
+ using F4 = std::array<float, 4>;
+ const F4 alpha{0.f, 63.f / 255, 127.f / 255, 1.f};
+ F4 r{120, 130, 140, 150};
+ F4 g{124, 134, 144, 154};
+ F4 b{127, 137, 147, 157};
- PremultiplyAlpha(r, g, b, alpha, 4);
- EXPECT_THAT(
- r, ElementsAre(FloatNear(0.f, 1e-5f), FloatNear(130 * 63.f / 255, 1e-5f),
- FloatNear(140 * 127.f / 255, 1e-5f), 150));
- EXPECT_THAT(
- g, ElementsAre(FloatNear(0.f, 1e-5f), FloatNear(134 * 63.f / 255, 1e-5f),
- FloatNear(144 * 127.f / 255, 1e-5f), 154));
- EXPECT_THAT(
- b, ElementsAre(FloatNear(0.f, 1e-5f), FloatNear(137 * 63.f / 255, 1e-5f),
- FloatNear(147 * 127.f / 255, 1e-5f), 157));
+ PremultiplyAlpha(r.data(), g.data(), b.data(), alpha.data(), alpha.size());
+ EXPECT_ARRAY_NEAR(r, (F4{0.0f, 130 * 63.f / 255, 140 * 127.f / 255, 150}),
+ 1e-5f);
+ EXPECT_ARRAY_NEAR(g, (F4{0.0f, 134 * 63.f / 255, 144 * 127.f / 255, 154}),
+ 1e-5f);
+ EXPECT_ARRAY_NEAR(b, (F4{0.0f, 137 * 63.f / 255, 147 * 127.f / 255, 157}),
+ 1e-5f);
- UnpremultiplyAlpha(r, g, b, alpha, 4);
- EXPECT_THAT(r, ElementsAre(FloatNear(120, 1e-4f), FloatNear(130, 1e-4f),
- FloatNear(140, 1e-4f), FloatNear(150, 1e-4f)));
- EXPECT_THAT(g, ElementsAre(FloatNear(124, 1e-4f), FloatNear(134, 1e-4f),
- FloatNear(144, 1e-4f), FloatNear(154, 1e-4f)));
- EXPECT_THAT(b, ElementsAre(FloatNear(127, 1e-4f), FloatNear(137, 1e-4f),
- FloatNear(147, 1e-4f), FloatNear(157, 1e-4f)));
+ UnpremultiplyAlpha(r.data(), g.data(), b.data(), alpha.data(), alpha.size());
+ EXPECT_ARRAY_NEAR(r, (F4{120, 130, 140, 150}), 1e-4f);
+ EXPECT_ARRAY_NEAR(g, (F4{124, 134, 144, 154}), 1e-4f);
+ EXPECT_ARRAY_NEAR(b, (F4{127, 137, 147, 157}), 1e-4f);
}
TEST(AlphaTest, UnpremultiplyAndPremultiply) {
- const float alpha[] = {0.f, 63.f / 255, 127.f / 255, 1.f};
- float r[] = {50, 60, 70, 80};
- float g[] = {54, 64, 74, 84};
- float b[] = {57, 67, 77, 87};
+ using F4 = std::array<float, 4>;
+ const F4 alpha{0.f, 63.f / 255, 127.f / 255, 1.f};
+ F4 r{50, 60, 70, 80};
+ F4 g{54, 64, 74, 84};
+ F4 b{57, 67, 77, 87};
- UnpremultiplyAlpha(r, g, b, alpha, 4);
- EXPECT_THAT(r, ElementsAre(_, FloatNear(60 * 255.f / 63, 1e-4f),
- FloatNear(70 * 255.f / 127, 1e-4f), 80));
- EXPECT_THAT(g, ElementsAre(_, FloatNear(64 * 255.f / 63, 1e-4f),
- FloatNear(74 * 255.f / 127, 1e-4f), 84));
- EXPECT_THAT(b, ElementsAre(_, FloatNear(67 * 255.f / 63, 1e-4f),
- FloatNear(77 * 255.f / 127, 1e-4f), 87));
+ UnpremultiplyAlpha(r.data(), g.data(), b.data(), alpha.data(), alpha.size());
+ EXPECT_ARRAY_NEAR(
+ r, (F4{50.0f * (1 << 26), 60 * 255.f / 63, 70 * 255.f / 127, 80}), 1e-4f);
+ EXPECT_ARRAY_NEAR(
+ g, (F4{54.0f * (1 << 26), 64 * 255.f / 63, 74 * 255.f / 127, 84}), 1e-4f);
+ EXPECT_ARRAY_NEAR(
+ b, (F4{57.0f * (1 << 26), 67 * 255.f / 63, 77 * 255.f / 127, 87}), 1e-4f);
- PremultiplyAlpha(r, g, b, alpha, 4);
- EXPECT_THAT(r, ElementsAre(FloatNear(50, 1e-4f), FloatNear(60, 1e-4f),
- FloatNear(70, 1e-4f), FloatNear(80, 1e-4f)));
- EXPECT_THAT(g, ElementsAre(FloatNear(54, 1e-4f), FloatNear(64, 1e-4f),
- FloatNear(74, 1e-4f), FloatNear(84, 1e-4f)));
- EXPECT_THAT(b, ElementsAre(FloatNear(57, 1e-4f), FloatNear(67, 1e-4f),
- FloatNear(77, 1e-4f), FloatNear(87, 1e-4f)));
+ PremultiplyAlpha(r.data(), g.data(), b.data(), alpha.data(), alpha.size());
+ EXPECT_ARRAY_NEAR(r, (F4{50, 60, 70, 80}), 1e-4);
+ EXPECT_ARRAY_NEAR(g, (F4{54, 64, 74, 84}), 1e-4);
+ EXPECT_ARRAY_NEAR(b, (F4{57, 67, 77, 87}), 1e-4);
}
} // namespace
diff --git a/third_party/jpeg-xl/lib/jxl/ans_common.h b/third_party/jpeg-xl/lib/jxl/ans_common.h
index fb5058e310..44b8e3fba1 100644
--- a/third_party/jpeg-xl/lib/jxl/ans_common.h
+++ b/third_party/jpeg-xl/lib/jxl/ans_common.h
@@ -24,7 +24,8 @@ namespace jxl {
static JXL_INLINE uint32_t GetPopulationCountPrecision(uint32_t logcount,
uint32_t shift) {
int32_t r = std::min<int>(
- logcount, int(shift) - int((ANS_LOG_TAB_SIZE - logcount) >> 1));
+ logcount, static_cast<int>(shift) -
+ static_cast<int>((ANS_LOG_TAB_SIZE - logcount) >> 1));
if (r < 0) return 0;
return r;
}
diff --git a/third_party/jpeg-xl/lib/jxl/ans_test.cc b/third_party/jpeg-xl/lib/jxl/ans_test.cc
index c28daf7b85..5d6a5ef090 100644
--- a/third_party/jpeg-xl/lib/jxl/ans_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/ans_test.cc
@@ -113,8 +113,8 @@ void RoundtripRandomUnbalancedStream(int alphabet_size) {
Rng rng(0);
for (size_t i = 0; i < kReps; i++) {
std::vector<int> distributions[kNumHistograms] = {};
- for (int j = 0; j < kNumHistograms; j++) {
- distributions[j].resize(kPrecision);
+ for (auto& distr : distributions) {
+ distr.resize(kPrecision);
int symbol = 0;
int remaining = 1;
for (int k = 0; k < kPrecision; k++) {
@@ -126,7 +126,7 @@ void RoundtripRandomUnbalancedStream(int alphabet_size) {
// sufficiently dissimilar.
remaining = rng.UniformU(0, kPrecision - k + 1);
}
- distributions[j][k] = symbol;
+ distr[k] = symbol;
remaining--;
}
}
@@ -158,7 +158,8 @@ TEST(ANSTest, RandomUnbalancedStreamRoundtripBig) {
TEST(ANSTest, UintConfigRoundtrip) {
for (size_t log_alpha_size = 5; log_alpha_size <= 8; log_alpha_size++) {
- std::vector<HybridUintConfig> uint_config, uint_config_dec;
+ std::vector<HybridUintConfig> uint_config;
+ std::vector<HybridUintConfig> uint_config_dec;
for (size_t i = 0; i < log_alpha_size; i++) {
for (size_t j = 0; j <= i; j++) {
for (size_t k = 0; k <= i - j; k++) {
@@ -187,16 +188,16 @@ TEST(ANSTest, UintConfigRoundtrip) {
void TestCheckpointing(bool ans, bool lz77) {
std::vector<std::vector<Token>> input_values(1);
for (size_t i = 0; i < 1024; i++) {
- input_values[0].push_back(Token(0, i % 4));
+ input_values[0].emplace_back(0, i % 4);
}
// up to lz77 window size.
for (size_t i = 0; i < (1 << 20) - 1022; i++) {
- input_values[0].push_back(Token(0, (i % 5) + 4));
+ input_values[0].emplace_back(0, (i % 5) + 4);
}
// Ensure that when the window wraps around, new values are different.
- input_values[0].push_back(Token(0, 0));
+ input_values[0].emplace_back(0, 0);
for (size_t i = 0; i < 1024; i++) {
- input_values[0].push_back(Token(0, i % 4));
+ input_values[0].emplace_back(0, i % 4);
}
std::vector<uint8_t> context_map;
diff --git a/third_party/jpeg-xl/lib/jxl/base/bits.h b/third_party/jpeg-xl/lib/jxl/base/bits.h
index 9f86118e72..a79fdc2c99 100644
--- a/third_party/jpeg-xl/lib/jxl/base/bits.h
+++ b/third_party/jpeg-xl/lib/jxl/base/bits.h
@@ -26,7 +26,8 @@ struct SizeTag {};
template <typename T>
constexpr bool IsSigned() {
- return T(0) > T(-1);
+ // TODO(eustas): remove dupes
+ return static_cast<T>(0) > static_cast<T>(-1);
}
// Undefined results for x == 0.
diff --git a/third_party/jpeg-xl/lib/jxl/base/byte_order.h b/third_party/jpeg-xl/lib/jxl/base/byte_order.h
index 8966834e08..cf8d7db082 100644
--- a/third_party/jpeg-xl/lib/jxl/base/byte_order.h
+++ b/third_party/jpeg-xl/lib/jxl/base/byte_order.h
@@ -237,22 +237,22 @@ struct OrderLE {};
// Wrappers for calling from generic code.
static JXL_INLINE void Store16(OrderBE /*tag*/, const uint32_t native,
uint8_t* p) {
- return StoreBE16(native, p);
+ StoreBE16(native, p);
}
static JXL_INLINE void Store16(OrderLE /*tag*/, const uint32_t native,
uint8_t* p) {
- return StoreLE16(native, p);
+ StoreLE16(native, p);
}
static JXL_INLINE void Store32(OrderBE /*tag*/, const uint32_t native,
uint8_t* p) {
- return StoreBE32(native, p);
+ StoreBE32(native, p);
}
static JXL_INLINE void Store32(OrderLE /*tag*/, const uint32_t native,
uint8_t* p) {
- return StoreLE32(native, p);
+ StoreLE32(native, p);
}
static JXL_INLINE uint32_t Load16(OrderBE /*tag*/, const uint8_t* p) {
diff --git a/third_party/jpeg-xl/lib/jxl/base/common.h b/third_party/jpeg-xl/lib/jxl/base/common.h
index b7fe6ab0bc..0893ef26b5 100644
--- a/third_party/jpeg-xl/lib/jxl/base/common.h
+++ b/third_party/jpeg-xl/lib/jxl/base/common.h
@@ -8,11 +8,13 @@
// Shared constants and helper functions.
+#include <array>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <memory>
#include <string>
+#include <type_traits>
#include "lib/jxl/base/compiler_specific.h"
@@ -22,11 +24,11 @@ namespace jxl {
constexpr size_t kBitsPerByte = 8; // more clear than CHAR_BIT
constexpr inline size_t RoundUpBitsToByteMultiple(size_t bits) {
- return (bits + 7) & ~size_t(7);
+ return (bits + 7) & ~static_cast<size_t>(7);
}
constexpr inline size_t RoundUpToBlockDim(size_t dim) {
- return (dim + 7) & ~size_t(7);
+ return (dim + 7) & ~static_cast<size_t>(7);
}
static inline bool JXL_MAYBE_UNUSED SafeAdd(const uint64_t a, const uint64_t b,
@@ -68,6 +70,37 @@ std::unique_ptr<T> make_unique(Args&&... args) {
using std::make_unique;
#endif
+typedef std::array<float, 3> Color;
+
+// Backported std::experimental::to_array
+
+template <typename T>
+using remove_cv_t = typename std::remove_cv<T>::type;
+
+template <size_t... I>
+struct index_sequence {};
+
+template <size_t N, size_t... I>
+struct make_index_sequence : make_index_sequence<N - 1, N - 1, I...> {};
+
+template <size_t... I>
+struct make_index_sequence<0, I...> : index_sequence<I...> {};
+
+namespace detail {
+
+template <typename T, size_t N, size_t... I>
+constexpr auto to_array(T (&&arr)[N], index_sequence<I...> _)
+ -> std::array<remove_cv_t<T>, N> {
+ return {{std::move(arr[I])...}};
+}
+
+} // namespace detail
+
+template <typename T, size_t N>
+constexpr auto to_array(T (&&arr)[N]) -> std::array<remove_cv_t<T>, N> {
+ return detail::to_array(std::move(arr), make_index_sequence<N>());
+}
+
template <typename T>
JXL_INLINE T Clamp1(T val, T low, T hi) {
return val < low ? low : val > hi ? hi : val;
@@ -77,10 +110,10 @@ JXL_INLINE T Clamp1(T val, T low, T hi) {
template <typename T>
std::string ToString(T n) {
char data[32] = {};
- if (T(0.1) != T(0)) {
+ if (std::is_floating_point<T>::value) {
// float
snprintf(data, sizeof(data), "%g", static_cast<double>(n));
- } else if (T(-1) > T(0)) {
+ } else if (std::is_unsigned<T>::value) {
// unsigned
snprintf(data, sizeof(data), "%llu", static_cast<unsigned long long>(n));
} else {
@@ -90,6 +123,9 @@ std::string ToString(T n) {
return data;
}
+#define JXL_JOIN(x, y) JXL_DO_JOIN(x, y)
+#define JXL_DO_JOIN(x, y) x##y
+
} // namespace jxl
#endif // LIB_JXL_BASE_COMMON_H_
diff --git a/third_party/jpeg-xl/lib/jxl/base/exif.h b/third_party/jpeg-xl/lib/jxl/base/exif.h
index 2caafddc04..a3574a16ff 100644
--- a/third_party/jpeg-xl/lib/jxl/base/exif.h
+++ b/third_party/jpeg-xl/lib/jxl/base/exif.h
@@ -79,7 +79,6 @@ JXL_INLINE void InterpretExif(const std::vector<uint8_t>& exif,
uint32_t count = (bigendian ? LoadBE32(t) : LoadLE32(t));
t += 4;
uint16_t value = (bigendian ? LoadBE16(t) : LoadLE16(t));
- t += 4;
if (type == 3 && count == 1 && value >= 1 && value <= 8) {
*orientation = static_cast<JxlOrientation>(value);
}
diff --git a/third_party/jpeg-xl/lib/jxl/base/float.h b/third_party/jpeg-xl/lib/jxl/base/float.h
index 00e112bb34..0f5b3b1f3a 100644
--- a/third_party/jpeg-xl/lib/jxl/base/float.h
+++ b/third_party/jpeg-xl/lib/jxl/base/float.h
@@ -17,9 +17,9 @@
namespace jxl {
-namespace {
+namespace detail {
// Based on highway scalar implementation, for testing
-float LoadFloat16(uint16_t bits16) {
+static JXL_INLINE float LoadFloat16(uint16_t bits16) {
const uint32_t sign = bits16 >> 15;
const uint32_t biased_exp = (bits16 >> 10) & 0x1F;
const uint32_t mantissa = bits16 & 0x3FF;
@@ -40,7 +40,7 @@ float LoadFloat16(uint16_t bits16) {
memcpy(&result, &bits32, 4);
return result;
}
-} // namespace
+} // namespace detail
template <typename SaveFloatAtFn>
static Status JXL_INLINE LoadFloatRow(const uint8_t* src, size_t count,
@@ -83,11 +83,11 @@ static Status JXL_INLINE LoadFloatRow(const uint8_t* src, size_t count,
case JXL_TYPE_FLOAT16:
if (little_endian) {
for (size_t i = 0; i < count; ++i) {
- callback(i, LoadFloat16(LoadLE16(src + stride * i)));
+ callback(i, detail::LoadFloat16(LoadLE16(src + stride * i)));
}
} else {
for (size_t i = 0; i < count; ++i) {
- callback(i, LoadFloat16(LoadBE16(src + stride * i)));
+ callback(i, detail::LoadFloat16(LoadBE16(src + stride * i)));
}
}
return true;
diff --git a/third_party/jpeg-xl/lib/jxl/base/matrix_ops.h b/third_party/jpeg-xl/lib/jxl/base/matrix_ops.h
index 1a969bd4f0..cde6a64b1e 100644
--- a/third_party/jpeg-xl/lib/jxl/base/matrix_ops.h
+++ b/third_party/jpeg-xl/lib/jxl/base/matrix_ops.h
@@ -8,6 +8,7 @@
// 3x3 matrix operations.
+#include <array>
#include <cmath> // abs
#include <cstddef>
@@ -15,66 +16,67 @@
namespace jxl {
+typedef std::array<float, 3> Vector3;
+typedef std::array<double, 3> Vector3d;
+typedef std::array<Vector3, 3> Matrix3x3;
+typedef std::array<Vector3d, 3> Matrix3x3d;
+
// Computes C = A * B, where A, B, C are 3x3 matrices.
-template <typename T>
-void Mul3x3Matrix(const T* a, const T* b, T* c) {
- alignas(16) T temp[3]; // For transposed column
+template <typename Matrix>
+void Mul3x3Matrix(const Matrix& a, const Matrix& b, Matrix& c) {
for (size_t x = 0; x < 3; x++) {
- for (size_t z = 0; z < 3; z++) {
- temp[z] = b[z * 3 + x];
- }
+ alignas(16) Vector3d temp{b[0][x], b[1][x], b[2][x]}; // transpose
for (size_t y = 0; y < 3; y++) {
- double e = 0;
- for (size_t z = 0; z < 3; z++) {
- e += a[y * 3 + z] * temp[z];
- }
- c[y * 3 + x] = e;
+ c[y][x] = a[y][0] * temp[0] + a[y][1] * temp[1] + a[y][2] * temp[2];
}
}
}
// Computes C = A * B, where A is 3x3 matrix and B is vector.
-template <typename T>
-void Mul3x3Vector(const T* a, const T* b, T* c) {
+template <typename Matrix, typename Vector>
+void Mul3x3Vector(const Matrix& a, const Vector& b, Vector& c) {
for (size_t y = 0; y < 3; y++) {
double e = 0;
for (size_t x = 0; x < 3; x++) {
- e += a[y * 3 + x] * b[x];
+ e += a[y][x] * b[x];
}
c[y] = e;
}
}
// Inverts a 3x3 matrix in place.
-template <typename T>
-Status Inv3x3Matrix(T* matrix) {
+template <typename Matrix>
+Status Inv3x3Matrix(Matrix& matrix) {
// Intermediate computation is done in double precision.
- double temp[9];
- temp[0] = static_cast<double>(matrix[4]) * matrix[8] -
- static_cast<double>(matrix[5]) * matrix[7];
- temp[1] = static_cast<double>(matrix[2]) * matrix[7] -
- static_cast<double>(matrix[1]) * matrix[8];
- temp[2] = static_cast<double>(matrix[1]) * matrix[5] -
- static_cast<double>(matrix[2]) * matrix[4];
- temp[3] = static_cast<double>(matrix[5]) * matrix[6] -
- static_cast<double>(matrix[3]) * matrix[8];
- temp[4] = static_cast<double>(matrix[0]) * matrix[8] -
- static_cast<double>(matrix[2]) * matrix[6];
- temp[5] = static_cast<double>(matrix[2]) * matrix[3] -
- static_cast<double>(matrix[0]) * matrix[5];
- temp[6] = static_cast<double>(matrix[3]) * matrix[7] -
- static_cast<double>(matrix[4]) * matrix[6];
- temp[7] = static_cast<double>(matrix[1]) * matrix[6] -
- static_cast<double>(matrix[0]) * matrix[7];
- temp[8] = static_cast<double>(matrix[0]) * matrix[4] -
- static_cast<double>(matrix[1]) * matrix[3];
- double det = matrix[0] * temp[0] + matrix[1] * temp[3] + matrix[2] * temp[6];
+ Matrix3x3d temp;
+ temp[0][0] = static_cast<double>(matrix[1][1]) * matrix[2][2] -
+ static_cast<double>(matrix[1][2]) * matrix[2][1];
+ temp[0][1] = static_cast<double>(matrix[0][2]) * matrix[2][1] -
+ static_cast<double>(matrix[0][1]) * matrix[2][2];
+ temp[0][2] = static_cast<double>(matrix[0][1]) * matrix[1][2] -
+ static_cast<double>(matrix[0][2]) * matrix[1][1];
+ temp[1][0] = static_cast<double>(matrix[1][2]) * matrix[2][0] -
+ static_cast<double>(matrix[1][0]) * matrix[2][2];
+ temp[1][1] = static_cast<double>(matrix[0][0]) * matrix[2][2] -
+ static_cast<double>(matrix[0][2]) * matrix[2][0];
+ temp[1][2] = static_cast<double>(matrix[0][2]) * matrix[1][0] -
+ static_cast<double>(matrix[0][0]) * matrix[1][2];
+ temp[2][0] = static_cast<double>(matrix[1][0]) * matrix[2][1] -
+ static_cast<double>(matrix[1][1]) * matrix[2][0];
+ temp[2][1] = static_cast<double>(matrix[0][1]) * matrix[2][0] -
+ static_cast<double>(matrix[0][0]) * matrix[2][1];
+ temp[2][2] = static_cast<double>(matrix[0][0]) * matrix[1][1] -
+ static_cast<double>(matrix[0][1]) * matrix[1][0];
+ double det = matrix[0][0] * temp[0][0] + matrix[0][1] * temp[1][0] +
+ matrix[0][2] * temp[2][0];
if (std::abs(det) < 1e-10) {
return JXL_FAILURE("Matrix determinant is too close to 0");
}
double idet = 1.0 / det;
- for (size_t i = 0; i < 9; i++) {
- matrix[i] = temp[i] * idet;
+ for (size_t j = 0; j < 3; j++) {
+ for (size_t i = 0; i < 3; i++) {
+ matrix[j][i] = temp[j][i] * idet;
+ }
}
return true;
}
diff --git a/third_party/jpeg-xl/lib/jxl/base/override.h b/third_party/jpeg-xl/lib/jxl/base/override.h
index 1f8b657974..da070e6e62 100644
--- a/third_party/jpeg-xl/lib/jxl/base/override.h
+++ b/third_party/jpeg-xl/lib/jxl/base/override.h
@@ -6,13 +6,15 @@
#ifndef LIB_JXL_BASE_OVERRIDE_H_
#define LIB_JXL_BASE_OVERRIDE_H_
+#include <cstdint>
+
// 'Trool' for command line arguments: force enable/disable, or use default.
namespace jxl {
// No effect if kDefault, otherwise forces a feature (typically a FrameHeader
// flag) on or off.
-enum class Override : int { kOn = 1, kOff = 0, kDefault = -1 };
+enum class Override : int8_t { kOn = 1, kOff = 0, kDefault = -1 };
static inline Override OverrideFromBool(bool flag) {
return flag ? Override::kOn : Override::kOff;
diff --git a/third_party/jpeg-xl/lib/jxl/base/rational_polynomial-inl.h b/third_party/jpeg-xl/lib/jxl/base/rational_polynomial-inl.h
index e073937675..7a89c0bac1 100644
--- a/third_party/jpeg-xl/lib/jxl/base/rational_polynomial-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/base/rational_polynomial-inl.h
@@ -13,6 +13,7 @@
#define LIB_JXL_BASE_RATIONAL_POLYNOMIAL_INL_H_
#endif
+#include <jxl/types.h>
#include <stddef.h>
#include <hwy/highway.h>
@@ -42,7 +43,7 @@ struct FastDivision<float, V> {
}
V operator()(const V n, const V d) const {
-#if 1 // Faster on SKX
+#if JXL_TRUE // Faster on SKX
return Div(n, d);
#else
return n * ReciprocalNR(d);
diff --git a/third_party/jpeg-xl/lib/jxl/base/scope_guard.h b/third_party/jpeg-xl/lib/jxl/base/scope_guard.h
index a18a44cb79..f060c5bc1d 100644
--- a/third_party/jpeg-xl/lib/jxl/base/scope_guard.h
+++ b/third_party/jpeg-xl/lib/jxl/base/scope_guard.h
@@ -24,8 +24,8 @@ class ScopeGuard {
}
template <typename CallbackParam>
- explicit ScopeGuard(CallbackParam &&callback)
- : callback_(std::forward<CallbackParam>(callback)), armed_(true) {}
+ ScopeGuard(CallbackParam &&callback, bool armed)
+ : callback_(std::forward<CallbackParam>(callback)), armed_(armed) {}
~ScopeGuard() {
if (armed_) callback_();
@@ -40,7 +40,7 @@ class ScopeGuard {
template <typename Callback>
ScopeGuard<Callback> MakeScopeGuard(Callback &&callback) {
- return ScopeGuard<Callback>{std::forward<Callback>(callback)};
+ return ScopeGuard<Callback>{std::forward<Callback>(callback), true};
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/base/span.h b/third_party/jpeg-xl/lib/jxl/base/span.h
index dc1c781b9d..ba09d62316 100644
--- a/third_party/jpeg-xl/lib/jxl/base/span.h
+++ b/third_party/jpeg-xl/lib/jxl/base/span.h
@@ -64,8 +64,8 @@ class Span {
// NCT == non-const-T; compiler will complain if NCT is not compatible with T.
template <typename NCT>
- void AppendTo(std::vector<NCT>* dst) const {
- dst->insert(dst->end(), begin(), end());
+ void AppendTo(std::vector<NCT>& dst) const {
+ dst.insert(dst.end(), begin(), end());
}
private:
diff --git a/third_party/jpeg-xl/lib/jxl/base/status.h b/third_party/jpeg-xl/lib/jxl/base/status.h
index b33bd64fc3..2e88ba68ae 100644
--- a/third_party/jpeg-xl/lib/jxl/base/status.h
+++ b/third_party/jpeg-xl/lib/jxl/base/status.h
@@ -16,6 +16,7 @@
#include <type_traits>
#include <utility>
+#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/sanitizer_definitions.h"
@@ -442,7 +443,7 @@ class JXL_MUST_USE_RESULT StatusOr {
#define JXL_ASSIGN_OR_RETURN(lhs, statusor) \
PRIVATE_JXL_ASSIGN_OR_RETURN_IMPL( \
- assign_or_return_temporary_variable##__LINE__, lhs, statusor)
+ JXL_JOIN(assign_or_return_temporary_variable, __LINE__), lhs, statusor)
// NOLINTBEGIN(bugprone-macro-parentheses)
#define PRIVATE_JXL_ASSIGN_OR_RETURN_IMPL(name, lhs, statusor) \
@@ -451,6 +452,18 @@ class JXL_MUST_USE_RESULT StatusOr {
lhs = std::move(name).value();
// NOLINTEND(bugprone-macro-parentheses)
+// NB: do not use outside of tests / tools!!!
+#define JXL_ASSIGN_OR_DIE(lhs, statusor) \
+ PRIVATE_JXL_ASSIGN_OR_DIE_IMPL( \
+ JXL_JOIN(assign_or_die_temporary_variable, __LINE__), lhs, statusor)
+
+// NOLINTBEGIN(bugprone-macro-parentheses)
+#define PRIVATE_JXL_ASSIGN_OR_DIE_IMPL(name, lhs, statusor) \
+ auto name = statusor; \
+ if (!name.ok()) jxl::Abort(); \
+ lhs = std::move(name).value();
+// NOLINTEND(bugprone-macro-parentheses)
+
} // namespace jxl
#endif // LIB_JXL_BASE_STATUS_H_
diff --git a/third_party/jpeg-xl/lib/jxl/bits_test.cc b/third_party/jpeg-xl/lib/jxl/bits_test.cc
index bd7aa548c8..45db8c0d6e 100644
--- a/third_party/jpeg-xl/lib/jxl/bits_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/bits_test.cc
@@ -38,7 +38,8 @@ TEST(BitsTest, TestFloorLog2) {
const size_t expected[7] = {0, 1, 1, 2, 2, 2, 2};
for (uint32_t i = 1; i <= 7; ++i) {
EXPECT_EQ(expected[i - 1], FloorLog2Nonzero(i)) << " " << i;
- EXPECT_EQ(expected[i - 1], FloorLog2Nonzero(uint64_t(i))) << " " << i;
+ EXPECT_EQ(expected[i - 1], FloorLog2Nonzero(static_cast<uint64_t>(i)))
+ << " " << i;
}
EXPECT_EQ(11u, FloorLog2Nonzero(0x00000fffu)); // 4095
@@ -63,7 +64,8 @@ TEST(BitsTest, TestCeilLog2) {
const size_t expected[7] = {0, 1, 2, 2, 3, 3, 3};
for (uint32_t i = 1; i <= 7; ++i) {
EXPECT_EQ(expected[i - 1], CeilLog2Nonzero(i)) << " " << i;
- EXPECT_EQ(expected[i - 1], CeilLog2Nonzero(uint64_t(i))) << " " << i;
+ EXPECT_EQ(expected[i - 1], CeilLog2Nonzero(static_cast<uint64_t>(i)))
+ << " " << i;
}
EXPECT_EQ(12u, CeilLog2Nonzero(0x00000fffu)); // 4095
diff --git a/third_party/jpeg-xl/lib/jxl/blending.cc b/third_party/jpeg-xl/lib/jxl/blending.cc
index ccb168ee45..7575ec6e4a 100644
--- a/third_party/jpeg-xl/lib/jxl/blending.cc
+++ b/third_party/jpeg-xl/lib/jxl/blending.cc
@@ -6,7 +6,6 @@
#include "lib/jxl/blending.h"
#include "lib/jxl/alpha.h"
-#include "lib/jxl/image_ops.h"
namespace jxl {
@@ -29,11 +28,11 @@ bool NeedsBlending(const FrameHeader& frame_header) {
return true;
}
-void PerformBlending(const float* const* bg, const float* const* fg,
- float* const* out, size_t x0, size_t xsize,
- const PatchBlending& color_blending,
- const PatchBlending* ec_blending,
- const std::vector<ExtraChannelInfo>& extra_channel_info) {
+Status PerformBlending(
+ const float* const* bg, const float* const* fg, float* const* out,
+ size_t x0, size_t xsize, const PatchBlending& color_blending,
+ const PatchBlending* ec_blending,
+ const std::vector<ExtraChannelInfo>& extra_channel_info) {
bool has_alpha = false;
size_t num_ec = extra_channel_info.size();
for (size_t i = 0; i < num_ec; i++) {
@@ -42,7 +41,7 @@ void PerformBlending(const float* const* bg, const float* const* fg,
break;
}
}
- ImageF tmp(xsize, 3 + num_ec);
+ JXL_ASSIGN_OR_RETURN(ImageF tmp, ImageF::Create(xsize, 3 + num_ec));
// Blend extra channels first so that we use the pre-blending alpha.
for (size_t i = 0; i < num_ec; i++) {
if (ec_blending[i].mode == PatchBlendMode::kAdd) {
@@ -146,6 +145,7 @@ void PerformBlending(const float* const* bg, const float* const* fg,
for (size_t i = 0; i < 3 + num_ec; i++) {
if (xsize != 0) memcpy(out[i] + x0, tmp.Row(i), xsize * sizeof(**out));
}
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/blending.h b/third_party/jpeg-xl/lib/jxl/blending.h
index 3f23297f1d..94bead8dd6 100644
--- a/third_party/jpeg-xl/lib/jxl/blending.h
+++ b/third_party/jpeg-xl/lib/jxl/blending.h
@@ -16,11 +16,11 @@ namespace jxl {
bool NeedsBlending(const FrameHeader& frame_header);
-void PerformBlending(const float* const* bg, const float* const* fg,
- float* const* out, size_t x0, size_t xsize,
- const PatchBlending& color_blending,
- const PatchBlending* ec_blending,
- const std::vector<ExtraChannelInfo>& extra_channel_info);
+Status PerformBlending(const float* const* bg, const float* const* fg,
+ float* const* out, size_t x0, size_t xsize,
+ const PatchBlending& color_blending,
+ const PatchBlending* ec_blending,
+ const std::vector<ExtraChannelInfo>& extra_channel_info);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/blending_test.cc b/third_party/jpeg-xl/lib/jxl/blending_test.cc
index c34ab5c7ca..c363358592 100644
--- a/third_party/jpeg-xl/lib/jxl/blending_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/blending_test.cc
@@ -20,8 +20,6 @@
namespace jxl {
namespace {
-using ::testing::SizeIs;
-
TEST(BlendingTest, Crops) {
const std::vector<uint8_t> compressed =
jxl::test::ReadTestData("jxl/blending/cropped_traffic_light.jxl");
@@ -30,7 +28,7 @@ TEST(BlendingTest, Crops) {
extras::PackedPixelFile decoded;
ASSERT_TRUE(DecodeImageJXL(compressed.data(), compressed.size(), dparams,
/*decoded_bytes=*/nullptr, &decoded));
- ASSERT_THAT(decoded.frames, SizeIs(4));
+ ASSERT_EQ(decoded.frames.size(), 4);
int i = 0;
for (auto&& decoded_frame : decoded.frames) {
@@ -40,8 +38,10 @@ TEST(BlendingTest, Crops) {
jxl::test::ReadTestData(filename.str());
extras::PackedPixelFile decoded_frame_ppf;
decoded_frame_ppf.info = decoded.info;
- decoded_frame_ppf.icc = decoded.icc;
+ decoded_frame_ppf.primary_color_representation =
+ decoded.primary_color_representation;
decoded_frame_ppf.color_encoding = decoded.color_encoding;
+ decoded_frame_ppf.icc = decoded.icc;
decoded_frame_ppf.extra_channels_info = decoded.extra_channels_info;
decoded_frame_ppf.frames.emplace_back(std::move(decoded_frame));
extras::PackedPixelFile expected_frame_ppf;
diff --git a/third_party/jpeg-xl/lib/jxl/box_content_decoder.cc b/third_party/jpeg-xl/lib/jxl/box_content_decoder.cc
index c4cba3a31a..c7d87f4ca0 100644
--- a/third_party/jpeg-xl/lib/jxl/box_content_decoder.cc
+++ b/third_party/jpeg-xl/lib/jxl/box_content_decoder.cc
@@ -9,7 +9,7 @@
namespace jxl {
-JxlBoxContentDecoder::JxlBoxContentDecoder() {}
+JxlBoxContentDecoder::JxlBoxContentDecoder() = default;
JxlBoxContentDecoder::~JxlBoxContentDecoder() {
if (brotli_dec) {
diff --git a/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.cc b/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.cc
index 66dde9afb1..2e06d79eba 100644
--- a/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.cc
+++ b/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.cc
@@ -28,11 +28,12 @@
#include <string.h>
#include <algorithm>
-#include <array>
#include <cmath>
-#include <new>
+#include <memory>
#include <vector>
+#include "lib/jxl/image.h"
+
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/butteraugli/butteraugli.cc"
#include <hwy/foreach_target.h>
@@ -222,8 +223,8 @@ void ConvolutionWithTranspose(const ImageF& in,
// We retain a special case for 5x5 kernels (even faster than gauss_blur),
// optionally use gauss_blur followed by fixup of the borders for large images,
// or fall back to the previous truncated FIR followed by a transpose.
-void Blur(const ImageF& in, float sigma, const ButteraugliParams& params,
- BlurTemp* temp, ImageF* out) {
+Status Blur(const ImageF& in, float sigma, const ButteraugliParams& params,
+ BlurTemp* temp, ImageF* out) {
std::vector<float> kernel = ComputeKernel(sigma);
// Separable5 does an in-place convolution, so this fast path is not safe if
// in aliases out.
@@ -241,12 +242,14 @@ void Blur(const ImageF& in, float sigma, const ButteraugliParams& params,
{HWY_REP4(w0), HWY_REP4(w1), HWY_REP4(w2)},
};
Separable5(in, Rect(in), weights, /*pool=*/nullptr, out);
- return;
+ return true;
}
- ImageF* JXL_RESTRICT temp_t = temp->GetTransposed(in);
+ ImageF* temp_t;
+ JXL_RETURN_IF_ERROR(temp->GetTransposed(in, &temp_t));
ConvolutionWithTranspose(in, kernel, temp_t);
ConvolutionWithTranspose(*temp_t, kernel, out);
+ return true;
}
// Allows PaddedMaltaUnit to call either function via overloading.
@@ -386,29 +389,32 @@ void Subtract(const ImageF& a, const ImageF& b, ImageF* c) {
}
}
-void SeparateLFAndMF(const ButteraugliParams& params, const Image3F& xyb,
- Image3F* lf, Image3F* mf, BlurTemp* blur_temp) {
+Status SeparateLFAndMF(const ButteraugliParams& params, const Image3F& xyb,
+ Image3F* lf, Image3F* mf, BlurTemp* blur_temp) {
static const double kSigmaLf = 7.15593339443;
for (int i = 0; i < 3; ++i) {
// Extract lf ...
- Blur(xyb.Plane(i), kSigmaLf, params, blur_temp, &lf->Plane(i));
+ JXL_RETURN_IF_ERROR(
+ Blur(xyb.Plane(i), kSigmaLf, params, blur_temp, &lf->Plane(i)));
// ... and keep everything else in mf.
Subtract(xyb.Plane(i), lf->Plane(i), &mf->Plane(i));
}
XybLowFreqToVals(lf);
+ return true;
}
-void SeparateMFAndHF(const ButteraugliParams& params, Image3F* mf, ImageF* hf,
- BlurTemp* blur_temp) {
+Status SeparateMFAndHF(const ButteraugliParams& params, Image3F* mf, ImageF* hf,
+ BlurTemp* blur_temp) {
const HWY_FULL(float) d;
static const double kSigmaHf = 3.22489901262;
const size_t xsize = mf->xsize();
const size_t ysize = mf->ysize();
- hf[0] = ImageF(xsize, ysize);
- hf[1] = ImageF(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(hf[0], ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_RETURN(hf[1], ImageF::Create(xsize, ysize));
for (int i = 0; i < 3; ++i) {
if (i == 2) {
- Blur(mf->Plane(i), kSigmaHf, params, blur_temp, &mf->Plane(i));
+ JXL_RETURN_IF_ERROR(
+ Blur(mf->Plane(i), kSigmaHf, params, blur_temp, &mf->Plane(i)));
break;
}
for (size_t y = 0; y < ysize; ++y) {
@@ -418,7 +424,8 @@ void SeparateMFAndHF(const ButteraugliParams& params, Image3F* mf, ImageF* hf,
Store(Load(d, row_mf + x), d, row_hf + x);
}
}
- Blur(mf->Plane(i), kSigmaHf, params, blur_temp, &mf->Plane(i));
+ JXL_RETURN_IF_ERROR(
+ Blur(mf->Plane(i), kSigmaHf, params, blur_temp, &mf->Plane(i)));
static const double kRemoveMfRange = 0.29;
static const double kAddMfRange = 0.1;
if (i == 0) {
@@ -450,16 +457,17 @@ void SeparateMFAndHF(const ButteraugliParams& params, Image3F* mf, ImageF* hf,
}
// Suppress red-green by intensity change in the high freq channels.
SuppressXByY(hf[1], &hf[0]);
+ return true;
}
-void SeparateHFAndUHF(const ButteraugliParams& params, ImageF* hf, ImageF* uhf,
- BlurTemp* blur_temp) {
+Status SeparateHFAndUHF(const ButteraugliParams& params, ImageF* hf,
+ ImageF* uhf, BlurTemp* blur_temp) {
const HWY_FULL(float) d;
const size_t xsize = hf[0].xsize();
const size_t ysize = hf[0].ysize();
static const double kSigmaUhf = 1.56416327805;
- uhf[0] = ImageF(xsize, ysize);
- uhf[1] = ImageF(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(uhf[0], ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_RETURN(uhf[1], ImageF::Create(xsize, ysize));
for (int i = 0; i < 2; ++i) {
// Divide hf into hf and uhf.
for (size_t y = 0; y < ysize; ++y) {
@@ -469,7 +477,7 @@ void SeparateHFAndUHF(const ButteraugliParams& params, ImageF* hf, ImageF* uhf,
row_uhf[x] = row_hf[x];
}
}
- Blur(hf[i], kSigmaUhf, params, blur_temp, &hf[i]);
+ JXL_RETURN_IF_ERROR(Blur(hf[i], kSigmaUhf, params, blur_temp, &hf[i]));
static const double kRemoveHfRange = 1.5;
static const double kAddHfRange = 0.132;
static const double kRemoveUhfRange = 0.04;
@@ -510,6 +518,7 @@ void SeparateHFAndUHF(const ButteraugliParams& params, ImageF* hf, ImageF* uhf,
}
}
}
+ return true;
}
void DeallocateHFAndUHF(ImageF* hf, ImageF* uhf) {
@@ -519,15 +528,16 @@ void DeallocateHFAndUHF(ImageF* hf, ImageF* uhf) {
}
}
-static void SeparateFrequencies(size_t xsize, size_t ysize,
- const ButteraugliParams& params,
- BlurTemp* blur_temp, const Image3F& xyb,
- PsychoImage& ps) {
- ps.lf = Image3F(xyb.xsize(), xyb.ysize());
- ps.mf = Image3F(xyb.xsize(), xyb.ysize());
- SeparateLFAndMF(params, xyb, &ps.lf, &ps.mf, blur_temp);
- SeparateMFAndHF(params, &ps.mf, &ps.hf[0], blur_temp);
- SeparateHFAndUHF(params, &ps.hf[0], &ps.uhf[0], blur_temp);
+Status SeparateFrequencies(size_t xsize, size_t ysize,
+ const ButteraugliParams& params, BlurTemp* blur_temp,
+ const Image3F& xyb, PsychoImage& ps) {
+ JXL_ASSIGN_OR_RETURN(ps.lf, Image3F::Create(xyb.xsize(), xyb.ysize()));
+ JXL_ASSIGN_OR_RETURN(ps.mf, Image3F::Create(xyb.xsize(), xyb.ysize()));
+ JXL_RETURN_IF_ERROR(SeparateLFAndMF(params, xyb, &ps.lf, &ps.mf, blur_temp));
+ JXL_RETURN_IF_ERROR(SeparateMFAndHF(params, &ps.mf, &ps.hf[0], blur_temp));
+ JXL_RETURN_IF_ERROR(
+ SeparateHFAndUHF(params, &ps.hf[0], &ps.uhf[0], blur_temp));
+ return true;
}
namespace {
@@ -1024,7 +1034,7 @@ static void MaltaDiffMapT(const Tag tag, const ImageF& lum0, const ImageF& lum1,
}
const HWY_FULL(float) df;
- const size_t aligned_x = std::max(size_t(4), Lanes(df));
+ const size_t aligned_x = std::max(static_cast<size_t>(4), Lanes(df));
const intptr_t stride = diffs->PixelsPerRow();
// Middle
@@ -1097,7 +1107,7 @@ void CombineChannelsForMasking(const ImageF* hf, const ImageF* uhf,
float xdiff = (row_x_uhf[x] + row_x_hf[x]) * muls[0];
float ydiff = row_y_uhf[x] * muls[1] + row_y_hf[x] * muls[2];
row[x] = xdiff * xdiff + ydiff * ydiff;
- row[x] = sqrt(row[x]);
+ row[x] = std::sqrt(row[x]);
}
}
}
@@ -1106,13 +1116,13 @@ void DiffPrecompute(const ImageF& xyb, float mul, float bias_arg, ImageF* out) {
const size_t xsize = xyb.xsize();
const size_t ysize = xyb.ysize();
const float bias = mul * bias_arg;
- const float sqrt_bias = sqrt(bias);
+ const float sqrt_bias = std::sqrt(bias);
for (size_t y = 0; y < ysize; ++y) {
const float* BUTTERAUGLI_RESTRICT row_in = xyb.Row(y);
float* BUTTERAUGLI_RESTRICT row_out = out->Row(y);
for (size_t x = 0; x < xsize; ++x) {
// kBias makes sqrt behave more linearly.
- row_out[x] = sqrt(mul * std::abs(row_in[x]) + bias) - sqrt_bias;
+ row_out[x] = std::sqrt(mul * std::abs(row_in[x]) + bias) - sqrt_bias;
}
}
}
@@ -1188,25 +1198,25 @@ void FuzzyErosion(const ImageF& from, ImageF* to) {
// Compute values of local frequency and dc masking based on the activity
// in the two images. img_diff_ac may be null.
-void Mask(const ImageF& mask0, const ImageF& mask1,
- const ButteraugliParams& params, BlurTemp* blur_temp,
- ImageF* BUTTERAUGLI_RESTRICT mask,
- ImageF* BUTTERAUGLI_RESTRICT diff_ac) {
+Status Mask(const ImageF& mask0, const ImageF& mask1,
+ const ButteraugliParams& params, BlurTemp* blur_temp,
+ ImageF* BUTTERAUGLI_RESTRICT mask,
+ ImageF* BUTTERAUGLI_RESTRICT diff_ac) {
const size_t xsize = mask0.xsize();
const size_t ysize = mask0.ysize();
- *mask = ImageF(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(*mask, ImageF::Create(xsize, ysize));
static const float kMul = 6.19424080439;
static const float kBias = 12.61050594197;
static const float kRadius = 2.7;
- ImageF diff0(xsize, ysize);
- ImageF diff1(xsize, ysize);
- ImageF blurred0(xsize, ysize);
- ImageF blurred1(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF diff0, ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_RETURN(ImageF diff1, ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_RETURN(ImageF blurred0, ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_RETURN(ImageF blurred1, ImageF::Create(xsize, ysize));
DiffPrecompute(mask0, kMul, kBias, &diff0);
DiffPrecompute(mask1, kMul, kBias, &diff1);
- Blur(diff0, kRadius, params, blur_temp, &blurred0);
+ JXL_RETURN_IF_ERROR(Blur(diff0, kRadius, params, blur_temp, &blurred0));
FuzzyErosion(blurred0, &diff0);
- Blur(diff1, kRadius, params, blur_temp, &blurred1);
+ JXL_RETURN_IF_ERROR(Blur(diff1, kRadius, params, blur_temp, &blurred1));
for (size_t y = 0; y < ysize; ++y) {
for (size_t x = 0; x < xsize; ++x) {
mask->Row(y)[x] = diff0.Row(y)[x];
@@ -1217,19 +1227,21 @@ void Mask(const ImageF& mask0, const ImageF& mask1,
}
}
}
+ return true;
}
// `diff_ac` may be null.
-void MaskPsychoImage(const PsychoImage& pi0, const PsychoImage& pi1,
- const size_t xsize, const size_t ysize,
- const ButteraugliParams& params, BlurTemp* blur_temp,
- ImageF* BUTTERAUGLI_RESTRICT mask,
- ImageF* BUTTERAUGLI_RESTRICT diff_ac) {
- ImageF mask0(xsize, ysize);
- ImageF mask1(xsize, ysize);
+Status MaskPsychoImage(const PsychoImage& pi0, const PsychoImage& pi1,
+ const size_t xsize, const size_t ysize,
+ const ButteraugliParams& params, BlurTemp* blur_temp,
+ ImageF* BUTTERAUGLI_RESTRICT mask,
+ ImageF* BUTTERAUGLI_RESTRICT diff_ac) {
+ JXL_ASSIGN_OR_RETURN(ImageF mask0, ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_RETURN(ImageF mask1, ImageF::Create(xsize, ysize));
CombineChannelsForMasking(&pi0.hf[0], &pi0.uhf[0], &mask0);
CombineChannelsForMasking(&pi1.hf[0], &pi1.uhf[0], &mask1);
- Mask(mask0, mask1, params, blur_temp, mask, diff_ac);
+ JXL_RETURN_IF_ERROR(Mask(mask0, mask1, params, blur_temp, mask, diff_ac));
+ return true;
}
double MaskY(double delta) {
@@ -1275,8 +1287,8 @@ void CombineChannelsToDiffmap(const ImageF& mask, const Image3F& block_diff_dc,
}
diff_ac[0] *= xmul;
diff_dc[0] *= xmul;
- row_out[x] =
- sqrt(MaskColor(diff_dc, dc_maskval) + MaskColor(diff_ac, maskval));
+ row_out[x] = std::sqrt(MaskColor(diff_dc, dc_maskval) +
+ MaskColor(diff_ac, maskval));
}
}
}
@@ -1430,12 +1442,15 @@ BUTTERAUGLI_INLINE void OpsinAbsorbance(const DF df, const V& in0, const V& in1,
}
// `blurred` is a temporary image used inside this function and not returned.
-void OpsinDynamicsImage(const Image3F& rgb, const ButteraugliParams& params,
- Image3F* blurred, BlurTemp* blur_temp, Image3F* xyb) {
+Status OpsinDynamicsImage(const Image3F& rgb, const ButteraugliParams& params,
+ Image3F* blurred, BlurTemp* blur_temp, Image3F* xyb) {
const double kSigma = 1.2;
- Blur(rgb.Plane(0), kSigma, params, blur_temp, &blurred->Plane(0));
- Blur(rgb.Plane(1), kSigma, params, blur_temp, &blurred->Plane(1));
- Blur(rgb.Plane(2), kSigma, params, blur_temp, &blurred->Plane(2));
+ JXL_RETURN_IF_ERROR(
+ Blur(rgb.Plane(0), kSigma, params, blur_temp, &blurred->Plane(0)));
+ JXL_RETURN_IF_ERROR(
+ Blur(rgb.Plane(1), kSigma, params, blur_temp, &blurred->Plane(1)));
+ JXL_RETURN_IF_ERROR(
+ Blur(rgb.Plane(2), kSigma, params, blur_temp, &blurred->Plane(2)));
const HWY_FULL(float) df;
const auto intensity_target_multiplier = Set(df, params.intensity_target);
for (size_t y = 0; y < rgb.ysize(); ++y) {
@@ -1497,31 +1512,36 @@ void OpsinDynamicsImage(const Image3F& rgb, const ButteraugliParams& params,
Store(cur_mixed2, df, row_out_b + x);
}
}
+ return true;
}
-void ButteraugliDiffmapInPlace(Image3F& image0, Image3F& image1,
- const ButteraugliParams& params,
- ImageF& diffmap) {
+Status ButteraugliDiffmapInPlace(Image3F& image0, Image3F& image1,
+ const ButteraugliParams& params,
+ ImageF& diffmap) {
// image0 and image1 are in linear sRGB color space
const size_t xsize = image0.xsize();
const size_t ysize = image0.ysize();
BlurTemp blur_temp;
{
// Convert image0 and image1 to XYB in-place
- Image3F temp(xsize, ysize);
- OpsinDynamicsImage(image0, params, &temp, &blur_temp, &image0);
- OpsinDynamicsImage(image1, params, &temp, &blur_temp, &image1);
+ JXL_ASSIGN_OR_RETURN(Image3F temp, Image3F::Create(xsize, ysize));
+ JXL_RETURN_IF_ERROR(
+ OpsinDynamicsImage(image0, params, &temp, &blur_temp, &image0));
+ JXL_RETURN_IF_ERROR(
+ OpsinDynamicsImage(image1, params, &temp, &blur_temp, &image1));
}
// image0 and image1 are in XYB color space
- ImageF block_diff_dc(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF block_diff_dc, ImageF::Create(xsize, ysize));
ZeroFillImage(&block_diff_dc);
{
// separate out LF components from image0 and image1 and compute the dc
// diff image from them
- Image3F lf0 = Image3F(xsize, ysize);
- Image3F lf1 = Image3F(xsize, ysize);
- SeparateLFAndMF(params, image0, &lf0, &image0, &blur_temp);
- SeparateLFAndMF(params, image1, &lf1, &image1, &blur_temp);
+ JXL_ASSIGN_OR_RETURN(Image3F lf0, Image3F::Create(xsize, ysize));
+ JXL_ASSIGN_OR_RETURN(Image3F lf1, Image3F::Create(xsize, ysize));
+ JXL_RETURN_IF_ERROR(
+ SeparateLFAndMF(params, image0, &lf0, &image0, &blur_temp));
+ JXL_RETURN_IF_ERROR(
+ SeparateLFAndMF(params, image1, &lf1, &image1, &blur_temp));
for (size_t c = 0; c < 3; ++c) {
L2Diff(lf0.Plane(c), lf1.Plane(c), wmul[6 + c], &block_diff_dc);
}
@@ -1529,15 +1549,15 @@ void ButteraugliDiffmapInPlace(Image3F& image0, Image3F& image1,
// image0 and image1 are MF residuals (before blurring) in XYB color space
ImageF hf0[2];
ImageF hf1[2];
- SeparateMFAndHF(params, &image0, &hf0[0], &blur_temp);
- SeparateMFAndHF(params, &image1, &hf1[0], &blur_temp);
+ JXL_RETURN_IF_ERROR(SeparateMFAndHF(params, &image0, &hf0[0], &blur_temp));
+ JXL_RETURN_IF_ERROR(SeparateMFAndHF(params, &image1, &hf1[0], &blur_temp));
// image0 and image1 are MF-images in XYB color space
- ImageF block_diff_ac(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF block_diff_ac, ImageF::Create(xsize, ysize));
ZeroFillImage(&block_diff_ac);
// start accumulating ac diff image from MF images
{
- ImageF diffs(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF diffs, ImageF::Create(xsize, ysize));
MaltaDiffMapLF(image0.Plane(1), image1.Plane(1), wMfMalta, wMfMalta,
norm1Mf, &diffs, &block_diff_ac);
MaltaDiffMapLF(image0.Plane(0), image1.Plane(0), wMfMaltaX, wMfMaltaX,
@@ -1553,13 +1573,13 @@ void ButteraugliDiffmapInPlace(Image3F& image0, Image3F& image1,
ImageF uhf0[2];
ImageF uhf1[2];
- SeparateHFAndUHF(params, &hf0[0], &uhf0[0], &blur_temp);
- SeparateHFAndUHF(params, &hf1[0], &uhf1[0], &blur_temp);
+ JXL_RETURN_IF_ERROR(SeparateHFAndUHF(params, &hf0[0], &uhf0[0], &blur_temp));
+ JXL_RETURN_IF_ERROR(SeparateHFAndUHF(params, &hf1[0], &uhf1[0], &blur_temp));
// continue accumulating ac diff image from HF and UHF images
const float hf_asymmetry = params.hf_asymmetry;
{
- ImageF diffs(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF diffs, ImageF::Create(xsize, ysize));
MaltaDiffMap(uhf0[1], uhf1[1], wUhfMalta * hf_asymmetry,
wUhfMalta / hf_asymmetry, norm1Uhf, &diffs, &block_diff_ac);
MaltaDiffMap(uhf0[0], uhf1[0], wUhfMaltaX * hf_asymmetry,
@@ -1577,19 +1597,20 @@ void ButteraugliDiffmapInPlace(Image3F& image0, Image3F& image1,
}
// compute mask image from HF and UHF X and Y images
- ImageF mask(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF mask, ImageF::Create(xsize, ysize));
{
- ImageF mask0(xsize, ysize);
- ImageF mask1(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF mask0, ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_RETURN(ImageF mask1, ImageF::Create(xsize, ysize));
CombineChannelsForMasking(&hf0[0], &uhf0[0], &mask0);
CombineChannelsForMasking(&hf1[0], &uhf1[0], &mask1);
DeallocateHFAndUHF(&hf1[0], &uhf1[0]);
DeallocateHFAndUHF(&hf0[0], &uhf0[0]);
- Mask(mask0, mask1, params, &blur_temp, &mask, &block_diff_ac);
+ JXL_RETURN_IF_ERROR(
+ Mask(mask0, mask1, params, &blur_temp, &mask, &block_diff_ac));
}
// compute final diffmap from mask image and ac and dc diff images
- diffmap = ImageF(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(diffmap, ImageF::Create(xsize, ysize));
for (size_t y = 0; y < ysize; ++y) {
const float* row_dc = block_diff_dc.Row(y);
const float* row_ac = block_diff_ac.Row(y);
@@ -1599,6 +1620,7 @@ void ButteraugliDiffmapInPlace(Image3F& image0, Image3F& image1,
row_out[x] = sqrt(row_dc[x] * MaskDcY(val) + row_ac[x] * MaskY(val));
}
}
+ return true;
}
// NOLINTNEXTLINE(google-readability-namespace-comments)
@@ -1669,10 +1691,10 @@ static inline void CheckImage(const ImageF& image, const char* name) {
// Calculate a 2x2 subsampled image for purposes of recursive butteraugli at
// multiresolution.
-static Image3F SubSample2x(const Image3F& in) {
+static StatusOr<Image3F> SubSample2x(const Image3F& in) {
size_t xs = (in.xsize() + 1) / 2;
size_t ys = (in.ysize() + 1) / 2;
- Image3F retval(xs, ys);
+ JXL_ASSIGN_OR_RETURN(Image3F retval, Image3F::Create(xs, ys));
for (size_t c = 0; c < 3; ++c) {
for (size_t y = 0; y < ys; ++y) {
for (size_t x = 0; x < xs; ++x) {
@@ -1724,69 +1746,86 @@ Image3F* ButteraugliComparator::Temp() const {
void ButteraugliComparator::ReleaseTemp() const { temp_in_use_.clear(); }
-ButteraugliComparator::ButteraugliComparator(const Image3F& rgb0,
+ButteraugliComparator::ButteraugliComparator(size_t xsize, size_t ysize,
const ButteraugliParams& params)
- : xsize_(rgb0.xsize()),
- ysize_(rgb0.ysize()),
- params_(params),
- temp_(xsize_, ysize_) {
- if (xsize_ < 8 || ysize_ < 8) {
- return;
+ : xsize_(xsize), ysize_(ysize), params_(params) {}
+
+StatusOr<std::unique_ptr<ButteraugliComparator>> ButteraugliComparator::Make(
+ const Image3F& rgb0, const ButteraugliParams& params) {
+ size_t xsize = rgb0.xsize();
+ size_t ysize = rgb0.ysize();
+ std::unique_ptr<ButteraugliComparator> result =
+ std::unique_ptr<ButteraugliComparator>(
+ new ButteraugliComparator(xsize, ysize, params));
+ JXL_ASSIGN_OR_RETURN(result->temp_, Image3F::Create(xsize, ysize));
+
+ if (xsize < 8 || ysize < 8) {
+ return result;
}
- Image3F xyb0(xsize_, ysize_);
- HWY_DYNAMIC_DISPATCH(OpsinDynamicsImage)
- (rgb0, params, Temp(), &blur_temp_, &xyb0);
- ReleaseTemp();
- HWY_DYNAMIC_DISPATCH(SeparateFrequencies)
- (xsize_, ysize_, params_, &blur_temp_, xyb0, pi0_);
+ JXL_ASSIGN_OR_RETURN(Image3F xyb0, Image3F::Create(xsize, ysize));
+ JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(OpsinDynamicsImage)(
+ rgb0, params, result->Temp(), &result->blur_temp_, &xyb0));
+ result->ReleaseTemp();
+ JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(SeparateFrequencies)(
+ xsize, ysize, params, &result->blur_temp_, xyb0, result->pi0_));
// Awful recursive construction of samples of different resolution.
// This is an after-thought and possibly somewhat parallel in
// functionality with the PsychoImage multi-resolution approach.
- sub_.reset(new ButteraugliComparator(SubSample2x(rgb0), params));
+ JXL_ASSIGN_OR_RETURN(Image3F subsampledRgb0, SubSample2x(rgb0));
+ StatusOr<std::unique_ptr<ButteraugliComparator>> sub =
+ ButteraugliComparator::Make(subsampledRgb0, params);
+ if (!sub.ok()) return sub.status();
+ result->sub_ = std::move(sub).value();
+
+ return result;
}
-void ButteraugliComparator::Mask(ImageF* BUTTERAUGLI_RESTRICT mask) const {
- HWY_DYNAMIC_DISPATCH(MaskPsychoImage)
- (pi0_, pi0_, xsize_, ysize_, params_, &blur_temp_, mask, nullptr);
+Status ButteraugliComparator::Mask(ImageF* BUTTERAUGLI_RESTRICT mask) const {
+ return HWY_DYNAMIC_DISPATCH(MaskPsychoImage)(
+ pi0_, pi0_, xsize_, ysize_, params_, &blur_temp_, mask, nullptr);
}
-void ButteraugliComparator::Diffmap(const Image3F& rgb1, ImageF& result) const {
+Status ButteraugliComparator::Diffmap(const Image3F& rgb1,
+ ImageF& result) const {
if (xsize_ < 8 || ysize_ < 8) {
ZeroFillImage(&result);
- return;
+ return true;
}
- Image3F xyb1(xsize_, ysize_);
- HWY_DYNAMIC_DISPATCH(OpsinDynamicsImage)
- (rgb1, params_, Temp(), &blur_temp_, &xyb1);
+ JXL_ASSIGN_OR_RETURN(Image3F xyb1, Image3F::Create(xsize_, ysize_));
+ JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(OpsinDynamicsImage)(
+ rgb1, params_, Temp(), &blur_temp_, &xyb1));
ReleaseTemp();
- DiffmapOpsinDynamicsImage(xyb1, result);
+ JXL_RETURN_IF_ERROR(DiffmapOpsinDynamicsImage(xyb1, result));
if (sub_) {
if (sub_->xsize_ < 8 || sub_->ysize_ < 8) {
- return;
+ return true;
}
- Image3F sub_xyb(sub_->xsize_, sub_->ysize_);
- HWY_DYNAMIC_DISPATCH(OpsinDynamicsImage)
- (SubSample2x(rgb1), params_, sub_->Temp(), &sub_->blur_temp_, &sub_xyb);
+ JXL_ASSIGN_OR_RETURN(Image3F sub_xyb,
+ Image3F::Create(sub_->xsize_, sub_->ysize_));
+ JXL_ASSIGN_OR_RETURN(Image3F subsampledRgb1, SubSample2x(rgb1));
+ JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(OpsinDynamicsImage)(
+ subsampledRgb1, params_, sub_->Temp(), &sub_->blur_temp_, &sub_xyb));
sub_->ReleaseTemp();
ImageF subresult;
- sub_->DiffmapOpsinDynamicsImage(sub_xyb, subresult);
+ JXL_RETURN_IF_ERROR(sub_->DiffmapOpsinDynamicsImage(sub_xyb, subresult));
AddSupersampled2x(subresult, 0.5, result);
}
+ return true;
}
-void ButteraugliComparator::DiffmapOpsinDynamicsImage(const Image3F& xyb1,
- ImageF& result) const {
+Status ButteraugliComparator::DiffmapOpsinDynamicsImage(const Image3F& xyb1,
+ ImageF& result) const {
if (xsize_ < 8 || ysize_ < 8) {
ZeroFillImage(&result);
- return;
+ return true;
}
PsychoImage pi1;
- HWY_DYNAMIC_DISPATCH(SeparateFrequencies)
- (xsize_, ysize_, params_, &blur_temp_, xyb1, pi1);
- result = ImageF(xsize_, ysize_);
- DiffmapPsychoImage(pi1, result);
+ JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(SeparateFrequencies)(
+ xsize_, ysize_, params_, &blur_temp_, xyb1, pi1));
+ JXL_ASSIGN_OR_RETURN(result, ImageF::Create(xsize_, ysize_));
+ return DiffmapPsychoImage(pi1, result);
}
namespace {
@@ -1809,18 +1848,18 @@ void MaltaDiffMapLF(const ImageF& lum0, const ImageF& lum1, const double w_0gt1,
} // namespace
-void ButteraugliComparator::DiffmapPsychoImage(const PsychoImage& pi1,
- ImageF& diffmap) const {
+Status ButteraugliComparator::DiffmapPsychoImage(const PsychoImage& pi1,
+ ImageF& diffmap) const {
if (xsize_ < 8 || ysize_ < 8) {
ZeroFillImage(&diffmap);
- return;
+ return true;
}
const float hf_asymmetry_ = params_.hf_asymmetry;
const float xmul_ = params_.xmul;
- ImageF diffs(xsize_, ysize_);
- Image3F block_diff_ac(xsize_, ysize_);
+ JXL_ASSIGN_OR_RETURN(ImageF diffs, ImageF::Create(xsize_, ysize_));
+ JXL_ASSIGN_OR_RETURN(Image3F block_diff_ac, Image3F::Create(xsize_, ysize_));
ZeroFillImage(&block_diff_ac);
MaltaDiffMap(pi0_.uhf[1], pi1.uhf[1], wUhfMalta * hf_asymmetry_,
wUhfMalta / hf_asymmetry_, norm1Uhf, &diffs, &block_diff_ac, 1);
@@ -1838,7 +1877,7 @@ void ButteraugliComparator::DiffmapPsychoImage(const PsychoImage& pi1,
MaltaDiffMapLF(pi0_.mf.Plane(0), pi1.mf.Plane(0), wMfMaltaX, wMfMaltaX,
norm1MfX, &diffs, &block_diff_ac, 0);
- Image3F block_diff_dc(xsize_, ysize_);
+ JXL_ASSIGN_OR_RETURN(Image3F block_diff_dc, Image3F::Create(xsize_, ysize_));
for (size_t c = 0; c < 3; ++c) {
if (c < 2) { // No blue channel error accumulated at HF.
HWY_DYNAMIC_DISPATCH(L2DiffAsymmetric)
@@ -1852,12 +1891,13 @@ void ButteraugliComparator::DiffmapPsychoImage(const PsychoImage& pi1,
}
ImageF mask;
- HWY_DYNAMIC_DISPATCH(MaskPsychoImage)
- (pi0_, pi1, xsize_, ysize_, params_, &blur_temp_, &mask,
- &block_diff_ac.Plane(1));
+ JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(MaskPsychoImage)(
+ pi0_, pi1, xsize_, ysize_, params_, &blur_temp_, &mask,
+ &block_diff_ac.Plane(1)));
HWY_DYNAMIC_DISPATCH(CombineChannelsToDiffmap)
(mask, block_diff_dc, block_diff_ac, xmul_, &diffmap);
+ return true;
}
double ButteraugliScoreFromDiffmap(const ImageF& diffmap,
@@ -1872,8 +1912,8 @@ double ButteraugliScoreFromDiffmap(const ImageF& diffmap,
return retval;
}
-bool ButteraugliDiffmap(const Image3F& rgb0, const Image3F& rgb1,
- double hf_asymmetry, double xmul, ImageF& diffmap) {
+Status ButteraugliDiffmap(const Image3F& rgb0, const Image3F& rgb1,
+ double hf_asymmetry, double xmul, ImageF& diffmap) {
ButteraugliParams params;
params.hf_asymmetry = hf_asymmetry;
params.xmul = xmul;
@@ -1893,8 +1933,8 @@ bool ButteraugliDiffmapSmall(const Image3F& rgb0, const Image3F& rgb1,
size_t yborder = ysize < kMax ? (kMax - ysize) / 2 : 0;
size_t xscaled = std::max<size_t>(kMax, xsize);
size_t yscaled = std::max<size_t>(kMax, ysize);
- Image3F scaled0(xscaled, yscaled);
- Image3F scaled1(xscaled, yscaled);
+ JXL_ASSIGN_OR_RETURN(Image3F scaled0, Image3F::Create(xscaled, yscaled));
+ JXL_ASSIGN_OR_RETURN(Image3F scaled1, Image3F::Create(xscaled, yscaled));
for (int i = 0; i < 3; ++i) {
for (size_t y = 0; y < yscaled; ++y) {
for (size_t x = 0; x < xscaled; ++x) {
@@ -1907,7 +1947,7 @@ bool ButteraugliDiffmapSmall(const Image3F& rgb0, const Image3F& rgb1,
}
ImageF diffmap_scaled;
const bool ok = ButteraugliDiffmap(scaled0, scaled1, params, diffmap_scaled);
- diffmap = ImageF(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(diffmap, ImageF::Create(xsize, ysize));
for (size_t y = 0; y < ysize; ++y) {
for (size_t x = 0; x < xsize; ++x) {
diffmap.Row(y)[x] = diffmap_scaled.Row(y + yborder)[x + xborder];
@@ -1916,8 +1956,8 @@ bool ButteraugliDiffmapSmall(const Image3F& rgb0, const Image3F& rgb1,
return ok;
}
-bool ButteraugliDiffmap(const Image3F& rgb0, const Image3F& rgb1,
- const ButteraugliParams& params, ImageF& diffmap) {
+Status ButteraugliDiffmap(const Image3F& rgb0, const Image3F& rgb1,
+ const ButteraugliParams& params, ImageF& diffmap) {
const size_t xsize = rgb0.xsize();
const size_t ysize = rgb0.ysize();
if (xsize < 1 || ysize < 1) {
@@ -1930,8 +1970,9 @@ bool ButteraugliDiffmap(const Image3F& rgb0, const Image3F& rgb1,
if (xsize < kMax || ysize < kMax) {
return ButteraugliDiffmapSmall<kMax>(rgb0, rgb1, params, diffmap);
}
- ButteraugliComparator butteraugli(rgb0, params);
- butteraugli.Diffmap(rgb1, diffmap);
+ JXL_ASSIGN_OR_RETURN(std::unique_ptr<ButteraugliComparator> butteraugli,
+ ButteraugliComparator::Make(rgb0, params));
+ JXL_RETURN_IF_ERROR(butteraugli->Diffmap(rgb1, diffmap));
return true;
}
@@ -1954,9 +1995,9 @@ bool ButteraugliInterface(const Image3F& rgb0, const Image3F& rgb1,
return true;
}
-bool ButteraugliInterfaceInPlace(Image3F&& rgb0, Image3F&& rgb1,
- const ButteraugliParams& params,
- ImageF& diffmap, double& diffvalue) {
+Status ButteraugliInterfaceInPlace(Image3F&& rgb0, Image3F&& rgb1,
+ const ButteraugliParams& params,
+ ImageF& diffmap, double& diffvalue) {
const size_t xsize = rgb0.xsize();
const size_t ysize = rgb0.ysize();
if (xsize < 1 || ysize < 1) {
@@ -1973,12 +2014,13 @@ bool ButteraugliInterfaceInPlace(Image3F&& rgb0, Image3F&& rgb1,
}
ImageF subdiffmap;
if (xsize >= 15 && ysize >= 15) {
- Image3F rgb0_sub = SubSample2x(rgb0);
- Image3F rgb1_sub = SubSample2x(rgb1);
- HWY_DYNAMIC_DISPATCH(ButteraugliDiffmapInPlace)
- (rgb0_sub, rgb1_sub, params, subdiffmap);
+ JXL_ASSIGN_OR_RETURN(Image3F rgb0_sub, SubSample2x(rgb0));
+ JXL_ASSIGN_OR_RETURN(Image3F rgb1_sub, SubSample2x(rgb1));
+ JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ButteraugliDiffmapInPlace)(
+ rgb0_sub, rgb1_sub, params, subdiffmap));
}
- HWY_DYNAMIC_DISPATCH(ButteraugliDiffmapInPlace)(rgb0, rgb1, params, diffmap);
+ JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ButteraugliDiffmapInPlace)(
+ rgb0, rgb1, params, diffmap));
if (xsize >= 15 && ysize >= 15) {
AddSupersampled2x(subdiffmap, 0.5, diffmap);
}
@@ -2066,9 +2108,11 @@ void ScoreToRgb(double score, double good_threshold, double bad_threshold,
} // namespace
-Image3F CreateHeatMapImage(const ImageF& distmap, double good_threshold,
- double bad_threshold) {
- Image3F heatmap(distmap.xsize(), distmap.ysize());
+StatusOr<Image3F> CreateHeatMapImage(const ImageF& distmap,
+ double good_threshold,
+ double bad_threshold) {
+ JXL_ASSIGN_OR_RETURN(Image3F heatmap,
+ Image3F::Create(distmap.xsize(), distmap.ysize()));
for (size_t y = 0; y < distmap.ysize(); ++y) {
const float* BUTTERAUGLI_RESTRICT row_distmap = distmap.ConstRow(y);
float* BUTTERAUGLI_RESTRICT row_h0 = heatmap.PlaneRow(0, y);
diff --git a/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.h b/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.h
index 29130e8768..e0bfd354e1 100644
--- a/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.h
+++ b/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.h
@@ -14,12 +14,12 @@
#include <atomic>
#include <cmath>
+#include <cstddef>
#include <memory>
-#include <vector>
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/image.h"
-#include "lib/jxl/image_ops.h"
#define BUTTERAUGLI_ENABLE_CHECKS 0
#define BUTTERAUGLI_RESTRICT JXL_RESTRICT
@@ -87,9 +87,9 @@ bool ButteraugliInterface(const Image3F &rgb0, const Image3F &rgb1,
// Same as ButteraugliInterface, but reuses rgb0 and rgb1 for other purposes
// inside the function after they are not needed any more, and it ignores
// params.xmul.
-bool ButteraugliInterfaceInPlace(Image3F &&rgb0, Image3F &&rgb1,
- const ButteraugliParams &params,
- ImageF &diffmap, double &diffvalue);
+Status ButteraugliInterfaceInPlace(Image3F &&rgb0, Image3F &&rgb1,
+ const ButteraugliParams &params,
+ ImageF &diffmap, double &diffvalue);
// Converts the butteraugli score into fuzzy class values that are continuous
// at the class boundary. The class boundary location is based on human
@@ -147,11 +147,13 @@ struct PsychoImage {
// Blur needs a transposed image.
// Hold it here and only allocate on demand to reduce memory usage.
struct BlurTemp {
- ImageF *GetTransposed(const ImageF &in) {
+ Status GetTransposed(const ImageF &in, ImageF **out) {
if (transposed_temp.xsize() == 0) {
- transposed_temp = ImageF(in.ysize(), in.xsize());
+ JXL_ASSIGN_OR_RETURN(transposed_temp,
+ ImageF::Create(in.ysize(), in.xsize()));
}
- return &transposed_temp;
+ *out = &transposed_temp;
+ return true;
}
ImageF transposed_temp;
@@ -162,22 +164,26 @@ class ButteraugliComparator {
// Butteraugli is calibrated at xmul = 1.0. We add a multiplier here so that
// we can test the hypothesis that a higher weighing of the X channel would
// improve results at higher Butteraugli values.
- ButteraugliComparator(const Image3F &rgb0, const ButteraugliParams &params);
virtual ~ButteraugliComparator() = default;
+ static StatusOr<std::unique_ptr<ButteraugliComparator>> Make(
+ const Image3F &rgb0, const ButteraugliParams &params);
+
// Computes the butteraugli map between the original image given in the
// constructor and the distorted image give here.
- void Diffmap(const Image3F &rgb1, ImageF &result) const;
+ Status Diffmap(const Image3F &rgb1, ImageF &result) const;
// Same as above, but OpsinDynamicsImage() was already applied.
- void DiffmapOpsinDynamicsImage(const Image3F &xyb1, ImageF &result) const;
+ Status DiffmapOpsinDynamicsImage(const Image3F &xyb1, ImageF &result) const;
// Same as above, but the frequency decomposition was already applied.
- void DiffmapPsychoImage(const PsychoImage &pi1, ImageF &diffmap) const;
+ Status DiffmapPsychoImage(const PsychoImage &pi1, ImageF &diffmap) const;
- void Mask(ImageF *BUTTERAUGLI_RESTRICT mask) const;
+ Status Mask(ImageF *BUTTERAUGLI_RESTRICT mask) const;
private:
+ ButteraugliComparator(size_t xsize, size_t ysize,
+ const ButteraugliParams &params);
Image3F *Temp() const;
void ReleaseTemp() const;
@@ -196,18 +202,19 @@ class ButteraugliComparator {
};
// Deprecated.
-bool ButteraugliDiffmap(const Image3F &rgb0, const Image3F &rgb1,
- double hf_asymmetry, double xmul, ImageF &diffmap);
+Status ButteraugliDiffmap(const Image3F &rgb0, const Image3F &rgb1,
+ double hf_asymmetry, double xmul, ImageF &diffmap);
-bool ButteraugliDiffmap(const Image3F &rgb0, const Image3F &rgb1,
- const ButteraugliParams &params, ImageF &diffmap);
+Status ButteraugliDiffmap(const Image3F &rgb0, const Image3F &rgb1,
+ const ButteraugliParams &params, ImageF &diffmap);
double ButteraugliScoreFromDiffmap(const ImageF &diffmap,
const ButteraugliParams *params = nullptr);
// Generate rgb-representation of the distance between two images.
-Image3F CreateHeatMapImage(const ImageF &distmap, double good_threshold,
- double bad_threshold);
+StatusOr<Image3F> CreateHeatMapImage(const ImageF &distmap,
+ double good_threshold,
+ double bad_threshold);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli_test.cc b/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli_test.cc
index c2ccf56175..39df4bd473 100644
--- a/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli_test.cc
@@ -30,7 +30,7 @@ using extras::PackedPixelFile;
using test::TestImage;
Image3F SinglePixelImage(float red, float green, float blue) {
- Image3F img(1, 1);
+ JXL_ASSIGN_OR_DIE(Image3F img, Image3F::Create(1, 1));
img.PlaneRow(0, 0)[0] = red;
img.PlaneRow(1, 0)[0] = green;
img.PlaneRow(2, 0)[0] = blue;
@@ -42,7 +42,7 @@ Image3F GetColorImage(const PackedPixelFile& ppf) {
const PackedImage& image = ppf.frames[0].color;
const JxlPixelFormat& format = image.format;
const uint8_t* pixels = reinterpret_cast<const uint8_t*>(image.pixels());
- Image3F color(image.xsize, image.ysize);
+ JXL_ASSIGN_OR_DIE(Image3F color, Image3F::Create(image.xsize, image.ysize));
for (size_t c = 0; c < format.num_channels; ++c) {
JXL_CHECK(ConvertFromExternal(pixels, image.pixels_size, image.xsize,
image.ysize, ppf.info.bits_per_sample, format,
@@ -93,7 +93,7 @@ TEST(ButteraugliInPlaceTest, LargeImage) {
TestImage img;
img.SetDimensions(xsize, ysize).AddFrame().RandomFill(777);
Image3F rgb0 = GetColorImage(img.ppf());
- Image3F rgb1(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(Image3F rgb1, Image3F::Create(xsize, ysize));
CopyImageTo(rgb0, &rgb1);
AddUniformNoise(&rgb1, 0.02f, 7777);
AddEdge(&rgb1, 0.1f, xsize / 2, xsize / 2);
diff --git a/third_party/jpeg-xl/lib/jxl/cache_aligned.cc b/third_party/jpeg-xl/lib/jxl/cache_aligned.cc
index 992efc4d48..8a95634d68 100644
--- a/third_party/jpeg-xl/lib/jxl/cache_aligned.cc
+++ b/third_party/jpeg-xl/lib/jxl/cache_aligned.cc
@@ -5,6 +5,7 @@
#include "lib/jxl/cache_aligned.h"
+#include <jxl/types.h>
#include <stdio.h>
#include <stdlib.h>
@@ -95,7 +96,7 @@ void* CacheAligned::Allocate(const size_t payload_size, size_t offset) {
aligned &= ~(kAlias - 1);
#endif
-#if 0
+#if JXL_FALSE
// No effect.
uintptr_t page_aligned = reinterpret_cast<uintptr_t>(allocated);
page_aligned &= ~(4096 - 1);
diff --git a/third_party/jpeg-xl/lib/jxl/cache_aligned.h b/third_party/jpeg-xl/lib/jxl/cache_aligned.h
index d79d7be461..8480471e5c 100644
--- a/third_party/jpeg-xl/lib/jxl/cache_aligned.h
+++ b/third_party/jpeg-xl/lib/jxl/cache_aligned.h
@@ -49,7 +49,7 @@ class CacheAligned {
// Avoids the need for a function pointer (deleter) in CacheAlignedUniquePtr.
struct CacheAlignedDeleter {
void operator()(uint8_t* aligned_pointer) const {
- return CacheAligned::Free(aligned_pointer);
+ CacheAligned::Free(aligned_pointer);
}
};
diff --git a/third_party/jpeg-xl/lib/jxl/chroma_from_luma.cc b/third_party/jpeg-xl/lib/jxl/chroma_from_luma.cc
index 63d21cbb4b..69585c44cf 100644
--- a/third_party/jpeg-xl/lib/jxl/chroma_from_luma.cc
+++ b/third_party/jpeg-xl/lib/jxl/chroma_from_luma.cc
@@ -5,17 +5,25 @@
#include "lib/jxl/chroma_from_luma.h"
+#include "lib/jxl/image_ops.h"
+
namespace jxl {
-ColorCorrelationMap::ColorCorrelationMap(size_t xsize, size_t ysize, bool XYB)
- : ytox_map(DivCeil(xsize, kColorTileDim), DivCeil(ysize, kColorTileDim)),
- ytob_map(DivCeil(xsize, kColorTileDim), DivCeil(ysize, kColorTileDim)) {
- ZeroFillImage(&ytox_map);
- ZeroFillImage(&ytob_map);
+StatusOr<ColorCorrelationMap> ColorCorrelationMap::Create(size_t xsize,
+ size_t ysize,
+ bool XYB) {
+ ColorCorrelationMap result;
+ size_t xblocks = DivCeil(xsize, kColorTileDim);
+ size_t yblocks = DivCeil(ysize, kColorTileDim);
+ JXL_ASSIGN_OR_RETURN(result.ytox_map, ImageSB::Create(xblocks, yblocks));
+ JXL_ASSIGN_OR_RETURN(result.ytob_map, ImageSB::Create(xblocks, yblocks));
+ ZeroFillImage(&result.ytox_map);
+ ZeroFillImage(&result.ytob_map);
if (!XYB) {
- base_correlation_b_ = 0;
+ result.base_correlation_b_ = 0;
}
- RecomputeDCFactors();
+ result.RecomputeDCFactors();
+ return result;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/chroma_from_luma.h b/third_party/jpeg-xl/lib/jxl/chroma_from_luma.h
index cb3b710762..1f2353d9af 100644
--- a/third_party/jpeg-xl/lib/jxl/chroma_from_luma.h
+++ b/third_party/jpeg-xl/lib/jxl/chroma_from_luma.h
@@ -12,19 +12,15 @@
#include <stddef.h>
#include <stdint.h>
-#include <vector>
+#include <limits>
-#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/cms/opsin_params.h"
#include "lib/jxl/dec_bit_reader.h"
-#include "lib/jxl/entropy_coder.h"
#include "lib/jxl/field_encodings.h"
#include "lib/jxl/fields.h"
#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/image.h"
-#include "lib/jxl/quant_weights.h"
namespace jxl {
@@ -55,7 +51,8 @@ struct ColorCorrelationMap {
// xsize/ysize are in pixels
// set XYB=false to do something close to no-op cmap (needed for now since
// cmap is mandatory)
- ColorCorrelationMap(size_t xsize, size_t ysize, bool XYB = true);
+ static StatusOr<ColorCorrelationMap> Create(size_t xsize, size_t ysize,
+ bool XYB = true);
float YtoXRatio(int32_t x_factor) const {
return base_correlation_x_ + x_factor * color_scale_;
@@ -96,7 +93,7 @@ struct ColorCorrelationMap {
color_factor_ == kDefaultColorFactor;
}
- int32_t RatioJPEG(int32_t factor) const {
+ static int32_t RatioJPEG(int32_t factor) {
return factor * (1 << kCFLFixedPointPrecision) / kDefaultColorFactor;
}
diff --git a/third_party/jpeg-xl/lib/jxl/cms/color_encoding_cms.h b/third_party/jpeg-xl/lib/jxl/cms/color_encoding_cms.h
index db61f820ca..3b7ae09d6f 100644
--- a/third_party/jpeg-xl/lib/jxl/cms/color_encoding_cms.h
+++ b/third_party/jpeg-xl/lib/jxl/cms/color_encoding_cms.h
@@ -96,6 +96,8 @@ enum class RenderingIntent : uint32_t {
// Chromaticity (Y is omitted because it is 1 for white points and implicit for
// primaries)
struct CIExy {
+ CIExy() = default;
+ CIExy(double x, double y) : x(x), y(y) {}
double x = 0.0;
double y = 0.0;
};
@@ -516,7 +518,7 @@ struct ColorEncoding {
JXL_RETURN_IF_ERROR(cms.set_fields_from_icc(cms.set_fields_data,
new_icc.data(), new_icc.size(),
&external, &new_cmyk));
- cmyk = new_cmyk;
+ cmyk = static_cast<bool>(new_cmyk);
JXL_RETURN_IF_ERROR(FromExternal(external));
icc = std::move(new_icc);
return true;
diff --git a/third_party/jpeg-xl/lib/jxl/cms/jxl_cms.cc b/third_party/jpeg-xl/lib/jxl/cms/jxl_cms.cc
index dd00b8b81f..e35b3ce172 100644
--- a/third_party/jpeg-xl/lib/jxl/cms/jxl_cms.cc
+++ b/third_party/jpeg-xl/lib/jxl/cms/jxl_cms.cc
@@ -307,7 +307,7 @@ int DoColorSpaceTransform(void* t, size_t thread, const float* buf_src,
#if JPEGXL_ENABLE_SKCMS
-JXL_MUST_USE_RESULT CIExy CIExyFromXYZ(const float XYZ[3]) {
+JXL_MUST_USE_RESULT CIExy CIExyFromXYZ(const Color& XYZ) {
const float factor = 1.f / (XYZ[0] + XYZ[1] + XYZ[2]);
CIExy xy;
xy.x = XYZ[0] * factor;
@@ -405,8 +405,8 @@ ColorSpace ColorSpaceFromProfile(const skcms_ICCProfile& profile) {
}
// vector_out := matmul(matrix, vector_in)
-void MatrixProduct(const skcms_Matrix3x3& matrix, const float vector_in[3],
- float vector_out[3]) {
+void MatrixProduct(const skcms_Matrix3x3& matrix, const Color& vector_in,
+ Color& vector_out) {
for (int i = 0; i < 3; ++i) {
vector_out[i] = 0;
for (int j = 0; j < 3; ++j) {
@@ -418,8 +418,8 @@ void MatrixProduct(const skcms_Matrix3x3& matrix, const float vector_in[3],
// Returns white point that was specified when creating the profile.
JXL_MUST_USE_RESULT Status UnadaptedWhitePoint(const skcms_ICCProfile& profile,
CIExy* out) {
- float media_white_point_XYZ[3];
- if (!skcms_GetWTPT(&profile, media_white_point_XYZ)) {
+ Color media_white_point_XYZ;
+ if (!skcms_GetWTPT(&profile, media_white_point_XYZ.data())) {
return JXL_FAILURE("ICC profile does not contain WhitePoint tag");
}
skcms_Matrix3x3 CHAD;
@@ -435,7 +435,7 @@ JXL_MUST_USE_RESULT Status UnadaptedWhitePoint(const skcms_ICCProfile& profile,
if (!skcms_Matrix3x3_invert(&CHAD, &inverse_CHAD)) {
return JXL_FAILURE("Non-invertible ChromaticAdaptation matrix");
}
- float unadapted_white_point_XYZ[3];
+ Color unadapted_white_point_XYZ;
MatrixProduct(inverse_CHAD, media_white_point_XYZ, unadapted_white_point_XYZ);
*out = CIExyFromXYZ(unadapted_white_point_XYZ);
return true;
@@ -445,7 +445,8 @@ Status IdentifyPrimaries(const skcms_ICCProfile& profile,
const CIExy& wp_unadapted, ColorEncoding* c) {
if (!c->HasPrimaries()) return true;
- skcms_Matrix3x3 CHAD, inverse_CHAD;
+ skcms_Matrix3x3 CHAD;
+ skcms_Matrix3x3 inverse_CHAD;
if (skcms_GetCHAD(&profile, &CHAD)) {
JXL_RETURN_IF_ERROR(skcms_Matrix3x3_invert(&CHAD, &inverse_CHAD));
} else {
@@ -457,11 +458,12 @@ Status IdentifyPrimaries(const skcms_ICCProfile& profile,
{{0.9869929, -0.1470543, 0.1599627},
{0.4323053, 0.5183603, 0.0492912},
{-0.0085287, 0.0400428, 0.9684867}}};
- static constexpr float kWpD50XYZ[3] = {0.96420288, 1.0, 0.82490540};
- float wp_unadapted_XYZ[3];
+ static constexpr Color kWpD50XYZ{0.96420288, 1.0, 0.82490540};
+ Color wp_unadapted_XYZ;
JXL_RETURN_IF_ERROR(
CIEXYZFromWhiteCIExy(wp_unadapted.x, wp_unadapted.y, wp_unadapted_XYZ));
- float wp_D50_LMS[3], wp_unadapted_LMS[3];
+ Color wp_D50_LMS;
+ Color wp_unadapted_LMS;
MatrixProduct(kLMSFromXYZ, kWpD50XYZ, wp_D50_LMS);
MatrixProduct(kLMSFromXYZ, wp_unadapted_XYZ, wp_unadapted_LMS);
inverse_CHAD = {{{wp_unadapted_LMS[0] / wp_D50_LMS[0], 0, 0},
@@ -471,16 +473,16 @@ Status IdentifyPrimaries(const skcms_ICCProfile& profile,
inverse_CHAD = skcms_Matrix3x3_concat(&inverse_CHAD, &kLMSFromXYZ);
}
- float XYZ[3];
+ Color XYZ;
PrimariesCIExy primaries;
CIExy* const chromaticities[] = {&primaries.r, &primaries.g, &primaries.b};
for (int i = 0; i < 3; ++i) {
float RGB[3] = {};
RGB[i] = 1;
skcms_Transform(RGB, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Opaque,
- &profile, XYZ, skcms_PixelFormat_RGB_fff,
+ &profile, XYZ.data(), skcms_PixelFormat_RGB_fff,
skcms_AlphaFormat_Opaque, skcms_XYZD50_profile(), 1);
- float unadapted_XYZ[3];
+ Color unadapted_XYZ;
MatrixProduct(inverse_CHAD, XYZ, unadapted_XYZ);
*chromaticities[i] = CIExyFromXYZ(unadapted_XYZ);
}
@@ -829,17 +831,17 @@ Status GetPrimariesLuminances(const ColorEncoding& encoding,
// From there, by multiplying each total by its corresponding y, we get Y for
// that primary.
- float white_XYZ[3];
+ Color white_XYZ;
CIExy wp = encoding.GetWhitePoint();
JXL_RETURN_IF_ERROR(CIEXYZFromWhiteCIExy(wp.x, wp.y, white_XYZ));
const PrimariesCIExy primaries = encoding.GetPrimaries();
- double chromaticities[3][3] = {
- {primaries.r.x, primaries.g.x, primaries.b.x},
- {primaries.r.y, primaries.g.y, primaries.b.y},
- {1 - primaries.r.x - primaries.r.y, 1 - primaries.g.x - primaries.g.y,
- 1 - primaries.b.x - primaries.b.y}};
- JXL_RETURN_IF_ERROR(Inv3x3Matrix(&chromaticities[0][0]));
+ Matrix3x3d chromaticities{
+ {{primaries.r.x, primaries.g.x, primaries.b.x},
+ {primaries.r.y, primaries.g.y, primaries.b.y},
+ {1 - primaries.r.x - primaries.r.y, 1 - primaries.g.x - primaries.g.y,
+ 1 - primaries.b.x - primaries.b.y}}};
+ JXL_RETURN_IF_ERROR(Inv3x3Matrix(chromaticities));
const double ys[3] = {primaries.r.y, primaries.g.y, primaries.b.y};
for (size_t i = 0; i < 3; ++i) {
luminances[i] = ys[i] * (chromaticities[i][0] * white_XYZ[0] +
@@ -971,14 +973,31 @@ JXL_BOOL JxlCmsSetFieldsFromICC(void* user_data, const uint8_t* icc_data,
JXL_RETURN_IF_ERROR(skcms_Parse(icc_data, icc_size, &profile));
// skcms does not return the rendering intent, so get it from the file. It
- // is encoded as big-endian 32-bit integer in bytes 60..63.
- uint32_t rendering_intent32 = icc_data[67];
- if (rendering_intent32 > 3 || icc_data[64] != 0 || icc_data[65] != 0 ||
- icc_data[66] != 0) {
- return JXL_FAILURE("Invalid rendering intent %u\n", rendering_intent32);
+ // should be encoded as big-endian 32-bit integer in bytes 60..63.
+ uint32_t big_endian_rendering_intent = icc_data[67] + (icc_data[66] << 8) +
+ (icc_data[65] << 16) +
+ (icc_data[64] << 24);
+ // Some files encode rendering intent as little endian, which is not spec
+ // compliant. However we accept those with a warning.
+ uint32_t little_endian_rendering_intent = (icc_data[67] << 24) +
+ (icc_data[66] << 16) +
+ (icc_data[65] << 8) + icc_data[64];
+ uint32_t candidate_rendering_intent =
+ std::min(big_endian_rendering_intent, little_endian_rendering_intent);
+ if (candidate_rendering_intent != big_endian_rendering_intent) {
+ JXL_WARNING(
+ "Invalid rendering intent bytes: [0x%02X 0x%02X 0x%02X 0x%02X], "
+ "assuming %u was meant",
+ icc_data[64], icc_data[65], icc_data[66], icc_data[67],
+ candidate_rendering_intent);
+ }
+ if (candidate_rendering_intent > 3) {
+ return JXL_FAILURE("Invalid rendering intent %u\n",
+ candidate_rendering_intent);
}
// ICC and RenderingIntent have the same values (0..3).
- c_enc.rendering_intent = static_cast<RenderingIntent>(rendering_intent32);
+ c_enc.rendering_intent =
+ static_cast<RenderingIntent>(candidate_rendering_intent);
if (profile.has_CICP &&
ApplyCICP(profile.CICP.color_primaries,
@@ -986,11 +1005,11 @@ JXL_BOOL JxlCmsSetFieldsFromICC(void* user_data, const uint8_t* icc_data,
profile.CICP.matrix_coefficients,
profile.CICP.video_full_range_flag, &c_enc)) {
*c = c_enc.ToExternal();
- return true;
+ return JXL_TRUE;
}
c_enc.color_space = ColorSpaceFromProfile(profile);
- *cmyk = (profile.data_color_space == skcms_Signature_CMYK);
+ *cmyk = TO_JXL_BOOL(profile.data_color_space == skcms_Signature_CMYK);
CIExy wp_unadapted;
JXL_RETURN_IF_ERROR(UnadaptedWhitePoint(profile, &wp_unadapted));
@@ -1026,14 +1045,14 @@ JXL_BOOL JxlCmsSetFieldsFromICC(void* user_data, const uint8_t* icc_data,
ApplyCICP(cicp_buffer[8], cicp_buffer[9], cicp_buffer[10],
cicp_buffer[11], &c_enc)) {
*c = c_enc.ToExternal();
- return true;
+ return JXL_TRUE;
}
c_enc.color_space = ColorSpaceFromProfile(profile);
if (cmsGetColorSpace(profile.get()) == cmsSigCmykData) {
*cmyk = JXL_TRUE;
*c = c_enc.ToExternal();
- return true;
+ return JXL_TRUE;
}
const cmsCIEXYZ wp_unadapted = UnadaptedWhitePoint(context, profile, c_enc);
@@ -1049,7 +1068,7 @@ JXL_BOOL JxlCmsSetFieldsFromICC(void* user_data, const uint8_t* icc_data,
#endif // JPEGXL_ENABLE_SKCMS
*c = c_enc.ToExternal();
- return true;
+ return JXL_TRUE;
}
} // namespace
@@ -1084,9 +1103,10 @@ void* JxlCmsInit(void* init_data, size_t num_threads, size_t xsize,
const JxlColorProfile* input, const JxlColorProfile* output,
float intensity_target) {
JXL_ASSERT(init_data != nullptr);
- auto cms = static_cast<const JxlCmsInterface*>(init_data);
+ const auto* cms = static_cast<const JxlCmsInterface*>(init_data);
auto t = jxl::make_unique<JxlCms>();
- IccBytes icc_src, icc_dst;
+ IccBytes icc_src;
+ IccBytes icc_dst;
if (input->icc.size == 0) {
JXL_NOTIFY_ERROR("JxlCmsInit: empty input ICC");
return nullptr;
@@ -1259,8 +1279,6 @@ void* JxlCmsInit(void* init_data, size_t num_threads, size_t xsize,
// Not including alpha channel (copied separately).
const size_t channels_src = (c_src.cmyk ? 4 : c_src.Channels());
const size_t channels_dst = c_dst.Channels();
- JXL_CHECK(channels_src == channels_dst ||
- (channels_src == 4 && channels_dst == 3));
#if JXL_CMS_VERBOSE
printf("Channels: %" PRIuS "; Threads: %" PRIuS "\n", channels_src,
num_threads);
@@ -1294,13 +1312,14 @@ void* JxlCmsInit(void* init_data, size_t num_threads, size_t xsize,
// outputs (or vice versa), we use floating point input/output.
t->channels_src = channels_src;
t->channels_dst = channels_dst;
+#if !JPEGXL_ENABLE_SKCMS
size_t actual_channels_src = channels_src;
size_t actual_channels_dst = channels_dst;
-#if JPEGXL_ENABLE_SKCMS
+#else
// SkiaCMS doesn't support grayscale float buffers, so we create space for RGB
// float buffers anyway.
- actual_channels_src = (channels_src == 4 ? 4 : 3);
- actual_channels_dst = 3;
+ size_t actual_channels_src = (channels_src == 4 ? 4 : 3);
+ size_t actual_channels_dst = 3;
#endif
AllocateBuffer(xsize * actual_channels_src, num_threads, &t->src_storage,
&t->buf_src);
diff --git a/third_party/jpeg-xl/lib/jxl/cms/jxl_cms_internal.h b/third_party/jpeg-xl/lib/jxl/cms/jxl_cms_internal.h
index c00fe82d8c..7f59e688d0 100644
--- a/third_party/jpeg-xl/lib/jxl/cms/jxl_cms_internal.h
+++ b/third_party/jpeg-xl/lib/jxl/cms/jxl_cms_internal.h
@@ -41,7 +41,7 @@ enum class ExtraTF {
};
static Status PrimariesToXYZ(float rx, float ry, float gx, float gy, float bx,
- float by, float wx, float wy, float matrix[9]) {
+ float by, float wx, float wy, Matrix3x3& matrix) {
bool ok = (wx >= 0) && (wx <= 1) && (wy > 0) && (wy <= 1);
if (!ok) {
return JXL_FAILURE("Invalid white point");
@@ -49,51 +49,48 @@ static Status PrimariesToXYZ(float rx, float ry, float gx, float gy, float bx,
// TODO(lode): also require rx, ry, gx, gy, bx, to be in range 0-1? ICC
// profiles in theory forbid negative XYZ values, but in practice the ACES P0
// color space uses a negative y for the blue primary.
- float primaries[9] = {
- rx, gx, bx, ry, gy, by, 1.0f - rx - ry, 1.0f - gx - gy, 1.0f - bx - by};
- float primaries_inv[9];
- memcpy(primaries_inv, primaries, sizeof(float) * 9);
+ Matrix3x3 primaries{{{rx, gx, bx},
+ {ry, gy, by},
+ {1.0f - rx - ry, 1.0f - gx - gy, 1.0f - bx - by}}};
+ Matrix3x3 primaries_inv;
+ primaries_inv = primaries;
JXL_RETURN_IF_ERROR(Inv3x3Matrix(primaries_inv));
- float w[3] = {wx / wy, 1.0f, (1.0f - wx - wy) / wy};
+ Vector3 w{wx / wy, 1.0f, (1.0f - wx - wy) / wy};
// 1 / tiny float can still overflow
JXL_RETURN_IF_ERROR(std::isfinite(w[0]) && std::isfinite(w[2]));
- float xyz[3];
+ Vector3 xyz;
Mul3x3Vector(primaries_inv, w, xyz);
- float a[9] = {
- xyz[0], 0, 0, 0, xyz[1], 0, 0, 0, xyz[2],
- };
+ Matrix3x3 a{{{xyz[0], 0, 0}, {0, xyz[1], 0}, {0, 0, xyz[2]}}};
Mul3x3Matrix(primaries, a, matrix);
return true;
}
/* Chromatic adaptation matrices*/
-constexpr float kBradford[9] = {
- 0.8951f, 0.2664f, -0.1614f, -0.7502f, 1.7135f,
- 0.0367f, 0.0389f, -0.0685f, 1.0296f,
-};
-constexpr float kBradfordInv[9] = {
- 0.9869929f, -0.1470543f, 0.1599627f, 0.4323053f, 0.5183603f,
- 0.0492912f, -0.0085287f, 0.0400428f, 0.9684867f,
-};
+constexpr Matrix3x3 kBradford{{{0.8951f, 0.2664f, -0.1614f},
+ {-0.7502f, 1.7135f, 0.0367f},
+ {0.0389f, -0.0685f, 1.0296f}}};
+constexpr Matrix3x3 kBradfordInv{{{0.9869929f, -0.1470543f, 0.1599627f},
+ {0.4323053f, 0.5183603f, 0.0492912f},
+ {-0.0085287f, 0.0400428f, 0.9684867f}}};
// Adapts whitepoint x, y to D50
-static Status AdaptToXYZD50(float wx, float wy, float matrix[9]) {
+static Status AdaptToXYZD50(float wx, float wy, Matrix3x3& matrix) {
bool ok = (wx >= 0) && (wx <= 1) && (wy > 0) && (wy <= 1);
if (!ok) {
// Out of range values can cause division through zero
// further down with the bradford adaptation too.
return JXL_FAILURE("Invalid white point");
}
- float w[3] = {wx / wy, 1.0f, (1.0f - wx - wy) / wy};
+ Vector3 w{wx / wy, 1.0f, (1.0f - wx - wy) / wy};
// 1 / tiny float can still overflow
JXL_RETURN_IF_ERROR(std::isfinite(w[0]) && std::isfinite(w[2]));
- float w50[3] = {0.96422f, 1.0f, 0.82521f};
+ Vector3 w50{0.96422f, 1.0f, 0.82521f};
- float lms[3];
- float lms50[3];
+ Vector3 lms;
+ Vector3 lms50;
Mul3x3Vector(kBradford, w, lms);
Mul3x3Vector(kBradford, w50, lms50);
@@ -101,15 +98,15 @@ static Status AdaptToXYZD50(float wx, float wy, float matrix[9]) {
if (lms[0] == 0 || lms[1] == 0 || lms[2] == 0) {
return JXL_FAILURE("Invalid white point");
}
- float a[9] = {
- // /----> 0, 1, 2, 3, /----> 4, 5, 6, 7, /----> 8,
- lms50[0] / lms[0], 0, 0, 0, lms50[1] / lms[1], 0, 0, 0, lms50[2] / lms[2],
- };
- if (!std::isfinite(a[0]) || !std::isfinite(a[4]) || !std::isfinite(a[8])) {
+ Matrix3x3 a{{{lms50[0] / lms[0], 0, 0},
+ {0, lms50[1] / lms[1], 0},
+ {0, 0, lms50[2] / lms[2]}}};
+ if (!std::isfinite(a[0][0]) || !std::isfinite(a[1][1]) ||
+ !std::isfinite(a[2][2])) {
return JXL_FAILURE("Invalid white point");
}
- float b[9];
+ Matrix3x3 b;
Mul3x3Matrix(a, kBradford, b);
Mul3x3Matrix(kBradfordInv, b, matrix);
@@ -118,10 +115,10 @@ static Status AdaptToXYZD50(float wx, float wy, float matrix[9]) {
static Status PrimariesToXYZD50(float rx, float ry, float gx, float gy,
float bx, float by, float wx, float wy,
- float matrix[9]) {
- float toXYZ[9];
+ Matrix3x3& matrix) {
+ Matrix3x3 toXYZ;
JXL_RETURN_IF_ERROR(PrimariesToXYZ(rx, ry, gx, gy, bx, by, wx, wy, toXYZ));
- float d50[9];
+ Matrix3x3 d50;
JXL_RETURN_IF_ERROR(AdaptToXYZD50(wx, wy, d50));
Mul3x3Matrix(d50, toXYZ, matrix);
@@ -130,14 +127,13 @@ static Status PrimariesToXYZD50(float rx, float ry, float gx, float gy,
static Status ToneMapPixel(const JxlColorEncoding& c, const float in[3],
uint8_t pcslab_out[3]) {
- float primaries_XYZ[9];
+ Matrix3x3 primaries_XYZ;
JXL_RETURN_IF_ERROR(PrimariesToXYZ(
c.primaries_red_xy[0], c.primaries_red_xy[1], c.primaries_green_xy[0],
c.primaries_green_xy[1], c.primaries_blue_xy[0], c.primaries_blue_xy[1],
c.white_point_xy[0], c.white_point_xy[1], primaries_XYZ));
- const float luminances[3] = {primaries_XYZ[3], primaries_XYZ[4],
- primaries_XYZ[5]};
- float linear[3];
+ const Vector3 luminances = primaries_XYZ[1];
+ Color linear;
JxlTransferFunction tf = c.transfer_function;
if (tf == JXL_TRANSFER_FUNCTION_PQ) {
for (size_t i = 0; i < 3; ++i) {
@@ -151,25 +147,25 @@ static Status ToneMapPixel(const JxlColorEncoding& c, const float in[3],
}
if (tf == JXL_TRANSFER_FUNCTION_PQ) {
Rec2408ToneMapperBase tone_mapper({0, 10000}, {0, 250}, luminances);
- tone_mapper.ToneMap(&linear[0], &linear[1], &linear[2]);
+ tone_mapper.ToneMap(linear);
} else {
HlgOOTF_Base ootf(/*source_luminance=*/300, /*target_luminance=*/80,
luminances);
- ootf.Apply(&linear[0], &linear[1], &linear[2]);
+ ootf.Apply(linear);
}
- GamutMapScalar(&linear[0], &linear[1], &linear[2], luminances,
+ GamutMapScalar(linear, luminances,
/*preserve_saturation=*/0.3f);
- float chad[9];
+ Matrix3x3 chad;
JXL_RETURN_IF_ERROR(
AdaptToXYZD50(c.white_point_xy[0], c.white_point_xy[1], chad));
- float to_xyzd50[9];
+ Matrix3x3 to_xyzd50;
Mul3x3Matrix(chad, primaries_XYZ, to_xyzd50);
- float xyz[3] = {0, 0, 0};
+ Vector3 xyz{0, 0, 0};
for (size_t xyz_c = 0; xyz_c < 3; ++xyz_c) {
for (size_t rgb_c = 0; rgb_c < 3; ++rgb_c) {
- xyz[xyz_c] += linear[rgb_c] * to_xyzd50[3 * xyz_c + rgb_c];
+ xyz[xyz_c] += linear[rgb_c] * to_xyzd50[xyz_c][rgb_c];
}
}
@@ -206,7 +202,7 @@ static std::vector<uint16_t> CreateTableCurve(uint32_t N, const ExtraTF tf,
JXL_ASSERT(N <= 4096); // ICC MFT2 only allows 4K entries
JXL_ASSERT(tf == ExtraTF::kPQ || tf == ExtraTF::kHLG);
- static constexpr float kLuminances[] = {1.f / 3, 1.f / 3, 1.f / 3};
+ static constexpr Vector3 kLuminances{1.f / 3, 1.f / 3, 1.f / 3};
Rec2408ToneMapperBase tone_mapper({0, kPQIntensityTarget},
{0, kDefaultIntensityTarget}, kLuminances);
// No point using float - LCMS converts to 16-bit for A2B/MFT.
@@ -220,9 +216,10 @@ static std::vector<uint16_t> CreateTableCurve(uint32_t N, const ExtraTF tf,
: TF_PQ_Base::DisplayFromEncoded(kPQIntensityTarget, dx);
if (tone_map && tf == ExtraTF::kPQ &&
kPQIntensityTarget > kDefaultIntensityTarget) {
- float r = y * 10000 / kPQIntensityTarget, g = r, b = r;
- tone_mapper.ToneMap(&r, &g, &b);
- y = r;
+ float l = y * 10000 / kPQIntensityTarget;
+ Color gray{l, l, l};
+ tone_mapper.ToneMap(gray);
+ y = gray[0];
}
JXL_ASSERT(y >= 0.0);
// Clamp to table range - necessary for HLG.
@@ -233,7 +230,7 @@ static std::vector<uint16_t> CreateTableCurve(uint32_t N, const ExtraTF tf,
return table;
}
-static Status CIEXYZFromWhiteCIExy(double wx, double wy, float XYZ[3]) {
+static Status CIEXYZFromWhiteCIExy(double wx, double wy, Color& XYZ) {
// Target Y = 1.
if (std::abs(wy) < 1e-12) return JXL_FAILURE("Y value is too small");
const float factor = 1 / wy;
@@ -292,10 +289,18 @@ static void ICCComputeMD5(const std::vector<uint8_t>& data, uint8_t sum[16])
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
};
- uint32_t a0 = 0x67452301, b0 = 0xefcdab89, c0 = 0x98badcfe, d0 = 0x10325476;
+ uint32_t a0 = 0x67452301;
+ uint32_t b0 = 0xefcdab89;
+ uint32_t c0 = 0x98badcfe;
+ uint32_t d0 = 0x10325476;
for (size_t i = 0; i < data64.size(); i += 64) {
- uint32_t a = a0, b = b0, c = c0, d = d0, f, g;
+ uint32_t a = a0;
+ uint32_t b = b0;
+ uint32_t c = c0;
+ uint32_t d = d0;
+ uint32_t f;
+ uint32_t g;
for (size_t j = 0; j < 64; j++) {
if (j < 16) {
f = (b & c) | ((~b) & d);
@@ -310,8 +315,10 @@ static void ICCComputeMD5(const std::vector<uint8_t>& data, uint8_t sum[16])
f = c ^ (b | (~d));
g = (7 * j) & 0xf;
}
- uint32_t dg0 = data64[i + g * 4 + 0], dg1 = data64[i + g * 4 + 1],
- dg2 = data64[i + g * 4 + 2], dg3 = data64[i + g * 4 + 3];
+ uint32_t dg0 = data64[i + g * 4 + 0];
+ uint32_t dg1 = data64[i + g * 4 + 1];
+ uint32_t dg2 = data64[i + g * 4 + 2];
+ uint32_t dg3 = data64[i + g * 4 + 3];
uint32_t u = dg0 | (dg1 << 8u) | (dg2 << 16u) | (dg3 << 24u);
f += a + sineparts[j] + u;
a = d;
@@ -342,23 +349,23 @@ static void ICCComputeMD5(const std::vector<uint8_t>& data, uint8_t sum[16])
sum[15] = d0 >> 24u;
}
-static Status CreateICCChadMatrix(double wx, double wy, float result[9]) {
- float m[9];
+static Status CreateICCChadMatrix(double wx, double wy, Matrix3x3& result) {
+ Matrix3x3 m;
if (wy == 0) { // WhitePoint can not be pitch-black.
return JXL_FAILURE("Invalid WhitePoint");
}
JXL_RETURN_IF_ERROR(AdaptToXYZD50(wx, wy, m));
- memcpy(result, m, sizeof(float) * 9);
+ result = m;
return true;
}
// Creates RGB to XYZ matrix given RGB primaries and whitepoint in xy.
static Status CreateICCRGBMatrix(double rx, double ry, double gx, double gy,
double bx, double by, double wx, double wy,
- float result[9]) {
- float m[9];
+ Matrix3x3& result) {
+ Matrix3x3 m;
JXL_RETURN_IF_ERROR(PrimariesToXYZD50(rx, ry, gx, gy, bx, by, wx, wy, m));
- memcpy(result, m, sizeof(float) * 9);
+ result = m;
return true;
}
@@ -433,8 +440,12 @@ static Status CreateICCHeader(const JxlColorEncoding& c,
// Three uint32_t's date/time encoding.
// TODO(lode): encode actual date and time, this is a placeholder
- uint32_t year = 2019, month = 12, day = 1;
- uint32_t hour = 0, minute = 0, second = 0;
+ uint32_t year = 2019;
+ uint32_t month = 12;
+ uint32_t day = 1;
+ uint32_t hour = 0;
+ uint32_t minute = 0;
+ uint32_t second = 0;
WriteICCUint16(year, 24, header);
WriteICCUint16(month, 26, header);
WriteICCUint16(day, 28, header);
@@ -491,13 +502,13 @@ static void CreateICCMlucTag(const std::string& text,
WriteICCTag("enUS", tags->size(), tags);
WriteICCUint32(text.size() * 2, tags->size(), tags);
WriteICCUint32(28, tags->size(), tags);
- for (size_t i = 0; i < text.size(); i++) {
+ for (char c : text) {
tags->push_back(0); // prepend 0 for UTF-16
- tags->push_back(text[i]);
+ tags->push_back(c);
}
}
-static Status CreateICCXYZTag(float xyz[3], std::vector<uint8_t>* tags) {
+static Status CreateICCXYZTag(const Color& xyz, std::vector<uint8_t>* tags) {
WriteICCTag("XYZ ", tags->size(), tags);
WriteICCUint32(0, tags->size(), tags);
for (size_t i = 0; i < 3; ++i) {
@@ -506,11 +517,14 @@ static Status CreateICCXYZTag(float xyz[3], std::vector<uint8_t>* tags) {
return true;
}
-static Status CreateICCChadTag(float chad[9], std::vector<uint8_t>* tags) {
+static Status CreateICCChadTag(const Matrix3x3& chad,
+ std::vector<uint8_t>* tags) {
WriteICCTag("sf32", tags->size(), tags);
WriteICCUint32(0, tags->size(), tags);
- for (size_t i = 0; i < 9; i++) {
- JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(chad[i], tags->size(), tags));
+ for (size_t j = 0; j < 3; j++) {
+ for (size_t i = 0; i < 3; i++) {
+ JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(chad[j][i], tags->size(), tags));
+ }
}
return true;
}
@@ -573,8 +587,8 @@ static Status CreateICCCurvParaTag(std::vector<float> params, size_t curve_type,
WriteICCUint32(0, tags->size(), tags);
WriteICCUint16(curve_type, tags->size(), tags);
WriteICCUint16(0, tags->size(), tags);
- for (size_t i = 0; i < params.size(); i++) {
- JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(params[i], tags->size(), tags));
+ for (float param : params) {
+ JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(param, tags->size(), tags));
}
return true;
}
@@ -649,8 +663,8 @@ static Status CreateICCLutAtoBTagForXYB(std::vector<uint8_t>* tags) {
-0.050022, 0.5683655, -0.018344,
-1.387676, 1.1145555, 0.6857255};
// 12 * 4 = 48 bytes
- for (size_t i = 0; i < 9; ++i) {
- JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(matrix[i], tags->size(), tags));
+ for (double v : matrix) {
+ JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(v, tags->size(), tags));
}
for (size_t i = 0; i < 3; ++i) {
float intercept = 0;
@@ -880,7 +894,9 @@ static std::string ColorEncodingDescriptionImpl(const JxlColorEncoding& c) {
static Status MaybeCreateProfileImpl(const JxlColorEncoding& c,
std::vector<uint8_t>* icc) {
- std::vector<uint8_t> header, tagtable, tags;
+ std::vector<uint8_t> header;
+ std::vector<uint8_t> tagtable;
+ std::vector<uint8_t> tags;
JxlTransferFunction tf = c.transfer_function;
if (c.color_space == JXL_COLOR_SPACE_UNKNOWN ||
tf == JXL_TRANSFER_FUNCTION_UNKNOWN) {
@@ -910,7 +926,8 @@ static Status MaybeCreateProfileImpl(const JxlColorEncoding& c,
// tag count, deferred to later
WriteICCUint32(0, tagtable.size(), &tagtable);
- size_t tag_offset = 0, tag_size = 0;
+ size_t tag_offset = 0;
+ size_t tag_size = 0;
CreateICCMlucTag(ColorEncodingDescriptionImpl(c), &tags);
FinalizeICCTag(&tags, &tag_offset, &tag_size);
@@ -923,12 +940,12 @@ static Status MaybeCreateProfileImpl(const JxlColorEncoding& c,
// TODO(eustas): isn't it the other way round: gray image has d50 WhitePoint?
if (c.color_space == JXL_COLOR_SPACE_GRAY) {
- float wtpt[3];
+ Color wtpt;
JXL_RETURN_IF_ERROR(
CIEXYZFromWhiteCIExy(c.white_point_xy[0], c.white_point_xy[1], wtpt));
JXL_RETURN_IF_ERROR(CreateICCXYZTag(wtpt, &tags));
} else {
- float d50[3] = {0.964203, 1.0, 0.824905};
+ Color d50{0.964203, 1.0, 0.824905};
JXL_RETURN_IF_ERROR(CreateICCXYZTag(d50, &tags));
}
FinalizeICCTag(&tags, &tag_offset, &tag_size);
@@ -936,7 +953,7 @@ static Status MaybeCreateProfileImpl(const JxlColorEncoding& c,
if (c.color_space != JXL_COLOR_SPACE_GRAY) {
// Chromatic adaptation matrix
- float chad[9];
+ Matrix3x3 chad;
JXL_RETURN_IF_ERROR(
CreateICCChadMatrix(c.white_point_xy[0], c.white_point_xy[1], chad));
@@ -949,14 +966,14 @@ static Status MaybeCreateProfileImpl(const JxlColorEncoding& c,
MaybeCreateICCCICPTag(c, &tags, &tag_offset, &tag_size, &tagtable,
&offsets);
- float m[9];
+ Matrix3x3 m;
JXL_RETURN_IF_ERROR(CreateICCRGBMatrix(
c.primaries_red_xy[0], c.primaries_red_xy[1], c.primaries_green_xy[0],
c.primaries_green_xy[1], c.primaries_blue_xy[0], c.primaries_blue_xy[1],
c.white_point_xy[0], c.white_point_xy[1], m));
- float r[3] = {m[0], m[3], m[6]};
- float g[3] = {m[1], m[4], m[7]};
- float b[3] = {m[2], m[5], m[8]};
+ Color r{m[0][0], m[1][0], m[2][0]};
+ Color g{m[0][1], m[1][1], m[2][1]};
+ Color b{m[0][2], m[1][2], m[2][2]};
JXL_RETURN_IF_ERROR(CreateICCXYZTag(r, &tags));
FinalizeICCTag(&tags, &tag_offset, &tag_size);
@@ -1042,8 +1059,8 @@ static Status MaybeCreateProfileImpl(const JxlColorEncoding& c,
WriteICCUint32(header.size() + tagtable.size() + tags.size(), 0, &header);
*icc = header;
- Bytes(tagtable).AppendTo(icc);
- Bytes(tags).AppendTo(icc);
+ Bytes(tagtable).AppendTo(*icc);
+ Bytes(tags).AppendTo(*icc);
// The MD5 checksum must be computed on the profile with profile flags,
// rendering intent, and region of the checksum itself, set to 0.
diff --git a/third_party/jpeg-xl/lib/jxl/cms/opsin_params.h b/third_party/jpeg-xl/lib/jxl/cms/opsin_params.h
index 48e8e254f7..69dcd0b512 100644
--- a/third_party/jpeg-xl/lib/jxl/cms/opsin_params.h
+++ b/third_party/jpeg-xl/lib/jxl/cms/opsin_params.h
@@ -6,7 +6,7 @@
#ifndef LIB_JXL_CMS_OPSIN_PARAMS_H_
#define LIB_JXL_CMS_OPSIN_PARAMS_H_
-#include <array>
+#include "lib/jxl/base/matrix_ops.h"
// Constants that define the XYB color space.
@@ -35,21 +35,20 @@ constexpr float kOpsinAbsorbanceBias1 = kOpsinAbsorbanceBias0;
constexpr float kOpsinAbsorbanceBias2 = kOpsinAbsorbanceBias0;
// Opsin absorbance matrix is now frozen.
-constexpr std::array<float, 9> kOpsinAbsorbanceMatrix = {
- kM00, kM01, kM02, kM10, kM11, kM12, kM20, kM21, kM22,
-};
+constexpr Matrix3x3 kOpsinAbsorbanceMatrix{
+ {{kM00, kM01, kM02}, {kM10, kM11, kM12}, {kM20, kM21, kM22}}};
-constexpr std::array<float, 9> kDefaultInverseOpsinAbsorbanceMatrix = {
- 11.031566901960783f, -9.866943921568629f, -0.16462299647058826f,
- -3.254147380392157f, 4.418770392156863f, -0.16462299647058826f,
- -3.6588512862745097f, 2.7129230470588235f, 1.9459282392156863f};
+constexpr Matrix3x3 kDefaultInverseOpsinAbsorbanceMatrix{
+ {{11.031566901960783f, -9.866943921568629f, -0.16462299647058826f},
+ {-3.254147380392157f, 4.418770392156863f, -0.16462299647058826f},
+ {-3.6588512862745097f, 2.7129230470588235f, 1.9459282392156863f}}};
// Must be the inverse matrix of kOpsinAbsorbanceMatrix and match the spec.
-static inline const float* DefaultInverseOpsinAbsorbanceMatrix() {
- return kDefaultInverseOpsinAbsorbanceMatrix.data();
+static inline const Matrix3x3& DefaultInverseOpsinAbsorbanceMatrix() {
+ return kDefaultInverseOpsinAbsorbanceMatrix;
}
-constexpr std::array<float, 3> kOpsinAbsorbanceBias = {
+constexpr Vector3 kOpsinAbsorbanceBias = {
kOpsinAbsorbanceBias0,
kOpsinAbsorbanceBias1,
kOpsinAbsorbanceBias2,
@@ -63,14 +62,14 @@ constexpr float kScaledXYBOffset0 = 0.015386134f;
constexpr float kScaledXYBOffset1 = 0.0f;
constexpr float kScaledXYBOffset2 = 0.27770459f;
-constexpr std::array<float, 3> kScaledXYBOffset = {
- kScaledXYBOffset0, kScaledXYBOffset1, kScaledXYBOffset2};
+constexpr Vector3 kScaledXYBOffset = {kScaledXYBOffset0, kScaledXYBOffset1,
+ kScaledXYBOffset2};
constexpr float kScaledXYBScale0 = 22.995788804f;
constexpr float kScaledXYBScale1 = 1.183000077f;
constexpr float kScaledXYBScale2 = 1.502141333f;
-constexpr std::array<float, 3> kScaledXYBScale = {
+constexpr Vector3 kScaledXYBScale = {
kScaledXYBScale0,
kScaledXYBScale1,
kScaledXYBScale2,
diff --git a/third_party/jpeg-xl/lib/jxl/cms/tone_mapping-inl.h b/third_party/jpeg-xl/lib/jxl/cms/tone_mapping-inl.h
index 3d94ccea12..7d09beed32 100644
--- a/third_party/jpeg-xl/lib/jxl/cms/tone_mapping-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/cms/tone_mapping-inl.h
@@ -100,14 +100,14 @@ class HlgOOTF : HlgOOTF_Base {
using HlgOOTF_Base::HlgOOTF_Base;
static HlgOOTF FromSceneLight(float display_luminance,
- const float primaries_luminances[3]) {
+ const Vector3& primaries_luminances) {
return HlgOOTF(/*gamma=*/1.2f *
std::pow(1.111f, std::log2(display_luminance / 1000.f)),
primaries_luminances);
}
static HlgOOTF ToSceneLight(float display_luminance,
- const float primaries_luminances[3]) {
+ const Vector3& primaries_luminances) {
return HlgOOTF(
/*gamma=*/(1 / 1.2f) *
std::pow(1.111f, -std::log2(display_luminance / 1000.f)),
@@ -132,7 +132,7 @@ class HlgOOTF : HlgOOTF_Base {
};
template <typename V>
-void GamutMap(V* red, V* green, V* blue, const float primaries_luminances[3],
+void GamutMap(V* red, V* green, V* blue, const Vector3& primaries_luminances,
float preserve_saturation = 0.1f) {
hwy::HWY_NAMESPACE::DFromV<V> df;
const V luminance =
diff --git a/third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h b/third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h
index a114109ea6..81f301a31d 100644
--- a/third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h
+++ b/third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h
@@ -12,6 +12,7 @@
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/matrix_ops.h"
#include "lib/jxl/cms/transfer_functions.h"
namespace jxl {
@@ -20,7 +21,7 @@ class Rec2408ToneMapperBase {
public:
explicit Rec2408ToneMapperBase(std::pair<float, float> source_range,
std::pair<float, float> target_range,
- const float primaries_luminances[3])
+ const Vector3& primaries_luminances)
: source_range_(source_range),
target_range_(target_range),
red_Y_(primaries_luminances[0]),
@@ -28,10 +29,10 @@ class Rec2408ToneMapperBase {
blue_Y_(primaries_luminances[2]) {}
// TODO(eustas): test me
- void ToneMap(float* red, float* green, float* blue) const {
+ void ToneMap(Color& rgb) const {
const float luminance =
source_range_.second *
- (red_Y_ * *red + green_Y_ * *green + blue_Y_ * *blue);
+ (red_Y_ * rgb[0] + green_Y_ * rgb[1] + blue_Y_ * rgb[2]);
const float normalized_pq =
std::min(1.f, (InvEOTF(luminance) - pq_mastering_min_) *
inv_pq_mastering_range_);
@@ -49,8 +50,8 @@ class Rec2408ToneMapperBase {
const float ratio = new_luminance / std::max(luminance, min_luminance);
const float cap = new_luminance * inv_target_peak_;
const float multiplier = ratio * normalizer_;
- for (float* const val : {red, green, blue}) {
- *val = use_cap ? cap : *val * multiplier;
+ for (size_t idx : {0, 1, 2}) {
+ rgb[idx] = use_cap ? cap : rgb[idx] * multiplier;
}
}
@@ -96,23 +97,24 @@ class Rec2408ToneMapperBase {
class HlgOOTF_Base {
public:
explicit HlgOOTF_Base(float source_luminance, float target_luminance,
- const float primaries_luminances[3])
+ const Vector3& primaries_luminances)
: HlgOOTF_Base(/*gamma=*/std::pow(1.111f, std::log2(target_luminance /
source_luminance)),
primaries_luminances) {}
// TODO(eustas): test me
- void Apply(float* red, float* green, float* blue) const {
+ void Apply(Color& rgb) const {
if (!apply_ootf_) return;
- const float luminance = red_Y_ * *red + green_Y_ * *green + blue_Y_ * *blue;
+ const float luminance =
+ red_Y_ * rgb[0] + green_Y_ * rgb[1] + blue_Y_ * rgb[2];
const float ratio = std::min<float>(powf(luminance, exponent_), 1e9);
- *red *= ratio;
- *green *= ratio;
- *blue *= ratio;
+ rgb[0] *= ratio;
+ rgb[1] *= ratio;
+ rgb[2] *= ratio;
}
protected:
- explicit HlgOOTF_Base(float gamma, const float luminances[3])
+ explicit HlgOOTF_Base(float gamma, const Vector3& luminances)
: exponent_(gamma - 1),
red_Y_(luminances[0]),
green_Y_(luminances[1]),
@@ -124,13 +126,12 @@ class HlgOOTF_Base {
const float blue_Y_;
};
-static JXL_MAYBE_UNUSED void GamutMapScalar(float* red, float* green,
- float* blue,
- const float primaries_luminances[3],
+static JXL_MAYBE_UNUSED void GamutMapScalar(Color& rgb,
+ const Vector3& primaries_luminances,
float preserve_saturation = 0.1f) {
- const float luminance = primaries_luminances[0] * *red +
- primaries_luminances[1] * *green +
- primaries_luminances[2] * *blue;
+ const float luminance = primaries_luminances[0] * rgb[0] +
+ primaries_luminances[1] * rgb[1] +
+ primaries_luminances[2] * rgb[2];
// Desaturate out-of-gamut pixels. This is done by mixing each pixel
// with just enough gray of the target luminance to make all
@@ -142,8 +143,8 @@ static JXL_MAYBE_UNUSED void GamutMapScalar(float* red, float* green,
// done by mixing in yet more gray. That will desaturate it further.
float gray_mix_saturation = 0.0f;
float gray_mix_luminance = 0.0f;
- for (const float* ch : {red, green, blue}) {
- const float& val = *ch;
+ for (size_t idx : {0, 1, 2}) {
+ const float& val = rgb[idx];
const float val_minus_gray = val - luminance;
const float inv_val_minus_gray =
1.0f / ((val_minus_gray == 0.0f) ? 1.0f : val_minus_gray);
@@ -162,15 +163,14 @@ static JXL_MAYBE_UNUSED void GamutMapScalar(float* red, float* green,
Clamp1((preserve_saturation * (gray_mix_saturation - gray_mix_luminance) +
gray_mix_luminance),
0.0f, 1.0f);
- for (float* const ch : {red, green, blue}) {
- float& val = *ch;
+ for (size_t idx : {0, 1, 2}) {
+ float& val = rgb[idx];
val = gray_mix * (luminance - val) + val;
}
- const float max_clr = std::max({1.0f, *red, *green, *blue});
+ const float max_clr = std::max({1.0f, rgb[0], rgb[1], rgb[2]});
const float normalizer = 1.0f / max_clr;
- for (float* const ch : {red, green, blue}) {
- float& val = *ch;
- val *= normalizer;
+ for (size_t idx : {0, 1, 2}) {
+ rgb[idx] *= normalizer;
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/cms/tone_mapping_test.cc b/third_party/jpeg-xl/lib/jxl/cms/tone_mapping_test.cc
index dda2bbb0aa..76165d26e7 100644
--- a/third_party/jpeg-xl/lib/jxl/cms/tone_mapping_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/cms/tone_mapping_test.cc
@@ -30,17 +30,17 @@ HWY_NOINLINE void TestRec2408ToneMap() {
for (size_t i = 0; i < kNumTrials; i++) {
float src = 11000.0 + rng.UniformF(-150.0f, 150.0f);
float tgt = 250 + rng.UniformF(-5.0f, 5.0f);
- float luminances[3] = {rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f),
- rng.UniformF(0.2f, 0.4f)};
- float rgb[3] = {rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f),
- rng.UniformF(0.0f, 1.0f)};
+ Vector3 luminances{rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f),
+ rng.UniformF(0.2f, 0.4f)};
+ Color rgb{rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f),
+ rng.UniformF(0.0f, 1.0f)};
Rec2408ToneMapper<decltype(d)> tone_mapper({0, src}, {0, tgt}, luminances);
auto r = Set(d, rgb[0]);
auto g = Set(d, rgb[1]);
auto b = Set(d, rgb[2]);
tone_mapper.ToneMap(&r, &g, &b);
Rec2408ToneMapperBase tone_mapper_base({0, src}, {0, tgt}, luminances);
- tone_mapper_base.ToneMap(&rgb[0], &rgb[1], &rgb[2]);
+ tone_mapper_base.ToneMap(rgb);
const float actual_r = GetLane(r);
const float expected_r = rgb[0];
const float abs_err_r = std::abs(expected_r - actual_r);
@@ -66,17 +66,17 @@ HWY_NOINLINE void TestHlgOotfApply() {
for (size_t i = 0; i < kNumTrials; i++) {
float src = 300.0 + rng.UniformF(-50.0f, 50.0f);
float tgt = 80 + rng.UniformF(-5.0f, 5.0f);
- float luminances[3] = {rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f),
- rng.UniformF(0.2f, 0.4f)};
- float rgb[3] = {rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f),
- rng.UniformF(0.0f, 1.0f)};
+ Vector3 luminances{rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f),
+ rng.UniformF(0.2f, 0.4f)};
+ Color rgb{rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f),
+ rng.UniformF(0.0f, 1.0f)};
HlgOOTF ootf(src, tgt, luminances);
auto r = Set(d, rgb[0]);
auto g = Set(d, rgb[1]);
auto b = Set(d, rgb[2]);
ootf.Apply(&r, &g, &b);
HlgOOTF_Base ootf_base(src, tgt, luminances);
- ootf_base.Apply(&rgb[0], &rgb[1], &rgb[2]);
+ ootf_base.Apply(rgb);
const float actual_r = GetLane(r);
const float expected_r = rgb[0];
const float abs_err_r = std::abs(expected_r - actual_r);
@@ -101,15 +101,15 @@ HWY_NOINLINE void TestGamutMap() {
HWY_FULL(float) d;
for (size_t i = 0; i < kNumTrials; i++) {
float preserve_saturation = rng.UniformF(0.2f, 0.4f);
- float luminances[3] = {rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f),
- rng.UniformF(0.2f, 0.4f)};
- float rgb[3] = {rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f),
- rng.UniformF(0.0f, 1.0f)};
+ Vector3 luminances{rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f),
+ rng.UniformF(0.2f, 0.4f)};
+ Color rgb{rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f),
+ rng.UniformF(0.0f, 1.0f)};
auto r = Set(d, rgb[0]);
auto g = Set(d, rgb[1]);
auto b = Set(d, rgb[2]);
GamutMap(&r, &g, &b, luminances, preserve_saturation);
- GamutMapScalar(&rgb[0], &rgb[1], &rgb[2], luminances, preserve_saturation);
+ GamutMapScalar(rgb, luminances, preserve_saturation);
const float actual_r = GetLane(r);
const float expected_r = rgb[0];
const float abs_err_r = std::abs(expected_r - actual_r);
diff --git a/third_party/jpeg-xl/lib/jxl/coeff_order.h b/third_party/jpeg-xl/lib/jxl/coeff_order.h
index 75f6f99e9f..79c0c976c9 100644
--- a/third_party/jpeg-xl/lib/jxl/coeff_order.h
+++ b/third_party/jpeg-xl/lib/jxl/coeff_order.h
@@ -10,10 +10,10 @@
#include <stdint.h>
#include "lib/jxl/ac_strategy.h"
+#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/coeff_order_fwd.h"
-#include "lib/jxl/dct_util.h"
#include "lib/jxl/frame_dimensions.h"
namespace jxl {
@@ -21,22 +21,21 @@ namespace jxl {
class BitReader;
// Those offsets get multiplied by kDCTBlockSize.
-static constexpr size_t kCoeffOrderOffset[] = {
+
+static constexpr size_t kCoeffOrderLimit = 6156;
+
+static constexpr std::array<size_t, 3 * kNumOrders + 1> kCoeffOrderOffset = {
0, 1, 2, 3, 4, 5, 6, 10, 14, 18,
34, 50, 66, 68, 70, 72, 76, 80, 84, 92,
100, 108, 172, 236, 300, 332, 364, 396, 652, 908,
- 1164, 1292, 1420, 1548, 2572, 3596, 4620, 5132, 5644, 6156,
-};
-static_assert(3 * kNumOrders + 1 ==
- sizeof(kCoeffOrderOffset) / sizeof(*kCoeffOrderOffset),
- "Update this array when adding or removing order types.");
+ 1164, 1292, 1420, 1548, 2572, 3596, 4620, 5132, 5644, kCoeffOrderLimit};
-static constexpr size_t CoeffOrderOffset(size_t order, size_t c) {
- return kCoeffOrderOffset[3 * order + c] * kDCTBlockSize;
-}
+// TODO(eustas): rollback to constexpr once modern C++ becomes reuired.
+#define CoeffOrderOffset(O, C) \
+ (kCoeffOrderOffset[3 * (O) + (C)] * kDCTBlockSize)
-static constexpr size_t kCoeffOrderMaxSize =
- kCoeffOrderOffset[3 * kNumOrders] * kDCTBlockSize;
+static JXL_MAYBE_UNUSED constexpr size_t kCoeffOrderMaxSize =
+ kCoeffOrderLimit * kDCTBlockSize;
// Mapping from AC strategy to order bucket. Strategies with different natural
// orders must have different buckets.
@@ -49,7 +48,7 @@ static_assert(AcStrategy::kNumValidStrategies ==
sizeof(kStrategyOrder) / sizeof(*kStrategyOrder),
"Update this array when adding or removing AC strategies.");
-constexpr uint32_t kPermutationContexts = 8;
+constexpr JXL_MAYBE_UNUSED uint32_t kPermutationContexts = 8;
uint32_t CoeffOrderContext(uint32_t val);
diff --git a/third_party/jpeg-xl/lib/jxl/color_encoding_internal.cc b/third_party/jpeg-xl/lib/jxl/color_encoding_internal.cc
index 19273dad3c..895faaa07d 100644
--- a/third_party/jpeg-xl/lib/jxl/color_encoding_internal.cc
+++ b/third_party/jpeg-xl/lib/jxl/color_encoding_internal.cc
@@ -47,12 +47,12 @@ std::array<ColorEncoding, 2> ColorEncoding::CreateC2(Primaries pr,
const ColorEncoding& ColorEncoding::SRGB(bool is_gray) {
static std::array<ColorEncoding, 2> c2 =
CreateC2(Primaries::kSRGB, TransferFunction::kSRGB);
- return c2[is_gray];
+ return c2[is_gray ? 1 : 0];
}
const ColorEncoding& ColorEncoding::LinearSRGB(bool is_gray) {
static std::array<ColorEncoding, 2> c2 =
CreateC2(Primaries::kSRGB, TransferFunction::kLinear);
- return c2[is_gray];
+ return c2[is_gray ? 1 : 0];
}
Status ColorEncoding::SetWhitePointType(const WhitePoint& wp) {
diff --git a/third_party/jpeg-xl/lib/jxl/color_encoding_internal.h b/third_party/jpeg-xl/lib/jxl/color_encoding_internal.h
index 0a104a12b2..61e4628dbd 100644
--- a/third_party/jpeg-xl/lib/jxl/color_encoding_internal.h
+++ b/third_party/jpeg-xl/lib/jxl/color_encoding_internal.h
@@ -314,7 +314,6 @@ class ColorSpaceTransform {
Status Init(const ColorEncoding& c_src, const ColorEncoding& c_dst,
float intensity_target, size_t xsize, size_t num_threads) {
- xsize_ = xsize;
JxlColorProfile input_profile;
icc_src_ = c_src.ICC();
input_profile.icc.data = icc_src_.data();
@@ -343,8 +342,10 @@ class ColorSpaceTransform {
return cms_.get_dst_buf(cms_data_, thread);
}
- Status Run(const size_t thread, const float* buf_src, float* buf_dst) {
- return cms_.run(cms_data_, thread, buf_src, buf_dst, xsize_);
+ Status Run(const size_t thread, const float* buf_src, float* buf_dst,
+ size_t xsize) {
+ // TODO(eustas): convert false to Status?
+ return FROM_JXL_BOOL(cms_.run(cms_data_, thread, buf_src, buf_dst, xsize));
}
private:
@@ -353,7 +354,6 @@ class ColorSpaceTransform {
// The interface may retain pointers into these.
IccBytes icc_src_;
IccBytes icc_dst_;
- size_t xsize_;
};
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/color_encoding_internal_test.cc b/third_party/jpeg-xl/lib/jxl/color_encoding_internal_test.cc
index 4d2d3e8119..2a9f60427a 100644
--- a/third_party/jpeg-xl/lib/jxl/color_encoding_internal_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/color_encoding_internal_test.cc
@@ -97,24 +97,29 @@ TEST(ColorEncodingTest, InternalExternalConversion) {
ColorEncoding source_internal;
ColorEncoding destination_internal;
+ const auto rand_float = []() {
+ return (static_cast<float>(rand()) / static_cast<float>(RAND_MAX) * 0.5) +
+ 0.25;
+ };
+
for (int i = 0; i < 100; i++) {
source_internal.color_space = static_cast<ColorSpace>(rand() % 4);
CIExy wp;
- wp.x = (float(rand()) / float((RAND_MAX)) * 0.5) + 0.25;
- wp.y = (float(rand()) / float((RAND_MAX)) * 0.5) + 0.25;
+ wp.x = rand_float();
+ wp.y = rand_float();
EXPECT_TRUE(source_internal.SetWhitePoint(wp));
if (source_internal.HasPrimaries()) {
PrimariesCIExy primaries;
- primaries.r.x = (float(rand()) / float((RAND_MAX)) * 0.5) + 0.25;
- primaries.r.y = (float(rand()) / float((RAND_MAX)) * 0.5) + 0.25;
- primaries.g.x = (float(rand()) / float((RAND_MAX)) * 0.5) + 0.25;
- primaries.g.y = (float(rand()) / float((RAND_MAX)) * 0.5) + 0.25;
- primaries.b.x = (float(rand()) / float((RAND_MAX)) * 0.5) + 0.25;
- primaries.b.y = (float(rand()) / float((RAND_MAX)) * 0.5) + 0.25;
+ primaries.r.x = rand_float();
+ primaries.r.y = rand_float();
+ primaries.g.x = rand_float();
+ primaries.g.y = rand_float();
+ primaries.b.x = rand_float();
+ primaries.b.y = rand_float();
EXPECT_TRUE(source_internal.SetPrimaries(primaries));
}
jxl::cms::CustomTransferFunction tf;
- EXPECT_TRUE(tf.SetGamma((float(rand()) / float((RAND_MAX)) * 0.5) + 0.25));
+ EXPECT_TRUE(tf.SetGamma(rand_float()));
source_internal.tf = tf;
source_internal.rendering_intent = static_cast<RenderingIntent>(rand() % 4);
diff --git a/third_party/jpeg-xl/lib/jxl/color_management_test.cc b/third_party/jpeg-xl/lib/jxl/color_management_test.cc
index ca50c9960e..b2d47c73f9 100644
--- a/third_party/jpeg-xl/lib/jxl/color_management_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/color_management_test.cc
@@ -45,55 +45,10 @@ std::ostream& operator<<(std::ostream& os, const PrimariesCIExy& primaries) {
namespace {
-using ::testing::ElementsAre;
-using ::testing::FloatNear;
-
// Small enough to be fast. If changed, must update Generate*.
-static constexpr size_t kWidth = 16;
-
-static constexpr size_t kNumThreads = 1; // only have a single row.
+constexpr size_t kWidth = 16;
-MATCHER_P(HasSameFieldsAs, expected, "") {
- if (arg.GetRenderingIntent() != expected.GetRenderingIntent()) {
- *result_listener << "which has a different rendering intent: "
- << ToString(arg.GetRenderingIntent()) << " instead of "
- << ToString(expected.GetRenderingIntent());
- return false;
- }
- if (arg.GetColorSpace() != expected.GetColorSpace()) {
- *result_listener << "which has a different color space: "
- << ToString(arg.GetColorSpace()) << " instead of "
- << ToString(expected.GetColorSpace());
- return false;
- }
- if (arg.GetWhitePointType() != expected.GetWhitePointType()) {
- *result_listener << "which has a different white point: "
- << ToString(arg.GetWhitePointType()) << " instead of "
- << ToString(expected.GetWhitePointType());
- return false;
- }
- if (arg.HasPrimaries() &&
- arg.GetPrimariesType() != expected.GetPrimariesType()) {
- *result_listener << "which has different primaries: "
- << ToString(arg.GetPrimariesType()) << " instead of "
- << ToString(expected.GetPrimariesType());
- return false;
- }
- if (!arg.Tf().IsSame(expected.Tf())) {
- static const auto tf_to_string =
- [](const jxl::cms::CustomTransferFunction& tf) {
- if (tf.have_gamma) {
- return "g" + ToString(tf.GetGamma());
- }
- return ToString(tf.transfer_function);
- };
- *result_listener << "which has a different transfer function: "
- << tf_to_string(arg.Tf()) << " instead of "
- << tf_to_string(expected.Tf());
- return false;
- }
- return true;
-}
+constexpr size_t kNumThreads = 1; // only have a single row.
struct Globals {
// TODO(deymo): Make this a const.
@@ -106,15 +61,15 @@ struct Globals {
Globals() {
in_gray = GenerateGray();
in_color = GenerateColor();
- out_gray = ImageF(kWidth, 1);
- out_color = ImageF(kWidth * 3, 1);
+ JXL_ASSIGN_OR_DIE(out_gray, ImageF::Create(kWidth, 1));
+ JXL_ASSIGN_OR_DIE(out_color, ImageF::Create(kWidth * 3, 1));
c_native = ColorEncoding::LinearSRGB(/*is_gray=*/false);
c_gray = ColorEncoding::LinearSRGB(/*is_gray=*/true);
}
static ImageF GenerateGray() {
- ImageF gray(kWidth, 1);
+ JXL_ASSIGN_OR_DIE(ImageF gray, ImageF::Create(kWidth, 1));
float* JXL_RESTRICT row = gray.Row(0);
// Increasing left to right
for (uint32_t x = 0; x < kWidth; ++x) {
@@ -124,7 +79,7 @@ struct Globals {
}
static ImageF GenerateColor() {
- ImageF image(kWidth * 3, 1);
+ JXL_ASSIGN_OR_DIE(ImageF image, ImageF::Create(kWidth * 3, 1));
float* JXL_RESTRICT interleaved = image.Row(0);
std::fill(interleaved, interleaved + kWidth * 3, 0.0f);
@@ -182,8 +137,10 @@ class ColorManagementTest
const size_t thread = 0;
const ImageF& in = c.IsGray() ? g->in_gray : g->in_color;
ImageF* JXL_RESTRICT out = c.IsGray() ? &g->out_gray : &g->out_color;
- ASSERT_TRUE(xform_fwd.Run(thread, in.Row(0), xform_fwd.BufDst(thread)));
- ASSERT_TRUE(xform_rev.Run(thread, xform_fwd.BufDst(thread), out->Row(0)));
+ ASSERT_TRUE(
+ xform_fwd.Run(thread, in.Row(0), xform_fwd.BufDst(thread), kWidth));
+ ASSERT_TRUE(
+ xform_rev.Run(thread, xform_fwd.BufDst(thread), out->Row(0), kWidth));
// With lcms2, this value is lower: 5E-5
double max_l1 = 7E-4;
@@ -200,77 +157,108 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P(ColorManagementTestInstantiation,
// Exercises the ColorManagement interface for ALL ColorEncoding synthesizable
// via enums.
TEST_P(ColorManagementTest, VerifyAllProfiles) {
- ColorEncoding c = ColorEncodingFromDescriptor(GetParam());
- printf("%s\n", Description(c).c_str());
+ ColorEncoding actual = ColorEncodingFromDescriptor(GetParam());
+ printf("%s\n", Description(actual).c_str());
// Can create profile.
- ASSERT_TRUE(c.CreateICC());
+ ASSERT_TRUE(actual.CreateICC());
// Can set an equivalent ColorEncoding from the generated ICC profile.
- ColorEncoding c3;
- ASSERT_TRUE(c3.SetICC(IccBytes(c.ICC()), JxlGetDefaultCms()));
- EXPECT_THAT(c3, HasSameFieldsAs(c));
+ ColorEncoding expected;
+ ASSERT_TRUE(expected.SetICC(IccBytes(actual.ICC()), JxlGetDefaultCms()));
+
+ EXPECT_EQ(actual.GetRenderingIntent(), expected.GetRenderingIntent())
+ << "different rendering intent: " << ToString(actual.GetRenderingIntent())
+ << " instead of " << ToString(expected.GetRenderingIntent());
+ EXPECT_EQ(actual.GetColorSpace(), expected.GetColorSpace())
+ << "different color space: " << ToString(actual.GetColorSpace())
+ << " instead of " << ToString(expected.GetColorSpace());
+ EXPECT_EQ(actual.GetWhitePointType(), expected.GetWhitePointType())
+ << "different white point: " << ToString(actual.GetWhitePointType())
+ << " instead of " << ToString(expected.GetWhitePointType());
+ EXPECT_EQ(actual.HasPrimaries(), expected.HasPrimaries());
+ if (actual.HasPrimaries()) {
+ EXPECT_EQ(actual.GetPrimariesType(), expected.GetPrimariesType())
+ << "different primaries: " << ToString(actual.GetPrimariesType())
+ << " instead of " << ToString(expected.GetPrimariesType());
+ }
- VerifyPixelRoundTrip(c);
-}
+ static const auto tf_to_string =
+ [](const jxl::cms::CustomTransferFunction& tf) {
+ if (tf.have_gamma) {
+ return "g" + ToString(tf.GetGamma());
+ }
+ return ToString(tf.transfer_function);
+ };
+ EXPECT_TRUE(actual.Tf().IsSame(expected.Tf()))
+ << "different transfer function: " << tf_to_string(actual.Tf())
+ << " instead of " << tf_to_string(expected.Tf());
-testing::Matcher<CIExy> CIExyIs(const double x, const double y) {
- static constexpr double kMaxError = 1e-4;
- return testing::AllOf(
- testing::Field(&CIExy::x, testing::DoubleNear(x, kMaxError)),
- testing::Field(&CIExy::y, testing::DoubleNear(y, kMaxError)));
+ VerifyPixelRoundTrip(actual);
}
-testing::Matcher<PrimariesCIExy> PrimariesAre(
- const testing::Matcher<CIExy>& r, const testing::Matcher<CIExy>& g,
- const testing::Matcher<CIExy>& b) {
- return testing::AllOf(testing::Field(&PrimariesCIExy::r, r),
- testing::Field(&PrimariesCIExy::g, g),
- testing::Field(&PrimariesCIExy::b, b));
-}
+#define EXPECT_CIEXY_NEAR(A, E, T) \
+ { \
+ CIExy _actual = (A); \
+ CIExy _expected = (E); \
+ double _tolerance = (T); \
+ EXPECT_NEAR(_actual.x, _expected.x, _tolerance) << "x is different"; \
+ EXPECT_NEAR(_actual.y, _expected.y, _tolerance) << "y is different"; \
+ }
+
+#define EXPECT_PRIMARIES_NEAR(A, E, T) \
+ { \
+ PrimariesCIExy _actual = (A); \
+ PrimariesCIExy _expected = (E); \
+ double _tolerance = (T); \
+ EXPECT_NEAR(_actual.r.x, _expected.r.x, _tolerance) << "r.x is different"; \
+ EXPECT_NEAR(_actual.r.y, _expected.r.y, _tolerance) << "r.y is different"; \
+ EXPECT_NEAR(_actual.g.x, _expected.g.x, _tolerance) << "g.x is different"; \
+ EXPECT_NEAR(_actual.g.y, _expected.g.y, _tolerance) << "g.y is different"; \
+ EXPECT_NEAR(_actual.b.x, _expected.b.x, _tolerance) << "b.x is different"; \
+ EXPECT_NEAR(_actual.b.y, _expected.b.y, _tolerance) << "b.y is different"; \
+ }
TEST_F(ColorManagementTest, sRGBChromaticity) {
const ColorEncoding sRGB = ColorEncoding::SRGB();
- EXPECT_THAT(sRGB.GetWhitePoint(), CIExyIs(0.3127, 0.3290));
- EXPECT_THAT(sRGB.GetPrimaries(),
- PrimariesAre(CIExyIs(0.64, 0.33), CIExyIs(0.30, 0.60),
- CIExyIs(0.15, 0.06)));
+ EXPECT_CIEXY_NEAR(sRGB.GetWhitePoint(), CIExy(0.3127, 0.3290), 1e-4);
+ PrimariesCIExy srgb_primaries = {{0.64, 0.33}, {0.30, 0.60}, {0.15, 0.06}};
+ EXPECT_PRIMARIES_NEAR(sRGB.GetPrimaries(), srgb_primaries, 1e-4);
}
TEST_F(ColorManagementTest, D2700Chromaticity) {
std::vector<uint8_t> icc_data =
jxl::test::ReadTestData("jxl/color_management/sRGB-D2700.icc");
IccBytes icc;
- Bytes(icc_data).AppendTo(&icc);
+ Bytes(icc_data).AppendTo(icc);
ColorEncoding sRGB_D2700;
ASSERT_TRUE(sRGB_D2700.SetICC(std::move(icc), JxlGetDefaultCms()));
- EXPECT_THAT(sRGB_D2700.GetWhitePoint(), CIExyIs(0.45986, 0.41060));
+ EXPECT_CIEXY_NEAR(sRGB_D2700.GetWhitePoint(), CIExy(0.45986, 0.41060), 1e-4);
// The illuminant-relative chromaticities of this profile's primaries are the
// same as for sRGB. It is the PCS-relative chromaticities that would be
// different.
- EXPECT_THAT(sRGB_D2700.GetPrimaries(),
- PrimariesAre(CIExyIs(0.64, 0.33), CIExyIs(0.30, 0.60),
- CIExyIs(0.15, 0.06)));
+ PrimariesCIExy srgb_primaries = {{0.64, 0.33}, {0.30, 0.60}, {0.15, 0.06}};
+ EXPECT_PRIMARIES_NEAR(sRGB_D2700.GetPrimaries(), srgb_primaries, 1e-4);
}
TEST_F(ColorManagementTest, D2700ToSRGB) {
std::vector<uint8_t> icc_data =
jxl::test::ReadTestData("jxl/color_management/sRGB-D2700.icc");
IccBytes icc;
- Bytes(icc_data).AppendTo(&icc);
+ Bytes(icc_data).AppendTo(icc);
ColorEncoding sRGB_D2700;
ASSERT_TRUE(sRGB_D2700.SetICC(std::move(icc), JxlGetDefaultCms()));
ColorSpaceTransform transform(*JxlGetDefaultCms());
ASSERT_TRUE(transform.Init(sRGB_D2700, ColorEncoding::SRGB(),
kDefaultIntensityTarget, 1, 1));
- const float sRGB_D2700_values[3] = {0.863, 0.737, 0.490};
- float sRGB_values[3];
- ASSERT_TRUE(transform.Run(0, sRGB_D2700_values, sRGB_values));
- EXPECT_THAT(sRGB_values,
- ElementsAre(FloatNear(0.914, 1e-3), FloatNear(0.745, 1e-3),
- FloatNear(0.601, 1e-3)));
+ Color sRGB_D2700_values{0.863, 0.737, 0.490};
+ Color sRGB_values;
+ ASSERT_TRUE(
+ transform.Run(0, sRGB_D2700_values.data(), sRGB_values.data(), 1));
+ Color sRGB_expected{0.914, 0.745, 0.601};
+ EXPECT_ARRAY_NEAR(sRGB_values, sRGB_expected, 1e-3);
}
TEST_F(ColorManagementTest, P3HlgTo2020Hlg) {
@@ -287,12 +275,12 @@ TEST_F(ColorManagementTest, P3HlgTo2020Hlg) {
ColorSpaceTransform transform(*JxlGetDefaultCms());
ASSERT_TRUE(transform.Init(p3_hlg, rec2020_hlg, 1000, 1, 1));
- const float p3_hlg_values[3] = {0., 0.75, 0.};
- float rec2020_hlg_values[3];
- ASSERT_TRUE(transform.Run(0, p3_hlg_values, rec2020_hlg_values));
- EXPECT_THAT(rec2020_hlg_values,
- ElementsAre(FloatNear(0.3973, 1e-4), FloatNear(0.7382, 1e-4),
- FloatNear(0.1183, 1e-4)));
+ Color p3_hlg_values{0., 0.75, 0.};
+ Color rec2020_hlg_values;
+ ASSERT_TRUE(
+ transform.Run(0, p3_hlg_values.data(), rec2020_hlg_values.data(), 1));
+ Color rec2020_hlg_expected{0.3973, 0.7382, 0.1183};
+ EXPECT_ARRAY_NEAR(rec2020_hlg_values, rec2020_hlg_expected, 1e-4);
}
TEST_F(ColorManagementTest, HlgOotf) {
@@ -307,38 +295,34 @@ TEST_F(ColorManagementTest, HlgOotf) {
ASSERT_TRUE(
transform_to_1000.Init(p3_hlg, ColorEncoding::LinearSRGB(), 1000, 1, 1));
// HDR reference white: https://www.itu.int/pub/R-REP-BT.2408-4-2021
- float p3_hlg_values[3] = {0.75, 0.75, 0.75};
- float linear_srgb_values[3];
- ASSERT_TRUE(transform_to_1000.Run(0, p3_hlg_values, linear_srgb_values));
+ Color p3_hlg_values{0.75, 0.75, 0.75};
+ Color linear_srgb_values;
+ ASSERT_TRUE(transform_to_1000.Run(0, p3_hlg_values.data(),
+ linear_srgb_values.data(), 1));
// On a 1000-nit display, HDR reference white should be 203 cd/m² which is
// 0.203 times the maximum.
- EXPECT_THAT(linear_srgb_values,
- ElementsAre(FloatNear(0.203, 1e-3), FloatNear(0.203, 1e-3),
- FloatNear(0.203, 1e-3)));
+ EXPECT_ARRAY_NEAR(linear_srgb_values, (Color{0.203, 0.203, 0.203}), 1e-3);
ColorSpaceTransform transform_to_400(*JxlGetDefaultCms());
ASSERT_TRUE(
transform_to_400.Init(p3_hlg, ColorEncoding::LinearSRGB(), 400, 1, 1));
- ASSERT_TRUE(transform_to_400.Run(0, p3_hlg_values, linear_srgb_values));
+ ASSERT_TRUE(transform_to_400.Run(0, p3_hlg_values.data(),
+ linear_srgb_values.data(), 1));
// On a 400-nit display, it should be 100 cd/m².
- EXPECT_THAT(linear_srgb_values,
- ElementsAre(FloatNear(0.250, 1e-3), FloatNear(0.250, 1e-3),
- FloatNear(0.250, 1e-3)));
+ EXPECT_ARRAY_NEAR(linear_srgb_values, (Color{0.250, 0.250, 0.250}), 1e-3);
p3_hlg_values[2] = 0.50;
- ASSERT_TRUE(transform_to_1000.Run(0, p3_hlg_values, linear_srgb_values));
- EXPECT_THAT(linear_srgb_values,
- ElementsAre(FloatNear(0.201, 1e-3), FloatNear(0.201, 1e-3),
- FloatNear(0.050, 1e-3)));
+ ASSERT_TRUE(transform_to_1000.Run(0, p3_hlg_values.data(),
+ linear_srgb_values.data(), 1));
+ EXPECT_ARRAY_NEAR(linear_srgb_values, (Color{0.201, 0.201, 0.050}), 1e-3);
ColorSpaceTransform transform_from_400(*JxlGetDefaultCms());
ASSERT_TRUE(
transform_from_400.Init(ColorEncoding::LinearSRGB(), p3_hlg, 400, 1, 1));
linear_srgb_values[0] = linear_srgb_values[1] = linear_srgb_values[2] = 0.250;
- ASSERT_TRUE(transform_from_400.Run(0, linear_srgb_values, p3_hlg_values));
- EXPECT_THAT(p3_hlg_values,
- ElementsAre(FloatNear(0.75, 1e-3), FloatNear(0.75, 1e-3),
- FloatNear(0.75, 1e-3)));
+ ASSERT_TRUE(transform_from_400.Run(0, linear_srgb_values.data(),
+ p3_hlg_values.data(), 1));
+ EXPECT_ARRAY_NEAR(p3_hlg_values, (Color{0.75, 0.75, 0.75}), 1e-3);
ColorEncoding grayscale_hlg;
grayscale_hlg.SetColorSpace(ColorSpace::kGray);
@@ -352,8 +336,8 @@ TEST_F(ColorManagementTest, HlgOotf) {
const float grayscale_hlg_value = 0.75;
float linear_grayscale_value;
ASSERT_TRUE(grayscale_transform.Run(0, &grayscale_hlg_value,
- &linear_grayscale_value));
- EXPECT_THAT(linear_grayscale_value, FloatNear(0.203, 1e-3));
+ &linear_grayscale_value, 1));
+ EXPECT_NEAR(linear_grayscale_value, 0.203, 1e-3);
}
TEST_F(ColorManagementTest, XYBProfile) {
@@ -373,7 +357,7 @@ TEST_F(ColorManagementTest, XYBProfile) {
ImageMetadata metadata;
metadata.color_encoding = c_native;
ImageBundle ib(&metadata);
- Image3F native(kNumColors, 1);
+ JXL_ASSIGN_OR_DIE(Image3F native, Image3F::Create(kNumColors, 1));
float mul = 1.0f / (kGridDim - 1);
for (size_t ir = 0, x = 0; ir < kGridDim; ++ir) {
for (size_t ig = 0; ig < kGridDim; ++ig) {
@@ -386,10 +370,10 @@ TEST_F(ColorManagementTest, XYBProfile) {
}
ib.SetFromImage(std::move(native), c_native);
const Image3F& in = *ib.color();
- Image3F opsin(kNumColors, 1);
- ToXYB(ib, nullptr, &opsin, cms, nullptr);
+ JXL_ASSIGN_OR_DIE(Image3F opsin, Image3F::Create(kNumColors, 1));
+ JXL_CHECK(ToXYB(ib, nullptr, &opsin, cms, nullptr));
- Image3F opsin2(kNumColors, 1);
+ JXL_ASSIGN_OR_DIE(Image3F opsin2, Image3F::Create(kNumColors, 1));
CopyImageTo(opsin, &opsin2);
ScaleXYB(&opsin2);
@@ -401,9 +385,9 @@ TEST_F(ColorManagementTest, XYBProfile) {
}
float* dst = xform.BufDst(0);
- ASSERT_TRUE(xform.Run(0, src, dst));
+ ASSERT_TRUE(xform.Run(0, src, dst, kNumColors));
- Image3F out(kNumColors, 1);
+ JXL_ASSIGN_OR_DIE(Image3F out, Image3F::Create(kNumColors, 1));
for (size_t i = 0; i < kNumColors; ++i) {
for (size_t c = 0; c < 3; ++c) {
out.PlaneRow(c, 0)[i] = dst[3 * i + c];
diff --git a/third_party/jpeg-xl/lib/jxl/common.h b/third_party/jpeg-xl/lib/jxl/common.h
index d619711c9f..d593244433 100644
--- a/third_party/jpeg-xl/lib/jxl/common.h
+++ b/third_party/jpeg-xl/lib/jxl/common.h
@@ -33,6 +33,38 @@ constexpr size_t kMaxNumPasses = 11;
// Maximum number of reference frames.
constexpr size_t kMaxNumReferenceFrames = 4;
+enum class SpeedTier {
+ // Try multiple combinations of Glacier flags for modular mode. Otherwise
+ // like kGlacier.
+ kTectonicPlate = -1,
+ // Learn a global tree in Modular mode.
+ kGlacier = 0,
+ // Turns on FindBestQuantizationHQ loop. Equivalent to "guetzli" mode.
+ kTortoise = 1,
+ // Turns on FindBestQuantization butteraugli loop.
+ kKitten = 2,
+ // Turns on dots, patches, and spline detection by default, as well as full
+ // context clustering. Default.
+ kSquirrel = 3,
+ // Turns on error diffusion and full AC strategy heuristics. Equivalent to
+ // "fast" mode.
+ kWombat = 4,
+ // Turns on gaborish by default, non-default cmap, initial quant field.
+ kHare = 5,
+ // Turns on simple heuristics for AC strategy, quant field, and clustering;
+ // also enables coefficient reordering.
+ kCheetah = 6,
+ // Turns off most encoder features. Does context clustering.
+ // Modular: uses fixed tree with Weighted predictor.
+ kFalcon = 7,
+ // Currently fastest possible setting for VarDCT.
+ // Modular: uses fixed tree with Gradient predictor.
+ kThunder = 8,
+ // VarDCT: same as kThunder.
+ // Modular: no tree, Gradient predictor, fast histograms
+ kLightning = 9
+};
+
} // namespace jxl
#endif // LIB_JXL_COMMON_H_
diff --git a/third_party/jpeg-xl/lib/jxl/compressed_dc.cc b/third_party/jpeg-xl/lib/jxl/compressed_dc.cc
index b21b1da18b..250be9e9a6 100644
--- a/third_party/jpeg-xl/lib/jxl/compressed_dc.cc
+++ b/third_party/jpeg-xl/lib/jxl/compressed_dc.cc
@@ -10,9 +10,6 @@
#include <string.h>
#include <algorithm>
-#include <array>
-#include <memory>
-#include <utility>
#include <vector>
#undef HWY_TARGET_INCLUDE
@@ -21,17 +18,9 @@
#include <hwy/foreach_target.h>
#include <hwy/highway.h>
-#include "lib/jxl/ac_strategy.h"
-#include "lib/jxl/ans_params.h"
-#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/chroma_from_luma.h"
-#include "lib/jxl/dec_ans.h"
-#include "lib/jxl/dec_bit_reader.h"
-#include "lib/jxl/dec_cache.h"
-#include "lib/jxl/entropy_coder.h"
#include "lib/jxl/image.h"
HWY_BEFORE_NAMESPACE();
namespace jxl {
@@ -131,21 +120,21 @@ JXL_INLINE void ComputePixel(
Store(out, d, out_rows[2] + x);
}
-void AdaptiveDCSmoothing(const float* dc_factors, Image3F* dc,
- ThreadPool* pool) {
+Status AdaptiveDCSmoothing(const float* dc_factors, Image3F* dc,
+ ThreadPool* pool) {
const size_t xsize = dc->xsize();
const size_t ysize = dc->ysize();
- if (ysize <= 2 || xsize <= 2) return;
+ if (ysize <= 2 || xsize <= 2) return true;
// TODO(veluca): use tile-based processing?
// TODO(veluca): decide if changes to the y channel should be propagated to
// the x and b channels through color correlation.
JXL_ASSERT(w1 + w2 < 0.25f);
- Image3F smoothed(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(Image3F smoothed, Image3F::Create(xsize, ysize));
// Fill in borders that the loop below will not. First and last are unused.
for (size_t c = 0; c < 3; c++) {
- for (size_t y : {size_t(0), ysize - 1}) {
+ for (size_t y : {static_cast<size_t>(0), ysize - 1}) {
memcpy(smoothed.PlaneRow(c, y), dc->PlaneRow(c, y),
xsize * sizeof(float));
}
@@ -171,7 +160,7 @@ void AdaptiveDCSmoothing(const float* dc_factors, Image3F* dc,
smoothed.PlaneRow(1, y),
smoothed.PlaneRow(2, y),
};
- for (size_t x : {size_t(0), xsize - 1}) {
+ for (size_t x : {static_cast<size_t>(0), xsize - 1}) {
for (size_t c = 0; c < 3; c++) {
rows_out[c][x] = rows[c][x];
}
@@ -197,12 +186,13 @@ void AdaptiveDCSmoothing(const float* dc_factors, Image3F* dc,
JXL_CHECK(RunOnPool(pool, 1, ysize - 1, ThreadPool::NoInit, process_row,
"DCSmoothingRow"));
dc->Swap(smoothed);
+ return true;
}
// DC dequantization.
void DequantDC(const Rect& r, Image3F* dc, ImageB* quant_dc, const Image& in,
const float* dc_factors, float mul, const float* cfl_factors,
- YCbCrChromaSubsampling chroma_subsampling,
+ const YCbCrChromaSubsampling& chroma_subsampling,
const BlockCtxMap& bctx) {
const HWY_FULL(float) df;
const Rebind<pixel_type, HWY_FULL(float)> di; // assumes pixel_type <= float
@@ -265,7 +255,9 @@ void DequantDC(const Rect& r, Image3F* dc, ImageB* quant_dc, const Image& in,
const int32_t* quant_row_b =
in.channel[2].plane.Row(y >> chroma_subsampling.VShift(2));
for (size_t x = 0; x < r.xsize(); x++) {
- int bucket_x = 0, bucket_y = 0, bucket_b = 0;
+ int bucket_x = 0;
+ int bucket_y = 0;
+ int bucket_b = 0;
for (int t : bctx.dc_thresholds[0]) {
if (quant_row_x[x >> chroma_subsampling.HShift(0)] > t) bucket_x++;
}
@@ -296,17 +288,17 @@ namespace jxl {
HWY_EXPORT(DequantDC);
HWY_EXPORT(AdaptiveDCSmoothing);
-void AdaptiveDCSmoothing(const float* dc_factors, Image3F* dc,
- ThreadPool* pool) {
+Status AdaptiveDCSmoothing(const float* dc_factors, Image3F* dc,
+ ThreadPool* pool) {
return HWY_DYNAMIC_DISPATCH(AdaptiveDCSmoothing)(dc_factors, dc, pool);
}
void DequantDC(const Rect& r, Image3F* dc, ImageB* quant_dc, const Image& in,
const float* dc_factors, float mul, const float* cfl_factors,
- YCbCrChromaSubsampling chroma_subsampling,
+ const YCbCrChromaSubsampling& chroma_subsampling,
const BlockCtxMap& bctx) {
- return HWY_DYNAMIC_DISPATCH(DequantDC)(r, dc, quant_dc, in, dc_factors, mul,
- cfl_factors, chroma_subsampling, bctx);
+ HWY_DYNAMIC_DISPATCH(DequantDC)
+ (r, dc, quant_dc, in, dc_factors, mul, cfl_factors, chroma_subsampling, bctx);
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/compressed_dc.h b/third_party/jpeg-xl/lib/jxl/compressed_dc.h
index b06e5931f0..30259ebd56 100644
--- a/third_party/jpeg-xl/lib/jxl/compressed_dc.h
+++ b/third_party/jpeg-xl/lib/jxl/compressed_dc.h
@@ -21,12 +21,12 @@
namespace jxl {
// Smooth DC in already-smooth areas, to counteract banding.
-void AdaptiveDCSmoothing(const float* dc_factors, Image3F* dc,
- ThreadPool* pool);
+Status AdaptiveDCSmoothing(const float* dc_factors, Image3F* dc,
+ ThreadPool* pool);
void DequantDC(const Rect& r, Image3F* dc, ImageB* quant_dc, const Image& in,
const float* dc_factors, float mul, const float* cfl_factors,
- YCbCrChromaSubsampling chroma_subsampling,
+ const YCbCrChromaSubsampling& chroma_subsampling,
const BlockCtxMap& bctx);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/convolve-inl.h b/third_party/jpeg-xl/lib/jxl/convolve-inl.h
index cd79153a3a..949fd8ad67 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/convolve-inl.h
@@ -118,7 +118,7 @@ class Neighbors {
// Returns indices for SetTableIndices such that TableLookupLanes on the
// rightmost unaligned vector (rightmost sample in its most-significant lane)
// returns the mirrored values, with the mirror outside the last valid sample.
-static inline const int32_t* MirrorLanes(const size_t mod) {
+inline const int32_t* MirrorLanes(const size_t mod) {
const HWY_CAPPED(float, 16) d;
constexpr size_t kN = MaxLanes(d);
@@ -181,7 +181,7 @@ class ConvolveT {
JXL_CHECK(SameSize(rect, *out));
JXL_CHECK(rect.xsize() >= MinWidth());
- static_assert(int64_t(kRadius) <= 3,
+ static_assert(static_cast<int64_t>(kRadius) <= 3,
"Must handle [0, kRadius) and >= kRadius");
switch (rect.xsize() % Lanes(Simd())) {
case 0:
@@ -273,15 +273,17 @@ class ConvolveT {
const Weights& weights, ThreadPool* pool,
Image* out) {
const int64_t ysize = rect.ysize();
- RunBorderRows<kSizeModN>(in, rect, 0, std::min(int64_t(kRadius), ysize),
+ RunBorderRows<kSizeModN>(in, rect, 0,
+ std::min(static_cast<int64_t>(kRadius), ysize),
weights, out);
- if (ysize > 2 * int64_t(kRadius)) {
- RunInteriorRows<kSizeModN>(in, rect, int64_t(kRadius),
- ysize - int64_t(kRadius), weights, pool, out);
+ if (ysize > 2 * static_cast<int64_t>(kRadius)) {
+ RunInteriorRows<kSizeModN>(in, rect, static_cast<int64_t>(kRadius),
+ ysize - static_cast<int64_t>(kRadius), weights,
+ pool, out);
}
- if (ysize > int64_t(kRadius)) {
- RunBorderRows<kSizeModN>(in, rect, ysize - int64_t(kRadius), ysize,
- weights, out);
+ if (ysize > static_cast<int64_t>(kRadius)) {
+ RunBorderRows<kSizeModN>(in, rect, ysize - static_cast<int64_t>(kRadius),
+ ysize, weights, out);
}
}
};
diff --git a/third_party/jpeg-xl/lib/jxl/convolve_separable5.cc b/third_party/jpeg-xl/lib/jxl/convolve_separable5.cc
index db533606a1..ae618b9990 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve_separable5.cc
+++ b/third_party/jpeg-xl/lib/jxl/convolve_separable5.cc
@@ -185,7 +185,8 @@ class Separable5Strategy {
const V l1 = LoadU(d, row + x - 1);
const V l2 = LoadU(d, row + x - 2);
- V r1, r2;
+ V r1;
+ V r2;
#if HWY_TARGET == HWY_SCALAR
r1 = LoadU(d, row + Mirror(x + 1, xsize));
r2 = LoadU(d, row + Mirror(x + 2, xsize));
@@ -236,10 +237,11 @@ void Separable5(const ImageF& in, const Rect& rect,
ImageF* out) {
using Conv = ConvolveT<Separable5Strategy>;
if (rect.xsize() >= Conv::MinWidth()) {
- return Conv::Run(in, rect, weights, pool, out);
+ Conv::Run(in, rect, weights, pool, out);
+ return;
}
- return SlowSeparable5(in, rect, weights, pool, out, Rect(*out));
+ SlowSeparable5(in, rect, weights, pool, out, Rect(*out));
}
// NOLINTNEXTLINE(google-readability-namespace-comments)
@@ -254,7 +256,7 @@ HWY_EXPORT(Separable5);
void Separable5(const ImageF& in, const Rect& rect,
const WeightsSeparable5& weights, ThreadPool* pool,
ImageF* out) {
- return HWY_DYNAMIC_DISPATCH(Separable5)(in, rect, weights, pool, out);
+ HWY_DYNAMIC_DISPATCH(Separable5)(in, rect, weights, pool, out);
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/convolve_symmetric3.cc b/third_party/jpeg-xl/lib/jxl/convolve_symmetric3.cc
index 06b59dfb60..618ad03a86 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve_symmetric3.cc
+++ b/third_party/jpeg-xl/lib/jxl/convolve_symmetric3.cc
@@ -93,7 +93,9 @@ class Symmetric3Strategy {
const V mc = LoadU(d, row_m + x);
const V bc = LoadU(d, row_b + x);
- V tr, mr, br;
+ V tr;
+ V mr;
+ V br;
#if HWY_TARGET == HWY_SCALAR
tr = tc; // Single-lane => mirrored right neighbor = center value.
mr = mc;
@@ -169,10 +171,11 @@ void Symmetric3(const ImageF& in, const Rect& rect,
ImageF* out) {
using Conv = ConvolveT<Symmetric3Strategy>;
if (rect.xsize() >= Conv::MinWidth()) {
- return Conv::Run(in, rect, weights, pool, out);
+ Conv::Run(in, rect, weights, pool, out);
+ return;
}
- return SlowSymmetric3(in, rect, weights, pool, out);
+ SlowSymmetric3(in, rect, weights, pool, out);
}
// NOLINTNEXTLINE(google-readability-namespace-comments)
@@ -187,7 +190,7 @@ HWY_EXPORT(Symmetric3);
void Symmetric3(const ImageF& in, const Rect& rect,
const WeightsSymmetric3& weights, ThreadPool* pool,
ImageF* out) {
- return HWY_DYNAMIC_DISPATCH(Symmetric3)(in, rect, weights, pool, out);
+ HWY_DYNAMIC_DISPATCH(Symmetric3)(in, rect, weights, pool, out);
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/convolve_symmetric5.cc b/third_party/jpeg-xl/lib/jxl/convolve_symmetric5.cc
index 2e203fd08f..7ed384894e 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve_symmetric5.cc
+++ b/third_party/jpeg-xl/lib/jxl/convolve_symmetric5.cc
@@ -175,14 +175,13 @@ HWY_EXPORT(Symmetric5);
void Symmetric5(const ImageF& in, const Rect& in_rect,
const WeightsSymmetric5& weights, ThreadPool* pool,
ImageF* JXL_RESTRICT out, const Rect& out_rect) {
- return HWY_DYNAMIC_DISPATCH(Symmetric5)(in, in_rect, weights, pool, out,
- out_rect);
+ HWY_DYNAMIC_DISPATCH(Symmetric5)(in, in_rect, weights, pool, out, out_rect);
}
void Symmetric5(const ImageF& in, const Rect& rect,
const WeightsSymmetric5& weights, ThreadPool* pool,
ImageF* JXL_RESTRICT out) {
- return Symmetric5(in, rect, weights, pool, out, Rect(*out));
+ Symmetric5(in, rect, weights, pool, out, Rect(*out));
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/convolve_test.cc b/third_party/jpeg-xl/lib/jxl/convolve_test.cc
index 6a8dc9c400..09cbdc12a6 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/convolve_test.cc
@@ -5,6 +5,7 @@
#include "lib/jxl/convolve.h"
+#include <jxl/types.h>
#include <time.h>
#undef HWY_TARGET_INCLUDE
@@ -68,11 +69,11 @@ void VerifySymmetric3(const size_t xsize, const size_t ysize, ThreadPool* pool,
Rng* rng) {
const Rect rect(0, 0, xsize, ysize);
- ImageF in(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(ImageF in, ImageF::Create(xsize, ysize));
GenerateImage(*rng, &in, 0.0f, 1.0f);
- ImageF out_expected(xsize, ysize);
- ImageF out_actual(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(ImageF out_expected, ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_DIE(ImageF out_actual, ImageF::Create(xsize, ysize));
const WeightsSymmetric3& weights = WeightsSymmetric3Lowpass();
Symmetric3(in, rect, weights, pool, &out_expected);
@@ -86,7 +87,7 @@ std::vector<Rect> GenerateTestRectangles(size_t xsize, size_t ysize) {
for (size_t tl : {0, 1, 13}) {
for (size_t br : {0, 1, 13}) {
if (xsize > tl + br && ysize > tl + br) {
- out.push_back(Rect(tl, tl, xsize - tl - br, ysize - tl - br));
+ out.emplace_back(tl, tl, xsize - tl - br, ysize - tl - br);
}
}
}
@@ -96,7 +97,7 @@ std::vector<Rect> GenerateTestRectangles(size_t xsize, size_t ysize) {
// Ensures Symmetric and Separable give the same result.
void VerifySymmetric5(const size_t xsize, const size_t ysize, ThreadPool* pool,
Rng* rng) {
- ImageF in(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(ImageF in, ImageF::Create(xsize, ysize));
GenerateImage(*rng, &in, 0.0f, 1.0f);
for (const Rect& in_rect : GenerateTestRectangles(xsize, ysize)) {
@@ -105,8 +106,8 @@ void VerifySymmetric5(const size_t xsize, const size_t ysize, ThreadPool* pool,
in_rect.xsize(), in_rect.ysize(), in_rect.x0(), in_rect.y0());
{
Rect out_rect = in_rect;
- ImageF out_expected(xsize, ysize);
- ImageF out_actual(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(ImageF out_expected, ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_DIE(ImageF out_actual, ImageF::Create(xsize, ysize));
FillImage(-1.0f, &out_expected);
FillImage(-1.0f, &out_actual);
@@ -120,8 +121,10 @@ void VerifySymmetric5(const size_t xsize, const size_t ysize, ThreadPool* pool,
}
{
Rect out_rect(0, 0, in_rect.xsize(), in_rect.ysize());
- ImageF out_expected(out_rect.xsize(), out_rect.ysize());
- ImageF out_actual(out_rect.xsize(), out_rect.ysize());
+ JXL_ASSIGN_OR_DIE(ImageF out_expected,
+ ImageF::Create(out_rect.xsize(), out_rect.ysize()));
+ JXL_ASSIGN_OR_DIE(ImageF out_actual,
+ ImageF::Create(out_rect.xsize(), out_rect.ysize()));
SlowSeparable5(in, in_rect, WeightsSeparable5Lowpass(), pool,
&out_expected, out_rect);
@@ -138,11 +141,11 @@ void VerifySeparable5(const size_t xsize, const size_t ysize, ThreadPool* pool,
Rng* rng) {
const Rect rect(0, 0, xsize, ysize);
- ImageF in(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(ImageF in, ImageF::Create(xsize, ysize));
GenerateImage(*rng, &in, 0.0f, 1.0f);
- ImageF out_expected(xsize, ysize);
- ImageF out_actual(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(ImageF out_expected, ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_DIE(ImageF out_actual, ImageF::Create(xsize, ysize));
const WeightsSeparable5& weights = WeightsSeparable5Lowpass();
SlowSeparable5(in, rect, weights, pool, &out_expected, rect);
@@ -197,10 +200,10 @@ void BenchmarkConv(const char* caption, const Conv& conv,
hwy::Result results[kNumInputs];
const size_t kDim = 160; // in+out fit in L2
- ImageF in(kDim, kDim);
+ JXL_ASSIGN_OR_DIE(ImageF in, ImageF::Create(kDim, kDim));
ZeroFillImage(&in);
in.Row(kDim / 2)[kDim / 2] = unpredictable1;
- ImageF out(kDim, kDim);
+ JXL_ASSIGN_OR_DIE(ImageF out, ImageF::Create(kDim, kDim));
hwy::Params p;
p.verbose = false;
@@ -239,7 +242,7 @@ struct ConvSeparable5 {
};
void BenchmarkAll() {
-#if 0 // disabled to avoid test timeouts, run manually on demand
+#if JXL_FALSE // disabled to avoid test timeouts, run manually on demand
const hwy::FuncInput unpredictable1 = time(nullptr) != 1234;
BenchmarkConv("Symmetric3", ConvSymmetric3(), unpredictable1);
BenchmarkConv("Separable5", ConvSeparable5(), unpredictable1);
diff --git a/third_party/jpeg-xl/lib/jxl/dct-inl.h b/third_party/jpeg-xl/lib/jxl/dct-inl.h
index cb6c54bc46..05cfbde553 100644
--- a/third_party/jpeg-xl/lib/jxl/dct-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/dct-inl.h
@@ -154,12 +154,12 @@ struct DCT1DImpl;
template <size_t SZ>
struct DCT1DImpl<1, SZ> {
- JXL_INLINE void operator()(float* JXL_RESTRICT mem, float*) {}
+ JXL_INLINE void operator()(float* JXL_RESTRICT mem, float* /* tmp */) {}
};
template <size_t SZ>
struct DCT1DImpl<2, SZ> {
- JXL_INLINE void operator()(float* JXL_RESTRICT mem, float*) {
+ JXL_INLINE void operator()(float* JXL_RESTRICT mem, float* /* tmp */) {
auto in1 = Load(FV<SZ>(), mem);
auto in2 = Load(FV<SZ>(), mem + SZ);
Store(Add(in1, in2), FV<SZ>(), mem);
@@ -186,7 +186,7 @@ struct IDCT1DImpl;
template <size_t SZ>
struct IDCT1DImpl<1, SZ> {
JXL_INLINE void operator()(const float* from, size_t from_stride, float* to,
- size_t to_stride, float* JXL_RESTRICT) {
+ size_t to_stride, float* JXL_RESTRICT /* tmp */) {
StoreU(LoadU(FV<SZ>(), from), FV<SZ>(), to);
}
};
@@ -194,7 +194,7 @@ struct IDCT1DImpl<1, SZ> {
template <size_t SZ>
struct IDCT1DImpl<2, SZ> {
JXL_INLINE void operator()(const float* from, size_t from_stride, float* to,
- size_t to_stride, float* JXL_RESTRICT) {
+ size_t to_stride, float* JXL_RESTRICT /* tmp */) {
JXL_DASSERT(from_stride >= SZ);
JXL_DASSERT(to_stride >= SZ);
auto in1 = LoadU(FV<SZ>(), from);
diff --git a/third_party/jpeg-xl/lib/jxl/dct_block-inl.h b/third_party/jpeg-xl/lib/jxl/dct_block-inl.h
index 50646a737f..6db5f0e7c8 100644
--- a/third_party/jpeg-xl/lib/jxl/dct_block-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/dct_block-inl.h
@@ -44,7 +44,7 @@ class DCTFrom {
DCTFrom(const float* data, size_t stride) : stride_(stride), data_(data) {}
template <typename D>
- HWY_INLINE Vec<D> LoadPart(D, const size_t row, size_t i) const {
+ HWY_INLINE Vec<D> LoadPart(D /* tag */, const size_t row, size_t i) const {
JXL_DASSERT(Lanes(D()) <= stride_);
// Since these functions are used also for DC, no alignment at all is
// guaranteed in the case of floating blocks.
@@ -74,7 +74,7 @@ class DCTTo {
DCTTo(float* data, size_t stride) : stride_(stride), data_(data) {}
template <typename D>
- HWY_INLINE void StorePart(D, const Vec<D>& v, const size_t row,
+ HWY_INLINE void StorePart(D /* tag */, const Vec<D>& v, const size_t row,
size_t i) const {
JXL_DASSERT(Lanes(D()) <= stride_);
// Since these functions are used also for DC, no alignment at all is
diff --git a/third_party/jpeg-xl/lib/jxl/dct_util.h b/third_party/jpeg-xl/lib/jxl/dct_util.h
index 2f29449677..90a02658af 100644
--- a/third_party/jpeg-xl/lib/jxl/dct_util.h
+++ b/third_party/jpeg-xl/lib/jxl/dct_util.h
@@ -8,8 +8,9 @@
#include <stddef.h>
-#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/base/data_parallel.h"
+#include <memory>
+
+#include "lib/jxl/base/common.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/image.h"
#include "lib/jxl/image_ops.h"
@@ -50,12 +51,16 @@ template <typename T>
class ACImageT final : public ACImage {
public:
ACImageT() = default;
- ACImageT(size_t xsize, size_t ysize) {
+
+ static StatusOr<std::unique_ptr<ACImageT>> Make(size_t xsize, size_t ysize) {
static_assert(
std::is_same<T, int16_t>::value || std::is_same<T, int32_t>::value,
"ACImage must be either 32- or 16- bit");
- img_ = Image3<T>(xsize, ysize);
+ std::unique_ptr<ACImageT> result = jxl::make_unique<ACImageT>();
+ JXL_ASSIGN_OR_RETURN(result->img_, Image3<T>::Create(xsize, ysize));
+ return result;
}
+
ACType Type() const override {
return sizeof(T) == 2 ? ACType::k16 : ACType::k32;
}
diff --git a/third_party/jpeg-xl/lib/jxl/dec_ans.cc b/third_party/jpeg-xl/lib/jxl/dec_ans.cc
index 29d41c8062..8b7b54ce91 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_ans.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_ans.cc
@@ -154,7 +154,7 @@ Status ReadHistogram(int precision_bits, std::vector<int32_t>* counts,
(*counts)[i] = prev;
numsame--;
} else {
- int code = logcounts[i];
+ unsigned int code = logcounts[i];
// omit_pos may not be negative at this point (checked before).
if (i == static_cast<size_t>(omit_pos)) {
continue;
@@ -164,7 +164,7 @@ Status ReadHistogram(int precision_bits, std::vector<int32_t>* counts,
(*counts)[i] = 1;
} else {
int bitcount = GetPopulationCountPrecision(code - 1, shift);
- (*counts)[i] = (1 << (code - 1)) +
+ (*counts)[i] = (1u << (code - 1)) +
(input->ReadBits(bitcount) << (code - 1 - bitcount));
}
}
@@ -260,7 +260,8 @@ Status DecodeUintConfig(size_t log_alpha_size, HybridUintConfig* uint_config,
BitReader* br) {
br->Refill();
size_t split_exponent = br->ReadBits(CeilLog2Nonzero(log_alpha_size + 1));
- size_t msb_in_token = 0, lsb_in_token = 0;
+ size_t msb_in_token = 0;
+ size_t lsb_in_token = 0;
if (split_exponent != log_alpha_size) {
// otherwise, msb/lsb don't matter.
size_t nbits = CeilLog2Nonzero(split_exponent + 1);
@@ -284,9 +285,8 @@ Status DecodeUintConfigs(size_t log_alpha_size,
std::vector<HybridUintConfig>* uint_config,
BitReader* br) {
// TODO(veluca): RLE?
- for (size_t i = 0; i < uint_config->size(); i++) {
- JXL_RETURN_IF_ERROR(
- DecodeUintConfig(log_alpha_size, &(*uint_config)[i], br));
+ for (auto& cfg : *uint_config) {
+ JXL_RETURN_IF_ERROR(DecodeUintConfig(log_alpha_size, &cfg, br));
}
return true;
}
@@ -345,7 +345,7 @@ Status DecodeHistograms(BitReader* br, size_t num_contexts, ANSCode* code,
4, "Decoded context map of size %" PRIuS " and %" PRIuS " histograms",
num_contexts, num_histograms);
code->lz77.nonserialized_distance_context = context_map->back();
- code->use_prefix_code = br->ReadFixedBits<1>();
+ code->use_prefix_code = static_cast<bool>(br->ReadFixedBits<1>());
if (code->use_prefix_code) {
code->log_alpha_size = PREFIX_MAX_BITS;
} else {
diff --git a/third_party/jpeg-xl/lib/jxl/dec_ans.h b/third_party/jpeg-xl/lib/jxl/dec_ans.h
index 57faad25a7..cbff1deebe 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_ans.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_ans.h
@@ -9,6 +9,7 @@
// Library to decode the ANS population counts from the bit-stream and build a
// decoding table from them.
+#include <jxl/types.h>
#include <stddef.h>
#include <stdint.h>
@@ -133,6 +134,11 @@ static constexpr int8_t kSpecialDistances[kNumSpecialDistances][2] = {
{8, 0}, {4, 7}, {-4, 7}, {7, 4}, {-7, 4}, {8, 1}, {8, 2}, {6, 6},
{-6, 6}, {8, 3}, {5, 7}, {-5, 7}, {7, 5}, {-7, 5}, {8, 4}, {6, 7},
{-6, 7}, {7, 6}, {-7, 6}, {8, 5}, {7, 7}, {-7, 7}, {8, 6}, {8, 7}};
+static JXL_INLINE int SpecialDistance(size_t index, int multiplier) {
+ int dist = kSpecialDistances[index][0] +
+ static_cast<int>(multiplier) * kSpecialDistances[index][1];
+ return (dist > 1) ? dist : 1;
+}
struct ANSCode {
CacheAlignedUniquePtr alias_tables;
@@ -179,10 +185,7 @@ class ANSSymbolReader {
num_special_distances_ =
distance_multiplier == 0 ? 0 : kNumSpecialDistances;
for (size_t i = 0; i < num_special_distances_; i++) {
- int dist = kSpecialDistances[i][0];
- dist += static_cast<int>(distance_multiplier) * kSpecialDistances[i][1];
- if (dist < 1) dist = 1;
- special_distances_[i] = dist;
+ special_distances_[i] = SpecialDistance(i, distance_multiplier);
}
}
@@ -196,7 +199,7 @@ class ANSSymbolReader {
AliasTable::Lookup(table, res, log_entry_size_, entry_size_minus_1_);
state_ = symbol.freq * (state_ >> ANS_LOG_TAB_SIZE) + symbol.offset;
-#if 1
+#if JXL_TRUE
// Branchless version is about equally fast on SKX.
const uint32_t new_state =
(state_ << 16u) | static_cast<uint32_t>(br->PeekFixedBits<16>());
diff --git a/third_party/jpeg-xl/lib/jxl/dec_cache.cc b/third_party/jpeg-xl/lib/jxl/dec_cache.cc
index 8d12bce02e..2a89420018 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_cache.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_cache.cc
@@ -5,6 +5,7 @@
#include "lib/jxl/dec_cache.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/blending.h"
#include "lib/jxl/common.h" // JXL_HIGH_PRECISION
#include "lib/jxl/render_pipeline/stage_blending.h"
@@ -247,6 +248,7 @@ Status PassesDecoderState::PreparePipeline(const FrameHeader& frame_header,
}
linear = false;
}
+ (void)linear;
if (main_output.callback.IsPresent() || main_output.buffer) {
builder.AddStage(GetWriteToOutputStage(main_output, width, height,
@@ -257,7 +259,8 @@ Status PassesDecoderState::PreparePipeline(const FrameHeader& frame_header,
decoded, output_encoding_info.color_encoding));
}
}
- render_pipeline = std::move(builder).Finalize(shared->frame_dim);
+ JXL_ASSIGN_OR_RETURN(render_pipeline,
+ std::move(builder).Finalize(shared->frame_dim));
return render_pipeline->IsInitialized();
}
diff --git a/third_party/jpeg-xl/lib/jxl/dec_cache.h b/third_party/jpeg-xl/lib/jxl/dec_cache.h
index d4cc7a1957..d031074532 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_cache.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_cache.h
@@ -52,7 +52,8 @@ struct PixelCallback {
const bool has_init = init != nullptr;
const bool has_run = run != nullptr;
const bool has_destroy = destroy != nullptr;
- JXL_ASSERT(has_init == has_run && has_run == has_destroy);
+ const bool healthy = (has_init == has_run) && (has_run == has_destroy);
+ JXL_ASSERT(healthy);
#endif
}
@@ -128,7 +129,7 @@ struct PassesDecoderState {
std::atomic<uint32_t> used_acs{0};
// Storage for coefficients if in "accumulate" mode.
- std::unique_ptr<ACImage> coefficients = make_unique<ACImageT<int32_t>>(0, 0);
+ std::unique_ptr<ACImage> coefficients = make_unique<ACImageT<int32_t>>();
// Rendering pipeline.
std::unique_ptr<RenderPipeline> render_pipeline;
@@ -166,8 +167,10 @@ struct PassesDecoderState {
upsampler8x = GetUpsamplingStage(shared->metadata->transform_data, 0, 3);
if (frame_header.loop_filter.epf_iters > 0) {
- sigma = ImageF(shared->frame_dim.xsize_blocks + 2 * kSigmaPadding,
- shared->frame_dim.ysize_blocks + 2 * kSigmaPadding);
+ JXL_ASSIGN_OR_RETURN(
+ sigma,
+ ImageF::Create(shared->frame_dim.xsize_blocks + 2 * kSigmaPadding,
+ shared->frame_dim.ysize_blocks + 2 * kSigmaPadding));
}
return true;
}
@@ -193,14 +196,16 @@ struct PassesDecoderState {
// Temp images required for decoding a single group. Reduces memory allocations
// for large images because we only initialize min(#threads, #groups) instances.
struct GroupDecCache {
- void InitOnce(size_t num_passes, size_t used_acs) {
+ Status InitOnce(size_t num_passes, size_t used_acs) {
for (size_t i = 0; i < num_passes; i++) {
if (num_nzeroes[i].xsize() == 0) {
// Allocate enough for a whole group - partial groups on the
// right/bottom border just use a subset. The valid size is passed via
// Rect.
- num_nzeroes[i] = Image3I(kGroupDimInBlocks, kGroupDimInBlocks);
+ JXL_ASSIGN_OR_RETURN(
+ num_nzeroes[i],
+ Image3I::Create(kGroupDimInBlocks, kGroupDimInBlocks));
}
}
size_t max_block_area = 0;
@@ -227,13 +232,17 @@ struct GroupDecCache {
scratch_space = dec_group_block + max_block_area_ * 3;
dec_group_qblock = int32_memory_.get();
dec_group_qblock16 = int16_memory_.get();
+ return true;
}
- void InitDCBufferOnce() {
+ Status InitDCBufferOnce() {
if (dc_buffer.xsize() == 0) {
- dc_buffer = ImageF(kGroupDimInBlocks + kRenderPipelineXOffset * 2,
- kGroupDimInBlocks + 4);
+ JXL_ASSIGN_OR_RETURN(
+ dc_buffer,
+ ImageF::Create(kGroupDimInBlocks + kRenderPipelineXOffset * 2,
+ kGroupDimInBlocks + 4));
}
+ return true;
}
// Scratch space used by DecGroupImpl().
diff --git a/third_party/jpeg-xl/lib/jxl/dec_context_map.cc b/third_party/jpeg-xl/lib/jxl/dec_context_map.cc
index 2c936722da..baff87fa49 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_context_map.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_context_map.cc
@@ -6,6 +6,7 @@
#include "lib/jxl/dec_context_map.h"
#include <algorithm>
+#include <cstdint>
#include <vector>
#include "lib/jxl/ans_params.h"
@@ -41,18 +42,18 @@ Status VerifyContextMap(const std::vector<uint8_t>& context_map,
Status DecodeContextMap(std::vector<uint8_t>* context_map, size_t* num_htrees,
BitReader* input) {
- bool is_simple = input->ReadFixedBits<1>();
+ bool is_simple = static_cast<bool>(input->ReadFixedBits<1>());
if (is_simple) {
int bits_per_entry = input->ReadFixedBits<2>();
if (bits_per_entry != 0) {
- for (size_t i = 0; i < context_map->size(); i++) {
- (*context_map)[i] = input->ReadBits(bits_per_entry);
+ for (uint8_t& entry : *context_map) {
+ entry = input->ReadBits(bits_per_entry);
}
} else {
std::fill(context_map->begin(), context_map->end(), 0);
}
} else {
- bool use_mtf = input->ReadFixedBits<1>();
+ bool use_mtf = static_cast<bool>(input->ReadFixedBits<1>());
ANSCode code;
std::vector<uint8_t> sink_ctx_map;
// Usage of LZ77 is disallowed if decoding only two symbols. This doesn't
diff --git a/third_party/jpeg-xl/lib/jxl/dec_external_image.cc b/third_party/jpeg-xl/lib/jxl/dec_external_image.cc
index 06cd573378..51e12fcc81 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_external_image.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_external_image.cc
@@ -9,11 +9,11 @@
#include <string.h>
#include <algorithm>
-#include <array>
-#include <functional>
#include <utility>
#include <vector>
+#include "lib/jxl/base/status.h"
+
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/dec_external_image.cc"
#include <hwy/foreach_target.h>
@@ -113,7 +113,7 @@ Status UndoOrientation(jxl::Orientation undo_orientation, const Plane<T>& image,
const size_t ysize = image.ysize();
if (undo_orientation == Orientation::kFlipHorizontal) {
- out = Plane<T>(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(out, Plane<T>::Create(xsize, ysize));
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, static_cast<uint32_t>(ysize), ThreadPool::NoInit,
[&](const uint32_t task, size_t /*thread*/) {
@@ -126,7 +126,7 @@ Status UndoOrientation(jxl::Orientation undo_orientation, const Plane<T>& image,
},
"UndoOrientation"));
} else if (undo_orientation == Orientation::kRotate180) {
- out = Plane<T>(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(out, Plane<T>::Create(xsize, ysize));
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, static_cast<uint32_t>(ysize), ThreadPool::NoInit,
[&](const uint32_t task, size_t /*thread*/) {
@@ -139,7 +139,7 @@ Status UndoOrientation(jxl::Orientation undo_orientation, const Plane<T>& image,
},
"UndoOrientation"));
} else if (undo_orientation == Orientation::kFlipVertical) {
- out = Plane<T>(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(out, Plane<T>::Create(xsize, ysize));
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, static_cast<uint32_t>(ysize), ThreadPool::NoInit,
[&](const uint32_t task, size_t /*thread*/) {
@@ -152,7 +152,7 @@ Status UndoOrientation(jxl::Orientation undo_orientation, const Plane<T>& image,
},
"UndoOrientation"));
} else if (undo_orientation == Orientation::kTranspose) {
- out = Plane<T>(ysize, xsize);
+ JXL_ASSIGN_OR_RETURN(out, Plane<T>::Create(ysize, xsize));
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, static_cast<uint32_t>(ysize), ThreadPool::NoInit,
[&](const uint32_t task, size_t /*thread*/) {
@@ -164,7 +164,7 @@ Status UndoOrientation(jxl::Orientation undo_orientation, const Plane<T>& image,
},
"UndoOrientation"));
} else if (undo_orientation == Orientation::kRotate90) {
- out = Plane<T>(ysize, xsize);
+ JXL_ASSIGN_OR_RETURN(out, Plane<T>::Create(ysize, xsize));
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, static_cast<uint32_t>(ysize), ThreadPool::NoInit,
[&](const uint32_t task, size_t /*thread*/) {
@@ -176,7 +176,7 @@ Status UndoOrientation(jxl::Orientation undo_orientation, const Plane<T>& image,
},
"UndoOrientation"));
} else if (undo_orientation == Orientation::kAntiTranspose) {
- out = Plane<T>(ysize, xsize);
+ JXL_ASSIGN_OR_RETURN(out, Plane<T>::Create(ysize, xsize));
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, static_cast<uint32_t>(ysize), ThreadPool::NoInit,
[&](const uint32_t task, size_t /*thread*/) {
@@ -188,7 +188,7 @@ Status UndoOrientation(jxl::Orientation undo_orientation, const Plane<T>& image,
},
"UndoOrientation"));
} else if (undo_orientation == Orientation::kRotate270) {
- out = Plane<T>(ysize, xsize);
+ JXL_ASSIGN_OR_RETURN(out, Plane<T>::Create(ysize, xsize));
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, static_cast<uint32_t>(ysize), ThreadPool::NoInit,
[&](const uint32_t task, size_t /*thread*/) {
@@ -247,7 +247,8 @@ Status ConvertChannelsToExternal(const ImageF* in_channels[],
JXL_DASSERT(in_channels[0] != nullptr);
JXL_CHECK(float_out ? bits_per_sample == 16 || bits_per_sample == 32
: bits_per_sample > 0 && bits_per_sample <= 16);
- if (!!out_image == out_callback.IsPresent()) {
+ const bool has_out_image = (out_image != nullptr);
+ if (has_out_image == out_callback.IsPresent()) {
return JXL_FAILURE(
"Must provide either an out_image or an out_callback, but not both.");
}
@@ -309,7 +310,7 @@ Status ConvertChannelsToExternal(const ImageF* in_channels[],
ImageF ones;
for (size_t c = 0; c < num_channels; ++c) {
if (!channels[c]) {
- ones = ImageF(xsize, 1);
+ JXL_ASSIGN_OR_RETURN(ones, ImageF::Create(xsize, 1));
FillImage(1.0f, &ones);
break;
}
@@ -322,9 +323,12 @@ Status ConvertChannelsToExternal(const ImageF* in_channels[],
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, static_cast<uint32_t>(ysize),
[&](size_t num_threads) {
- f16_cache =
- Plane<hwy::float16_t>(xsize, num_channels * num_threads);
- return InitOutCallback(num_threads);
+ StatusOr<Plane<hwy::float16_t>> f16_cache_or =
+ Plane<hwy::float16_t>::Create(xsize,
+ num_channels * num_threads);
+ if (!f16_cache_or.ok()) return false;
+ f16_cache = std::move(f16_cache_or).value();
+ return !!InitOutCallback(num_threads);
},
[&](const uint32_t task, const size_t thread) {
const int64_t y = task;
@@ -398,8 +402,11 @@ Status ConvertChannelsToExternal(const ImageF* in_channels[],
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, static_cast<uint32_t>(ysize),
[&](size_t num_threads) {
- u32_cache = Plane<uint32_t>(xsize, num_channels * num_threads);
- return InitOutCallback(num_threads);
+ StatusOr<Plane<uint32_t>> u32_cache_or =
+ Plane<uint32_t>::Create(xsize, num_channels * num_threads);
+ if (!u32_cache_or.ok()) return false;
+ u32_cache = std::move(u32_cache_or).value();
+ return !!InitOutCallback(num_threads);
},
[&](const uint32_t task, const size_t thread) {
const int64_t y = task;
@@ -453,7 +460,8 @@ Status ConvertToExternal(const jxl::ImageBundle& ib, size_t bits_per_sample,
// Undo premultiplied alpha.
Image3F unpremul;
if (ib.AlphaIsPremultiplied() && ib.HasAlpha() && unpremul_alpha) {
- unpremul = Image3F(color->xsize(), color->ysize());
+ JXL_ASSIGN_OR_RETURN(unpremul,
+ Image3F::Create(color->xsize(), color->ysize()));
CopyImageTo(*color, &unpremul);
for (size_t y = 0; y < unpremul.ysize(); y++) {
UnpremultiplyAlpha(unpremul.PlaneRow(0, y), unpremul.PlaneRow(1, y),
diff --git a/third_party/jpeg-xl/lib/jxl/dec_external_image_gbench.cc b/third_party/jpeg-xl/lib/jxl/dec_external_image_gbench.cc
index c87a4d5f36..720a278fc0 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_external_image_gbench.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_external_image_gbench.cc
@@ -5,6 +5,7 @@
#include "benchmark/benchmark.h"
#include "lib/jxl/dec_external_image.h"
+#include "lib/jxl/image.h"
#include "lib/jxl/image_ops.h"
namespace jxl {
@@ -20,10 +21,10 @@ void BM_DecExternalImage_ConvertImageRGBA(benchmark::State& state) {
ImageMetadata im;
im.SetAlphaBits(8);
ImageBundle ib(&im);
- Image3F color(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(Image3F color, Image3F::Create(xsize, ysize));
ZeroFillImage(&color);
ib.SetFromImage(std::move(color), ColorEncoding::SRGB());
- ImageF alpha(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(ImageF alpha, ImageF::Create(xsize, ysize));
ZeroFillImage(&alpha);
ib.SetAlpha(std::move(alpha));
diff --git a/third_party/jpeg-xl/lib/jxl/dec_frame.cc b/third_party/jpeg-xl/lib/jxl/dec_frame.cc
index 918dbe7c37..a2a82ad1fb 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_frame.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_frame.cc
@@ -331,21 +331,23 @@ Status FrameDecoder::ProcessDCGroup(size_t dc_group_id, BitReader* br) {
} else if (lf.epf_iters > 0) {
FillImage(kInvSigmaNum / lf.epf_sigma_for_modular, &dec_state_->sigma);
}
- decoded_dc_groups_[dc_group_id] = uint8_t{true};
+ decoded_dc_groups_[dc_group_id] = JXL_TRUE;
return true;
}
-void FrameDecoder::FinalizeDC() {
+Status FrameDecoder::FinalizeDC() {
// Do Adaptive DC smoothing if enabled. This *must* happen between all the
// ProcessDCGroup and ProcessACGroup.
if (frame_header_.encoding == FrameEncoding::kVarDCT &&
!(frame_header_.flags & FrameHeader::kSkipAdaptiveDCSmoothing) &&
!(frame_header_.flags & FrameHeader::kUseDcFrame)) {
- AdaptiveDCSmoothing(dec_state_->shared->quantizer.MulDC(),
- &dec_state_->shared_storage.dc_storage, pool_);
+ JXL_RETURN_IF_ERROR(
+ AdaptiveDCSmoothing(dec_state_->shared->quantizer.MulDC(),
+ &dec_state_->shared_storage.dc_storage, pool_));
}
finalized_dc_ = true;
+ return true;
}
Status FrameDecoder::AllocateOutput() {
@@ -410,9 +412,11 @@ Status FrameDecoder::ProcessACGlobal(BitReader* br) {
size_t xs = store ? kGroupDim * kGroupDim : 0;
size_t ys = store ? frame_dim_.num_groups : 0;
if (use_16_bit) {
- dec_state_->coefficients = make_unique<ACImageT<int16_t>>(xs, ys);
+ JXL_ASSIGN_OR_RETURN(dec_state_->coefficients,
+ ACImageT<int16_t>::Make(xs, ys));
} else {
- dec_state_->coefficients = make_unique<ACImageT<int32_t>>(xs, ys);
+ JXL_ASSIGN_OR_RETURN(dec_state_->coefficients,
+ ACImageT<int32_t>::Make(xs, ys));
}
if (store) {
dec_state_->coefficients->ZeroFill();
@@ -482,8 +486,8 @@ Status FrameDecoder::ProcessACGroup(size_t ac_group_id,
bool should_run_pipeline = true;
if (frame_header_.encoding == FrameEncoding::kVarDCT) {
- group_dec_caches_[thread].InitOnce(frame_header_.passes.num_passes,
- dec_state_->used_acs);
+ JXL_RETURN_IF_ERROR(group_dec_caches_[thread].InitOnce(
+ frame_header_.passes.num_passes, dec_state_->used_acs));
JXL_RETURN_IF_ERROR(DecodeGroup(frame_header_, br, num_passes, ac_group_id,
dec_state_, &group_dec_caches_[thread],
thread, render_pipeline_input, decoded_,
@@ -498,10 +502,16 @@ Status FrameDecoder::ProcessACGroup(size_t ac_group_id,
size_t pass1 =
force_draw ? frame_header_.passes.num_passes : pass0 + num_passes;
for (size_t i = pass0; i < pass1; ++i) {
- int minShift, maxShift;
+ int minShift;
+ int maxShift;
frame_header_.passes.GetDownsamplingBracket(i, minShift, maxShift);
bool modular_pass_ready = true;
+ JXL_DEBUG_V(2, "Decoding modular in group %d pass %d",
+ static_cast<int>(ac_group_id), static_cast<int>(i));
if (i < pass0 + num_passes) {
+ JXL_DEBUG_V(2, "Bit reader position: %" PRIuS " / %" PRIuS,
+ br[i - pass0]->TotalBitsConsumed(),
+ br[i - pass0]->TotalBytes() * kBitsPerByte);
JXL_RETURN_IF_ERROR(modular_frame_decoder_.DecodeGroup(
frame_header_, mrect, br[i - pass0], minShift, maxShift,
ModularStreamId::ModularAC(ac_group_id, i),
@@ -546,7 +556,7 @@ Status FrameDecoder::ProcessACGroup(size_t ac_group_id,
if (!modular_frame_decoder_.UsesFullImage() && !decoded_->IsJPEG()) {
if (should_run_pipeline && modular_ready) {
- render_pipeline_input.Done();
+ JXL_RETURN_IF_ERROR(render_pipeline_input.Done());
} else if (force_draw) {
return JXL_FAILURE("Modular group decoding failed.");
}
@@ -555,11 +565,11 @@ Status FrameDecoder::ProcessACGroup(size_t ac_group_id,
}
void FrameDecoder::MarkSections(const SectionInfo* sections, size_t num,
- SectionStatus* section_status) {
+ const SectionStatus* section_status) {
num_sections_done_ += num;
for (size_t i = 0; i < num; i++) {
if (section_status[i] != SectionStatus::kDone) {
- processed_section_[sections[i].id] = false;
+ processed_section_[sections[i].id] = JXL_FALSE;
num_sections_done_--;
}
}
@@ -583,8 +593,8 @@ Status FrameDecoder::ProcessSections(const SectionInfo* sections, size_t num,
if (single_section) {
JXL_ASSERT(num == 1);
JXL_ASSERT(sections[0].id == 0);
- if (processed_section_[0] == false) {
- processed_section_[0] = true;
+ if (processed_section_[0] == JXL_FALSE) {
+ processed_section_[0] = JXL_TRUE;
ac_group_sec[0].resize(1);
dc_global_sec = ac_global_sec = dc_group_sec[0] = ac_group_sec[0][0] = 0;
desired_num_ac_passes[0] = 1;
@@ -614,7 +624,7 @@ Status FrameDecoder::ProcessSections(const SectionInfo* sections, size_t num,
}
ac_group_sec[acg][acp] = i;
}
- processed_section_[sections[i].id] = true;
+ processed_section_[sections[i].id] = JXL_TRUE;
}
// Count number of new passes per group.
for (size_t g = 0; g < ac_group_sec.size(); g++) {
@@ -645,9 +655,11 @@ Status FrameDecoder::ProcessSections(const SectionInfo* sections, size_t num,
pool_, 0, dc_group_sec.size(), ThreadPool::NoInit,
[this, &dc_group_sec, &num, &sections, &section_status, &has_error](
size_t i, size_t thread) {
+ if (has_error) return;
if (dc_group_sec[i] != num) {
if (!ProcessDCGroup(i, sections[dc_group_sec[i]].br)) {
has_error = true;
+ return;
} else {
section_status[dc_group_sec[i]] = SectionStatus::kDone;
}
@@ -657,8 +669,7 @@ Status FrameDecoder::ProcessSections(const SectionInfo* sections, size_t num,
}
if (has_error) return JXL_FAILURE("Error in DC group");
- if (*std::min_element(decoded_dc_groups_.begin(), decoded_dc_groups_.end()) &&
- !finalized_dc_) {
+ if (!HasDcGroupToDecode() && !finalized_dc_) {
PassesDecoderState::PipelineOptions pipeline_options;
pipeline_options.use_slow_render_pipeline = use_slow_rendering_pipeline_;
pipeline_options.coalescing = coalescing_;
@@ -666,7 +677,7 @@ Status FrameDecoder::ProcessSections(const SectionInfo* sections, size_t num,
pipeline_options.render_noise = true;
JXL_RETURN_IF_ERROR(
dec_state_->PreparePipeline(frame_header_, decoded_, pipeline_options));
- FinalizeDC();
+ JXL_RETURN_IF_ERROR(FinalizeDC());
JXL_RETURN_IF_ERROR(AllocateOutput());
if (progressive_detail_ >= JxlProgressiveDetail::kDC) {
MarkSections(sections, num, section_status);
@@ -776,21 +787,22 @@ Status FrameDecoder::Flush() {
decoded_passes_per_ac_group_.size());
},
[this, &has_error](const uint32_t g, size_t thread) {
+ if (has_error) return;
if (decoded_passes_per_ac_group_[g] ==
frame_header_.passes.num_passes) {
// This group was drawn already, nothing to do.
return;
}
BitReader* JXL_RESTRICT readers[kMaxNumPasses] = {};
- bool ok = ProcessACGroup(
- g, readers, /*num_passes=*/0, GetStorageLocation(thread, g),
- /*force_draw=*/true, /*dc_only=*/!decoded_ac_global_);
- if (!ok) has_error = true;
+ if (!ProcessACGroup(
+ g, readers, /*num_passes=*/0, GetStorageLocation(thread, g),
+ /*force_draw=*/true, /*dc_only=*/!decoded_ac_global_)) {
+ has_error = true;
+ return;
+ }
},
"ForceDrawGroup"));
- if (has_error) {
- return JXL_FAILURE("Drawing groups failed");
- }
+ if (has_error) return JXL_FAILURE("Drawing groups failed");
}
// undo global modular transforms and copy int pixel buffers to float ones
@@ -815,10 +827,8 @@ int FrameDecoder::SavedAs(const FrameHeader& header) {
bool FrameDecoder::HasEverything() const {
if (!decoded_dc_global_) return false;
if (!decoded_ac_global_) return false;
- for (auto& have_dc_group : decoded_dc_groups_) {
- if (!have_dc_group) return false;
- }
- for (auto& nb_passes : decoded_passes_per_ac_group_) {
+ if (HasDcGroupToDecode()) return false;
+ for (const auto& nb_passes : decoded_passes_per_ac_group_) {
if (nb_passes < frame_header_.passes.num_passes) return false;
}
return true;
@@ -840,9 +850,9 @@ int FrameDecoder::References() const {
result |= (1 << frame_header_.blending_info.source);
}
const auto& extra = frame_header_.extra_channel_blending_info;
- for (size_t i = 0; i < extra.size(); ++i) {
- if (cropped || extra[i].mode != BlendMode::kReplace) {
- result |= (1 << extra[i].source);
+ for (const auto& ecbi : extra) {
+ if (cropped || ecbi.mode != BlendMode::kReplace) {
+ result |= (1 << ecbi.source);
}
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/dec_frame.h b/third_party/jpeg-xl/lib/jxl/dec_frame.h
index 09bdbc9675..663f1a8b33 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_frame.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_frame.h
@@ -242,14 +242,14 @@ class FrameDecoder {
private:
Status ProcessDCGlobal(BitReader* br);
Status ProcessDCGroup(size_t dc_group_id, BitReader* br);
- void FinalizeDC();
+ Status FinalizeDC();
Status AllocateOutput();
Status ProcessACGlobal(BitReader* br);
Status ProcessACGroup(size_t ac_group_id, BitReader* JXL_RESTRICT* br,
size_t num_passes, size_t thread, bool force_draw,
bool dc_only);
void MarkSections(const SectionInfo* sections, size_t num,
- SectionStatus* section_status);
+ const SectionStatus* section_status);
// Allocates storage for parallel decoding using up to `num_threads` threads
// of up to `num_tasks` tasks. The value of `thread` passed to
@@ -262,9 +262,10 @@ class FrameDecoder {
group_dec_caches_.resize(storage_size);
}
use_task_id_ = num_threads > num_tasks;
- bool use_group_ids = (modular_frame_decoder_.UsesFullImage() &&
- (frame_header_.encoding == FrameEncoding::kVarDCT ||
- (frame_header_.flags & FrameHeader::kNoise)));
+ bool use_noise = (frame_header_.flags & FrameHeader::kNoise) != 0;
+ bool use_group_ids =
+ (modular_frame_decoder_.UsesFullImage() &&
+ (frame_header_.encoding == FrameEncoding::kVarDCT || use_noise));
if (dec_state_->render_pipeline) {
JXL_RETURN_IF_ERROR(dec_state_->render_pipeline->PrepareForThreads(
storage_size, use_group_ids));
@@ -272,7 +273,7 @@ class FrameDecoder {
return true;
}
- size_t GetStorageLocation(size_t thread, size_t task) {
+ size_t GetStorageLocation(size_t thread, size_t task) const {
if (use_task_id_) return task;
return thread;
}
@@ -292,6 +293,11 @@ class FrameDecoder {
return stride;
}
+ bool HasDcGroupToDecode() const {
+ return std::any_of(decoded_dc_groups_.cbegin(), decoded_dc_groups_.cend(),
+ [](uint8_t ready) { return ready == 0; });
+ }
+
PassesDecoderState* dec_state_;
ThreadPool* pool_;
std::vector<TocEntry> toc_;
diff --git a/third_party/jpeg-xl/lib/jxl/dec_group.cc b/third_party/jpeg-xl/lib/jxl/dec_group.cc
index 186318e63d..7dc4772eba 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_group.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_group.cc
@@ -27,13 +27,10 @@
#include "lib/jxl/base/status.h"
#include "lib/jxl/coeff_order.h"
#include "lib/jxl/common.h" // kMaxNumPasses
-#include "lib/jxl/convolve.h"
-#include "lib/jxl/dct_scales.h"
#include "lib/jxl/dec_cache.h"
#include "lib/jxl/dec_transforms-inl.h"
#include "lib/jxl/dec_xyb.h"
#include "lib/jxl/entropy_coder.h"
-#include "lib/jxl/epf.h"
#include "lib/jxl/quant_weights.h"
#include "lib/jxl/quantizer-inl.h"
#include "lib/jxl/quantizer.h"
@@ -70,6 +67,11 @@ namespace jxl {
namespace HWY_NAMESPACE {
// These templates are not found via ADL.
+using hwy::HWY_NAMESPACE::AllFalse;
+using hwy::HWY_NAMESPACE::Gt;
+using hwy::HWY_NAMESPACE::Le;
+using hwy::HWY_NAMESPACE::MaskFromVec;
+using hwy::HWY_NAMESPACE::Or;
using hwy::HWY_NAMESPACE::Rebind;
using hwy::HWY_NAMESPACE::ShiftRight;
@@ -77,9 +79,11 @@ using D = HWY_FULL(float);
using DU = HWY_FULL(uint32_t);
using DI = HWY_FULL(int32_t);
using DI16 = Rebind<int16_t, DI>;
+using DI16_FULL = HWY_CAPPED(int16_t, kDCTBlockSize);
constexpr D d;
constexpr DI di;
constexpr DI16 di16;
+constexpr DI16_FULL di16_full;
// TODO(veluca): consider SIMDfying.
void Transpose8x8InPlace(int32_t* JXL_RESTRICT block) {
@@ -181,6 +185,9 @@ Status DecodeGroupImpl(const FrameHeader& frame_header,
const YCbCrChromaSubsampling& cs = frame_header.chroma_subsampling;
+ const auto kJpegDctMin = Set(di16_full, -4095);
+ const auto kJpegDctMax = Set(di16_full, 4095);
+
size_t idct_stride[3];
for (size_t c = 0; c < 3; c++) {
idct_stride[c] = render_pipeline_input.GetBuffer(c).first->PixelsPerRow();
@@ -355,7 +362,7 @@ Status DecodeGroupImpl(const FrameHeader& frame_header,
int16_t* JXL_RESTRICT jpeg_pos =
jpeg_row[c] + sbx[c] * kDCTBlockSize;
// JPEG XL is transposed, JPEG is not.
- auto transposed_dct = qblock[c].ptr32;
+ auto* transposed_dct = qblock[c].ptr32;
Transpose8x8InPlace(transposed_dct);
// No CfL - no need to store the y block converted to integers.
if (!cs.Is444() ||
@@ -391,6 +398,16 @@ Status DecodeGroupImpl(const FrameHeader& frame_header,
}
jpeg_pos[0] =
Clamp1<float>(dc_rows[c][sbx[c]] - dcoff[c], -2047, 2047);
+ auto overflow = MaskFromVec(Set(di16_full, 0));
+ auto underflow = MaskFromVec(Set(di16_full, 0));
+ for (int i = 0; i < 64; i += Lanes(di16_full)) {
+ auto in = LoadU(di16_full, jpeg_pos + i);
+ overflow = Or(overflow, Gt(in, kJpegDctMax));
+ underflow = Or(underflow, Lt(in, kJpegDctMin));
+ }
+ if (!AllFalse(di16_full, Or(overflow, underflow))) {
+ return JXL_FAILURE("JPEG DCT coefficients out of range");
+ }
}
} else {
HWY_ALIGN float* const block = group_dec_cache->dec_group_block;
@@ -683,7 +700,7 @@ Status DecodeGroup(const FrameHeader& frame_header,
}
if (draw == kDraw && num_passes == 0 && first_pass == 0) {
- group_dec_cache->InitDCBufferOnce();
+ JXL_RETURN_IF_ERROR(group_dec_cache->InitDCBufferOnce());
const YCbCrChromaSubsampling& cs = frame_header.chroma_subsampling;
for (size_t c : {0, 1, 2}) {
size_t hs = cs.HShift(c);
@@ -726,7 +743,7 @@ Status DecodeGroup(const FrameHeader& frame_header,
y++) {
for (ssize_t iy = 0; iy < 5; iy++) {
input_rows[0][iy] = group_dec_cache->dc_buffer.Row(
- Mirror(ssize_t(y) + iy - 2,
+ Mirror(static_cast<ssize_t>(y) + iy - 2,
dec_state->shared->dc->Plane(c).ysize() >> vs) +
2 - src_rect.y0());
}
@@ -736,9 +753,9 @@ Status DecodeGroup(const FrameHeader& frame_header,
kRenderPipelineXOffset;
}
// Arguments set to 0/nullptr are not used.
- dec_state->upsampler8x->ProcessRow(input_rows, output_rows,
- /*xextra=*/0, src_rect.xsize(), 0, 0,
- thread);
+ JXL_RETURN_IF_ERROR(dec_state->upsampler8x->ProcessRow(
+ input_rows, output_rows,
+ /*xextra=*/0, src_rect.xsize(), 0, 0, thread));
}
}
return true;
@@ -780,9 +797,9 @@ Status DecodeGroupForRoundtrip(const FrameHeader& frame_header,
ImageBundle* JXL_RESTRICT decoded,
AuxOut* aux_out) {
GetBlockFromEncoder get_block(ac, group_idx, frame_header.passes.shift);
- group_dec_cache->InitOnce(
+ JXL_RETURN_IF_ERROR(group_dec_cache->InitOnce(
/*num_passes=*/0,
- /*used_acs=*/(1u << AcStrategy::kNumValidStrategies) - 1);
+ /*used_acs=*/(1u << AcStrategy::kNumValidStrategies) - 1));
return HWY_DYNAMIC_DISPATCH(DecodeGroupImpl)(
frame_header, &get_block, group_dec_cache, dec_state, thread, group_idx,
diff --git a/third_party/jpeg-xl/lib/jxl/dec_huffman.cc b/third_party/jpeg-xl/lib/jxl/dec_huffman.cc
index 05b275773a..849b1a5f64 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_huffman.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_huffman.cc
@@ -5,6 +5,7 @@
#include "lib/jxl/dec_huffman.h"
+#include <jxl/types.h>
#include <string.h> /* for memset */
#include <vector>
@@ -22,9 +23,9 @@ static const uint8_t kCodeLengthCodeOrder[kCodeLengthCodes] = {
static const uint8_t kDefaultCodeLength = 8;
static const uint8_t kCodeLengthRepeatCode = 16;
-int ReadHuffmanCodeLengths(const uint8_t* code_length_code_lengths,
- int num_symbols, uint8_t* code_lengths,
- BitReader* br) {
+JXL_BOOL ReadHuffmanCodeLengths(const uint8_t* code_length_code_lengths,
+ int num_symbols, uint8_t* code_lengths,
+ BitReader* br) {
int symbol = 0;
uint8_t prev_code_len = kDefaultCodeLength;
int repeat = 0;
@@ -38,7 +39,7 @@ int ReadHuffmanCodeLengths(const uint8_t* code_length_code_lengths,
}
if (!BuildHuffmanTable(table, 5, code_length_code_lengths, kCodeLengthCodes,
&counts[0])) {
- return 0;
+ return JXL_FALSE;
}
while (symbol < num_symbols && space > 0) {
@@ -47,7 +48,7 @@ int ReadHuffmanCodeLengths(const uint8_t* code_length_code_lengths,
br->Refill();
p += br->PeekFixedBits<5>();
br->Consume(p->bits);
- code_len = (uint8_t)p->value;
+ code_len = static_cast<uint8_t>(p->value);
if (code_len < kCodeLengthRepeatCode) {
repeat = 0;
code_lengths[symbol++] = code_len;
@@ -72,12 +73,13 @@ int ReadHuffmanCodeLengths(const uint8_t* code_length_code_lengths,
repeat -= 2;
repeat <<= extra_bits;
}
- repeat += (int)br->ReadBits(extra_bits) + 3;
+ repeat += static_cast<int>(br->ReadBits(extra_bits) + 3);
repeat_delta = repeat - old_repeat;
if (symbol + repeat_delta > num_symbols) {
return 0;
}
- memset(&code_lengths[symbol], repeat_code_len, (size_t)repeat_delta);
+ memset(&code_lengths[symbol], repeat_code_len,
+ static_cast<size_t>(repeat_delta));
symbol += repeat_delta;
if (repeat_code_len != 0) {
space -= repeat_delta << (15 - repeat_code_len);
@@ -85,10 +87,10 @@ int ReadHuffmanCodeLengths(const uint8_t* code_length_code_lengths,
}
}
if (space != 0) {
- return 0;
+ return JXL_FALSE;
}
- memset(&code_lengths[symbol], 0, (size_t)(num_symbols - symbol));
- return true;
+ memset(&code_lengths[symbol], 0, static_cast<size_t>(num_symbols - symbol));
+ return JXL_TRUE;
}
static JXL_INLINE bool ReadSimpleCode(size_t alphabet_size, BitReader* br,
@@ -176,7 +178,7 @@ static JXL_INLINE bool ReadSimpleCode(size_t alphabet_size, BitReader* br,
const uint32_t goal_size = 1u << kHuffmanTableBits;
while (table_size != goal_size) {
memcpy(&table[table_size], &table[0],
- (size_t)table_size * sizeof(table[0]));
+ static_cast<size_t>(table_size) * sizeof(table[0]));
table_size <<= 1;
}
@@ -212,16 +214,17 @@ bool HuffmanDecodingData::ReadFromBitStream(size_t alphabet_size,
br->Refill();
p += br->PeekFixedBits<4>();
br->Consume(p->bits);
- v = (uint8_t)p->value;
+ v = static_cast<uint8_t>(p->value);
code_length_code_lengths[code_len_idx] = v;
if (v != 0) {
space -= (32u >> v);
++num_codes;
}
}
- bool ok = (num_codes == 1 || space == 0) &&
- ReadHuffmanCodeLengths(code_length_code_lengths, alphabet_size,
- &code_lengths[0], br);
+ bool ok =
+ (num_codes == 1 || space == 0) &&
+ FROM_JXL_BOOL(ReadHuffmanCodeLengths(
+ code_length_code_lengths, alphabet_size, code_lengths.data(), br));
if (!ok) return false;
uint16_t counts[16] = {0};
@@ -230,7 +233,7 @@ bool HuffmanDecodingData::ReadFromBitStream(size_t alphabet_size,
}
table_.resize(alphabet_size + 376);
uint32_t table_size =
- BuildHuffmanTable(table_.data(), kHuffmanTableBits, &code_lengths[0],
+ BuildHuffmanTable(table_.data(), kHuffmanTableBits, code_lengths.data(),
alphabet_size, &counts[0]);
table_.resize(table_size);
return (table_size > 0);
diff --git a/third_party/jpeg-xl/lib/jxl/dec_modular.cc b/third_party/jpeg-xl/lib/jxl/dec_modular.cc
index 4fcba489e2..49561e6ec2 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_modular.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_modular.cc
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <atomic>
-#include <sstream>
#include <vector>
#include "lib/jxl/frame_header.h"
@@ -18,10 +17,8 @@
#include <hwy/foreach_target.h>
#include <hwy/highway.h>
-#include "lib/jxl/alpha.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/printf_macros.h"
-#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/compressed_dc.h"
#include "lib/jxl/epf.h"
@@ -189,7 +186,7 @@ Status ModularFrameDecoder::DecodeGlobalInfo(BitReader* reader,
}
do_color = decode_color;
size_t nb_extra = metadata.extra_channel_info.size();
- bool has_tree = reader->ReadBits(1);
+ bool has_tree = static_cast<bool>(reader->ReadBits(1));
if (!allow_truncated_group ||
reader->TotalBitsConsumed() < reader->TotalBytes() * kBitsPerByte) {
if (has_tree) {
@@ -216,8 +213,10 @@ Status ModularFrameDecoder::DecodeGlobalInfo(BitReader* reader,
}
}
- Image gi(frame_dim.xsize, frame_dim.ysize, metadata.bit_depth.bits_per_sample,
- nb_chans + nb_extra);
+ JXL_ASSIGN_OR_RETURN(
+ Image gi,
+ Image::Create(frame_dim.xsize, frame_dim.ysize,
+ metadata.bit_depth.bits_per_sample, nb_chans + nb_extra));
all_same_shift = true;
if (frame_header.color_transform == ColorTransform::kYCbCr) {
@@ -228,7 +227,7 @@ Status ModularFrameDecoder::DecodeGlobalInfo(BitReader* reader,
DivCeil(frame_dim.xsize, 1 << gi.channel[c].hshift);
size_t ysize_shifted =
DivCeil(frame_dim.ysize, 1 << gi.channel[c].vshift);
- gi.channel[c].shrink(xsize_shifted, ysize_shifted);
+ JXL_RETURN_IF_ERROR(gi.channel[c].shrink(xsize_shifted, ysize_shifted));
if (gi.channel[c].hshift != gi.channel[0].hshift ||
gi.channel[c].vshift != gi.channel[0].vshift)
all_same_shift = false;
@@ -237,8 +236,9 @@ Status ModularFrameDecoder::DecodeGlobalInfo(BitReader* reader,
for (size_t ec = 0, c = nb_chans; ec < nb_extra; ec++, c++) {
size_t ecups = frame_header.extra_channel_upsampling[ec];
- gi.channel[c].shrink(DivCeil(frame_dim.xsize_upsampled, ecups),
- DivCeil(frame_dim.ysize_upsampled, ecups));
+ JXL_RETURN_IF_ERROR(
+ gi.channel[c].shrink(DivCeil(frame_dim.xsize_upsampled, ecups),
+ DivCeil(frame_dim.ysize_upsampled, ecups)));
gi.channel[c].hshift = gi.channel[c].vshift =
CeilLog2Nonzero(ecups) - CeilLog2Nonzero(frame_header.upsampling);
if (gi.channel[c].hshift != gi.channel[0].hshift ||
@@ -306,7 +306,8 @@ Status ModularFrameDecoder::DecodeGroup(
stream.kind == ModularStreamId::kModularAC);
const size_t xsize = rect.xsize();
const size_t ysize = rect.ysize();
- Image gi(xsize, ysize, full_image.bitdepth, 0);
+ JXL_ASSIGN_OR_RETURN(Image gi,
+ Image::Create(xsize, ysize, full_image.bitdepth, 0));
// start at the first bigger-than-groupsize non-metachannel
size_t c = full_image.nb_meta_channels;
for (; c < full_image.channel.size(); c++) {
@@ -328,7 +329,7 @@ Status ModularFrameDecoder::DecodeGroup(
memset(row_out, 0, r.xsize() * sizeof(*row_out));
}
} else {
- Channel gc(r.xsize(), r.ysize());
+ JXL_ASSIGN_OR_RETURN(Channel gc, Channel::Create(r.xsize(), r.ysize()));
if (zerofill) ZeroFillImage(&gc.plane);
gc.hshift = fc.hshift;
gc.vshift = fc.vshift;
@@ -398,7 +399,8 @@ Status ModularFrameDecoder::DecodeVarDCTDC(const FrameHeader& frame_header,
// 3 comes from XybToRgb that cubes the values, and "magic" is
// the sum of all other contributions. 2**18 is known to lead
// to NaN on input found by fuzzing (see commit message).
- Image image(r.xsize(), r.ysize(), full_image.bitdepth, 3);
+ JXL_ASSIGN_OR_RETURN(
+ Image image, Image::Create(r.xsize(), r.ysize(), full_image.bitdepth, 3));
size_t stream_id = ModularStreamId::VarDCTDC(group_id).ID(frame_dim);
reader->Refill();
size_t extra_precision = reader->ReadFixedBits<2>();
@@ -408,12 +410,13 @@ Status ModularFrameDecoder::DecodeVarDCTDC(const FrameHeader& frame_header,
Channel& ch = image.channel[c < 2 ? c ^ 1 : c];
ch.w >>= frame_header.chroma_subsampling.HShift(c);
ch.h >>= frame_header.chroma_subsampling.VShift(c);
- ch.shrink();
+ JXL_RETURN_IF_ERROR(ch.shrink());
}
if (!ModularGenericDecompress(
reader, image, /*header=*/nullptr, stream_id, &options,
/*undo_transforms=*/true, &tree, &code, &context_map)) {
- return JXL_FAILURE("Failed to decode VarDCT DC group");
+ return JXL_FAILURE("Failed to decode VarDCT DC group (DC group id %d)",
+ static_cast<int>(group_id));
}
DequantDC(r, &dec_state->shared_storage.dc_storage,
&dec_state->shared_storage.quant_dc, image,
@@ -433,12 +436,15 @@ Status ModularFrameDecoder::DecodeAcMetadata(const FrameHeader& frame_header,
size_t count = reader->ReadBits(CeilLog2Nonzero(upper_bound)) + 1;
size_t stream_id = ModularStreamId::ACMetadata(group_id).ID(frame_dim);
// YToX, YToB, ACS + QF, EPF
- Image image(r.xsize(), r.ysize(), full_image.bitdepth, 4);
+ JXL_ASSIGN_OR_RETURN(
+ Image image, Image::Create(r.xsize(), r.ysize(), full_image.bitdepth, 4));
static_assert(kColorTileDimInBlocks == 8, "Color tile size changed");
Rect cr(r.x0() >> 3, r.y0() >> 3, (r.xsize() + 7) >> 3, (r.ysize() + 7) >> 3);
- image.channel[0] = Channel(cr.xsize(), cr.ysize(), 3, 3);
- image.channel[1] = Channel(cr.xsize(), cr.ysize(), 3, 3);
- image.channel[2] = Channel(count, 2, 0, 0);
+ JXL_ASSIGN_OR_RETURN(image.channel[0],
+ Channel::Create(cr.xsize(), cr.ysize(), 3, 3));
+ JXL_ASSIGN_OR_RETURN(image.channel[1],
+ Channel::Create(cr.xsize(), cr.ysize(), 3, 3));
+ JXL_ASSIGN_OR_RETURN(image.channel[2], Channel::Create(count, 2, 0, 0));
ModularOptions options;
if (!ModularGenericDecompress(
reader, image, /*header=*/nullptr, stream_id, &options,
@@ -513,7 +519,7 @@ Status ModularFrameDecoder::DecodeAcMetadata(const FrameHeader& frame_header,
Status ModularFrameDecoder::ModularImageToDecodedRect(
const FrameHeader& frame_header, Image& gi, PassesDecoderState* dec_state,
jxl::ThreadPool* pool, RenderPipelineInput& render_pipeline_input,
- Rect modular_rect) {
+ Rect modular_rect) const {
const auto* metadata = frame_header.nonserialized_metadata;
JXL_CHECK(gi.transform.empty());
@@ -686,7 +692,12 @@ Status ModularFrameDecoder::FinalizeDecoding(const FrameHeader& frame_header,
jxl::ThreadPool* pool,
bool inplace) {
if (!use_full_image) return true;
- Image gi = (inplace ? std::move(full_image) : full_image.clone());
+ Image gi;
+ if (inplace) {
+ gi = std::move(full_image);
+ } else {
+ JXL_ASSIGN_OR_RETURN(gi, Image::Clone(full_image));
+ }
size_t xsize = gi.w;
size_t ysize = gi.h;
@@ -714,6 +725,7 @@ Status ModularFrameDecoder::FinalizeDecoding(const FrameHeader& frame_header,
use_group_ids);
},
[&](const uint32_t group, size_t thread_id) {
+ if (has_error) return;
RenderPipelineInput input =
dec_state->render_pipeline->GetInputBuffers(group, thread_id);
if (!ModularImageToDecodedRect(
@@ -722,12 +734,13 @@ Status ModularFrameDecoder::FinalizeDecoding(const FrameHeader& frame_header,
has_error = true;
return;
}
- input.Done();
+ if (!input.Done()) {
+ has_error = true;
+ return;
+ }
},
"ModularToRect"));
- if (has_error) {
- return JXL_FAILURE("Error producing input to render pipeline");
- }
+ if (has_error) return JXL_FAILURE("Error producing input to render pipeline");
return true;
}
@@ -743,7 +756,8 @@ Status ModularFrameDecoder::DecodeQuantTable(
// be negative.
return JXL_FAILURE("Invalid qtable_den: value too small");
}
- Image image(required_size_x, required_size_y, 8, 3);
+ JXL_ASSIGN_OR_RETURN(Image image,
+ Image::Create(required_size_x, required_size_y, 8, 3));
ModularOptions options;
if (modular_frame_decoder) {
JXL_RETURN_IF_ERROR(ModularGenericDecompress(
diff --git a/third_party/jpeg-xl/lib/jxl/dec_modular.h b/third_party/jpeg-xl/lib/jxl/dec_modular.h
index 58a6562740..23caad0c16 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_modular.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_modular.h
@@ -123,7 +123,7 @@ class ModularFrameDecoder {
PassesDecoderState* dec_state,
jxl::ThreadPool* pool,
RenderPipelineInput& render_pipeline_input,
- Rect modular_rect);
+ Rect modular_rect) const;
Image full_image;
std::vector<Transform> global_transform;
diff --git a/third_party/jpeg-xl/lib/jxl/dec_noise.cc b/third_party/jpeg-xl/lib/jxl/dec_noise.cc
index ae46b1062f..24f0136490 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_noise.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_noise.cc
@@ -108,9 +108,8 @@ void Random3Planes(size_t visible_frame_index, size_t nonvisible_frame_index,
size_t x0, size_t y0, const std::pair<ImageF*, Rect>& plane0,
const std::pair<ImageF*, Rect>& plane1,
const std::pair<ImageF*, Rect>& plane2) {
- return HWY_DYNAMIC_DISPATCH(Random3Planes)(visible_frame_index,
- nonvisible_frame_index, x0, y0,
- plane0, plane1, plane2);
+ HWY_DYNAMIC_DISPATCH(Random3Planes)
+ (visible_frame_index, nonvisible_frame_index, x0, y0, plane0, plane1, plane2);
}
void DecodeFloatParam(float precision, float* val, BitReader* br) {
diff --git a/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.cc b/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.cc
index 0ae2223252..120a977ca7 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.cc
@@ -10,26 +10,16 @@
#include <sys/types.h>
#include <algorithm>
-#include <string>
-#include <tuple>
#include <utility>
#include <vector>
-#include "lib/jxl/ans_params.h"
-#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/base/override.h"
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/blending.h"
-#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/common.h" // kMaxNumReferenceFrames
#include "lib/jxl/dec_ans.h"
-#include "lib/jxl/dec_frame.h"
-#include "lib/jxl/entropy_coder.h"
-#include "lib/jxl/frame_header.h"
#include "lib/jxl/image.h"
#include "lib/jxl/image_bundle.h"
-#include "lib/jxl/image_ops.h"
#include "lib/jxl/pack_signed.h"
#include "lib/jxl/patch_dictionary_internal.h"
@@ -138,7 +128,8 @@ Status PatchDictionary::Decode(BitReader* br, size_t xsize, size_t ysize,
}
for (size_t j = 0; j < num_ec + 1; j++) {
uint32_t blend_mode = read_num(kPatchBlendModeContext);
- if (blend_mode >= uint32_t(PatchBlendMode::kNumBlendModes)) {
+ if (blend_mode >=
+ static_cast<uint32_t>(PatchBlendMode::kNumBlendModes)) {
return JXL_FAILURE("Invalid patch blend mode: %u", blend_mode);
}
PatchBlending info;
@@ -157,21 +148,22 @@ Status PatchDictionary::Decode(BitReader* br, size_t xsize, size_t ysize,
return JXL_FAILURE(
"Invalid alpha channel for blending: %u out of %u\n",
info.alpha_channel,
- (uint32_t)shared_->metadata->m.extra_channel_info.size());
+ static_cast<uint32_t>(
+ shared_->metadata->m.extra_channel_info.size()));
}
} else {
info.alpha_channel = 0;
}
if (UsesClamp(info.mode)) {
- info.clamp = read_num(kPatchClampContext);
+ info.clamp = static_cast<bool>(read_num(kPatchClampContext));
} else {
info.clamp = false;
}
blendings_.push_back(info);
}
- positions_.push_back(std::move(pos));
+ positions_.emplace_back(pos);
}
- ref_positions_.emplace_back(std::move(ref_pos));
+ ref_positions_.emplace_back(ref_pos);
}
positions_.shrink_to_fit();
@@ -185,8 +177,8 @@ Status PatchDictionary::Decode(BitReader* br, size_t xsize, size_t ysize,
int PatchDictionary::GetReferences() const {
int result = 0;
- for (size_t i = 0; i < ref_positions_.size(); ++i) {
- result |= (1 << static_cast<int>(ref_positions_[i].ref));
+ for (const auto& ref_pos : ref_positions_) {
+ result |= (1 << static_cast<int>(ref_pos.ref));
}
return result;
}
@@ -263,11 +255,11 @@ void PatchDictionary::ComputePatchTree() {
node.start = sorted_patches_y0_.size();
for (ssize_t i = static_cast<ssize_t>(right_start) - 1;
i >= static_cast<ssize_t>(left_end); --i) {
- sorted_patches_y1_.push_back({intervals[i].y1, intervals[i].idx});
+ sorted_patches_y1_.emplace_back(intervals[i].y1, intervals[i].idx);
}
sort_by_y0(left_end, right_start);
for (size_t i = left_end; i < right_start; ++i) {
- sorted_patches_y0_.push_back({intervals[i].y0, intervals[i].idx});
+ sorted_patches_y0_.emplace_back(intervals[i].y0, intervals[i].idx);
}
// Create the left and right nodes (if not empty).
node.left_child = node.right_child = -1;
@@ -294,7 +286,7 @@ std::vector<size_t> PatchDictionary::GetPatchesForRow(size_t y) const {
if (y < num_patches_.size() && num_patches_[y] > 0) {
result.reserve(num_patches_[y]);
for (ssize_t tree_idx = 0; tree_idx != -1;) {
- JXL_DASSERT(tree_idx < (ssize_t)patch_tree_.size());
+ JXL_DASSERT(tree_idx < static_cast<ssize_t>(patch_tree_.size()));
const auto& node = patch_tree_[tree_idx];
if (y <= node.y_center) {
for (size_t i = 0; i < node.num; ++i) {
@@ -322,8 +314,8 @@ std::vector<size_t> PatchDictionary::GetPatchesForRow(size_t y) const {
// Adds patches to a segment of `xsize` pixels, starting at `inout`, assumed
// to be located at position (x0, y) in the frame.
-void PatchDictionary::AddOneRow(float* const* inout, size_t y, size_t x0,
- size_t xsize) const {
+Status PatchDictionary::AddOneRow(float* const* inout, size_t y, size_t x0,
+ size_t xsize) const {
size_t num_ec = shared_->metadata->m.num_extra_channels;
std::vector<const float*> fg_ptrs(3 + num_ec);
for (size_t pos_idx : GetPatchesForRow(y)) {
@@ -352,10 +344,11 @@ void PatchDictionary::AddOneRow(float* const* inout, size_t y, size_t x0,
ref_pos.y0 + iy) +
ref_pos.x0 + x0 - bx;
}
- PerformBlending(inout, fg_ptrs.data(), inout, patch_x0 - x0,
- patch_x1 - patch_x0, blendings_[blending_idx],
- blendings_.data() + blending_idx + 1,
- shared_->metadata->m.extra_channel_info);
+ JXL_RETURN_IF_ERROR(PerformBlending(
+ inout, fg_ptrs.data(), inout, patch_x0 - x0, patch_x1 - patch_x0,
+ blendings_[blending_idx], blendings_.data() + blending_idx + 1,
+ shared_->metadata->m.extra_channel_info));
}
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.h b/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.h
index aac6111ae6..72dca8f057 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.h
@@ -12,12 +12,10 @@
#include <string.h>
#include <sys/types.h>
-#include <tuple>
#include <vector>
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_bit_reader.h"
-#include "lib/jxl/image.h"
namespace jxl {
@@ -109,7 +107,8 @@ class PatchDictionary {
// Adds patches to a segment of `xsize` pixels, starting at `inout`, assumed
// to be located at position (x0, y) in the frame.
- void AddOneRow(float* const* inout, size_t y, size_t x0, size_t xsize) const;
+ Status AddOneRow(float* const* inout, size_t y, size_t x0,
+ size_t xsize) const;
// Returns dependencies of this patch dictionary on reference frame ids as a
// bit mask: bits 0-3 indicate reference frame 0-3.
diff --git a/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.cc b/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.cc
index 2d40740262..6451c41f6d 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.cc
@@ -21,21 +21,21 @@ void TransformToPixels(AcStrategy::Type strategy,
float* JXL_RESTRICT coefficients,
float* JXL_RESTRICT pixels, size_t pixels_stride,
float* scratch_space) {
- return HWY_DYNAMIC_DISPATCH(TransformToPixels)(strategy, coefficients, pixels,
- pixels_stride, scratch_space);
+ HWY_DYNAMIC_DISPATCH(TransformToPixels)
+ (strategy, coefficients, pixels, pixels_stride, scratch_space);
}
HWY_EXPORT(LowestFrequenciesFromDC);
void LowestFrequenciesFromDC(const jxl::AcStrategy::Type strategy,
const float* dc, size_t dc_stride, float* llf,
float* JXL_RESTRICT scratch) {
- return HWY_DYNAMIC_DISPATCH(LowestFrequenciesFromDC)(strategy, dc, dc_stride,
- llf, scratch);
+ HWY_DYNAMIC_DISPATCH(LowestFrequenciesFromDC)
+ (strategy, dc, dc_stride, llf, scratch);
}
HWY_EXPORT(AFVIDCT4x4);
void AFVIDCT4x4(const float* JXL_RESTRICT coeffs, float* JXL_RESTRICT pixels) {
- return HWY_DYNAMIC_DISPATCH(AFVIDCT4x4)(coeffs, pixels);
+ HWY_DYNAMIC_DISPATCH(AFVIDCT4x4)(coeffs, pixels);
}
#endif // HWY_ONCE
diff --git a/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.h b/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.h
index f68481fda9..2cbf6bd5f6 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.h
@@ -22,8 +22,8 @@ void TransformToPixels(AcStrategy::Type strategy,
float* JXL_RESTRICT scratch_space);
// Equivalent of the above for DC image.
-void LowestFrequenciesFromDC(const jxl::AcStrategy::Type strategy,
- const float* dc, size_t dc_stride, float* llf,
+void LowestFrequenciesFromDC(jxl::AcStrategy::Type strategy, const float* dc,
+ size_t dc_stride, float* llf,
float* JXL_RESTRICT scratch);
void AFVIDCT4x4(const float* JXL_RESTRICT coeffs, float* JXL_RESTRICT pixels);
diff --git a/third_party/jpeg-xl/lib/jxl/dec_xyb-inl.h b/third_party/jpeg-xl/lib/jxl/dec_xyb-inl.h
index 495693b257..09a8013960 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_xyb-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_xyb-inl.h
@@ -83,7 +83,7 @@ HWY_INLINE HWY_MAYBE_UNUSED void XybToRgb(D d, const V opsin_x, const V opsin_y,
*linear_b = MulAdd(LoadDup128(d, &inverse_matrix[8 * 4]), mixed_b, *linear_b);
}
-static inline HWY_MAYBE_UNUSED bool HasFastXYBTosRGB8() {
+inline HWY_MAYBE_UNUSED bool HasFastXYBTosRGB8() {
#if HWY_TARGET == HWY_NEON
return true;
#else
@@ -91,9 +91,9 @@ static inline HWY_MAYBE_UNUSED bool HasFastXYBTosRGB8() {
#endif
}
-static inline HWY_MAYBE_UNUSED void FastXYBTosRGB8(const float* input[4],
- uint8_t* output,
- bool is_rgba, size_t xsize) {
+inline HWY_MAYBE_UNUSED void FastXYBTosRGB8(const float* input[4],
+ uint8_t* output, bool is_rgba,
+ size_t xsize) {
// This function is very NEON-specific. As such, it uses intrinsics directly.
#if HWY_TARGET == HWY_NEON
// WARNING: doing fixed point arithmetic correctly is very complicated.
diff --git a/third_party/jpeg-xl/lib/jxl/dec_xyb.cc b/third_party/jpeg-xl/lib/jxl/dec_xyb.cc
index 7010f0d813..a719b3eb8c 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_xyb.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_xyb.cc
@@ -160,20 +160,19 @@ namespace jxl {
HWY_EXPORT(OpsinToLinearInplace);
void OpsinToLinearInplace(Image3F* JXL_RESTRICT inout, ThreadPool* pool,
const OpsinParams& opsin_params) {
- return HWY_DYNAMIC_DISPATCH(OpsinToLinearInplace)(inout, pool, opsin_params);
+ HWY_DYNAMIC_DISPATCH(OpsinToLinearInplace)(inout, pool, opsin_params);
}
HWY_EXPORT(OpsinToLinear);
void OpsinToLinear(const Image3F& opsin, const Rect& rect, ThreadPool* pool,
Image3F* JXL_RESTRICT linear,
const OpsinParams& opsin_params) {
- return HWY_DYNAMIC_DISPATCH(OpsinToLinear)(opsin, rect, pool, linear,
- opsin_params);
+ HWY_DYNAMIC_DISPATCH(OpsinToLinear)(opsin, rect, pool, linear, opsin_params);
}
HWY_EXPORT(YcbcrToRgb);
void YcbcrToRgb(const Image3F& ycbcr, Image3F* rgb, const Rect& rect) {
- return HWY_DYNAMIC_DISPATCH(YcbcrToRgb)(ycbcr, rgb, rect);
+ HWY_DYNAMIC_DISPATCH(YcbcrToRgb)(ycbcr, rgb, rect);
}
HWY_EXPORT(HasFastXYBTosRGB8);
@@ -182,7 +181,7 @@ bool HasFastXYBTosRGB8() { return HWY_DYNAMIC_DISPATCH(HasFastXYBTosRGB8)(); }
HWY_EXPORT(FastXYBTosRGB8);
void FastXYBTosRGB8(const float* input[4], uint8_t* output, bool is_rgba,
size_t xsize) {
- return HWY_DYNAMIC_DISPATCH(FastXYBTosRGB8)(input, output, is_rgba, xsize);
+ HWY_DYNAMIC_DISPATCH(FastXYBTosRGB8)(input, output, is_rgba, xsize);
}
void OpsinParams::Init(float intensity_target) {
@@ -218,7 +217,7 @@ Status OutputEncodingInfo::SetFromMetadata(const CodecMetadata& metadata) {
orig_intensity_target = metadata.m.IntensityTarget();
desired_intensity_target = orig_intensity_target;
const auto& im = metadata.transform_data.opsin_inverse_matrix;
- memcpy(orig_inverse_matrix, im.inverse_matrix, sizeof(orig_inverse_matrix));
+ orig_inverse_matrix = im.inverse_matrix;
default_transform = im.all_default;
xyb_encoded = metadata.m.xyb_encoded;
std::copy(std::begin(im.opsin_biases), std::end(im.opsin_biases),
@@ -258,38 +257,38 @@ Status OutputEncodingInfo::SetColorEncoding(const ColorEncoding& c_desired) {
// Compute the opsin inverse matrix and luminances based on primaries and
// white point.
- float inverse_matrix[9];
+ Matrix3x3 inverse_matrix;
bool inverse_matrix_is_default = default_transform;
- memcpy(inverse_matrix, orig_inverse_matrix, sizeof(inverse_matrix));
- constexpr float kSRGBLuminances[3] = {0.2126, 0.7152, 0.0722};
- memcpy(luminances, kSRGBLuminances, sizeof(luminances));
+ inverse_matrix = orig_inverse_matrix;
+ constexpr Vector3 kSRGBLuminances{0.2126, 0.7152, 0.0722};
+ luminances = kSRGBLuminances;
if ((c_desired.GetPrimariesType() != Primaries::kSRGB ||
c_desired.GetWhitePointType() != WhitePoint::kD65) &&
!c_desired.IsGray()) {
- float srgb_to_xyzd50[9];
+ Matrix3x3 srgb_to_xyzd50;
const auto& srgb = ColorEncoding::SRGB(/*is_gray=*/false);
PrimariesCIExy p = srgb.GetPrimaries();
CIExy w = srgb.GetWhitePoint();
JXL_CHECK(PrimariesToXYZD50(p.r.x, p.r.y, p.g.x, p.g.y, p.b.x, p.b.y, w.x,
w.y, srgb_to_xyzd50));
- float original_to_xyz[3][3];
+ Matrix3x3 original_to_xyz;
p = c_desired.GetPrimaries();
w = c_desired.GetWhitePoint();
if (!PrimariesToXYZ(p.r.x, p.r.y, p.g.x, p.g.y, p.b.x, p.b.y, w.x, w.y,
- &original_to_xyz[0][0])) {
+ original_to_xyz)) {
return JXL_FAILURE("PrimariesToXYZ failed");
}
- memcpy(luminances, original_to_xyz[1], sizeof luminances);
+ luminances = original_to_xyz[1];
if (xyb_encoded) {
- float adapt_to_d50[9];
+ Matrix3x3 adapt_to_d50;
if (!AdaptToXYZD50(c_desired.GetWhitePoint().x,
c_desired.GetWhitePoint().y, adapt_to_d50)) {
return JXL_FAILURE("AdaptToXYZD50 failed");
}
- float xyzd50_to_original[9];
- Mul3x3Matrix(adapt_to_d50, &original_to_xyz[0][0], xyzd50_to_original);
+ Matrix3x3 xyzd50_to_original;
+ Mul3x3Matrix(adapt_to_d50, original_to_xyz, xyzd50_to_original);
JXL_RETURN_IF_ERROR(Inv3x3Matrix(xyzd50_to_original));
- float srgb_to_original[9];
+ Matrix3x3 srgb_to_original;
Mul3x3Matrix(xyzd50_to_original, srgb_to_xyzd50, srgb_to_original);
Mul3x3Matrix(srgb_to_original, orig_inverse_matrix, inverse_matrix);
inverse_matrix_is_default = false;
@@ -297,12 +296,8 @@ Status OutputEncodingInfo::SetColorEncoding(const ColorEncoding& c_desired) {
}
if (c_desired.IsGray()) {
- float tmp_inv_matrix[9];
- memcpy(tmp_inv_matrix, inverse_matrix, sizeof(inverse_matrix));
- float srgb_to_luma[9];
- memcpy(&srgb_to_luma[0], luminances, sizeof(luminances));
- memcpy(&srgb_to_luma[3], luminances, sizeof(luminances));
- memcpy(&srgb_to_luma[6], luminances, sizeof(luminances));
+ Matrix3x3 tmp_inv_matrix = inverse_matrix;
+ Matrix3x3 srgb_to_luma{luminances, luminances, luminances};
Mul3x3Matrix(srgb_to_luma, tmp_inv_matrix, inverse_matrix);
}
diff --git a/third_party/jpeg-xl/lib/jxl/dec_xyb.h b/third_party/jpeg-xl/lib/jxl/dec_xyb.h
index ddfd555632..65317f2f54 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_xyb.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_xyb.h
@@ -39,7 +39,7 @@ struct OutputEncodingInfo {
// Used for the HLG OOTF and PQ tone mapping.
float orig_intensity_target;
// Opsin inverse matrix taken from the metadata.
- float orig_inverse_matrix[9];
+ Matrix3x3 orig_inverse_matrix;
bool default_transform;
bool xyb_encoded;
//
@@ -60,7 +60,7 @@ struct OutputEncodingInfo {
// Luminances of color_encoding's primaries, used for the HLG inverse OOTF and
// for PQ tone mapping.
// Default to sRGB's.
- float luminances[3];
+ Vector3 luminances;
// Used for the HLG inverse OOTF and PQ tone mapping.
float desired_intensity_target;
bool cms_set = false;
diff --git a/third_party/jpeg-xl/lib/jxl/decode.cc b/third_party/jpeg-xl/lib/jxl/decode.cc
index b674d1ba88..605c2d6fd6 100644
--- a/third_party/jpeg-xl/lib/jxl/decode.cc
+++ b/third_party/jpeg-xl/lib/jxl/decode.cc
@@ -721,7 +721,7 @@ void JxlDecoderRewindDecodingState(JxlDecoder* dec) {
dec->events_wanted = dec->orig_events_wanted;
dec->basic_info_size_hint = InitialBasicInfoSizeHint();
- dec->have_container = 0;
+ dec->have_container = false;
dec->box_count = 0;
dec->downsampling_target = 8;
dec->image_out_buffer_set = false;
@@ -733,7 +733,7 @@ void JxlDecoderRewindDecodingState(JxlDecoder* dec) {
dec->image_out_size = 0;
dec->image_out_bit_depth.type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT;
dec->extra_channel_output.clear();
- dec->next_in = 0;
+ dec->next_in = nullptr;
dec->avail_in = 0;
dec->input_closed = false;
@@ -839,9 +839,9 @@ void JxlDecoderSkipFrames(JxlDecoder* dec, size_t amount) {
internal_index, dec->frame_saved_as, dec->frame_references);
dec->frame_required.resize(internal_index + 1, 0);
- for (size_t i = 0; i < deps.size(); i++) {
- JXL_ASSERT(deps[i] < dec->frame_required.size());
- dec->frame_required[deps[i]] = 1;
+ for (size_t idx : deps) {
+ JXL_ASSERT(idx < dec->frame_required.size());
+ dec->frame_required[idx] = 1;
}
}
}
@@ -894,7 +894,7 @@ JxlDecoderStatus JxlDecoderSetKeepOrientation(JxlDecoder* dec,
if (dec->stage != DecoderStage::kInited) {
return JXL_API_ERROR("Must set keep_orientation option before starting");
}
- dec->keep_orientation = !!skip_reorientation;
+ dec->keep_orientation = FROM_JXL_BOOL(skip_reorientation);
return JXL_DEC_SUCCESS;
}
@@ -903,7 +903,7 @@ JxlDecoderStatus JxlDecoderSetUnpremultiplyAlpha(JxlDecoder* dec,
if (dec->stage != DecoderStage::kInited) {
return JXL_API_ERROR("Must set unpremul_alpha option before starting");
}
- dec->unpremul_alpha = !!unpremul_alpha;
+ dec->unpremul_alpha = FROM_JXL_BOOL(unpremul_alpha);
return JXL_DEC_SUCCESS;
}
@@ -912,7 +912,7 @@ JxlDecoderStatus JxlDecoderSetRenderSpotcolors(JxlDecoder* dec,
if (dec->stage != DecoderStage::kInited) {
return JXL_API_ERROR("Must set render_spotcolors option before starting");
}
- dec->render_spotcolors = !!render_spotcolors;
+ dec->render_spotcolors = FROM_JXL_BOOL(render_spotcolors);
return JXL_DEC_SUCCESS;
}
@@ -920,7 +920,7 @@ JxlDecoderStatus JxlDecoderSetCoalescing(JxlDecoder* dec, JXL_BOOL coalescing) {
if (dec->stage != DecoderStage::kInited) {
return JXL_API_ERROR("Must set coalescing option before starting");
}
- dec->coalescing = !!coalescing;
+ dec->coalescing = FROM_JXL_BOOL(coalescing);
return JXL_DEC_SUCCESS;
}
@@ -1076,7 +1076,7 @@ JxlDecoderStatus JxlDecoderReadAllHeaders(JxlDecoder* dec) {
return JXL_DEC_ERROR;
}
IccBytes icc;
- Bytes(decoded_icc).AppendTo(&icc);
+ Bytes(decoded_icc).AppendTo(icc);
dec->metadata.m.color_encoding.SetICCRaw(std::move(icc));
}
@@ -1118,7 +1118,7 @@ JxlDecoderStatus JxlDecoderProcessSections(JxlDecoder* dec) {
if (OutOfBounds(pos, size, span.size())) {
break;
}
- auto br = new jxl::BitReader(jxl::Bytes(span.data() + pos, size));
+ auto* br = new jxl::BitReader(jxl::Bytes(span.data() + pos, size));
section_info.emplace_back(jxl::FrameDecoder::SectionInfo{br, id, i});
section_status.emplace_back();
pos += size;
@@ -1263,9 +1263,9 @@ JxlDecoderStatus JxlDecoderProcessCodestream(JxlDecoder* dec) {
frame_dim.ysize_upsampled_padded)) {
return JXL_INPUT_ERROR("frame is too large");
}
- bool output_needed =
- (dec->preview_frame ? (dec->events_wanted & JXL_DEC_PREVIEW_IMAGE)
- : (dec->events_wanted & JXL_DEC_FULL_IMAGE));
+ int output_type =
+ dec->preview_frame ? JXL_DEC_PREVIEW_IMAGE : JXL_DEC_FULL_IMAGE;
+ bool output_needed = ((dec->events_wanted & output_type) != 0);
if (output_needed) {
JXL_API_RETURN_IF_ERROR(dec->frame_dec->InitFrameOutput());
}
@@ -1376,7 +1376,7 @@ JxlDecoderStatus JxlDecoderProcessCodestream(JxlDecoder* dec) {
} else {
dec->frame_prog_detail = JxlProgressiveDetail::kFrames;
}
- dec->dc_frame_progression_done = 0;
+ dec->dc_frame_progression_done = false;
dec->next_section = 0;
dec->section_processed.clear();
@@ -1413,7 +1413,8 @@ JxlDecoderStatus JxlDecoderProcessCodestream(JxlDecoder* dec) {
}
if (dec->image_out_buffer_set) {
- size_t xsize, ysize;
+ size_t xsize;
+ size_t ysize;
GetCurrentDimensions(dec, xsize, ysize);
size_t bits_per_sample = GetBitDepth(
dec->image_out_bit_depth, dec->metadata.m, dec->image_out_format);
@@ -1765,7 +1766,8 @@ static JxlDecoderStatus HandleBoxes(JxlDecoder* dec) {
return JXL_DEC_SUCCESS;
}
- uint64_t box_size, header_size;
+ uint64_t box_size;
+ uint64_t header_size;
JxlDecoderStatus status =
ParseBoxHeader(dec->next_in, dec->avail_in, 0, dec->file_pos,
dec->box_type, &box_size, &header_size);
@@ -2042,7 +2044,7 @@ JxlDecoderStatus JxlDecoderProcessInput(JxlDecoder* dec) {
dec->got_signature = true;
if (sig == JXL_SIG_CONTAINER) {
- dec->have_container = 1;
+ dec->have_container = true;
} else {
dec->last_codestream_seen = true;
}
@@ -2083,16 +2085,16 @@ JxlDecoderStatus JxlDecoderGetBasicInfo(const JxlDecoder* dec,
const jxl::ImageMetadata& meta = dec->metadata.m;
- info->have_container = dec->have_container;
+ info->have_container = TO_JXL_BOOL(dec->have_container);
info->xsize = dec->metadata.size.xsize();
info->ysize = dec->metadata.size.ysize();
- info->uses_original_profile = !meta.xyb_encoded;
+ info->uses_original_profile = TO_JXL_BOOL(!meta.xyb_encoded);
info->bits_per_sample = meta.bit_depth.bits_per_sample;
info->exponent_bits_per_sample = meta.bit_depth.exponent_bits_per_sample;
- info->have_preview = meta.have_preview;
- info->have_animation = meta.have_animation;
+ info->have_preview = TO_JXL_BOOL(meta.have_preview);
+ info->have_animation = TO_JXL_BOOL(meta.have_animation);
info->orientation = static_cast<JxlOrientation>(meta.orientation);
if (!dec->keep_orientation) {
@@ -2107,14 +2109,15 @@ JxlDecoderStatus JxlDecoderGetBasicInfo(const JxlDecoder* dec,
info->intensity_target = dec->desired_intensity_target;
}
info->min_nits = meta.tone_mapping.min_nits;
- info->relative_to_max_display = meta.tone_mapping.relative_to_max_display;
+ info->relative_to_max_display =
+ TO_JXL_BOOL(meta.tone_mapping.relative_to_max_display);
info->linear_below = meta.tone_mapping.linear_below;
const jxl::ExtraChannelInfo* alpha = meta.Find(jxl::ExtraChannel::kAlpha);
if (alpha != nullptr) {
info->alpha_bits = alpha->bit_depth.bits_per_sample;
info->alpha_exponent_bits = alpha->bit_depth.exponent_bits_per_sample;
- info->alpha_premultiplied = alpha->alpha_associated;
+ info->alpha_premultiplied = TO_JXL_BOOL(alpha->alpha_associated);
} else {
info->alpha_bits = 0;
info->alpha_exponent_bits = 0;
@@ -2136,7 +2139,8 @@ JxlDecoderStatus JxlDecoderGetBasicInfo(const JxlDecoder* dec,
info->animation.tps_denominator =
dec->metadata.m.animation.tps_denominator;
info->animation.num_loops = dec->metadata.m.animation.num_loops;
- info->animation.have_timecodes = dec->metadata.m.animation.have_timecodes;
+ info->animation.have_timecodes =
+ TO_JXL_BOOL(dec->metadata.m.animation.have_timecodes);
}
if (meta.have_intrinsic_size) {
@@ -2170,7 +2174,7 @@ JxlDecoderStatus JxlDecoderGetExtraChannelInfo(const JxlDecoder* dec,
: 0;
info->dim_shift = channel.dim_shift;
info->name_length = channel.name.size();
- info->alpha_premultiplied = channel.alpha_associated;
+ info->alpha_premultiplied = TO_JXL_BOOL(channel.alpha_associated);
info->spot_color[0] = channel.spot_color[0];
info->spot_color[1] = channel.spot_color[1];
info->spot_color[2] = channel.spot_color[2];
@@ -2348,29 +2352,41 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetCms(JxlDecoder* dec,
return JXL_DEC_SUCCESS;
}
-JXL_EXPORT JxlDecoderStatus JxlDecoderPreviewOutBufferSize(
- const JxlDecoder* dec, const JxlPixelFormat* format, size_t* size) {
+static JxlDecoderStatus GetMinSize(const JxlDecoder* dec,
+ const JxlPixelFormat* format,
+ size_t num_channels, size_t* min_size,
+ bool preview) {
size_t bits;
JxlDecoderStatus status = PrepareSizeCheck(dec, format, &bits);
if (status != JXL_DEC_SUCCESS) return status;
- if (format->num_channels < 3 &&
- !dec->image_metadata.color_encoding.IsGray()) {
- return JXL_API_ERROR("Number of channels is too low for color output");
+ size_t xsize;
+ size_t ysize;
+ if (preview) {
+ xsize = dec->metadata.oriented_preview_xsize(dec->keep_orientation);
+ ysize = dec->metadata.oriented_preview_ysize(dec->keep_orientation);
+ } else {
+ GetCurrentDimensions(dec, xsize, ysize);
}
-
- size_t xsize = dec->metadata.oriented_preview_xsize(dec->keep_orientation);
- size_t ysize = dec->metadata.oriented_preview_ysize(dec->keep_orientation);
-
+ if (num_channels == 0) num_channels = format->num_channels;
size_t row_size =
- jxl::DivCeil(xsize * format->num_channels * bits, jxl::kBitsPerByte);
+ jxl::DivCeil(xsize * num_channels * bits, jxl::kBitsPerByte);
size_t last_row_size = row_size;
if (format->align > 1) {
row_size = jxl::DivCeil(row_size, format->align) * format->align;
}
- *size = row_size * (ysize - 1) + last_row_size;
+ *min_size = row_size * (ysize - 1) + last_row_size;
return JXL_DEC_SUCCESS;
}
+JXL_EXPORT JxlDecoderStatus JxlDecoderPreviewOutBufferSize(
+ const JxlDecoder* dec, const JxlPixelFormat* format, size_t* size) {
+ if (format->num_channels < 3 &&
+ !dec->image_metadata.color_encoding.IsGray()) {
+ return JXL_API_ERROR("Number of channels is too low for color output");
+ }
+ return GetMinSize(dec, format, 0, size, true);
+}
+
JXL_EXPORT JxlDecoderStatus JxlDecoderSetPreviewOutBuffer(
JxlDecoder* dec, const JxlPixelFormat* format, void* buffer, size_t size) {
if (!dec->got_basic_info || !dec->metadata.m.have_preview ||
@@ -2401,23 +2417,12 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetPreviewOutBuffer(
JXL_EXPORT JxlDecoderStatus JxlDecoderImageOutBufferSize(
const JxlDecoder* dec, const JxlPixelFormat* format, size_t* size) {
- size_t bits;
- JxlDecoderStatus status = PrepareSizeCheck(dec, format, &bits);
- if (status != JXL_DEC_SUCCESS) return status;
if (format->num_channels < 3 &&
!dec->image_metadata.color_encoding.IsGray()) {
return JXL_API_ERROR("Number of channels is too low for color output");
}
- size_t xsize, ysize;
- GetCurrentDimensions(dec, xsize, ysize);
- size_t row_size =
- jxl::DivCeil(xsize * format->num_channels * bits, jxl::kBitsPerByte);
- if (format->align > 1) {
- row_size = jxl::DivCeil(row_size, format->align) * format->align;
- }
- *size = row_size * ysize;
- return JXL_DEC_SUCCESS;
+ return GetMinSize(dec, format, 0, size, false);
}
JxlDecoderStatus JxlDecoderSetImageOutBuffer(JxlDecoder* dec,
@@ -2463,22 +2468,7 @@ JxlDecoderStatus JxlDecoderExtraChannelBufferSize(const JxlDecoder* dec,
return JXL_API_ERROR("Invalid extra channel index");
}
- size_t num_channels = 1; // Do not use format's num_channels
-
- size_t bits;
- JxlDecoderStatus status = PrepareSizeCheck(dec, format, &bits);
- if (status != JXL_DEC_SUCCESS) return status;
-
- size_t xsize, ysize;
- GetCurrentDimensions(dec, xsize, ysize);
- size_t row_size =
- jxl::DivCeil(xsize * num_channels * bits, jxl::kBitsPerByte);
- if (format->align > 1) {
- row_size = jxl::DivCeil(row_size, format->align) * format->align;
- }
- *size = row_size * ysize;
-
- return JXL_DEC_SUCCESS;
+ return GetMinSize(dec, format, 1, size, false);
}
JxlDecoderStatus JxlDecoderSetExtraChannelBuffer(JxlDecoder* dec,
@@ -2577,8 +2567,9 @@ JxlDecoderStatus JxlDecoderGetFrameHeader(const JxlDecoder* dec,
}
}
header->name_length = dec->frame_header->name.size();
- header->is_last = dec->frame_header->is_last;
- size_t xsize, ysize;
+ header->is_last = TO_JXL_BOOL(dec->frame_header->is_last);
+ size_t xsize;
+ size_t ysize;
GetCurrentDimensions(dec, xsize, ysize);
header->layer_info.xsize = xsize;
header->layer_info.ysize = ysize;
@@ -2620,7 +2611,7 @@ JxlDecoderStatus JxlDecoderGetFrameHeader(const JxlDecoder* dec,
header->layer_info.blend_info.alpha =
dec->frame_header->blending_info.alpha_channel;
header->layer_info.blend_info.clamp =
- dec->frame_header->blending_info.clamp;
+ TO_JXL_BOOL(dec->frame_header->blending_info.clamp);
header->layer_info.save_as_reference = dec->frame_header->save_as_reference;
}
return JXL_DEC_SUCCESS;
@@ -2643,7 +2634,7 @@ JxlDecoderStatus JxlDecoderGetExtraChannelBlendInfo(const JxlDecoder* dec,
blend_info->alpha =
dec->frame_header->extra_channel_blending_info[index].alpha_channel;
blend_info->clamp =
- dec->frame_header->extra_channel_blending_info[index].clamp;
+ TO_JXL_BOOL(dec->frame_header->extra_channel_blending_info[index].clamp);
return JXL_DEC_SUCCESS;
}
@@ -2717,7 +2708,7 @@ JxlDecoderStatus JxlDecoderSetOutputColorProfile(
"setting output color profile from icc_data not yet implemented.");
}
JXL_API_RETURN_IF_ERROR(
- (int)output_encoding.MaybeSetColorEncoding(std::move(c_dst)));
+ static_cast<int>(output_encoding.MaybeSetColorEncoding(c_dst)));
return JXL_DEC_SUCCESS;
}
@@ -2769,7 +2760,7 @@ JxlDecoderStatus JxlDecoderSetDecompressBoxes(JxlDecoder* dec,
JXL_BOOL decompress) {
// TODO(lode): return error if libbrotli is not compiled in the jxl decoding
// library
- dec->decompress_boxes = decompress;
+ dec->decompress_boxes = FROM_JXL_BOOL(decompress);
return JXL_DEC_SUCCESS;
}
@@ -2798,6 +2789,17 @@ JxlDecoderStatus JxlDecoderGetBoxSizeRaw(const JxlDecoder* dec,
return JXL_DEC_SUCCESS;
}
+JxlDecoderStatus JxlDecoderGetBoxSizeContents(const JxlDecoder* dec,
+ uint64_t* size) {
+ if (!dec->box_event) {
+ return JXL_API_ERROR("can only get box info after JXL_DEC_BOX event");
+ }
+ if (size) {
+ *size = dec->box_contents_size;
+ }
+ return JXL_DEC_SUCCESS;
+}
+
JxlDecoderStatus JxlDecoderSetProgressiveDetail(JxlDecoder* dec,
JxlProgressiveDetail detail) {
if (detail != kDC && detail != kLastPasses && detail != kPasses) {
diff --git a/third_party/jpeg-xl/lib/jxl/decode_test.cc b/third_party/jpeg-xl/lib/jxl/decode_test.cc
index caee6dbc56..33176cfd66 100644
--- a/third_party/jpeg-xl/lib/jxl/decode_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/decode_test.cc
@@ -47,7 +47,6 @@
#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/dec_external_image.h"
#include "lib/jxl/enc_aux_out.h"
-#include "lib/jxl/enc_butteraugli_comparator.h"
#include "lib/jxl/enc_external_image.h"
#include "lib/jxl/enc_fields.h"
#include "lib/jxl/enc_frame.h"
@@ -113,23 +112,23 @@ enum CodeStreamBoxFormat {
};
// Unknown boxes for testing
-static const char* unk1_box_type = "unk1";
-static const char* unk1_box_contents = "abcdefghijklmnopqrstuvwxyz";
-static const size_t unk1_box_size = strlen(unk1_box_contents);
-static const char* unk2_box_type = "unk2";
-static const char* unk2_box_contents = "0123456789";
-static const size_t unk2_box_size = strlen(unk2_box_contents);
-static const char* unk3_box_type = "unk3";
-static const char* unk3_box_contents = "ABCDEF123456";
-static const size_t unk3_box_size = strlen(unk3_box_contents);
+const char* unk1_box_type = "unk1";
+const char* unk1_box_contents = "abcdefghijklmnopqrstuvwxyz";
+const size_t unk1_box_size = strlen(unk1_box_contents);
+const char* unk2_box_type = "unk2";
+const char* unk2_box_contents = "0123456789";
+const size_t unk2_box_size = strlen(unk2_box_contents);
+const char* unk3_box_type = "unk3";
+const char* unk3_box_contents = "ABCDEF123456";
+const size_t unk3_box_size = strlen(unk3_box_contents);
// Box with brob-compressed exif, including header
-static const uint8_t* box_brob_exif = reinterpret_cast<const uint8_t*>(
+const uint8_t* box_brob_exif = reinterpret_cast<const uint8_t*>(
"\0\0\0@brobExif\241\350\2\300\177\244v\2525\304\360\27=?\267{"
"\33\37\314\332\214QX17PT\"\256\0\0\202s\214\313t\333\310\320k\20\276\30"
"\204\277l$\326c#\1\b");
size_t box_brob_exif_size = 64;
// The uncompressed Exif data from the brob box
-static const uint8_t* exif_uncompressed = reinterpret_cast<const uint8_t*>(
+const uint8_t* exif_uncompressed = reinterpret_cast<const uint8_t*>(
"\0\0\0\0MM\0*"
"\0\0\0\b\0\5\1\22\0\3\0\0\0\1\0\5\0\0\1\32\0\5\0\0\0\1\0\0\0J\1\33\0\5\0\0"
"\0\1\0\0\0R\1("
@@ -193,7 +192,7 @@ void AppendTestBox(const char* type, const char* contents, size_t contents_size,
bytes->push_back(type[2]);
bytes->push_back(type[3]);
const uint8_t* contents_u = reinterpret_cast<const uint8_t*>(contents);
- Bytes(contents_u, contents_size).AppendTo(bytes);
+ Bytes(contents_u, contents_size).AppendTo(*bytes);
}
enum PreviewMode {
@@ -214,13 +213,15 @@ void GeneratePreview(PreviewMode preview_mode, ImageBundle* ib) {
}
}
};
- Image3F preview(ib->xsize() * 7, ib->ysize() * 7);
+ JXL_ASSIGN_OR_DIE(Image3F preview,
+ Image3F::Create(ib->xsize() * 7, ib->ysize() * 7));
for (size_t c = 0; c < 3; ++c) {
upsample7(ib->color()->Plane(c), &preview.Plane(c));
}
std::vector<ImageF> extra_channels;
for (size_t i = 0; i < ib->extra_channels().size(); ++i) {
- ImageF ec(ib->xsize() * 7, ib->ysize() * 7);
+ JXL_ASSIGN_OR_DIE(ImageF ec,
+ ImageF::Create(ib->xsize() * 7, ib->ysize() * 7));
upsample7(ib->extra_channels()[i], &ec);
extra_channels.emplace_back(std::move(ec));
}
@@ -258,7 +259,8 @@ std::vector<uint8_t> CreateTestJXLCodestream(
const TestCodestreamParams& params) {
// Compress the pixels with JPEG XL.
bool grayscale = (num_channels <= 2);
- bool include_alpha = !(num_channels & 1) && params.jpeg_codestream == nullptr;
+ bool have_alpha = ((num_channels & 1) == 0);
+ bool include_alpha = have_alpha && params.jpeg_codestream == nullptr;
size_t bitdepth = params.jpeg_codestream == nullptr ? 16 : 8;
CodecInOut io;
io.SetSize(xsize, ysize);
@@ -296,7 +298,8 @@ std::vector<uint8_t> CreateTestJXLCodestream(
if (jxl::extras::CanDecode(jxl::extras::Codec::kJPG)) {
std::vector<uint8_t> jpeg_bytes;
extras::PackedPixelFile ppf;
- extras::PackedFrame frame(xsize, ysize, format);
+ JXL_ASSIGN_OR_DIE(extras::PackedFrame frame,
+ extras::PackedFrame::Create(xsize, ysize, format));
JXL_ASSERT(frame.color.pixels_size == pixels.size());
memcpy(frame.color.pixels(0, 0, 0), pixels.data(), pixels.size());
ppf.frames.emplace_back(std::move(frame));
@@ -307,9 +310,9 @@ std::vector<uint8_t> CreateTestJXLCodestream(
auto encoder = extras::GetJPEGEncoder();
encoder->SetOption("quality", "70");
extras::EncodedImage encoded;
- EXPECT_TRUE(encoder->Encode(ppf, &encoded));
+ EXPECT_TRUE(encoder->Encode(ppf, &encoded, nullptr));
jpeg_bytes = encoded.bitstreams[0];
- Bytes(jpeg_bytes).AppendTo(params.jpeg_codestream);
+ Bytes(jpeg_bytes).AppendTo(*params.jpeg_codestream);
EXPECT_TRUE(jxl::jpeg::DecodeImageJPG(
jxl::Bytes(jpeg_bytes.data(), jpeg_bytes.size()), &io));
EXPECT_TRUE(
@@ -321,7 +324,7 @@ std::vector<uint8_t> CreateTestJXLCodestream(
}
}
if (params.preview_mode) {
- io.preview_frame = io.Main().Copy();
+ JXL_ASSIGN_OR_DIE(io.preview_frame, io.Main().Copy());
GeneratePreview(params.preview_mode, &io.preview_frame);
io.metadata.m.have_preview = true;
EXPECT_TRUE(io.metadata.m.preview_size.Set(io.preview_frame.xsize(),
@@ -358,11 +361,11 @@ std::vector<uint8_t> CreateTestJXLCodestream(
compressed.data() + compressed.size());
std::vector<uint8_t> c;
- Bytes(header).AppendTo(&c);
+ Bytes(header).AppendTo(c);
if (params.jpeg_codestream != nullptr) {
jxl::AppendBoxHeader(jxl::MakeBoxType("jbrd"), jpeg_data.size(), false,
&c);
- Bytes(jpeg_data).AppendTo(&c);
+ Bytes(jpeg_data).AppendTo(c);
}
uint32_t jxlp_index = 0;
if (add_container == kCSBF_Multi_First_Empty) {
@@ -381,7 +384,7 @@ std::vector<uint8_t> CreateTestJXLCodestream(
c.push_back('l');
c.push_back('p');
AppendU32BE(jxlp_index++, &c);
- Bytes(compressed0).AppendTo(&c);
+ Bytes(compressed0).AppendTo(c);
// A few non-codestream boxes in between
AppendTestBox(unk1_box_type, unk1_box_contents, unk1_box_size, false, &c);
AppendTestBox(unk2_box_type, unk2_box_contents, unk2_box_size, false, &c);
@@ -399,7 +402,7 @@ std::vector<uint8_t> CreateTestJXLCodestream(
c.push_back('l');
c.push_back('p');
AppendU32BE(jxlp_index++, &c);
- Bytes(compressed1).AppendTo(&c);
+ Bytes(compressed1).AppendTo(c);
// Third (last) codestream part
AppendU32BE(add_container == kCSBF_Multi_Zero_Terminated
? 0
@@ -414,7 +417,7 @@ std::vector<uint8_t> CreateTestJXLCodestream(
} else {
AppendU32BE(jxlp_index++, &c);
}
- Bytes(compressed2).AppendTo(&c);
+ Bytes(compressed2).AppendTo(c);
if (add_container == kCSBF_Multi_Last_Empty_Other) {
// Empty placeholder codestream part
AppendU32BE(12, &c);
@@ -437,14 +440,14 @@ std::vector<uint8_t> CreateTestJXLCodestream(
compressed.swap(c);
} else {
std::vector<uint8_t> c;
- Bytes(header).AppendTo(&c);
+ Bytes(header).AppendTo(c);
if (params.jpeg_codestream != nullptr) {
jxl::AppendBoxHeader(jxl::MakeBoxType("jbrd"), jpeg_data.size(), false,
&c);
- Bytes(jpeg_data).AppendTo(&c);
+ Bytes(jpeg_data).AppendTo(c);
}
if (add_container == kCSBF_Brob_Exif) {
- Bytes(box_brob_exif, box_brob_exif_size).AppendTo(&c);
+ Bytes(box_brob_exif, box_brob_exif_size).AppendTo(c);
}
AppendU32BE(add_container == kCSBF_Single_Zero_Terminated
? 0
@@ -454,7 +457,7 @@ std::vector<uint8_t> CreateTestJXLCodestream(
c.push_back('x');
c.push_back('l');
c.push_back('c');
- Bytes(compressed).AppendTo(&c);
+ Bytes(compressed).AppendTo(c);
if (add_container == kCSBF_Single_Other) {
AppendTestBox(unk1_box_type, unk1_box_contents, unk1_box_size, false,
&c);
@@ -609,7 +612,7 @@ std::vector<uint8_t> DecodeWithAPI(Span<const uint8_t> compressed,
bool use_callback, bool set_buffer_early,
bool use_resizable_runner,
bool require_boxes, bool expect_success) {
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
std::vector<uint8_t> pixels =
DecodeWithAPI(dec, compressed, format, use_callback, set_buffer_early,
use_resizable_runner, require_boxes, expect_success);
@@ -622,6 +625,11 @@ std::vector<uint8_t> DecodeWithAPI(Span<const uint8_t> compressed,
////////////////////////////////////////////////////////////////////////////////
+using jxl::Image3F;
+using jxl::ImageF;
+using jxl::test::BoolToCStr;
+using jxl::test::ButteraugliDistance;
+
TEST(DecodeTest, JxlSignatureCheckTest) {
std::vector<std::pair<int, std::vector<uint8_t>>> tests = {
// No JPEGXL header starts with 'a'.
@@ -728,22 +736,22 @@ std::vector<uint8_t> GetTestHeader(size_t xsize, size_t ysize,
const std::vector<uint8_t> codestream_box_header = {0, 0, 0, 0xff,
'j', 'x', 'l', 'c'};
- for (size_t i = 0; i < signature_box.size(); i++) {
- writer.Write(8, signature_box[i]);
+ for (uint8_t c : signature_box) {
+ writer.Write(8, c);
}
- for (size_t i = 0; i < filetype_box.size(); i++) {
- writer.Write(8, filetype_box[i]);
+ for (uint8_t c : filetype_box) {
+ writer.Write(8, c);
}
if (insert_extra_box) {
- for (size_t i = 0; i < extra_box_header.size(); i++) {
- writer.Write(8, extra_box_header[i]);
+ for (uint8_t c : extra_box_header) {
+ writer.Write(8, c);
}
for (size_t i = 0; i < 255 - 8; i++) {
writer.Write(8, 0);
}
}
- for (size_t i = 0; i < codestream_box_header.size(); i++) {
- writer.Write(8, codestream_box_header[i]);
+ for (uint8_t c : codestream_box_header) {
+ writer.Write(8, c);
}
}
@@ -794,7 +802,7 @@ TEST(DecodeTest, BasicInfoTest) {
size_t bits_per_sample[2] = {8, 23};
size_t orientation[2] = {3, 5};
size_t alpha_bits[2] = {0, 8};
- JXL_BOOL have_container[2] = {0, 1};
+ bool have_container[2] = {false, true};
bool xyb_encoded = false;
std::vector<std::vector<uint8_t>> test_samples;
@@ -823,14 +831,15 @@ TEST(DecodeTest, BasicInfoTest) {
JxlDecoderStatus status = JxlDecoderProcessInput(dec);
JxlBasicInfo info;
- bool have_basic_info = !JxlDecoderGetBasicInfo(dec, &info);
+ JxlDecoderStatus bi_status = JxlDecoderGetBasicInfo(dec, &info);
+ bool have_basic_info = (bi_status == JXL_DEC_SUCCESS);
if (size == data.size()) {
EXPECT_EQ(JXL_DEC_BASIC_INFO, status);
// All header bytes given so the decoder must have the basic info.
EXPECT_EQ(true, have_basic_info);
- EXPECT_EQ(have_container[i], info.have_container);
+ EXPECT_EQ(have_container[i], FROM_JXL_BOOL(info.have_container));
EXPECT_EQ(alpha_bits[i], info.alpha_bits);
// Orientations 5..8 swap the dimensions
if (orientation[i] >= 5) {
@@ -1291,7 +1300,7 @@ class DecodeTestParam : public ::testing::TestWithParam<PixelTestConfig> {};
TEST_P(DecodeTestParam, PixelTest) {
PixelTestConfig config = GetParam();
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
if (config.keep_orientation) {
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetKeepOrientation(dec, JXL_TRUE));
@@ -1352,7 +1361,7 @@ TEST_P(DecodeTestParam, PixelTest) {
color_encoding, 16, format_orig, nullptr,
&io.Main()));
- for (size_t i = 0; i < pixels.size(); i++) pixels[i] = 0;
+ for (uint8_t& pixel : pixels) pixel = 0;
EXPECT_TRUE(ConvertToExternal(
io.Main(), 16,
/*float_out=*/false, orig_channels, JXL_BIG_ENDIAN,
@@ -1420,7 +1429,7 @@ std::vector<PixelTestConfig> GeneratePixelTests() {
c.add_intrinsic_size = intrinsic_size;
c.xsize = xsize;
c.ysize = ysize;
- c.add_container = (CodeStreamBoxFormat)box;
+ c.add_container = box;
c.output_channels = ch.output_channels;
c.data_type = format.data_type;
c.endianness = format.endianness;
@@ -1435,7 +1444,7 @@ std::vector<PixelTestConfig> GeneratePixelTests() {
// Test output formats and methods.
for (ChannelInfo ch : ch_info) {
- for (int use_callback = 0; use_callback <= 1; use_callback++) {
+ for (bool use_callback : {false, true}) {
for (size_t upsampling : {1, 2, 4, 8}) {
for (OutputFormat fmt : out_formats) {
make_test(ch, 301, 33, jxl::kNoPreview,
@@ -1451,8 +1460,8 @@ std::vector<PixelTestConfig> GeneratePixelTests() {
// Test codestream formats.
for (size_t box = 1; box < kCSBF_NUM_ENTRIES; ++box) {
make_test(ch_info[0], 77, 33, jxl::kNoPreview,
- /*add_intrinsic_size=*/false, (CodeStreamBoxFormat)box,
- JXL_ORIENT_IDENTITY,
+ /*add_intrinsic_size=*/false,
+ static_cast<CodeStreamBoxFormat>(box), JXL_ORIENT_IDENTITY,
/*keep_orientation=*/false, out_formats[0],
/*use_callback=*/false,
/*set_buffer_early=*/false, /*resizable_runner=*/false, 1);
@@ -1460,7 +1469,7 @@ std::vector<PixelTestConfig> GeneratePixelTests() {
// Test previews.
for (int preview_mode = 0; preview_mode < jxl::kNumPreviewModes;
preview_mode++) {
- make_test(ch_info[0], 77, 33, (jxl::PreviewMode)preview_mode,
+ make_test(ch_info[0], 77, 33, static_cast<jxl::PreviewMode>(preview_mode),
/*add_intrinsic_size=*/false, CodeStreamBoxFormat::kCSBF_None,
JXL_ORIENT_IDENTITY,
/*keep_orientation=*/false, out_formats[0],
@@ -1468,8 +1477,7 @@ std::vector<PixelTestConfig> GeneratePixelTests() {
/*resizable_runner=*/false, 1);
}
// Test intrinsic sizes.
- for (int add_intrinsic_size = 0; add_intrinsic_size <= 1;
- add_intrinsic_size++) {
+ for (bool add_intrinsic_size : {false, true}) {
make_test(ch_info[0], 55, 34, jxl::kNoPreview, add_intrinsic_size,
CodeStreamBoxFormat::kCSBF_None, JXL_ORIENT_IDENTITY,
/*keep_orientation=*/false, out_formats[0],
@@ -1496,8 +1504,8 @@ std::vector<PixelTestConfig> GeneratePixelTests() {
// Test orientations.
for (int orientation = 2; orientation <= 8; ++orientation) {
- for (int keep_orientation = 0; keep_orientation <= 1; keep_orientation++) {
- for (int use_callback = 0; use_callback <= 1; use_callback++) {
+ for (bool keep_orientation : {false, true}) {
+ for (bool use_callback : {false, true}) {
for (ChannelInfo ch : ch_info) {
for (OutputFormat fmt : out_formats) {
make_test(ch, 280, 12, jxl::kNoPreview,
@@ -1549,7 +1557,7 @@ std::ostream& operator<<(std::ostream& os, const PixelTestConfig& c) {
}
if (c.add_container != CodeStreamBoxFormat::kCSBF_None) {
os << "Box";
- os << (size_t)c.add_container;
+ os << static_cast<size_t>(c.add_container);
}
if (c.preview_mode == jxl::kSmallPreview) os << "Preview";
if (c.preview_mode == jxl::kBigPreview) os << "BigPreview";
@@ -1575,9 +1583,10 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P(DecodeTest, DecodeTestParam,
PixelTestDescription);
TEST(DecodeTest, PixelTestWithICCProfileLossless) {
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
size_t num_pixels = xsize * ysize;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0);
JxlPixelFormat format_orig = {4, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
@@ -1642,9 +1651,10 @@ TEST(DecodeTest, PixelTestWithICCProfileLossless) {
}
TEST(DecodeTest, PixelTestWithICCProfileLossy) {
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
size_t num_pixels = xsize * ysize;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
JxlPixelFormat format_orig = {3, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
@@ -1678,7 +1688,7 @@ TEST(DecodeTest, PixelTestWithICCProfileLossy) {
jxl::ColorEncoding color_encoding1;
jxl::IccBytes icc;
- jxl::Bytes(icc_data).AppendTo(&icc);
+ jxl::Bytes(icc_data).AppendTo(icc);
EXPECT_TRUE(color_encoding1.SetICC(std::move(icc), JxlGetDefaultCms()));
jxl::Span<const uint8_t> span1(pixels2.data(), pixels2.size());
jxl::CodecInOut io1;
@@ -1688,10 +1698,10 @@ TEST(DecodeTest, PixelTestWithICCProfileLossy) {
/*pool=*/nullptr, &io1.Main()));
jxl::ButteraugliParams ba;
- EXPECT_THAT(
+ EXPECT_SLIGHTLY_BELOW(
ButteraugliDistance(io0.frames, io1.frames, ba, *JxlGetDefaultCms(),
/*distmap=*/nullptr, nullptr),
- IsSlightlyBelow(0.56f));
+ 0.56f);
JxlDecoderDestroy(dec);
}
@@ -1753,7 +1763,8 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P(
DecodeAllEncodingsTestInstantiation, DecodeAllEncodingsTest,
::testing::ValuesIn(jxl::test::AllEncodings()));
TEST_P(DecodeAllEncodingsTest, PreserveOriginalProfileTest) {
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
JxlPixelFormat format = {3, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
int events = JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING | JXL_DEC_FULL_IMAGE;
@@ -1796,7 +1807,8 @@ namespace {
void SetPreferredColorProfileTest(
const jxl::test::ColorEncodingDescriptor& from, bool icc_dst,
bool use_cms) {
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
int events = JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING | JXL_DEC_FULL_IMAGE;
jxl::ColorEncoding c_in = jxl::test::ColorEncodingFromDescriptor(from);
if (c_in.GetRenderingIntent() != jxl::RenderingIntent::kRelative) return;
@@ -1970,6 +1982,7 @@ void DecodeImageWithColorEncoding(const std::vector<uint8_t>& compressed,
EXPECT_EQ(JXL_DEC_BASIC_INFO, JxlDecoderProcessInput(dec));
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBasicInfo(dec, &info));
EXPECT_EQ(JXL_DEC_COLOR_ENCODING, JxlDecoderProcessInput(dec));
+ // TODO(eustas): why unused?
std::string color_space_in = GetOrigProfile(dec);
if (with_cms) {
JxlDecoderSetCms(dec, *JxlGetDefaultCms());
@@ -2009,7 +2022,8 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P(
TEST_P(DecodeAllEncodingsWithCMSTest, DecodeWithCMS) {
auto all_encodings = jxl::test::AllEncodings();
uint32_t num_channels = 3;
- size_t xsize = 177, ysize = 123;
+ size_t xsize = 177;
+ size_t ysize = 123;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, num_channels, 0);
jxl::TestCodestreamParams params;
@@ -2045,9 +2059,10 @@ TEST_P(DecodeAllEncodingsWithCMSTest, DecodeWithCMS) {
// and to RGBA8
TEST(DecodeTest, PixelTestOpaqueSrgbLossy) {
for (unsigned channels = 3; channels <= 4; channels++) {
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
size_t num_pixels = xsize * ysize;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
@@ -2082,10 +2097,10 @@ TEST(DecodeTest, PixelTestOpaqueSrgbLossy) {
/*pool=*/nullptr, &io1.Main()));
jxl::ButteraugliParams ba;
- EXPECT_THAT(
+ EXPECT_SLIGHTLY_BELOW(
ButteraugliDistance(io0.frames, io1.frames, ba, *JxlGetDefaultCms(),
/*distmap=*/nullptr, nullptr),
- IsSlightlyBelow(0.65f));
+ 0.65f);
JxlDecoderDestroy(dec);
}
@@ -2094,9 +2109,10 @@ TEST(DecodeTest, PixelTestOpaqueSrgbLossy) {
// Opaque image with noise enabled, decoded to RGB8 and RGBA8.
TEST(DecodeTest, PixelTestOpaqueSrgbLossyNoise) {
for (unsigned channels = 3; channels <= 4; channels++) {
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
- size_t xsize = 512, ysize = 300;
+ size_t xsize = 512;
+ size_t ysize = 300;
size_t num_pixels = xsize * ysize;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
@@ -2132,26 +2148,28 @@ TEST(DecodeTest, PixelTestOpaqueSrgbLossyNoise) {
/*pool=*/nullptr, &io1.Main()));
jxl::ButteraugliParams ba;
- EXPECT_THAT(
+ EXPECT_SLIGHTLY_BELOW(
ButteraugliDistance(io0.frames, io1.frames, ba, *JxlGetDefaultCms(),
/*distmap=*/nullptr, nullptr),
- IsSlightlyBelow(1.3f));
+ 1.3f);
JxlDecoderDestroy(dec);
}
}
TEST(DecodeTest, ProcessEmptyInputWithBoxes) {
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
jxl::CompressParams cparams;
uint32_t channels = 3;
JxlPixelFormat format = {channels, JXL_TYPE_FLOAT, JXL_LITTLE_ENDIAN, 0};
for (int i = 0; i < kCSBF_NUM_ENTRIES; ++i) {
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
jxl::TestCodestreamParams params;
- params.box_format = (CodeStreamBoxFormat)i;
- printf("Testing empty input with box format %d\n", (int)params.box_format);
+ params.box_format = static_cast<CodeStreamBoxFormat>(i);
+ printf("Testing empty input with box format %d\n",
+ static_cast<int>(params.box_format));
std::vector<uint8_t> compressed = jxl::CreateTestJXLCodestream(
jxl::Bytes(pixels.data(), pixels.size()), xsize, ysize, 3, params);
const int events =
@@ -2175,14 +2193,15 @@ TEST(DecodeTest, ProcessEmptyInputWithBoxes) {
}
TEST(DecodeTest, ExtraBytesAfterCompressedStream) {
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
size_t num_pixels = xsize * ysize;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
jxl::CompressParams cparams;
for (int i = 0; i < kCSBF_NUM_ENTRIES; ++i) {
- CodeStreamBoxFormat box_format = (CodeStreamBoxFormat)i;
+ CodeStreamBoxFormat box_format = static_cast<CodeStreamBoxFormat>(i);
if (box_format == kCSBF_Multi_Other_Zero_Terminated) continue;
- printf("Testing with box format %d\n", (int)box_format);
+ printf("Testing with box format %d\n", static_cast<int>(box_format));
size_t last_unknown_box_size = 0;
if (box_format == kCSBF_Single_Other) {
last_unknown_box_size = unk1_box_size + 8;
@@ -2201,7 +2220,7 @@ TEST(DecodeTest, ExtraBytesAfterCompressedStream) {
compressed.push_back(0);
compressed.push_back(1);
compressed.push_back(2);
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
uint32_t channels = 3;
JxlPixelFormat format = {channels, JXL_TYPE_FLOAT, JXL_LITTLE_ENDIAN, 0};
std::vector<uint8_t> pixels2 = jxl::DecodeWithAPI(
@@ -2217,14 +2236,15 @@ TEST(DecodeTest, ExtraBytesAfterCompressedStream) {
}
TEST(DecodeTest, ExtraBytesAfterCompressedStreamRequireBoxes) {
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
size_t num_pixels = xsize * ysize;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
jxl::CompressParams cparams;
for (int i = 0; i < kCSBF_NUM_ENTRIES; ++i) {
- CodeStreamBoxFormat box_format = (CodeStreamBoxFormat)i;
+ CodeStreamBoxFormat box_format = static_cast<CodeStreamBoxFormat>(i);
if (box_format == kCSBF_Multi_Other_Zero_Terminated) continue;
- printf("Testing with box format %d\n", (int)box_format);
+ printf("Testing with box format %d\n", static_cast<int>(box_format));
bool expect_success = (box_format == kCSBF_None ||
box_format == kCSBF_Single_Zero_Terminated ||
box_format == kCSBF_Multi_Zero_Terminated);
@@ -2236,7 +2256,7 @@ TEST(DecodeTest, ExtraBytesAfterCompressedStreamRequireBoxes) {
compressed.push_back(0);
compressed.push_back(1);
compressed.push_back(2);
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
uint32_t channels = 3;
JxlPixelFormat format = {channels, JXL_TYPE_FLOAT, JXL_LITTLE_ENDIAN, 0};
std::vector<uint8_t> pixels2 = jxl::DecodeWithAPI(
@@ -2251,35 +2271,38 @@ TEST(DecodeTest, ExtraBytesAfterCompressedStreamRequireBoxes) {
}
TEST(DecodeTest, ConcatenatedCompressedStreams) {
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
size_t num_pixels = xsize * ysize;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
jxl::CompressParams cparams;
for (int i = 0; i < kCSBF_NUM_ENTRIES; ++i) {
- CodeStreamBoxFormat first_box_format = (CodeStreamBoxFormat)i;
+ CodeStreamBoxFormat first_box_format = static_cast<CodeStreamBoxFormat>(i);
if (first_box_format == kCSBF_Multi_Other_Zero_Terminated) continue;
jxl::TestCodestreamParams params1;
params1.box_format = first_box_format;
std::vector<uint8_t> compressed1 = jxl::CreateTestJXLCodestream(
jxl::Bytes(pixels.data(), pixels.size()), xsize, ysize, 3, params1);
for (int j = 0; j < kCSBF_NUM_ENTRIES; ++j) {
- CodeStreamBoxFormat second_box_format = (CodeStreamBoxFormat)j;
+ CodeStreamBoxFormat second_box_format =
+ static_cast<CodeStreamBoxFormat>(j);
if (second_box_format == kCSBF_Multi_Other_Zero_Terminated) continue;
- printf("Testing with box format pair %d, %d\n", (int)first_box_format,
- (int)second_box_format);
+ printf("Testing with box format pair %d, %d\n",
+ static_cast<int>(first_box_format),
+ static_cast<int>(second_box_format));
jxl::TestCodestreamParams params2;
params2.box_format = second_box_format;
std::vector<uint8_t> compressed2 = jxl::CreateTestJXLCodestream(
jxl::Bytes(pixels.data(), pixels.size()), xsize, ysize, 3, params2);
std::vector<uint8_t> concat;
- jxl::Bytes(compressed1).AppendTo(&concat);
- jxl::Bytes(compressed2).AppendTo(&concat);
+ jxl::Bytes(compressed1).AppendTo(concat);
+ jxl::Bytes(compressed2).AppendTo(concat);
uint32_t channels = 3;
JxlPixelFormat format = {channels, JXL_TYPE_FLOAT, JXL_LITTLE_ENDIAN, 0};
size_t remaining = concat.size();
for (int part = 0; part < 2; ++part) {
printf(" Decoding part %d\n", part + 1);
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
size_t pos = concat.size() - remaining;
bool expect_success =
(part == 0 || second_box_format == kCSBF_None ||
@@ -2300,7 +2323,8 @@ TEST(DecodeTest, ConcatenatedCompressedStreams) {
}
void TestPartialStream(bool reconstructible_jpeg) {
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
uint32_t channels = 4;
if (reconstructible_jpeg) {
channels = 3;
@@ -2325,7 +2349,7 @@ void TestPartialStream(bool reconstructible_jpeg) {
std::vector<std::vector<uint8_t>> codestreams(kCSBF_NUM_ENTRIES);
std::vector<std::vector<uint8_t>> jpeg_codestreams(kCSBF_NUM_ENTRIES);
for (size_t i = 0; i < kCSBF_NUM_ENTRIES; ++i) {
- params.box_format = (CodeStreamBoxFormat)i;
+ params.box_format = static_cast<CodeStreamBoxFormat>(i);
if (reconstructible_jpeg) {
params.jpeg_codestream = &jpeg_codestreams[i];
}
@@ -2338,10 +2362,10 @@ void TestPartialStream(bool reconstructible_jpeg) {
// box parsing.
std::vector<size_t> increments = {1, 3, 17, 23, 120, 700, 1050};
- for (size_t index = 0; index < increments.size(); index++) {
+ for (size_t increment : increments) {
for (size_t i = 0; i < kCSBF_NUM_ENTRIES; ++i) {
- if (reconstructible_jpeg &&
- (CodeStreamBoxFormat)i == CodeStreamBoxFormat::kCSBF_None) {
+ if (reconstructible_jpeg && static_cast<CodeStreamBoxFormat>(i) ==
+ CodeStreamBoxFormat::kCSBF_None) {
continue;
}
const std::vector<uint8_t>& data = codestreams[i];
@@ -2376,7 +2400,6 @@ void TestPartialStream(bool reconstructible_jpeg) {
break;
}
- size_t increment = increments[index];
// End of the file reached, should be the final test.
if (total_size + increment > data.size()) {
increment = data.size() - total_size;
@@ -2467,7 +2490,7 @@ TEST(DecodeTest, DCNotGettableTest) {
"\363\6\22\bp\0\200\237\34\231W2d\255$\1",
68);
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
EXPECT_EQ(JXL_DEC_SUCCESS,
JxlDecoderSubscribeEvents(dec, JXL_DEC_BASIC_INFO));
@@ -2487,7 +2510,8 @@ TEST(DecodeTest, DCNotGettableTest) {
}
TEST(DecodeTest, PreviewTest) {
- size_t xsize = 77, ysize = 120;
+ size_t xsize = 77;
+ size_t ysize = 120;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
JxlPixelFormat format_orig = {3, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
for (jxl::PreviewMode mode : {jxl::kSmallPreview, jxl::kBigPreview}) {
@@ -2499,7 +2523,7 @@ TEST(DecodeTest, PreviewTest) {
JxlPixelFormat format = {3, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, 0};
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
const uint8_t* next_in = compressed.data();
size_t avail_in = compressed.size();
@@ -2561,7 +2585,8 @@ TEST(DecodeTest, PreviewTest) {
}
TEST(DecodeTest, AlignTest) {
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0);
JxlPixelFormat format_orig = {4, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
@@ -2575,22 +2600,27 @@ TEST(DecodeTest, AlignTest) {
size_t align = 17;
JxlPixelFormat format = {3, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, align};
// On purpose not using jxl::RoundUpTo to test it independently.
- size_t expected_line_bytes = (1 * 3 * xsize + align - 1) / align * align;
+ size_t expected_line_size_last = 1 * 3 * xsize;
+ size_t expected_line_size =
+ ((expected_line_size_last + align - 1) / align) * align;
+ size_t expected_pixels_size =
+ expected_line_size * (ysize - 1) + expected_line_size_last;
- for (int use_callback = 0; use_callback <= 1; ++use_callback) {
+ for (bool use_callback : {false, true}) {
std::vector<uint8_t> pixels2 = jxl::DecodeWithAPI(
jxl::Bytes(compressed.data(), compressed.size()), format, use_callback,
/*set_buffer_early=*/false,
/*use_resizable_runner=*/false, /*require_boxes=*/false,
/*expect_success=*/true);
- EXPECT_EQ(expected_line_bytes * ysize, pixels2.size());
+ EXPECT_EQ(expected_pixels_size, pixels2.size());
EXPECT_EQ(0u, jxl::test::ComparePixels(pixels.data(), pixels2.data(), xsize,
ysize, format_orig, format));
}
}
TEST(DecodeTest, AnimationTest) {
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
static const size_t num_frames = 2;
std::vector<uint8_t> frames[2];
frames[0] = jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
@@ -2631,12 +2661,12 @@ TEST(DecodeTest, AnimationTest) {
// Decode and test the animation frames
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
const uint8_t* next_in = compressed.data();
size_t avail_in = compressed.size();
void* runner = JxlThreadParallelRunnerCreate(
- NULL, JxlThreadParallelRunnerDefaultNumWorkerThreads());
+ nullptr, JxlThreadParallelRunnerDefaultNumWorkerThreads());
EXPECT_EQ(JXL_DEC_SUCCESS,
JxlDecoderSetParallelRunner(dec, JxlThreadParallelRunner, runner));
@@ -2690,7 +2720,8 @@ TEST(DecodeTest, AnimationTest) {
}
TEST(DecodeTest, AnimationTestStreaming) {
- size_t xsize = 123, ysize = 77;
+ size_t xsize = 123;
+ size_t ysize = 77;
static const size_t num_frames = 2;
std::vector<uint8_t> frames[2];
frames[0] = jxl::test::GetSomeTestImage(xsize, ysize, 3, 0);
@@ -2733,7 +2764,7 @@ TEST(DecodeTest, AnimationTestStreaming) {
const size_t step_size = 16;
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
const uint8_t* next_in = compressed.data();
size_t avail_in = 0;
size_t frame_headers_seen = 0;
@@ -2741,7 +2772,7 @@ TEST(DecodeTest, AnimationTestStreaming) {
bool seen_basic_info = false;
void* runner = JxlThreadParallelRunnerCreate(
- NULL, JxlThreadParallelRunnerDefaultNumWorkerThreads());
+ nullptr, JxlThreadParallelRunnerDefaultNumWorkerThreads());
EXPECT_EQ(JXL_DEC_SUCCESS,
JxlDecoderSetParallelRunner(dec, JxlThreadParallelRunner, runner));
@@ -2805,7 +2836,7 @@ TEST(DecodeTest, AnimationTestStreaming) {
frames_seen++;
EXPECT_EQ(frame_headers_seen, frames_seen);
} else {
- fprintf(stderr, "Unexpected status: %d\n", (int)status);
+ fprintf(stderr, "Unexpected status: %d\n", static_cast<int>(status));
FAIL();
}
}
@@ -2822,7 +2853,8 @@ TEST(DecodeTest, AnimationTestStreaming) {
}
TEST(DecodeTest, ExtraChannelTest) {
- size_t xsize = 55, ysize = 257;
+ size_t xsize = 55;
+ size_t ysize = 257;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0);
JxlPixelFormat format_orig = {4, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
@@ -2836,7 +2868,7 @@ TEST(DecodeTest, ExtraChannelTest) {
size_t align = 17;
JxlPixelFormat format = {3, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, align};
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSubscribeEvents(
dec, JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE));
@@ -2899,7 +2931,8 @@ TEST(DecodeTest, ExtraChannelTest) {
}
TEST(DecodeTest, SkipCurrentFrameTest) {
- size_t xsize = 90, ysize = 120;
+ size_t xsize = 90;
+ size_t ysize = 120;
constexpr size_t num_frames = 7;
std::vector<uint8_t> frames[num_frames];
for (size_t i = 0; i < num_frames; i++) {
@@ -2945,7 +2978,7 @@ TEST(DecodeTest, SkipCurrentFrameTest) {
cparams.custom_progressive_mode = &progressive_mode;
EXPECT_TRUE(jxl::test::EncodeFile(cparams, &io, &compressed));
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
const uint8_t* next_in = compressed.data();
size_t avail_in = compressed.size();
@@ -2964,7 +2997,7 @@ TEST(DecodeTest, SkipCurrentFrameTest) {
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBasicInfo(dec, &info));
for (size_t i = 0; i < num_frames; ++i) {
- printf("Decoding frame %d\n", (int)i);
+ printf("Decoding frame %d\n", static_cast<int>(i));
EXPECT_EQ(JXL_DEC_ERROR, JxlDecoderSkipCurrentFrame(dec));
std::vector<uint8_t> pixels(buffer_size);
EXPECT_EQ(JXL_DEC_FRAME, JxlDecoderProcessInput(dec));
@@ -3010,7 +3043,8 @@ TEST(DecodeTest, SkipCurrentFrameTest) {
}
TEST(DecodeTest, SkipFrameTest) {
- size_t xsize = 90, ysize = 120;
+ size_t xsize = 90;
+ size_t ysize = 120;
constexpr size_t num_frames = 16;
std::vector<uint8_t> frames[num_frames];
for (size_t i = 0; i < num_frames; i++) {
@@ -3056,12 +3090,12 @@ TEST(DecodeTest, SkipFrameTest) {
// Decode and test the animation frames
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
const uint8_t* next_in = compressed.data();
size_t avail_in = compressed.size();
void* runner = JxlThreadParallelRunnerCreate(
- NULL, JxlThreadParallelRunnerDefaultNumWorkerThreads());
+ nullptr, JxlThreadParallelRunnerDefaultNumWorkerThreads());
EXPECT_EQ(JXL_DEC_SUCCESS,
JxlDecoderSetParallelRunner(dec, JxlThreadParallelRunner, runner));
@@ -3146,7 +3180,8 @@ TEST(DecodeTest, SkipFrameTest) {
}
TEST(DecodeTest, SkipFrameWithBlendingTest) {
- size_t xsize = 90, ysize = 120;
+ size_t xsize = 90;
+ size_t ysize = 120;
constexpr size_t num_frames = 16;
std::vector<uint8_t> frames[num_frames];
JxlPixelFormat format = {3, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
@@ -3213,23 +3248,22 @@ TEST(DecodeTest, SkipFrameWithBlendingTest) {
// Independently decode all frames without any skipping, to create the
// expected blended frames, for the actual tests below to compare with.
{
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
const uint8_t* next_in = compressed.data();
size_t avail_in = compressed.size();
void* runner = JxlThreadParallelRunnerCreate(
- NULL, JxlThreadParallelRunnerDefaultNumWorkerThreads());
+ nullptr, JxlThreadParallelRunnerDefaultNumWorkerThreads());
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetParallelRunner(
dec, JxlThreadParallelRunner, runner));
EXPECT_EQ(JXL_DEC_SUCCESS,
JxlDecoderSubscribeEvents(dec, JXL_DEC_FULL_IMAGE));
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetInput(dec, next_in, avail_in));
- for (size_t i = 0; i < num_frames; ++i) {
+ for (auto& frame : frames) {
EXPECT_EQ(JXL_DEC_NEED_IMAGE_OUT_BUFFER, JxlDecoderProcessInput(dec));
- frames[i].resize(xsize * ysize * 6);
- EXPECT_EQ(JXL_DEC_SUCCESS,
- JxlDecoderSetImageOutBuffer(dec, &format, frames[i].data(),
- frames[i].size()));
+ frame.resize(xsize * ysize * 6);
+ EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetImageOutBuffer(
+ dec, &format, frame.data(), frame.size()));
EXPECT_EQ(JXL_DEC_FULL_IMAGE, JxlDecoderProcessInput(dec));
}
@@ -3240,12 +3274,12 @@ TEST(DecodeTest, SkipFrameWithBlendingTest) {
JxlDecoderDestroy(dec);
}
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
const uint8_t* next_in = compressed.data();
size_t avail_in = compressed.size();
void* runner = JxlThreadParallelRunnerCreate(
- NULL, JxlThreadParallelRunnerDefaultNumWorkerThreads());
+ nullptr, JxlThreadParallelRunnerDefaultNumWorkerThreads());
EXPECT_EQ(JXL_DEC_SUCCESS,
JxlDecoderSetParallelRunner(dec, JxlThreadParallelRunner, runner));
@@ -3360,7 +3394,8 @@ TEST(DecodeTest, SkipFrameWithBlendingTest) {
}
TEST(DecodeTest, SkipFrameWithAlphaBlendingTest) {
- size_t xsize = 90, ysize = 120;
+ size_t xsize = 90;
+ size_t ysize = 120;
constexpr size_t num_frames = 16;
std::vector<uint8_t> frames[num_frames + 5];
JxlPixelFormat format = {4, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
@@ -3376,7 +3411,10 @@ TEST(DecodeTest, SkipFrameWithAlphaBlendingTest) {
std::vector<uint32_t> frame_durations_c;
std::vector<uint32_t> frame_durations_nc;
- std::vector<uint32_t> frame_xsize, frame_ysize, frame_x0, frame_y0;
+ std::vector<uint32_t> frame_xsize;
+ std::vector<uint32_t> frame_ysize;
+ std::vector<uint32_t> frame_x0;
+ std::vector<uint32_t> frame_y0;
for (size_t i = 0; i < num_frames; ++i) {
size_t cropxsize = 1 + xsize * 2 / (i + 1);
@@ -3444,12 +3482,12 @@ TEST(DecodeTest, SkipFrameWithAlphaBlendingTest) {
// Independently decode all frames without any skipping, to create the
// expected blended frames, for the actual tests below to compare with.
{
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
const uint8_t* next_in = compressed.data();
size_t avail_in = compressed.size();
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetCoalescing(dec, coalescing));
void* runner = JxlThreadParallelRunnerCreate(
- NULL, JxlThreadParallelRunnerDefaultNumWorkerThreads());
+ nullptr, JxlThreadParallelRunnerDefaultNumWorkerThreads());
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetParallelRunner(
dec, JxlThreadParallelRunner, runner));
EXPECT_EQ(JXL_DEC_SUCCESS,
@@ -3479,13 +3517,13 @@ TEST(DecodeTest, SkipFrameWithAlphaBlendingTest) {
JxlDecoderDestroy(dec);
}
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
const uint8_t* next_in = compressed.data();
size_t avail_in = compressed.size();
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetCoalescing(dec, coalescing));
void* runner = JxlThreadParallelRunnerCreate(
- NULL, JxlThreadParallelRunnerDefaultNumWorkerThreads());
+ nullptr, JxlThreadParallelRunnerDefaultNumWorkerThreads());
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetParallelRunner(
dec, JxlThreadParallelRunner, runner));
@@ -3648,7 +3686,8 @@ TEST(DecodeTest, SkipFrameWithAlphaBlendingTest) {
TEST(DecodeTest, OrientedCroppedFrameTest) {
const auto test = [](bool keep_orientation, uint32_t orientation,
uint32_t resampling) {
- size_t xsize = 90, ysize = 120;
+ size_t xsize = 90;
+ size_t ysize = 120;
JxlPixelFormat format = {4, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
size_t oxsize = (!keep_orientation && orientation > 4 ? ysize : xsize);
size_t oysize = (!keep_orientation && orientation > 4 ? xsize : ysize);
@@ -3698,14 +3737,14 @@ TEST(DecodeTest, OrientedCroppedFrameTest) {
// Independently decode all frames without any skipping, to create the
// expected blended frames, for the actual tests below to compare with.
{
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
const uint8_t* next_in = compressed.data();
size_t avail_in = compressed.size();
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetCoalescing(dec, coalescing));
EXPECT_EQ(JXL_DEC_SUCCESS,
JxlDecoderSetKeepOrientation(dec, keep_orientation));
void* runner = JxlThreadParallelRunnerCreate(
- NULL, JxlThreadParallelRunnerDefaultNumWorkerThreads());
+ nullptr, JxlThreadParallelRunnerDefaultNumWorkerThreads());
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetParallelRunner(
dec, JxlThreadParallelRunner, runner));
EXPECT_EQ(JXL_DEC_SUCCESS,
@@ -3747,10 +3786,10 @@ TEST(DecodeTest, OrientedCroppedFrameTest) {
for (int y = 0; y < static_cast<int>(oysize); y++) {
if (y < y0 || y >= y0 + h) continue;
// pointers do whole 16-bit RGBA pixels at a time
- uint64_t* row_merged = static_cast<uint64_t*>(
- (void*)(frames[4].data() + y * oxsize * 8));
- uint64_t* row_layer = static_cast<uint64_t*>(
- (void*)(frames[i].data() + (y - y0) * w * 8));
+ uint64_t* row_merged = reinterpret_cast<uint64_t*>(
+ frames[4].data() + y * oxsize * 8);
+ uint64_t* row_layer = reinterpret_cast<uint64_t*>(
+ frames[i].data() + (y - y0) * w * 8);
for (int x = 0; x < static_cast<int>(oxsize); x++) {
if (x < x0 || x >= x0 + w) continue;
row_merged[x] = row_layer[x - x0];
@@ -3825,18 +3864,18 @@ void AnalyzeCodestream(const std::vector<uint8_t>& data,
codestream.insert(codestream.end(), in + pos + 8, in + pos + box_size);
codestream_end = true;
} else if (memcmp(in + pos + 4, "jxlp", 4) == 0) {
- codestream_end = (LoadBE32(in + pos + 8) & 0x80000000);
+ codestream_end = ((LoadBE32(in + pos + 8) & 0x80000000) != 0);
if (codestream.empty()) {
streampos->codestream_start = pos + 12;
} else if (box_size > 12 || !codestream_end) {
- breakpoints.push_back({codestream.size(), 12});
+ breakpoints.emplace_back(codestream.size(), 12);
}
codestream.insert(codestream.end(), in + pos + 12, in + pos + box_size);
} else if (memcmp(in + pos + 4, "jbrd", 4) == 0) {
EXPECT_TRUE(codestream.empty());
streampos->jbrd_end = pos + box_size;
} else if (!codestream.empty() && !codestream_end) {
- breakpoints.push_back({codestream.size(), box_size});
+ breakpoints.emplace_back(codestream.size(), box_size);
}
pos += box_size;
}
@@ -3931,7 +3970,7 @@ void VerifyProgression(size_t xsize, size_t ysize, uint32_t num_channels,
double prev_dist = 1.0;
for (;;) {
JxlDecoderStatus status = JxlDecoderProcessInput(dec);
- printf("bp: %d status: 0x%x\n", bp, (int)status);
+ printf("bp: %d status: 0x%x\n", bp, static_cast<int>(status));
if (status == JXL_DEC_BASIC_INFO) {
JxlBasicInfo info;
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBasicInfo(dec, &info));
@@ -3977,7 +4016,7 @@ void VerifyProgression(size_t xsize, size_t ysize, uint32_t num_channels,
avail_in = breakpoints[bp].file_pos - (next_in - data.data());
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetInput(dec, next_in, avail_in));
} else {
- printf("Unexpected status: 0x%x\n", (int)status);
+ printf("Unexpected status: 0x%x\n", static_cast<int>(status));
FAIL(); // unexpected returned status
}
}
@@ -3985,7 +4024,8 @@ void VerifyProgression(size_t xsize, size_t ysize, uint32_t num_channels,
}
TEST(DecodeTest, ProgressionTest) {
- size_t xsize = 508, ysize = 470;
+ size_t xsize = 508;
+ size_t ysize = 470;
uint32_t num_channels = 3;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, num_channels, 0);
@@ -4020,7 +4060,8 @@ TEST(DecodeTest, ProgressionTest) {
}
TEST(DecodeTest, ProgressionTestLosslessAlpha) {
- size_t xsize = 508, ysize = 470;
+ size_t xsize = 508;
+ size_t ysize = 470;
uint32_t num_channels = 4;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, num_channels, 0);
@@ -4063,7 +4104,8 @@ void VerifyFilePosition(size_t expected_pos, const std::vector<uint8_t>& data,
}
TEST(DecodeTest, InputHandlingTestOneShot) {
- size_t xsize = 508, ysize = 470;
+ size_t xsize = 508;
+ size_t ysize = 470;
uint32_t num_channels = 3;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, num_channels, 0);
@@ -4072,7 +4114,7 @@ TEST(DecodeTest, InputHandlingTestOneShot) {
jxl::TestCodestreamParams params;
params.cparams.progressive_dc = 1;
params.preview_mode = jxl::kSmallPreview;
- params.box_format = (CodeStreamBoxFormat)i;
+ params.box_format = static_cast<CodeStreamBoxFormat>(i);
std::vector<uint8_t> data =
jxl::CreateTestJXLCodestream(jxl::Bytes(pixels.data(), pixels.size()),
xsize, ysize, num_channels, params);
@@ -4167,7 +4209,7 @@ TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(InputHandlingTestJPEGOneshot)) {
params.cparams.color_transform = jxl::ColorTransform::kNone;
params.jpeg_codestream = &jpeg_codestream;
params.preview_mode = jxl::kSmallPreview;
- params.box_format = (CodeStreamBoxFormat)i;
+ params.box_format = static_cast<CodeStreamBoxFormat>(i);
std::vector<uint8_t> data =
jxl::CreateTestJXLCodestream(jxl::Bytes(pixels.data(), pixels.size()),
xsize, ysize, channels, params);
@@ -4246,7 +4288,8 @@ TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(InputHandlingTestJPEGOneshot)) {
}
TEST(DecodeTest, InputHandlingTestStreaming) {
- size_t xsize = 508, ysize = 470;
+ size_t xsize = 508;
+ size_t ysize = 470;
uint32_t num_channels = 3;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, num_channels, 0);
@@ -4255,7 +4298,7 @@ TEST(DecodeTest, InputHandlingTestStreaming) {
fflush(stdout);
jxl::TestCodestreamParams params;
params.cparams.progressive_dc = 1;
- params.box_format = (CodeStreamBoxFormat)i;
+ params.box_format = static_cast<CodeStreamBoxFormat>(i);
params.preview_mode = jxl::kSmallPreview;
std::vector<uint8_t> data =
jxl::CreateTestJXLCodestream(jxl::Bytes(pixels.data(), pixels.size()),
@@ -4334,7 +4377,7 @@ TEST(DecodeTest, InputHandlingTestStreaming) {
ASSERT_LT(box_index, streampos.box_start.size());
EXPECT_EQ(file_pos, streampos.box_start[box_index++]);
} else {
- printf("Unexpected status: 0x%x\n", (int)status);
+ printf("Unexpected status: 0x%x\n", static_cast<int>(status));
FAIL();
}
}
@@ -4346,7 +4389,8 @@ TEST(DecodeTest, InputHandlingTestStreaming) {
TEST(DecodeTest, FlushTest) {
// Size large enough for multiple groups, required to have progressive
// stages
- size_t xsize = 333, ysize = 300;
+ size_t xsize = 333;
+ size_t ysize = 300;
uint32_t num_channels = 3;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, num_channels, 0);
@@ -4421,7 +4465,8 @@ TEST(DecodeTest, FlushTest) {
TEST(DecodeTest, FlushTestImageOutCallback) {
// Size large enough for multiple groups, required to have progressive
// stages
- size_t xsize = 333, ysize = 300;
+ size_t xsize = 333;
+ size_t ysize = 300;
uint32_t num_channels = 3;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, num_channels, 0);
@@ -4507,7 +4552,8 @@ TEST(DecodeTest, FlushTestImageOutCallback) {
TEST(DecodeTest, FlushTestLossyProgressiveAlpha) {
// Size large enough for multiple groups, required to have progressive
// stages
- size_t xsize = 333, ysize = 300;
+ size_t xsize = 333;
+ size_t ysize = 300;
uint32_t num_channels = 4;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, num_channels, 0);
@@ -4577,7 +4623,8 @@ TEST(DecodeTest, FlushTestLossyProgressiveAlpha) {
JxlDecoderDestroy(dec);
}
TEST(DecodeTest, FlushTestLossyProgressiveAlphaUpsampling) {
- size_t xsize = 533, ysize = 401;
+ size_t xsize = 533;
+ size_t ysize = 401;
uint32_t num_channels = 4;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, num_channels, 0);
@@ -4651,7 +4698,8 @@ TEST(DecodeTest, FlushTestLossyProgressiveAlphaUpsampling) {
TEST(DecodeTest, FlushTestLosslessProgressiveAlpha) {
// Size large enough for multiple groups, required to have progressive
// stages
- size_t xsize = 333, ysize = 300;
+ size_t xsize = 333;
+ size_t ysize = 300;
uint32_t num_channels = 4;
std::vector<uint8_t> pixels =
jxl::test::GetSomeTestImage(xsize, ysize, num_channels, 0);
@@ -4731,17 +4779,19 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P(DecodeProgressiveTestInstantiation,
::testing::Range(0, 8));
TEST_P(DecodeProgressiveTest, ProgressiveEventTest) {
const int params = GetParam();
- int single_group = params & 1;
- int lossless = (params >> 1) & 1;
+ bool single_group = ((params & 1) != 0);
+ bool lossless = (((params >> 1) & 1) != 0);
uint32_t num_channels = 3 + ((params >> 2) & 1);
+ bool has_alpha = ((num_channels & 1) == 0);
std::set<JxlProgressiveDetail> progressive_details = {kDC, kLastPasses,
kPasses};
for (auto prog_detail : progressive_details) {
// Only few combinations are expected to support outputting
// intermediate flushes for complete DC and complete passes.
// The test can be updated if more cases are expected to support it.
- bool expect_flush = (num_channels & 1) && !lossless;
- size_t xsize, ysize;
+ bool expect_flush = !has_alpha && !lossless;
+ size_t xsize;
+ size_t ysize;
if (single_group) {
// An image smaller than 256x256 ensures it contains only 1 group.
xsize = 99;
@@ -4774,12 +4824,13 @@ TEST_P(DecodeProgressiveTest, ProgressiveEventTest) {
jxl::CreateTestJXLCodestream(jxl::Bytes(pixels.data(), pixels.size()),
xsize, ysize, num_channels, params);
- for (size_t increment : {(size_t)1, data.size()}) {
+ for (size_t increment : {static_cast<size_t>(1), data.size()}) {
printf(
- "Testing with single_group=%d, lossless=%d, "
+ "Testing with single_group=%s, lossless=%s, "
"num_channels=%d, prog_detail=%d, increment=%d\n",
- single_group, lossless, (int)num_channels, (int)prog_detail,
- (int)increment);
+ BoolToCStr(single_group), BoolToCStr(lossless),
+ static_cast<int>(num_channels), static_cast<int>(prog_detail),
+ static_cast<int>(increment));
std::vector<std::vector<uint8_t>> passes(kNumPasses + 1);
for (int i = 0; i <= kNumPasses; ++i) {
passes[i].resize(pixels.size());
@@ -4963,13 +5014,13 @@ TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionTest)) {
ASSERT_TRUE(
EncodeJPEGData(*orig_io.Main().jpeg_data.get(), &jpeg_data, cparams));
std::vector<uint8_t> container;
- jxl::Bytes(jxl::kContainerHeader).AppendTo(&container);
+ jxl::Bytes(jxl::kContainerHeader).AppendTo(container);
jxl::AppendBoxHeader(jxl::MakeBoxType("jbrd"), jpeg_data.size(), false,
&container);
- jxl::Bytes(jpeg_data).AppendTo(&container);
+ jxl::Bytes(jpeg_data).AppendTo(container);
jxl::AppendBoxHeader(jxl::MakeBoxType("jxlc"), 0, true, &container);
jxl::PaddedBytes codestream = std::move(writer).TakeBytes();
- jxl::Bytes(codestream).AppendTo(&container);
+ jxl::Bytes(codestream).AppendTo(container);
VerifyJPEGReconstruction(jxl::Bytes(container), jxl::Bytes(orig));
}
@@ -4982,7 +5033,8 @@ TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionMetadataTest)) {
}
TEST(DecodeTest, ContinueFinalNonEssentialBoxTest) {
- size_t xsize = 80, ysize = 90;
+ size_t xsize = 80;
+ size_t ysize = 90;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0);
jxl::TestCodestreamParams params;
params.box_format = kCSBF_Multi_Other_Terminated;
@@ -5038,7 +5090,7 @@ TEST(DecodeTest, ContinueFinalNonEssentialBoxTest) {
}
namespace {
-bool BoxTypeEquals(const std::string& type_string, JxlBoxType type) {
+bool BoxTypeEquals(const std::string& type_string, const JxlBoxType type) {
return type_string.size() == 4 && type_string[0] == type[0] &&
type_string[1] == type[1] && type_string[2] == type[2] &&
type_string[3] == type[3];
@@ -5054,28 +5106,38 @@ TEST(DecodeTest, ExtentedBoxSizeTest) {
JxlBoxType type;
uint64_t box_size;
+ uint64_t contents_size;
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetInput(dec, orig.data(), orig.size()));
EXPECT_EQ(JXL_DEC_BOX, JxlDecoderProcessInput(dec));
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBoxType(dec, type, JXL_FALSE));
EXPECT_TRUE(BoxTypeEquals("JXL ", type));
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBoxSizeRaw(dec, &box_size));
EXPECT_EQ(12, box_size);
+ EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBoxSizeContents(dec, &contents_size));
+ EXPECT_EQ(contents_size + 8, box_size);
EXPECT_EQ(JXL_DEC_BOX, JxlDecoderProcessInput(dec));
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBoxType(dec, type, JXL_FALSE));
EXPECT_TRUE(BoxTypeEquals("ftyp", type));
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBoxSizeRaw(dec, &box_size));
EXPECT_EQ(20, box_size);
+ EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBoxSizeContents(dec, &contents_size));
+ EXPECT_EQ(contents_size + 8, box_size);
EXPECT_EQ(JXL_DEC_BOX, JxlDecoderProcessInput(dec));
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBoxType(dec, type, JXL_FALSE));
EXPECT_TRUE(BoxTypeEquals("jxlc", type));
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBoxSizeRaw(dec, &box_size));
EXPECT_EQ(72, box_size);
+ EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBoxSizeContents(dec, &contents_size));
+ // This is an extended box, hence the difference between `box_size` and
+ // `contents_size` is 16.
+ EXPECT_EQ(contents_size + 8 + 8, box_size);
JxlDecoderDestroy(dec);
}
TEST(DecodeTest, JXL_BOXES_TEST(BoxTest)) {
- size_t xsize = 1, ysize = 1;
+ size_t xsize = 1;
+ size_t ysize = 1;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0);
jxl::TestCodestreamParams params;
params.box_format = kCSBF_Multi_Other_Terminated;
@@ -5096,6 +5158,7 @@ TEST(DecodeTest, JXL_BOXES_TEST(BoxTest)) {
JxlBoxType type;
uint64_t box_size;
+ uint64_t contents_size;
std::vector<uint8_t> contents(50);
size_t expected_release_size = 0;
@@ -5113,6 +5176,9 @@ TEST(DecodeTest, JXL_BOXES_TEST(BoxTest)) {
EXPECT_TRUE(BoxTypeEquals(expected_box_types[i], type));
if (expected_box_sizes[i]) {
EXPECT_EQ(expected_box_sizes[i], box_size);
+ EXPECT_EQ(JXL_DEC_SUCCESS,
+ JxlDecoderGetBoxSizeContents(dec, &contents_size));
+ EXPECT_EQ(contents_size + 8, box_size);
}
if (expected_release_size > 0) {
@@ -5147,7 +5213,8 @@ TEST(DecodeTest, JXL_BOXES_TEST(BoxTest)) {
}
TEST(DecodeTest, JXL_BOXES_TEST(ExifBrobBoxTest)) {
- size_t xsize = 1, ysize = 1;
+ size_t xsize = 1;
+ size_t ysize = 1;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0);
jxl::TestCodestreamParams params;
// Lossless to verify pixels exactly after roundtrip.
@@ -5328,7 +5395,8 @@ TEST(DecodeTest, JXL_BOXES_TEST(ExifBrobBoxTest)) {
}
TEST(DecodeTest, JXL_BOXES_TEST(PartialCodestreamBoxTest)) {
- size_t xsize = 23, ysize = 81;
+ size_t xsize = 23;
+ size_t ysize = 81;
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0);
JxlPixelFormat format_orig = {4, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
// Lossless to verify pixels exactly after roundtrip.
@@ -5482,10 +5550,11 @@ TEST(DecodeTest, JXL_BOXES_TEST(PartialCodestreamBoxTest)) {
TEST(DecodeTest, SpotColorTest) {
jxl::CodecInOut io;
- size_t xsize = 55, ysize = 257;
+ size_t xsize = 55;
+ size_t ysize = 257;
io.metadata.m.color_encoding = jxl::ColorEncoding::LinearSRGB();
- jxl::Image3F main(xsize, ysize);
- jxl::ImageF spot(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(Image3F main, Image3F::Create(xsize, ysize));
+ JXL_ASSIGN_OR_DIE(ImageF spot, ImageF::Create(xsize, ysize));
jxl::ZeroFillImage(&main);
jxl::ZeroFillImage(&spot);
@@ -5508,7 +5577,7 @@ TEST(DecodeTest, SpotColorTest) {
info.spot_color[3] = 0.5f;
io.metadata.m.extra_channel_info.push_back(info);
- std::vector<jxl::ImageF> ec;
+ std::vector<ImageF> ec;
ec.push_back(std::move(spot));
io.frames[0].SetExtraChannels(std::move(ec));
@@ -5524,7 +5593,7 @@ TEST(DecodeTest, SpotColorTest) {
for (size_t render_spot = 0; render_spot < 2; render_spot++) {
JxlPixelFormat format = {3, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, 0};
- JxlDecoder* dec = JxlDecoderCreate(NULL);
+ JxlDecoder* dec = JxlDecoderCreate(nullptr);
EXPECT_EQ(JXL_DEC_SUCCESS,
JxlDecoderSubscribeEvents(
@@ -5545,7 +5614,8 @@ TEST(DecodeTest, SpotColorTest) {
JxlExtraChannelInfo extra_info;
EXPECT_EQ(JXL_DEC_SUCCESS,
JxlDecoderGetExtraChannelInfo(dec, 0, &extra_info));
- EXPECT_EQ((unsigned int)jxl::ExtraChannel::kSpotColor, extra_info.type);
+ EXPECT_EQ(static_cast<unsigned int>(jxl::ExtraChannel::kSpotColor),
+ extra_info.type);
EXPECT_EQ(JXL_DEC_NEED_IMAGE_OUT_BUFFER, JxlDecoderProcessInput(dec));
size_t buffer_size;
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.cc b/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.cc
index d3b5ad3269..4aafd7a5e5 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.cc
@@ -18,20 +18,15 @@
#include <hwy/highway.h>
#include "lib/jxl/ac_strategy.h"
-#include "lib/jxl/ans_params.h"
#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/fast_math-inl.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/coeff_order_fwd.h"
-#include "lib/jxl/convolve.h"
-#include "lib/jxl/dct_scales.h"
#include "lib/jxl/dec_transforms-inl.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_debug_image.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/enc_transforms-inl.h"
-#include "lib/jxl/entropy_coder.h"
#include "lib/jxl/simd_util.h"
// Some of the floating point constants in this file and in other
@@ -215,10 +210,10 @@ const uint8_t* TypeMask(const uint8_t& raw_strategy) {
return kMask[raw_strategy];
}
-void DumpAcStrategy(const AcStrategyImage& ac_strategy, size_t xsize,
- size_t ysize, const char* tag, AuxOut* aux_out,
- const CompressParams& cparams) {
- Image3F color_acs(xsize, ysize);
+Status DumpAcStrategy(const AcStrategyImage& ac_strategy, size_t xsize,
+ size_t ysize, const char* tag, AuxOut* aux_out,
+ const CompressParams& cparams) {
+ JXL_ASSIGN_OR_RETURN(Image3F color_acs, Image3F::Create(xsize, ysize));
for (size_t y = 0; y < ysize; y++) {
float* JXL_RESTRICT rows[3] = {
color_acs.PlaneRow(0, y),
@@ -269,7 +264,7 @@ void DumpAcStrategy(const AcStrategyImage& ac_strategy, size_t xsize,
}
}
}
- DumpImage(cparams, tag, color_acs);
+ return DumpImage(cparams, tag, color_acs);
}
} // namespace
@@ -353,7 +348,9 @@ bool MultiBlockTransformCrossesVerticalBoundary(
float EstimateEntropy(const AcStrategy& acs, float entropy_mul, size_t x,
size_t y, const ACSConfig& config,
const float* JXL_RESTRICT cmap_factors, float* block,
- float* scratch_space, uint32_t* quantized) {
+ float* full_scratch_space, uint32_t* quantized) {
+ float* mem = full_scratch_space;
+ float* scratch_space = full_scratch_space + AcStrategy::kMaxCoeffArea;
const size_t size = (1 << acs.log2_covered_blocks()) * kDCTBlockSize;
// Apply transform.
@@ -403,8 +400,6 @@ float EstimateEntropy(const AcStrategy& acs, float entropy_mul, size_t x,
float entropy = 0.0f;
const HWY_CAPPED(float, 8) df8;
- auto mem_alloc = hwy::AllocateAligned<float>(AcStrategy::kMaxCoeffArea);
- float* mem = mem_alloc.get();
auto loss = Zero(df8);
for (size_t c = 0; c < 3; c++) {
const float* inv_matrix = config.dequant->InvMatrix(acs.RawStrategy(), c);
@@ -792,6 +787,7 @@ void FindBestFirstLevelDivisionForSquare(
void ProcessRectACS(const CompressParams& cparams, const ACSConfig& config,
const Rect& rect, const ColorCorrelationMap& cmap,
+ float* JXL_RESTRICT block, uint32_t* JXL_RESTRICT quantized,
AcStrategyImage* ac_strategy) {
// Main philosophy here:
// 1. First find best 8x8 transform for each area.
@@ -804,15 +800,7 @@ void ProcessRectACS(const CompressParams& cparams, const ACSConfig& config,
// integral transforms cross these boundaries leads to
// additional complications.
const float butteraugli_target = cparams.butteraugli_distance;
- const size_t dct_scratch_size =
- 3 * (MaxVectorSize() / sizeof(float)) * AcStrategy::kMaxBlockDim;
- // TODO(veluca): reuse allocations
- auto mem = hwy::AllocateAligned<float>(5 * AcStrategy::kMaxCoeffArea +
- dct_scratch_size);
- auto qmem = hwy::AllocateAligned<uint32_t>(AcStrategy::kMaxCoeffArea);
- uint32_t* JXL_RESTRICT quantized = qmem.get();
- float* JXL_RESTRICT block = mem.get();
- float* JXL_RESTRICT scratch_space = mem.get() + 3 * AcStrategy::kMaxCoeffArea;
+ float* JXL_RESTRICT scratch_space = block + 3 * AcStrategy::kMaxCoeffArea;
size_t bx = rect.x0();
size_t by = rect.y0();
JXL_ASSERT(rect.xsize() <= 8);
@@ -1085,26 +1073,37 @@ void AcStrategyHeuristics::Init(const Image3F& src, const Rect& rect_in,
static const float kPow1 = 0.33677806662454718;
static const float kPow2 = 0.50990926717963703;
static const float kPow3 = 0.36702940662370243;
- config.info_loss_multiplier *= pow(ratio, kPow1);
- config.zeros_mul *= pow(ratio, kPow2);
- config.cost_delta *= pow(ratio, kPow3);
+ config.info_loss_multiplier *= std::pow(ratio, kPow1);
+ config.zeros_mul *= std::pow(ratio, kPow2);
+ config.cost_delta *= std::pow(ratio, kPow3);
+}
+
+void AcStrategyHeuristics::PrepareForThreads(std::size_t num_threads) {
+ const size_t dct_scratch_size =
+ 3 * (MaxVectorSize() / sizeof(float)) * AcStrategy::kMaxBlockDim;
+ mem_per_thread = 6 * AcStrategy::kMaxCoeffArea + dct_scratch_size;
+ mem = hwy::AllocateAligned<float>(num_threads * mem_per_thread);
+ qmem_per_thread = AcStrategy::kMaxCoeffArea;
+ qmem = hwy::AllocateAligned<uint32_t>(num_threads * qmem_per_thread);
}
void AcStrategyHeuristics::ProcessRect(const Rect& rect,
const ColorCorrelationMap& cmap,
- AcStrategyImage* ac_strategy) {
+ AcStrategyImage* ac_strategy,
+ size_t thread) {
// In Falcon mode, use DCT8 everywhere and uniform quantization.
if (cparams.speed_tier >= SpeedTier::kCheetah) {
ac_strategy->FillDCT8(rect);
return;
}
HWY_DYNAMIC_DISPATCH(ProcessRectACS)
- (cparams, config, rect, cmap, ac_strategy);
+ (cparams, config, rect, cmap, mem.get() + thread * mem_per_thread,
+ qmem.get() + thread * qmem_per_thread, ac_strategy);
}
-void AcStrategyHeuristics::Finalize(const FrameDimensions& frame_dim,
- const AcStrategyImage& ac_strategy,
- AuxOut* aux_out) {
+Status AcStrategyHeuristics::Finalize(const FrameDimensions& frame_dim,
+ const AcStrategyImage& ac_strategy,
+ AuxOut* aux_out) {
// Accounting and debug output.
if (aux_out != nullptr) {
aux_out->num_small_blocks =
@@ -1141,9 +1140,11 @@ void AcStrategyHeuristics::Finalize(const FrameDimensions& frame_dim,
// if (JXL_DEBUG_AC_STRATEGY && WantDebugOutput(aux_out)) {
if (JXL_DEBUG_AC_STRATEGY && WantDebugOutput(cparams)) {
- DumpAcStrategy(ac_strategy, frame_dim.xsize, frame_dim.ysize, "ac_strategy",
- aux_out, cparams);
+ JXL_RETURN_IF_ERROR(DumpAcStrategy(ac_strategy, frame_dim.xsize,
+ frame_dim.ysize, "ac_strategy", aux_out,
+ cparams));
}
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.h b/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.h
index 9f6d92a6f7..31eb73c6a0 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.h
@@ -58,16 +58,22 @@ struct ACSConfig {
};
struct AcStrategyHeuristics {
- AcStrategyHeuristics(const CompressParams& cparams) : cparams(cparams) {}
+ explicit AcStrategyHeuristics(const CompressParams& cparams)
+ : cparams(cparams), mem_per_thread(0), qmem_per_thread(0) {}
void Init(const Image3F& src, const Rect& rect_in, const ImageF& quant_field,
const ImageF& mask, const ImageF& mask1x1,
DequantMatrices* matrices);
+ void PrepareForThreads(std::size_t num_threads);
void ProcessRect(const Rect& rect, const ColorCorrelationMap& cmap,
- AcStrategyImage* ac_strategy);
- void Finalize(const FrameDimensions& frame_dim,
- const AcStrategyImage& ac_strategy, AuxOut* aux_out);
+ AcStrategyImage* ac_strategy, size_t thread);
+ Status Finalize(const FrameDimensions& frame_dim,
+ const AcStrategyImage& ac_strategy, AuxOut* aux_out);
const CompressParams& cparams;
- ACSConfig config;
+ ACSConfig config = {};
+ size_t mem_per_thread;
+ hwy::AlignedFreeUniquePtr<float[]> mem;
+ size_t qmem_per_thread;
+ hwy::AlignedFreeUniquePtr<uint32_t[]> qmem;
};
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.cc b/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.cc
index ae4cd3bd3b..4c2ddba95b 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.cc
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <algorithm>
+#include <atomic>
#include <cmath>
#include <string>
#include <vector>
@@ -26,8 +27,6 @@
#include "lib/jxl/base/status.h"
#include "lib/jxl/butteraugli/butteraugli.h"
#include "lib/jxl/cms/opsin_params.h"
-#include "lib/jxl/coeff_order_fwd.h"
-#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/convolve.h"
#include "lib/jxl/dec_cache.h"
#include "lib/jxl/dec_group.h"
@@ -102,12 +101,12 @@ V ComputeMask(const D d, const V out_val) {
}
// mul and mul2 represent a scaling difference between jxl and butteraugli.
-static const float kSGmul = 226.77216153508914f;
-static const float kSGmul2 = 1.0f / 73.377132366608819f;
-static const float kLog2 = 0.693147181f;
+const float kSGmul = 226.77216153508914f;
+const float kSGmul2 = 1.0f / 73.377132366608819f;
+const float kLog2 = 0.693147181f;
// Includes correction factor for std::log -> log2.
-static const float kSGRetMul = kSGmul2 * 18.6580932135f * kLog2;
-static const float kSGVOffset = 7.7825991679894591f;
+const float kSGRetMul = kSGmul2 * 18.6580932135f * kLog2;
+const float kSGVOffset = 7.7825991679894591f;
template <bool invert, typename D, typename V>
V RatioOfDerivativesOfCubicRootToSimpleGamma(const D d, V v) {
@@ -131,7 +130,7 @@ V RatioOfDerivativesOfCubicRootToSimpleGamma(const D d, V v) {
}
template <bool invert = false>
-static float RatioOfDerivativesOfCubicRootToSimpleGamma(float v) {
+float RatioOfDerivativesOfCubicRootToSimpleGamma(float v) {
using DScalar = HWY_CAPPED(float, 1);
auto vscalar = Load(DScalar(), &v);
return GetLane(
@@ -396,12 +395,16 @@ void FuzzyErosion(const float butteraugli_target, const Rect& from_rect,
}
struct AdaptiveQuantizationImpl {
- void PrepareBuffers(size_t num_threads) {
- diff_buffer = ImageF(kEncTileDim + 8, num_threads);
+ Status PrepareBuffers(size_t num_threads) {
+ JXL_ASSIGN_OR_RETURN(diff_buffer,
+ ImageF::Create(kEncTileDim + 8, num_threads));
for (size_t i = pre_erosion.size(); i < num_threads; i++) {
- pre_erosion.emplace_back(kEncTileDimInBlocks * 2 + 2,
- kEncTileDimInBlocks * 2 + 2);
+ JXL_ASSIGN_OR_RETURN(ImageF tmp,
+ ImageF::Create(kEncTileDimInBlocks * 2 + 2,
+ kEncTileDimInBlocks * 2 + 2));
+ pre_erosion.emplace_back(std::move(tmp));
}
+ return true;
}
void ComputeTile(float butteraugli_target, float scale, const Image3F& xyb,
@@ -568,8 +571,7 @@ struct AdaptiveQuantizationImpl {
ImageF diff_buffer;
};
-static void Blur1x1Masking(ThreadPool* pool, ImageF* mask1x1,
- const Rect& rect) {
+Status Blur1x1Masking(ThreadPool* pool, ImageF* mask1x1, const Rect& rect) {
// Blur the mask1x1 to obtain the masking image.
// Before blurring it contains an image of absolute value of the
// Laplacian of the intensity channel.
@@ -595,30 +597,30 @@ static void Blur1x1Masking(ThreadPool* pool, ImageF* mask1x1,
{HWY_REP4(normalize_mul * kFilterMask1x1[1])},
{HWY_REP4(normalize_mul * kFilterMask1x1[4])},
{HWY_REP4(normalize_mul * kFilterMask1x1[3])}};
- ImageF temp(rect.xsize(), rect.ysize());
+ JXL_ASSIGN_OR_RETURN(ImageF temp, ImageF::Create(rect.xsize(), rect.ysize()));
Symmetric5(*mask1x1, rect, weights, pool, &temp);
*mask1x1 = std::move(temp);
+ return true;
}
-ImageF AdaptiveQuantizationMap(const float butteraugli_target,
- const Image3F& xyb, const Rect& rect,
- float scale, ThreadPool* pool, ImageF* mask,
- ImageF* mask1x1) {
+StatusOr<ImageF> AdaptiveQuantizationMap(const float butteraugli_target,
+ const Image3F& xyb, const Rect& rect,
+ float scale, ThreadPool* pool,
+ ImageF* mask, ImageF* mask1x1) {
JXL_DASSERT(rect.xsize() % kBlockDim == 0);
JXL_DASSERT(rect.ysize() % kBlockDim == 0);
AdaptiveQuantizationImpl impl;
const size_t xsize_blocks = rect.xsize() / kBlockDim;
const size_t ysize_blocks = rect.ysize() / kBlockDim;
- impl.aq_map = ImageF(xsize_blocks, ysize_blocks);
- *mask = ImageF(xsize_blocks, ysize_blocks);
- *mask1x1 = ImageF(xyb.xsize(), xyb.ysize());
+ JXL_ASSIGN_OR_RETURN(impl.aq_map, ImageF::Create(xsize_blocks, ysize_blocks));
+ JXL_ASSIGN_OR_RETURN(*mask, ImageF::Create(xsize_blocks, ysize_blocks));
+ JXL_ASSIGN_OR_RETURN(*mask1x1, ImageF::Create(xyb.xsize(), xyb.ysize()));
JXL_CHECK(RunOnPool(
pool, 0,
DivCeil(xsize_blocks, kEncTileDimInBlocks) *
DivCeil(ysize_blocks, kEncTileDimInBlocks),
[&](const size_t num_threads) {
- impl.PrepareBuffers(num_threads);
- return true;
+ return !!impl.PrepareBuffers(num_threads);
},
[&](const uint32_t tid, const size_t thread) {
size_t n_enc_tiles = DivCeil(xsize_blocks, kEncTileDimInBlocks);
@@ -634,7 +636,7 @@ ImageF AdaptiveQuantizationMap(const float butteraugli_target,
},
"AQ DiffPrecompute"));
- Blur1x1Masking(pool, mask1x1, rect);
+ JXL_RETURN_IF_ERROR(Blur1x1Masking(pool, mask1x1, rect));
return std::move(impl).aq_map;
}
@@ -654,24 +656,28 @@ namespace {
// If true, prints the quantization maps at each iteration.
constexpr bool FLAGS_dump_quant_state = false;
-void DumpHeatmap(const CompressParams& cparams, const AuxOut* aux_out,
- const std::string& label, const ImageF& image,
- float good_threshold, float bad_threshold) {
+Status DumpHeatmap(const CompressParams& cparams, const AuxOut* aux_out,
+ const std::string& label, const ImageF& image,
+ float good_threshold, float bad_threshold) {
if (JXL_DEBUG_ADAPTIVE_QUANTIZATION) {
- Image3F heatmap = CreateHeatMapImage(image, good_threshold, bad_threshold);
+ JXL_ASSIGN_OR_RETURN(
+ Image3F heatmap,
+ CreateHeatMapImage(image, good_threshold, bad_threshold));
char filename[200];
snprintf(filename, sizeof(filename), "%s%05d", label.c_str(),
aux_out->num_butteraugli_iters);
- DumpImage(cparams, filename, heatmap);
+ JXL_RETURN_IF_ERROR(DumpImage(cparams, filename, heatmap));
}
+ return true;
}
-void DumpHeatmaps(const CompressParams& cparams, const AuxOut* aux_out,
- float ba_target, const ImageF& quant_field,
- const ImageF& tile_heatmap, const ImageF& bt_diffmap) {
+Status DumpHeatmaps(const CompressParams& cparams, const AuxOut* aux_out,
+ float ba_target, const ImageF& quant_field,
+ const ImageF& tile_heatmap, const ImageF& bt_diffmap) {
if (JXL_DEBUG_ADAPTIVE_QUANTIZATION) {
- if (!WantDebugOutput(cparams)) return;
- ImageF inv_qmap(quant_field.xsize(), quant_field.ysize());
+ if (!WantDebugOutput(cparams)) return true;
+ JXL_ASSIGN_OR_RETURN(ImageF inv_qmap, ImageF::Create(quant_field.xsize(),
+ quant_field.ysize()));
for (size_t y = 0; y < quant_field.ysize(); ++y) {
const float* JXL_RESTRICT row_q = quant_field.ConstRow(y);
float* JXL_RESTRICT row_inv_q = inv_qmap.Row(y);
@@ -679,21 +685,24 @@ void DumpHeatmaps(const CompressParams& cparams, const AuxOut* aux_out,
row_inv_q[x] = 1.0f / row_q[x]; // never zero
}
}
- DumpHeatmap(cparams, aux_out, "quant_heatmap", inv_qmap, 4.0f * ba_target,
- 6.0f * ba_target);
- DumpHeatmap(cparams, aux_out, "tile_heatmap", tile_heatmap, ba_target,
- 1.5f * ba_target);
+ JXL_RETURN_IF_ERROR(DumpHeatmap(cparams, aux_out, "quant_heatmap", inv_qmap,
+ 4.0f * ba_target, 6.0f * ba_target));
+ JXL_RETURN_IF_ERROR(DumpHeatmap(cparams, aux_out, "tile_heatmap",
+ tile_heatmap, ba_target, 1.5f * ba_target));
// matches heat maps produced by the command line tool.
- DumpHeatmap(cparams, aux_out, "bt_diffmap", bt_diffmap,
- ButteraugliFuzzyInverse(1.5), ButteraugliFuzzyInverse(0.5));
+ JXL_RETURN_IF_ERROR(DumpHeatmap(cparams, aux_out, "bt_diffmap", bt_diffmap,
+ ButteraugliFuzzyInverse(1.5),
+ ButteraugliFuzzyInverse(0.5)));
}
+ return true;
}
-ImageF TileDistMap(const ImageF& distmap, int tile_size, int margin,
- const AcStrategyImage& ac_strategy) {
+StatusOr<ImageF> TileDistMap(const ImageF& distmap, int tile_size, int margin,
+ const AcStrategyImage& ac_strategy) {
const int tile_xsize = (distmap.xsize() + tile_size - 1) / tile_size;
const int tile_ysize = (distmap.ysize() + tile_size - 1) / tile_size;
- ImageF tile_distmap(tile_xsize, tile_ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF tile_distmap,
+ ImageF::Create(tile_xsize, tile_ysize));
size_t distmap_stride = tile_distmap.PixelsPerRow();
for (int tile_y = 0; tile_y < tile_ysize; ++tile_y) {
AcStrategyRow ac_strategy_row = ac_strategy.ConstRow(tile_y);
@@ -754,14 +763,16 @@ ImageF TileDistMap(const ImageF& distmap, int tile_size, int margin,
return tile_distmap;
}
-static const float kDcQuantPow = 0.83f;
-static const float kDcQuant = 1.095924047623553f;
-static const float kAcQuant = 0.7381485255235064f;
+const float kDcQuantPow = 0.83f;
+const float kDcQuant = 1.095924047623553f;
+const float kAcQuant = 0.7381485255235064f;
// Computes the decoded image for a given set of compression parameters.
-ImageBundle RoundtripImage(const FrameHeader& frame_header,
- const Image3F& opsin, PassesEncoderState* enc_state,
- const JxlCmsInterface& cms, ThreadPool* pool) {
+StatusOr<ImageBundle> RoundtripImage(const FrameHeader& frame_header,
+ const Image3F& opsin,
+ PassesEncoderState* enc_state,
+ const JxlCmsInterface& cms,
+ ThreadPool* pool) {
std::unique_ptr<PassesDecoderState> dec_state =
jxl::make_unique<PassesDecoderState>();
JXL_CHECK(dec_state->output_encoding_info.SetFromMetadata(
@@ -775,7 +786,8 @@ ImageBundle RoundtripImage(const FrameHeader& frame_header,
size_t num_special_frames = enc_state->special_frames.size();
size_t num_passes = enc_state->progressive_splitter.GetNumPasses();
- ModularFrameEncoder modular_frame_encoder(frame_header, enc_state->cparams);
+ ModularFrameEncoder modular_frame_encoder(frame_header, enc_state->cparams,
+ false);
JXL_CHECK(InitializePassesEncoder(frame_header, opsin, Rect(opsin), cms, pool,
enc_state, &modular_frame_encoder,
nullptr));
@@ -784,7 +796,9 @@ ImageBundle RoundtripImage(const FrameHeader& frame_header,
ImageBundle decoded(&enc_state->shared.metadata->m);
decoded.origin = frame_header.frame_origin;
- decoded.SetFromImage(Image3F(opsin.xsize(), opsin.ysize()),
+ JXL_ASSIGN_OR_RETURN(Image3F tmp,
+ Image3F::Create(opsin.xsize(), opsin.ysize()));
+ decoded.SetFromImage(std::move(tmp),
dec_state->output_encoding_info.color_encoding);
PassesDecoderState::PipelineOptions options;
@@ -806,8 +820,10 @@ ImageBundle RoundtripImage(const FrameHeader& frame_header,
group_dec_caches = hwy::MakeUniqueAlignedArray<GroupDecCache>(num_threads);
return true;
};
+ std::atomic<bool> has_error{false};
const auto process_group = [&](const uint32_t group_index,
const size_t thread) {
+ if (has_error) return;
if (frame_header.loop_filter.epf_iters > 0) {
ComputeSigma(frame_header.loop_filter,
dec_state->shared->frame_dim.BlockGroupRect(group_index),
@@ -822,10 +838,14 @@ ImageBundle RoundtripImage(const FrameHeader& frame_header,
std::pair<ImageF*, Rect> ri = input.GetBuffer(3 + c);
FillPlane(0.0f, ri.first, ri.second);
}
- input.Done();
+ if (!input.Done()) {
+ has_error = true;
+ return;
+ }
};
JXL_CHECK(RunOnPool(pool, 0, num_groups, allocate_storage, process_group,
"AQ loop"));
+ if (has_error) return JXL_FAILURE("AQ loop failure");
// Ensure we don't create any new special frames.
enc_state->special_frames.resize(num_special_frames);
@@ -835,18 +855,18 @@ ImageBundle RoundtripImage(const FrameHeader& frame_header,
constexpr int kMaxButteraugliIters = 4;
-void FindBestQuantization(const FrameHeader& frame_header,
- const Image3F& linear, const Image3F& opsin,
- ImageF& quant_field, PassesEncoderState* enc_state,
- const JxlCmsInterface& cms, ThreadPool* pool,
- AuxOut* aux_out) {
+Status FindBestQuantization(const FrameHeader& frame_header,
+ const Image3F& linear, const Image3F& opsin,
+ ImageF& quant_field, PassesEncoderState* enc_state,
+ const JxlCmsInterface& cms, ThreadPool* pool,
+ AuxOut* aux_out) {
const CompressParams& cparams = enc_state->cparams;
if (cparams.resampling > 1 &&
cparams.original_butteraugli_distance <= 4.0 * cparams.resampling) {
// For downsampled opsin image, the butteraugli based adaptive quantization
// loop would only make the size bigger without improving the distance much,
// so in this case we enable it only for very high butteraugli targets.
- return;
+ return true;
}
Quantizer& quantizer = enc_state->shared.quantizer;
ImageI& raw_quant_field = enc_state->shared.raw_quant_field;
@@ -863,10 +883,13 @@ void FindBestQuantization(const FrameHeader& frame_header,
AdjustQuantField(enc_state->shared.ac_strategy, Rect(quant_field),
original_butteraugli, &quant_field);
ImageF tile_distmap;
- ImageF initial_quant_field(quant_field.xsize(), quant_field.ysize());
+ JXL_ASSIGN_OR_RETURN(
+ ImageF initial_quant_field,
+ ImageF::Create(quant_field.xsize(), quant_field.ysize()));
CopyImageTo(quant_field, &initial_quant_field);
- float initial_qf_min, initial_qf_max;
+ float initial_qf_min;
+ float initial_qf_max;
ImageMinMax(initial_quant_field, &initial_qf_min, &initial_qf_max);
float initial_qf_ratio = initial_qf_max / initial_qf_min;
float qf_max_deviation_low = std::sqrt(250 / initial_qf_ratio);
@@ -893,8 +916,9 @@ void FindBestQuantization(const FrameHeader& frame_header,
}
}
quantizer.SetQuantField(initial_quant_dc, quant_field, &raw_quant_field);
- ImageBundle dec_linear =
- RoundtripImage(frame_header, opsin, enc_state, cms, pool);
+ JXL_ASSIGN_OR_RETURN(
+ ImageBundle dec_linear,
+ RoundtripImage(frame_header, opsin, enc_state, cms, pool));
float score;
ImageF diffmap;
JXL_CHECK(comparator.CompareWith(dec_linear, &diffmap, &score));
@@ -902,16 +926,19 @@ void FindBestQuantization(const FrameHeader& frame_header,
score = -score;
ScaleImage(-1.0f, &diffmap);
}
- tile_distmap = TileDistMap(diffmap, 8 * cparams.resampling, 0,
- enc_state->shared.ac_strategy);
+ JXL_ASSIGN_OR_RETURN(tile_distmap,
+ TileDistMap(diffmap, 8 * cparams.resampling, 0,
+ enc_state->shared.ac_strategy));
if (JXL_DEBUG_ADAPTIVE_QUANTIZATION && WantDebugOutput(cparams)) {
- DumpImage(cparams, ("dec" + ToString(i)).c_str(), *dec_linear.color());
- DumpHeatmaps(cparams, aux_out, butteraugli_target, quant_field,
- tile_distmap, diffmap);
+ JXL_RETURN_IF_ERROR(DumpImage(cparams, ("dec" + ToString(i)).c_str(),
+ *dec_linear.color()));
+ JXL_RETURN_IF_ERROR(DumpHeatmaps(cparams, aux_out, butteraugli_target,
+ quant_field, tile_distmap, diffmap));
}
if (aux_out != nullptr) ++aux_out->num_butteraugli_iters;
if (JXL_DEBUG_ADAPTIVE_QUANTIZATION) {
- float minval, maxval;
+ float minval;
+ float maxval;
ImageMinMax(quant_field, &minval, &maxval);
printf("\nButteraugli iter: %d/%d\n", i, kMaxButteraugliIters);
printf("Butteraugli distance: %f (target = %f)\n", score,
@@ -967,8 +994,10 @@ void FindBestQuantization(const FrameHeader& frame_header,
if (diff > 1.0f) {
float old = row_q[x];
row_q[x] *= diff;
- int qf_old = old * quantizer.InvGlobalScale() + 0.5;
- int qf_new = row_q[x] * quantizer.InvGlobalScale() + 0.5;
+ int qf_old =
+ static_cast<int>(std::lround(old * quantizer.InvGlobalScale()));
+ int qf_new = static_cast<int>(
+ std::lround(row_q[x] * quantizer.InvGlobalScale()));
if (qf_old == qf_new) {
row_q[x] = old + quantizer.Scale();
}
@@ -988,8 +1017,10 @@ void FindBestQuantization(const FrameHeader& frame_header,
} else {
float old = row_q[x];
row_q[x] *= diff;
- int qf_old = old * quantizer.InvGlobalScale() + 0.5;
- int qf_new = row_q[x] * quantizer.InvGlobalScale() + 0.5;
+ int qf_old =
+ static_cast<int>(std::lround(old * quantizer.InvGlobalScale()));
+ int qf_new = static_cast<int>(
+ std::lround(row_q[x] * quantizer.InvGlobalScale()));
if (qf_old == qf_new) {
row_q[x] = old + quantizer.Scale();
}
@@ -1001,13 +1032,14 @@ void FindBestQuantization(const FrameHeader& frame_header,
}
}
quantizer.SetQuantField(initial_quant_dc, quant_field, &raw_quant_field);
+ return true;
}
-void FindBestQuantizationMaxError(const FrameHeader& frame_header,
- const Image3F& opsin, ImageF& quant_field,
- PassesEncoderState* enc_state,
- const JxlCmsInterface& cms, ThreadPool* pool,
- AuxOut* aux_out) {
+Status FindBestQuantizationMaxError(const FrameHeader& frame_header,
+ const Image3F& opsin, ImageF& quant_field,
+ PassesEncoderState* enc_state,
+ const JxlCmsInterface& cms,
+ ThreadPool* pool, AuxOut* aux_out) {
// TODO(szabadka): Make this work for non-opsin color spaces.
const CompressParams& cparams = enc_state->cparams;
Quantizer& quantizer = enc_state->shared.quantizer;
@@ -1026,12 +1058,15 @@ void FindBestQuantizationMaxError(const FrameHeader& frame_header,
for (int i = 0; i < kMaxButteraugliIters + 1; ++i) {
quantizer.SetQuantField(initial_quant_dc, quant_field, &raw_quant_field);
if (JXL_DEBUG_ADAPTIVE_QUANTIZATION && aux_out) {
- DumpXybImage(cparams, ("ops" + ToString(i)).c_str(), opsin);
+ JXL_RETURN_IF_ERROR(
+ DumpXybImage(cparams, ("ops" + ToString(i)).c_str(), opsin));
}
- ImageBundle decoded =
- RoundtripImage(frame_header, opsin, enc_state, cms, pool);
+ JXL_ASSIGN_OR_RETURN(
+ ImageBundle decoded,
+ RoundtripImage(frame_header, opsin, enc_state, cms, pool));
if (JXL_DEBUG_ADAPTIVE_QUANTIZATION && aux_out) {
- DumpXybImage(cparams, ("dec" + ToString(i)).c_str(), *decoded.color());
+ JXL_RETURN_IF_ERROR(DumpXybImage(cparams, ("dec" + ToString(i)).c_str(),
+ *decoded.color()));
}
for (size_t by = 0; by < enc_state->shared.frame_dim.ysize_blocks; by++) {
AcStrategyRow ac_strategy_row =
@@ -1073,6 +1108,7 @@ void FindBestQuantizationMaxError(const FrameHeader& frame_header,
}
}
quantizer.SetQuantField(initial_quant_dc, quant_field, &raw_quant_field);
+ return true;
}
} // namespace
@@ -1142,28 +1178,31 @@ float InitialQuantDC(float butteraugli_target) {
return std::min(kDcQuant / butteraugli_target_dc, 50.f);
}
-ImageF InitialQuantField(const float butteraugli_target, const Image3F& opsin,
- const Rect& rect, ThreadPool* pool, float rescale,
- ImageF* mask, ImageF* mask1x1) {
+StatusOr<ImageF> InitialQuantField(const float butteraugli_target,
+ const Image3F& opsin, const Rect& rect,
+ ThreadPool* pool, float rescale,
+ ImageF* mask, ImageF* mask1x1) {
const float quant_ac = kAcQuant / butteraugli_target;
return HWY_DYNAMIC_DISPATCH(AdaptiveQuantizationMap)(
butteraugli_target, opsin, rect, quant_ac * rescale, pool, mask, mask1x1);
}
-void FindBestQuantizer(const FrameHeader& frame_header, const Image3F* linear,
- const Image3F& opsin, ImageF& quant_field,
- PassesEncoderState* enc_state,
- const JxlCmsInterface& cms, ThreadPool* pool,
- AuxOut* aux_out, double rescale) {
+Status FindBestQuantizer(const FrameHeader& frame_header, const Image3F* linear,
+ const Image3F& opsin, ImageF& quant_field,
+ PassesEncoderState* enc_state,
+ const JxlCmsInterface& cms, ThreadPool* pool,
+ AuxOut* aux_out, double rescale) {
const CompressParams& cparams = enc_state->cparams;
if (cparams.max_error_mode) {
- FindBestQuantizationMaxError(frame_header, opsin, quant_field, enc_state,
- cms, pool, aux_out);
+ JXL_RETURN_IF_ERROR(FindBestQuantizationMaxError(
+ frame_header, opsin, quant_field, enc_state, cms, pool, aux_out));
} else if (linear && cparams.speed_tier <= SpeedTier::kKitten) {
// Normal encoding to a butteraugli score.
- FindBestQuantization(frame_header, *linear, opsin, quant_field, enc_state,
- cms, pool, aux_out);
+ JXL_RETURN_IF_ERROR(FindBestQuantization(frame_header, *linear, opsin,
+ quant_field, enc_state, cms, pool,
+ aux_out));
}
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.h b/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.h
index 6aa8b10df6..26ed3f26ca 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.h
@@ -31,10 +31,11 @@ struct AuxOut;
// of the input image, while a value less than 1.0 indicates that less
// fine-grained quantization should be enough. Returns a mask, too, which
// can later be used to make better decisions about ac strategy.
-ImageF InitialQuantField(float butteraugli_target, const Image3F& opsin,
- const Rect& rect, ThreadPool* pool, float rescale,
- ImageF* initial_quant_mask,
- ImageF* initial_quant_mask1x1);
+StatusOr<ImageF> InitialQuantField(float butteraugli_target,
+ const Image3F& opsin, const Rect& rect,
+ ThreadPool* pool, float rescale,
+ ImageF* initial_quant_mask,
+ ImageF* initial_quant_mask1x1);
float InitialQuantDC(float butteraugli_target);
@@ -45,11 +46,11 @@ void AdjustQuantField(const AcStrategyImage& ac_strategy, const Rect& rect,
// quant_field. Also computes the dequant_map corresponding to the given
// dequant_float_map and chosen quantization levels.
// `linear` is only used in Kitten mode or slower.
-void FindBestQuantizer(const FrameHeader& frame_header, const Image3F* linear,
- const Image3F& opsin, ImageF& quant_field,
- PassesEncoderState* enc_state,
- const JxlCmsInterface& cms, ThreadPool* pool,
- AuxOut* aux_out, double rescale = 1.0);
+Status FindBestQuantizer(const FrameHeader& frame_header, const Image3F* linear,
+ const Image3F& opsin, ImageF& quant_field,
+ PassesEncoderState* enc_state,
+ const JxlCmsInterface& cms, ThreadPool* pool,
+ AuxOut* aux_out, double rescale = 1.0);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ans.cc b/third_party/jpeg-xl/lib/jxl/enc_ans.cc
index 3efa62d8e1..5e59790b1e 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ans.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_ans.cc
@@ -5,11 +5,13 @@
#include "lib/jxl/enc_ans.h"
+#include <jxl/types.h>
#include <stdint.h>
#include <algorithm>
#include <array>
#include <cmath>
+#include <cstdint>
#include <limits>
#include <numeric>
#include <type_traits>
@@ -20,12 +22,15 @@
#include "lib/jxl/ans_common.h"
#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/fast_math-inl.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_ans.h"
+#include "lib/jxl/enc_ans_params.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_cluster.h"
#include "lib/jxl/enc_context_map.h"
#include "lib/jxl/enc_fields.h"
#include "lib/jxl/enc_huffman.h"
+#include "lib/jxl/enc_params.h"
#include "lib/jxl/fields.h"
namespace jxl {
@@ -37,7 +42,7 @@ constexpr
#endif
bool ans_fuzzer_friendly_ = false;
-static const int kMaxNumSymbolsForSmallCode = 4;
+const int kMaxNumSymbolsForSmallCode = 4;
void ANSBuildInfoTable(const ANSHistBin* counts, const AliasTable::Entry* table,
size_t alphabet_size, size_t log_alpha_size,
@@ -99,16 +104,16 @@ float EstimateDataBitsFlat(const ANSHistBin* histogram, size_t len) {
// Static Huffman code for encoding logcounts. The last symbol is used as RLE
// sequence.
-static const uint8_t kLogCountBitLengths[ANS_LOG_TAB_SIZE + 2] = {
+const uint8_t kLogCountBitLengths[ANS_LOG_TAB_SIZE + 2] = {
5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 6, 7, 7,
};
-static const uint8_t kLogCountSymbols[ANS_LOG_TAB_SIZE + 2] = {
+const uint8_t kLogCountSymbols[ANS_LOG_TAB_SIZE + 2] = {
17, 11, 15, 3, 9, 7, 4, 2, 5, 6, 0, 33, 1, 65,
};
// Returns the difference between largest count that can be represented and is
// smaller than "count" and smallest representable count larger than "count".
-static int SmallestIncrement(uint32_t count, uint32_t shift) {
+int SmallestIncrement(uint32_t count, uint32_t shift) {
int bits = count == 0 ? -1 : FloorLog2Nonzero(count);
int drop_bits = bits - GetPopulationCountPrecision(bits, shift);
return drop_bits < 0 ? 1 : (1 << drop_bits);
@@ -148,10 +153,11 @@ bool RebalanceHistogram(const float* targets, int max_symbol, int table_size,
int inc = SmallestIncrement(counts[n], shift);
counts[n] -= counts[n] & (inc - 1);
// TODO(robryk): Should we rescale targets[n]?
- const float target =
- minimize_error_of_sum ? (sum_nonrounded - sum) : targets[n];
+ const int target = minimize_error_of_sum
+ ? (static_cast<int>(sum_nonrounded) - sum)
+ : static_cast<int>(targets[n]);
if (counts[n] == 0 ||
- (target > counts[n] + inc / 2 && counts[n] + inc < table_size)) {
+ (target >= counts[n] + inc / 2 && counts[n] + inc < table_size)) {
counts[n] += inc;
}
sum += counts[n];
@@ -203,11 +209,11 @@ Status NormalizeCounts(ANSHistBin* counts, int* omit_pos, const int length,
for (size_t n = 0; n < targets.size(); ++n) {
targets[n] = norm * counts[n];
}
- if (!RebalanceHistogram<false>(&targets[0], max_symbol, table_size, shift,
+ if (!RebalanceHistogram<false>(targets.data(), max_symbol, table_size, shift,
omit_pos, counts)) {
// Use an alternative rebalancing mechanism if the one above failed
// to create a histogram that is positive wherever the original one was.
- if (!RebalanceHistogram<true>(&targets[0], max_symbol, table_size, shift,
+ if (!RebalanceHistogram<true>(targets.data(), max_symbol, table_size, shift,
omit_pos, counts)) {
return JXL_FAILURE("Logic error: couldn't rebalance a histogram");
}
@@ -482,8 +488,8 @@ size_t BuildAndStoreANSEncodingData(
std::vector<ANSHistBin> counts(histogram, histogram + alphabet_size);
if (!counts.empty()) {
size_t sum = 0;
- for (size_t i = 0; i < counts.size(); i++) {
- sum += counts[i];
+ for (int count : counts) {
+ sum += count;
}
if (sum == 0) {
counts[0] = ANS_TAB_SIZE;
@@ -538,8 +544,8 @@ template <typename Writer>
void EncodeUintConfigs(const std::vector<HybridUintConfig>& uint_config,
Writer* writer, size_t log_alpha_size) {
// TODO(veluca): RLE?
- for (size_t i = 0; i < uint_config.size(); i++) {
- EncodeUintConfig(uint_config[i], writer, log_alpha_size);
+ for (const auto& cfg : uint_config) {
+ EncodeUintConfig(cfg, writer, log_alpha_size);
}
}
template void EncodeUintConfigs(const std::vector<HybridUintConfig>&,
@@ -553,8 +559,7 @@ void ChooseUintConfigs(const HistogramParams& params,
std::vector<Histogram>* clustered_histograms,
EntropyEncodingData* codes, size_t* log_alpha_size) {
codes->uint_config.resize(clustered_histograms->size());
- if (params.streaming_mode ||
- params.uint_method == HistogramParams::HybridUintMethod::kNone) {
+ if (params.uint_method == HistogramParams::HybridUintMethod::kNone) {
return;
}
if (params.uint_method == HistogramParams::HybridUintMethod::k000) {
@@ -570,6 +575,12 @@ void ChooseUintConfigs(const HistogramParams& params,
return;
}
+ // If the uint config is adaptive, just stick with the default in streaming
+ // mode.
+ if (params.streaming_mode) {
+ return;
+ }
+
// Brute-force method that tries a few options.
std::vector<HybridUintConfig> configs;
if (params.uint_method == HistogramParams::HybridUintMethod::kBest) {
@@ -619,12 +630,11 @@ void ChooseUintConfigs(const HistogramParams& params,
std::fill(is_valid.begin(), is_valid.end(), true);
std::fill(extra_bits.begin(), extra_bits.end(), 0);
- for (size_t i = 0; i < clustered_histograms->size(); i++) {
- (*clustered_histograms)[i].Clear();
+ for (auto& histo : *clustered_histograms) {
+ histo.Clear();
}
- for (size_t i = 0; i < tokens.size(); ++i) {
- for (size_t j = 0; j < tokens[i].size(); ++j) {
- const Token token = tokens[i][j];
+ for (const auto& stream : tokens) {
+ for (const auto& token : stream) {
// TODO(veluca): do not ignore lz77 commands.
if (token.is_lz77_length) continue;
size_t histo = context_map[token.context];
@@ -632,7 +642,7 @@ void ChooseUintConfigs(const HistogramParams& params,
cfg.Encode(token.value, &tok, &nbits, &bits);
if (tok >= max_alpha ||
(codes->lz77.enabled && tok >= codes->lz77.min_symbol)) {
- is_valid[histo] = false;
+ is_valid[histo] = JXL_FALSE;
continue;
}
extra_bits[histo] += nbits;
@@ -654,13 +664,12 @@ void ChooseUintConfigs(const HistogramParams& params,
}
// Rebuild histograms.
- for (size_t i = 0; i < clustered_histograms->size(); i++) {
- (*clustered_histograms)[i].Clear();
+ for (auto& histo : *clustered_histograms) {
+ histo.Clear();
}
*log_alpha_size = 4;
- for (size_t i = 0; i < tokens.size(); ++i) {
- for (size_t j = 0; j < tokens[i].size(); ++j) {
- const Token token = tokens[i][j];
+ for (const auto& stream : tokens) {
+ for (const auto& token : stream) {
uint32_t tok, nbits, bits;
size_t histo = context_map[token.context];
(token.is_lz77_length ? codes->lz77.length_uint_config
@@ -771,7 +780,7 @@ class HistogramBuilder {
}
SizeWriter size_writer; // Used if writer == nullptr to estimate costs.
cost += 1;
- if (writer) writer->Write(1, codes->use_prefix_code);
+ if (writer) writer->Write(1, TO_JXL_BOOL(codes->use_prefix_code));
if (codes->use_prefix_code) {
log_alpha_size = PREFIX_MAX_BITS;
@@ -785,8 +794,8 @@ class HistogramBuilder {
EncodeUintConfigs(codes->uint_config, writer, log_alpha_size);
}
if (codes->use_prefix_code) {
- for (size_t c = 0; c < clustered_histograms.size(); ++c) {
- size_t alphabet_size = clustered_histograms[c].alphabet_size();
+ for (const auto& histo : clustered_histograms) {
+ size_t alphabet_size = histo.alphabet_size();
if (writer) {
StoreVarLenUint16(alphabet_size - 1, writer);
} else {
@@ -832,9 +841,8 @@ class SymbolCostEstimator {
HistogramBuilder builder(num_contexts);
// Build histograms for estimating lz77 savings.
HybridUintConfig uint_config;
- for (size_t i = 0; i < tokens.size(); ++i) {
- for (size_t j = 0; j < tokens[i].size(); ++j) {
- const Token token = tokens[i][j];
+ for (const auto& stream : tokens) {
+ for (const auto& token : stream) {
uint32_t tok, nbits, bits;
(token.is_lz77_length ? lz77.length_uint_config : uint_config)
.Encode(token.value, &tok, &nbits, &bits);
@@ -1025,12 +1033,7 @@ struct HashChain {
// Count down, so if due to small distance multiplier multiple distances
// map to the same code, the smallest code will be used in the end.
for (int i = kNumSpecialDistances - 1; i >= 0; --i) {
- int xi = kSpecialDistances[i][0];
- int yi = kSpecialDistances[i][1];
- int distance = yi * distance_multiplier + xi;
- // Ensure that we map distance 1 to the lowest symbols.
- if (distance < 1) distance = 1;
- special_dist_table_[distance] = i;
+ special_dist_table_[SpecialDistance(i, distance_multiplier)] = i;
}
num_special_distances_ = kNumSpecialDistances;
}
@@ -1041,9 +1044,9 @@ struct HashChain {
if (pos + 2 < size_) {
// TODO(lode): take the MSB's of the uint32_t values into account as well,
// given that the hash code itself is less than 32 bits.
- result ^= (uint32_t)(data_[pos + 0] << 0u);
- result ^= (uint32_t)(data_[pos + 1] << hash_shift_);
- result ^= (uint32_t)(data_[pos + 2] << (hash_shift_ * 2));
+ result ^= static_cast<uint32_t>(data_[pos + 0] << 0u);
+ result ^= static_cast<uint32_t>(data_[pos + 1] << hash_shift_);
+ result ^= static_cast<uint32_t>(data_[pos + 2] << (hash_shift_ * 2));
} else {
// No need to compute hash of last 2 bytes, the length 2 is too short.
return 0;
@@ -1071,7 +1074,7 @@ struct HashChain {
uint32_t hashval = GetHash(pos);
uint32_t wpos = pos & window_mask_;
- val[wpos] = (int)hashval;
+ val[wpos] = static_cast<int>(hashval);
if (head[hashval] != -1) chain[wpos] = head[hashval];
head[hashval] = wpos;
@@ -1142,7 +1145,10 @@ struct HashChain {
} else {
if (hashpos == chain[hashpos]) break;
hashpos = chain[hashpos];
- if (val[hashpos] != (int)hashval) break; // outdated hash value
+ if (val[hashpos] != static_cast<int>(hashval)) {
+ // outdated hash value
+ break;
+ }
}
}
}
@@ -1274,7 +1280,8 @@ void ApplyLZ77_LZ77(const HistogramParams& params, size_t num_contexts,
HashChain chain(in.data(), in.size(), window_size, min_length, max_length,
distance_multiplier);
- size_t len, dist_symbol;
+ size_t len;
+ size_t dist_symbol;
const size_t max_lazy_match_len = 256; // 0 to disable lazy matching
@@ -1507,7 +1514,7 @@ void EncodeHistograms(const std::vector<uint8_t>& context_map,
}
EncodeContextMap(context_map, codes.encoding_info.size(), writer, layer,
aux_out);
- writer->Write(1, codes.use_prefix_code);
+ writer->Write(1, TO_JXL_BOOL(codes.use_prefix_code));
size_t log_alpha_size = 8;
if (codes.use_prefix_code) {
log_alpha_size = PREFIX_MAX_BITS;
@@ -1583,10 +1590,9 @@ size_t BuildAndEncodeHistograms(const HistogramParams& params,
if (ans_fuzzer_friendly_) {
uint_config = HybridUintConfig(10, 0, 0);
}
- for (size_t i = 0; i < tokens.size(); ++i) {
+ for (const auto& stream : tokens) {
if (codes->lz77.enabled) {
- for (size_t j = 0; j < tokens[i].size(); ++j) {
- const Token& token = tokens[i][j];
+ for (const auto& token : stream) {
total_tokens++;
uint32_t tok, nbits, bits;
(token.is_lz77_length ? codes->lz77.length_uint_config : uint_config)
@@ -1595,16 +1601,14 @@ size_t BuildAndEncodeHistograms(const HistogramParams& params,
builder.VisitSymbol(tok, token.context);
}
} else if (num_contexts == 1) {
- for (size_t j = 0; j < tokens[i].size(); ++j) {
- const Token& token = tokens[i][j];
+ for (const auto& token : stream) {
total_tokens++;
uint32_t tok, nbits, bits;
uint_config.Encode(token.value, &tok, &nbits, &bits);
builder.VisitSymbol(tok, /*token.context=*/0);
}
} else {
- for (size_t j = 0; j < tokens[i].size(); ++j) {
- const Token& token = tokens[i][j];
+ for (const auto& token : stream) {
total_tokens++;
uint32_t tok, nbits, bits;
uint_config.Encode(token.value, &tok, &nbits, &bits);
@@ -1654,10 +1658,10 @@ size_t BuildAndEncodeHistograms(const HistogramParams& params,
codes->encoded_histograms.emplace_back();
BitWriter* histo_writer = &codes->encoded_histograms.back();
BitWriter::Allotment allotment(histo_writer, 256 + alphabet_size * 24);
- BuildAndStoreANSEncodingData(params.ans_histogram_strategy, counts.data(),
- alphabet_size, log_alpha_size,
- codes->use_prefix_code,
- &codes->encoding_info.back()[0], histo_writer);
+ BuildAndStoreANSEncodingData(
+ params.ans_histogram_strategy, counts.data(), alphabet_size,
+ log_alpha_size, codes->use_prefix_code,
+ codes->encoding_info.back().data(), histo_writer);
allotment.ReclaimAndCharge(histo_writer, 0, nullptr);
}
@@ -1680,9 +1684,8 @@ size_t WriteTokens(const std::vector<Token>& tokens,
size_t context_offset, BitWriter* writer) {
size_t num_extra_bits = 0;
if (codes.use_prefix_code) {
- for (size_t i = 0; i < tokens.size(); i++) {
+ for (const auto& token : tokens) {
uint32_t tok, nbits, bits;
- const Token& token = tokens[i];
size_t histo = context_map[context_offset + token.context];
(token.is_lz77_length ? codes.lz77.length_uint_config
: codes.uint_config[histo])
@@ -1693,7 +1696,8 @@ size_t WriteTokens(const std::vector<Token>& tokens,
// codes.encoding_info[histo][tok].bits);
// writer->Write(nbits, bits);
uint64_t data = codes.encoding_info[histo][tok].bits;
- data |= bits << codes.encoding_info[histo][tok].depth;
+ data |= static_cast<uint64_t>(bits)
+ << codes.encoding_info[histo][tok].depth;
writer->Write(codes.encoding_info[histo][tok].depth + nbits, data);
num_extra_bits += nbits;
}
@@ -1765,7 +1769,8 @@ void WriteTokens(const std::vector<Token>& tokens,
const EntropyEncodingData& codes,
const std::vector<uint8_t>& context_map, size_t context_offset,
BitWriter* writer, size_t layer, AuxOut* aux_out) {
- BitWriter::Allotment allotment(writer, 32 * tokens.size() + 32 * 1024 * 4);
+ // Theoretically, we could have 15 prefix code bits + 31 extra bits.
+ BitWriter::Allotment allotment(writer, 46 * tokens.size() + 32 * 1024 * 4);
size_t num_extra_bits =
WriteTokens(tokens, codes, context_map, context_offset, writer);
allotment.ReclaimAndCharge(writer, layer, aux_out);
@@ -1779,4 +1784,51 @@ void SetANSFuzzerFriendly(bool ans_fuzzer_friendly) {
ans_fuzzer_friendly_ = ans_fuzzer_friendly;
#endif
}
+
+HistogramParams HistogramParams::ForModular(
+ const CompressParams& cparams,
+ const std::vector<uint8_t>& extra_dc_precision, bool streaming_mode) {
+ HistogramParams params;
+ params.streaming_mode = streaming_mode;
+ if (cparams.speed_tier > SpeedTier::kKitten) {
+ params.clustering = HistogramParams::ClusteringType::kFast;
+ params.ans_histogram_strategy =
+ cparams.speed_tier > SpeedTier::kThunder
+ ? HistogramParams::ANSHistogramStrategy::kFast
+ : HistogramParams::ANSHistogramStrategy::kApproximate;
+ params.lz77_method =
+ cparams.decoding_speed_tier >= 3 && cparams.modular_mode
+ ? (cparams.speed_tier >= SpeedTier::kFalcon
+ ? HistogramParams::LZ77Method::kRLE
+ : HistogramParams::LZ77Method::kLZ77)
+ : HistogramParams::LZ77Method::kNone;
+ // Near-lossless DC, as well as modular mode, require choosing hybrid uint
+ // more carefully.
+ if ((!extra_dc_precision.empty() && extra_dc_precision[0] != 0) ||
+ (cparams.modular_mode && cparams.speed_tier < SpeedTier::kCheetah)) {
+ params.uint_method = HistogramParams::HybridUintMethod::kFast;
+ } else {
+ params.uint_method = HistogramParams::HybridUintMethod::kNone;
+ }
+ } else if (cparams.speed_tier <= SpeedTier::kTortoise) {
+ params.lz77_method = HistogramParams::LZ77Method::kOptimal;
+ } else {
+ params.lz77_method = HistogramParams::LZ77Method::kLZ77;
+ }
+ if (cparams.decoding_speed_tier >= 1) {
+ params.max_histograms = 12;
+ }
+ if (cparams.decoding_speed_tier >= 1 && cparams.responsive) {
+ params.lz77_method = cparams.speed_tier >= SpeedTier::kCheetah
+ ? HistogramParams::LZ77Method::kRLE
+ : cparams.speed_tier >= SpeedTier::kKitten
+ ? HistogramParams::LZ77Method::kLZ77
+ : HistogramParams::LZ77Method::kOptimal;
+ }
+ if (cparams.decoding_speed_tier >= 2 && cparams.responsive) {
+ params.uint_method = HistogramParams::HybridUintMethod::k000;
+ params.force_huffman = true;
+ }
+ return params;
+}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ans.h b/third_party/jpeg-xl/lib/jxl/enc_ans.h
index 445a5f0c9a..ae4d955a56 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ans.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_ans.h
@@ -84,7 +84,7 @@ struct EntropyEncodingData {
// Integer to be encoded by an entropy coder, either ANS or Huffman.
struct Token {
- Token() {}
+ Token() = default;
Token(uint32_t c, uint32_t value)
: is_lz77_length(false), context(c), value(value) {}
uint32_t is_lz77_length : 1;
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ans_params.h b/third_party/jpeg-xl/lib/jxl/enc_ans_params.h
index 86664f593e..23921097b4 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ans_params.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_ans_params.h
@@ -11,10 +11,15 @@
#include <stdint.h>
#include <stdlib.h>
-#include "lib/jxl/enc_params.h"
+#include <vector>
+
+#include "lib/jxl/common.h"
namespace jxl {
+// Forward declaration to break include cycle.
+struct CompressParams;
+
// RebalanceHistogram requires a signed type.
using ANSHistBin = int32_t;
@@ -65,6 +70,10 @@ struct HistogramParams {
}
}
+ static HistogramParams ForModular(
+ const CompressParams& cparams,
+ const std::vector<uint8_t>& extra_dc_precision, bool streaming_mode);
+
ClusteringType clustering = ClusteringType::kBest;
HybridUintMethod uint_method = HybridUintMethod::kBest;
LZ77Method lz77_method = LZ77Method::kRLE;
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.cc b/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.cc
index ed8a42d299..e80771248e 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.cc
@@ -17,16 +17,10 @@
#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/chroma_from_luma.h"
-#include "lib/jxl/enc_adaptive_quantization.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/image.h"
-#include "lib/jxl/image_bundle.h"
#include "lib/jxl/image_ops.h"
-#include "lib/jxl/quant_weights.h"
-#include "lib/jxl/quantizer.h"
HWY_BEFORE_NAMESPACE();
namespace jxl {
@@ -40,11 +34,12 @@ using hwy::HWY_NAMESPACE::Mul;
using hwy::HWY_NAMESPACE::MulAdd;
using hwy::HWY_NAMESPACE::Sqrt;
-void ProcessTile(const CompressParams& cparams, const FrameHeader& frame_header,
- const Image3F& opsin, const Rect& opsin_rect,
- const ImageF& quant_field, const AcStrategyImage& ac_strategy,
- ImageB* epf_sharpness, const Rect& rect,
- ArControlFieldHeuristics::TempImages* temp_image) {
+Status ProcessTile(const CompressParams& cparams,
+ const FrameHeader& frame_header, const Image3F& opsin,
+ const Rect& opsin_rect, const ImageF& quant_field,
+ const AcStrategyImage& ac_strategy, ImageB* epf_sharpness,
+ const Rect& rect,
+ ArControlFieldHeuristics::TempImages* temp_image) {
JXL_ASSERT(opsin_rect.x0() % 8 == 0);
JXL_ASSERT(opsin_rect.y0() % 8 == 0);
JXL_ASSERT(opsin_rect.xsize() % 8 == 0);
@@ -54,7 +49,7 @@ void ProcessTile(const CompressParams& cparams, const FrameHeader& frame_header,
cparams.speed_tier > SpeedTier::kWombat ||
frame_header.loop_filter.epf_iters == 0) {
FillPlane(static_cast<uint8_t>(4), epf_sharpness, rect);
- return;
+ return true;
}
// Likely better to have a higher X weight, like:
@@ -70,7 +65,7 @@ void ProcessTile(const CompressParams& cparams, const FrameHeader& frame_header,
size_t by1 = by0 + rect.ysize();
size_t bx0 = opsin_rect.x0() / 8 + rect.x0();
size_t bx1 = bx0 + rect.xsize();
- temp_image->InitOnce();
+ JXL_RETURN_IF_ERROR(temp_image->InitOnce());
ImageF& laplacian_sqrsum = temp_image->laplacian_sqrsum;
// Calculate the L2 of the 3x3 Laplacian in an integral transform
// (for example 32x32 dct). This relates to transforms ability
@@ -295,6 +290,7 @@ void ProcessTile(const CompressParams& cparams, const FrameHeader& frame_header,
}
}
}
+ return true;
}
} // namespace
@@ -307,14 +303,14 @@ HWY_AFTER_NAMESPACE();
namespace jxl {
HWY_EXPORT(ProcessTile);
-void ArControlFieldHeuristics::RunRect(
+Status ArControlFieldHeuristics::RunRect(
const CompressParams& cparams, const FrameHeader& frame_header,
const Rect& block_rect, const Image3F& opsin, const Rect& opsin_rect,
const ImageF& quant_field, const AcStrategyImage& ac_strategy,
ImageB* epf_sharpness, size_t thread) {
- HWY_DYNAMIC_DISPATCH(ProcessTile)
- (cparams, frame_header, opsin, opsin_rect, quant_field, ac_strategy,
- epf_sharpness, block_rect, &temp_images[thread]);
+ return HWY_DYNAMIC_DISPATCH(ProcessTile)(
+ cparams, frame_header, opsin, opsin_rect, quant_field, ac_strategy,
+ epf_sharpness, block_rect, &temp_images[thread]);
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.h b/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.h
index fe602c16e3..f3c5a97a1b 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.h
@@ -21,11 +21,15 @@ struct PassesEncoderState;
struct ArControlFieldHeuristics {
struct TempImages {
- void InitOnce() {
- if (laplacian_sqrsum.xsize() != 0) return;
- laplacian_sqrsum = ImageF(kEncTileDim + 4, kEncTileDim + 4);
- sqrsum_00 = ImageF(kEncTileDim / 4, kEncTileDim / 4);
- sqrsum_22 = ImageF(kEncTileDim / 4 + 1, kEncTileDim / 4 + 1);
+ Status InitOnce() {
+ if (laplacian_sqrsum.xsize() != 0) return true;
+ JXL_ASSIGN_OR_RETURN(laplacian_sqrsum,
+ ImageF::Create(kEncTileDim + 4, kEncTileDim + 4));
+ JXL_ASSIGN_OR_RETURN(sqrsum_00,
+ ImageF::Create(kEncTileDim / 4, kEncTileDim / 4));
+ JXL_ASSIGN_OR_RETURN(
+ sqrsum_22, ImageF::Create(kEncTileDim / 4 + 1, kEncTileDim / 4 + 1));
+ return true;
}
ImageF laplacian_sqrsum;
@@ -37,11 +41,11 @@ struct ArControlFieldHeuristics {
temp_images.resize(num_threads);
}
- void RunRect(const CompressParams& cparams, const FrameHeader& frame_header,
- const Rect& block_rect, const Image3F& opsin,
- const Rect& opsin_rect, const ImageF& quant_field,
- const AcStrategyImage& ac_strategy, ImageB* epf_sharpness,
- size_t thread);
+ Status RunRect(const CompressParams& cparams, const FrameHeader& frame_header,
+ const Rect& block_rect, const Image3F& opsin,
+ const Rect& opsin_rect, const ImageF& quant_field,
+ const AcStrategyImage& ac_strategy, ImageB* epf_sharpness,
+ size_t thread);
std::vector<TempImages> temp_images;
};
diff --git a/third_party/jpeg-xl/lib/jxl/enc_aux_out.cc b/third_party/jpeg-xl/lib/jxl/enc_aux_out.cc
index 12c8619e91..d529b381f8 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_aux_out.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_aux_out.cc
@@ -5,16 +5,10 @@
#include "lib/jxl/enc_aux_out.h"
-#ifndef __STDC_FORMAT_MACROS
-#define __STDC_FORMAT_MACROS
-#endif
-
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
-#include <algorithm>
-#include <numeric> // accumulate
#include <sstream>
#include "lib/jxl/base/printf_macros.h"
@@ -61,13 +55,11 @@ const char* LayerName(size_t layer) {
void AuxOut::LayerTotals::Print(size_t num_inputs) const {
if (JXL_DEBUG_V_LEVEL > 0) {
- printf("%10" PRId64, static_cast<int64_t>(total_bits));
+ printf("%10" PRIuS, total_bits);
if (histogram_bits != 0) {
- printf(" [c/i:%6.2f | hst:%8" PRId64 " | ex:%8" PRId64
- " | h+c+e:%12.3f",
- num_clustered_histograms * 1.0 / num_inputs,
- static_cast<int64_t>(histogram_bits >> 3),
- static_cast<int64_t>(extra_bits >> 3),
+ printf(" [c/i:%6.2f | hst:%8" PRIuS " | ex:%8" PRIuS " | h+c+e:%12.3f",
+ num_clustered_histograms * 1.0 / num_inputs, histogram_bits >> 3,
+ extra_bits >> 3,
(histogram_bits + clustered_entropy + extra_bits) / 8.0);
printf("]");
}
@@ -99,8 +91,8 @@ void AuxOut::Print(size_t num_inputs) const {
if (num_inputs == 0) return;
LayerTotals all_layers;
- for (size_t i = 0; i < layers.size(); ++i) {
- all_layers.Assimilate(layers[i]);
+ for (const auto& layer : layers) {
+ all_layers.Assimilate(layer);
}
printf("Average butteraugli iters: %10.2f\n",
diff --git a/third_party/jpeg-xl/lib/jxl/enc_bit_writer.cc b/third_party/jpeg-xl/lib/jxl/enc_bit_writer.cc
index a9a86dca3b..6e6e6a353c 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_bit_writer.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_bit_writer.cc
@@ -5,6 +5,7 @@
#include "lib/jxl/enc_bit_writer.h"
+#include <jxl/types.h>
#include <string.h> // memcpy
#include "lib/jxl/base/byte_order.h"
@@ -43,10 +44,11 @@ void BitWriter::Allotment::FinishedHistogram(BitWriter* JXL_RESTRICT writer) {
void BitWriter::Allotment::ReclaimAndCharge(BitWriter* JXL_RESTRICT writer,
size_t layer,
AuxOut* JXL_RESTRICT aux_out) {
- size_t used_bits = 0, unused_bits = 0;
+ size_t used_bits = 0;
+ size_t unused_bits = 0;
PrivateReclaim(writer, &used_bits, &unused_bits);
-#if 0
+#if JXL_FALSE
printf("Layer %s bits: max %" PRIuS " used %" PRIuS " unused %" PRIuS "\n",
LayerName(layer), MaxBits(), used_bits, unused_bits);
#endif
@@ -77,7 +79,7 @@ void BitWriter::Allotment::PrivateReclaim(BitWriter* JXL_RESTRICT writer,
writer->storage_.resize(writer->storage_.size() - unused_bytes);
writer->current_allotment_ = parent_;
// Ensure we don't also charge the parent for these bits.
- auto parent = parent_;
+ auto* parent = parent_;
while (parent != nullptr) {
parent->prev_bits_written_ += *used_bits;
parent = parent->parent_;
diff --git a/third_party/jpeg-xl/lib/jxl/enc_butteraugli_comparator.cc b/third_party/jpeg-xl/lib/jxl/enc_butteraugli_comparator.cc
index 019d6125a2..b20fa751c1 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_butteraugli_comparator.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_butteraugli_comparator.cc
@@ -5,9 +5,7 @@
#include "lib/jxl/enc_butteraugli_comparator.h"
-#include <algorithm>
-#include <vector>
-
+#include "lib/jxl/base/status.h"
#include "lib/jxl/enc_image_bundle.h"
namespace jxl {
@@ -24,9 +22,8 @@ Status JxlButteraugliComparator::SetReferenceImage(const ImageBundle& ref) {
/*pool=*/nullptr, &store, &ref_linear_srgb)) {
return false;
}
-
- comparator_.reset(
- new ButteraugliComparator(ref_linear_srgb->color(), params_));
+ JXL_ASSIGN_OR_RETURN(comparator_, ButteraugliComparator::Make(
+ ref_linear_srgb->color(), params_));
xsize_ = ref.xsize();
ysize_ = ref.ysize();
return true;
@@ -34,7 +31,8 @@ Status JxlButteraugliComparator::SetReferenceImage(const ImageBundle& ref) {
Status JxlButteraugliComparator::SetLinearReferenceImage(
const Image3F& linear) {
- comparator_.reset(new ButteraugliComparator(linear, params_));
+ JXL_ASSIGN_OR_RETURN(comparator_,
+ ButteraugliComparator::Make(linear, params_));
xsize_ = linear.xsize();
ysize_ = linear.ysize();
return true;
@@ -58,8 +56,9 @@ Status JxlButteraugliComparator::CompareWith(const ImageBundle& actual,
return false;
}
- ImageF temp_diffmap(xsize_, ysize_);
- comparator_->Diffmap(actual_linear_srgb->color(), temp_diffmap);
+ JXL_ASSIGN_OR_RETURN(ImageF temp_diffmap, ImageF::Create(xsize_, ysize_));
+ JXL_RETURN_IF_ERROR(
+ comparator_->Diffmap(actual_linear_srgb->color(), temp_diffmap));
if (score != nullptr) {
*score = ButteraugliScoreFromDiffmap(temp_diffmap, &params_);
@@ -79,29 +78,4 @@ float JxlButteraugliComparator::BadQualityScore() const {
return ButteraugliFuzzyInverse(0.5);
}
-float ButteraugliDistance(const ImageBundle& rgb0, const ImageBundle& rgb1,
- const ButteraugliParams& params,
- const JxlCmsInterface& cms, ImageF* distmap,
- ThreadPool* pool, bool ignore_alpha) {
- JxlButteraugliComparator comparator(params, cms);
- return ComputeScore(rgb0, rgb1, &comparator, cms, distmap, pool,
- ignore_alpha);
-}
-
-float ButteraugliDistance(const std::vector<ImageBundle>& frames0,
- const std::vector<ImageBundle>& frames1,
- const ButteraugliParams& params,
- const JxlCmsInterface& cms, ImageF* distmap,
- ThreadPool* pool) {
- JxlButteraugliComparator comparator(params, cms);
- JXL_ASSERT(frames0.size() == frames1.size());
- float max_dist = 0.0f;
- for (size_t i = 0; i < frames0.size(); ++i) {
- max_dist = std::max(
- max_dist,
- ComputeScore(frames0[i], frames1[i], &comparator, cms, distmap, pool));
- }
- return max_dist;
-}
-
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_butteraugli_comparator.h b/third_party/jpeg-xl/lib/jxl/enc_butteraugli_comparator.h
index 641d7732d5..4f70e21a1b 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_butteraugli_comparator.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_butteraugli_comparator.h
@@ -10,9 +10,7 @@
#include <stddef.h>
#include <memory>
-#include <vector>
-#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/butteraugli/butteraugli.h"
#include "lib/jxl/enc_comparator.h"
@@ -43,20 +41,6 @@ class JxlButteraugliComparator : public Comparator {
size_t ysize_ = 0;
};
-// Returns the butteraugli distance between rgb0 and rgb1.
-// If distmap is not null, it must be the same size as rgb0 and rgb1.
-float ButteraugliDistance(const ImageBundle& rgb0, const ImageBundle& rgb1,
- const ButteraugliParams& params,
- const JxlCmsInterface& cms, ImageF* distmap = nullptr,
- ThreadPool* pool = nullptr,
- bool ignore_alpha = false);
-
-float ButteraugliDistance(const std::vector<ImageBundle>& frames0,
- const std::vector<ImageBundle>& frames1,
- const ButteraugliParams& params,
- const JxlCmsInterface& cms, ImageF* distmap = nullptr,
- ThreadPool* pool = nullptr);
-
} // namespace jxl
#endif // LIB_JXL_ENC_BUTTERAUGLI_COMPARATOR_H_
diff --git a/third_party/jpeg-xl/lib/jxl/enc_cache.cc b/third_party/jpeg-xl/lib/jxl/enc_cache.cc
index ff62c57e4d..200ec83b65 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_cache.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_cache.cc
@@ -8,15 +8,14 @@
#include <stddef.h>
#include <stdint.h>
-#include <type_traits>
+#include <memory>
-#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/span.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/compressed_dc.h"
-#include "lib/jxl/dct_scales.h"
#include "lib/jxl/dct_util.h"
#include "lib/jxl/dec_frame.h"
#include "lib/jxl/enc_aux_out.h"
@@ -50,8 +49,11 @@ Status InitializePassesEncoder(const FrameHeader& frame_header,
for (size_t i = enc_state->coeffs.size();
i < frame_header.passes.num_passes; i++) {
// Allocate enough coefficients for each group on every row.
- enc_state->coeffs.emplace_back(make_unique<ACImageT<int32_t>>(
- kGroupDim * kGroupDim, shared.frame_dim.num_groups));
+ JXL_ASSIGN_OR_RETURN(
+ std::unique_ptr<ACImageT<int32_t>> coeffs,
+ ACImageT<int32_t>::Make(kGroupDim * kGroupDim,
+ shared.frame_dim.num_groups));
+ enc_state->coeffs.emplace_back(std::move(coeffs));
}
}
while (enc_state->coeffs.size() > frame_header.passes.num_passes) {
@@ -65,7 +67,9 @@ Status InitializePassesEncoder(const FrameHeader& frame_header,
shared.quantizer.RecomputeFromGlobalScale();
}
- Image3F dc(shared.frame_dim.xsize_blocks, shared.frame_dim.ysize_blocks);
+ JXL_ASSIGN_OR_RETURN(Image3F dc,
+ Image3F::Create(shared.frame_dim.xsize_blocks,
+ shared.frame_dim.ysize_blocks));
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, shared.frame_dim.num_groups, ThreadPool::NoInit,
[&](size_t group_idx, size_t _) {
@@ -90,9 +94,9 @@ Status InitializePassesEncoder(const FrameHeader& frame_header,
// and kModular for the smallest DC (first in the bitstream)
if (cparams.progressive_dc == 0) {
cparams.modular_mode = true;
- cparams.speed_tier =
- SpeedTier(std::max(static_cast<int>(SpeedTier::kTortoise),
- static_cast<int>(cparams.speed_tier) - 1));
+ cparams.speed_tier = static_cast<SpeedTier>(
+ std::max(static_cast<int>(SpeedTier::kTortoise),
+ static_cast<int>(cparams.speed_tier) - 1));
cparams.butteraugli_distance =
std::max(kMinButteraugliDistance,
enc_state->cparams.butteraugli_distance * 0.02f);
@@ -120,7 +124,8 @@ Status InitializePassesEncoder(const FrameHeader& frame_header,
std::vector<ImageF> extra_channels;
extra_channels.reserve(ib.metadata()->extra_channel_info.size());
for (size_t i = 0; i < ib.metadata()->extra_channel_info.size(); i++) {
- extra_channels.emplace_back(ib.xsize(), ib.ysize());
+ JXL_ASSIGN_OR_RETURN(ImageF ch, ImageF::Create(ib.xsize(), ib.ysize()));
+ extra_channels.emplace_back(std::move(ch));
// Must initialize the image with data to not affect blending with
// uninitialized memory.
// TODO(lode): dc_level must copy and use the real extra channels
@@ -168,32 +173,41 @@ Status InitializePassesEncoder(const FrameHeader& frame_header,
// outputs multiple frames, this assumption could be wrong.
const Image3F& dc_frame =
dec_state->shared->dc_frames[frame_header.dc_level];
- shared.dc_storage = Image3F(dc_frame.xsize(), dc_frame.ysize());
+ JXL_ASSIGN_OR_RETURN(shared.dc_storage,
+ Image3F::Create(dc_frame.xsize(), dc_frame.ysize()));
CopyImageTo(dc_frame, &shared.dc_storage);
ZeroFillImage(&shared.quant_dc);
shared.dc = &shared.dc_storage;
JXL_CHECK(encoded_size == 0);
} else {
+ std::atomic<bool> has_error{false};
auto compute_dc_coeffs = [&](int group_index, int /* thread */) {
+ if (has_error) return;
const Rect r = enc_state->shared.frame_dim.DCGroupRect(group_index);
int modular_group_index = group_index;
if (enc_state->streaming_mode) {
JXL_ASSERT(group_index == 0);
modular_group_index = enc_state->dc_group_index;
}
- modular_frame_encoder->AddVarDCTDC(
- frame_header, dc, r, modular_group_index,
- enc_state->cparams.speed_tier < SpeedTier::kFalcon, enc_state,
- /*jpeg_transcode=*/false);
+ if (!modular_frame_encoder->AddVarDCTDC(
+ frame_header, dc, r, modular_group_index,
+ enc_state->cparams.speed_tier < SpeedTier::kFalcon, enc_state,
+ /*jpeg_transcode=*/false)) {
+ has_error = true;
+ return;
+ }
};
JXL_RETURN_IF_ERROR(RunOnPool(pool, 0, shared.frame_dim.num_dc_groups,
ThreadPool::NoInit, compute_dc_coeffs,
"Compute DC coeffs"));
+ if (has_error) return JXL_FAILURE("Compute DC coeffs failed");
// TODO(veluca): this is only useful in tests and if inspection is enabled.
if (!(frame_header.flags & FrameHeader::kSkipAdaptiveDCSmoothing)) {
- AdaptiveDCSmoothing(shared.quantizer.MulDC(), &shared.dc_storage, pool);
+ JXL_RETURN_IF_ERROR(AdaptiveDCSmoothing(shared.quantizer.MulDC(),
+ &shared.dc_storage, pool));
}
}
+ std::atomic<bool> has_error{false};
auto compute_ac_meta = [&](int group_index, int /* thread */) {
const Rect r = enc_state->shared.frame_dim.DCGroupRect(group_index);
int modular_group_index = group_index;
@@ -201,13 +215,17 @@ Status InitializePassesEncoder(const FrameHeader& frame_header,
JXL_ASSERT(group_index == 0);
modular_group_index = enc_state->dc_group_index;
}
- modular_frame_encoder->AddACMetadata(r, modular_group_index,
- /*jpeg_transcode=*/false, enc_state);
+ if (!modular_frame_encoder->AddACMetadata(r, modular_group_index,
+ /*jpeg_transcode=*/false,
+ enc_state)) {
+ has_error = true;
+ return;
+ }
};
JXL_RETURN_IF_ERROR(RunOnPool(pool, 0, shared.frame_dim.num_dc_groups,
ThreadPool::NoInit, compute_ac_meta,
"Compute AC Metadata"));
-
+ if (has_error) return JXL_FAILURE("Compute AC Metadata failed");
return true;
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_cache.h b/third_party/jpeg-xl/lib/jxl/enc_cache.h
index 6efcc081c1..43ee7bc9c8 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_cache.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_cache.h
@@ -55,7 +55,7 @@ struct PassesEncoderState {
};
std::vector<PassData> passes;
- std::vector<uint8_t> histogram_idx;
+ std::vector<size_t> histogram_idx;
// Block sizes seen so far.
uint32_t used_acs = 0;
diff --git a/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.cc b/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.cc
index 9a894d89cc..4039da2858 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.cc
@@ -9,7 +9,6 @@
#include <stdlib.h>
#include <algorithm>
-#include <array>
#include <cmath>
#undef HWY_TARGET_INCLUDE
@@ -18,18 +17,13 @@
#include <hwy/foreach_target.h>
#include <hwy/highway.h>
-#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/common.h"
-#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/cms/opsin_params.h"
#include "lib/jxl/dec_transforms-inl.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/enc_transforms-inl.h"
-#include "lib/jxl/entropy_coder.h"
-#include "lib/jxl/image_ops.h"
-#include "lib/jxl/modular/encoding/encoding.h"
#include "lib/jxl/quantizer.h"
#include "lib/jxl/simd_util.h"
HWY_BEFORE_NAMESPACE();
@@ -149,7 +143,8 @@ int32_t FindBestMultiplier(const float* values_m, const float* values_s,
// Derivatives are approximate due to the high amount of noise in the exact
// derivatives.
for (size_t i = 0; i < 20; i++) {
- float dfpeps, dfmeps;
+ float dfpeps;
+ float dfmeps;
float df = fn.Compute(x, eps, &dfpeps, &dfmeps);
float ddf = (dfpeps - dfmeps) / (2 * eps);
float kExperimentalInsignificantStabilizer = 0.85;
@@ -175,12 +170,13 @@ int32_t FindBestMultiplier(const float* values_m, const float* values_s,
return std::max(-128.0f, std::min(127.0f, roundf(x)));
}
-void InitDCStorage(size_t num_blocks, ImageF* dc_values) {
+Status InitDCStorage(size_t num_blocks, ImageF* dc_values) {
// First row: Y channel
// Second row: X channel
// Third row: Y channel
// Fourth row: B channel
- *dc_values = ImageF(RoundUpTo(num_blocks, Lanes(df)), 4);
+ JXL_ASSIGN_OR_RETURN(*dc_values,
+ ImageF::Create(RoundUpTo(num_blocks, Lanes(df)), 4));
JXL_ASSERT(dc_values->xsize() != 0);
// Zero-fill the last lanes
@@ -190,6 +186,7 @@ void InitDCStorage(size_t num_blocks, ImageF* dc_values) {
dc_values->Row(y)[x] = 0;
}
}
+ return true;
}
void ComputeTile(const Image3F& opsin, const Rect& opsin_rect,
@@ -352,11 +349,11 @@ namespace jxl {
HWY_EXPORT(InitDCStorage);
HWY_EXPORT(ComputeTile);
-void CfLHeuristics::Init(const Rect& rect) {
+Status CfLHeuristics::Init(const Rect& rect) {
size_t xsize_blocks = rect.xsize() / kBlockDim;
size_t ysize_blocks = rect.ysize() / kBlockDim;
- HWY_DYNAMIC_DISPATCH(InitDCStorage)
- (xsize_blocks * ysize_blocks, &dc_values);
+ return HWY_DYNAMIC_DISPATCH(InitDCStorage)(xsize_blocks * ysize_blocks,
+ &dc_values);
}
void CfLHeuristics::ComputeTile(const Rect& r, const Image3F& opsin,
diff --git a/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.h b/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.h
index 04743842bf..c6481a0ec9 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.h
@@ -29,7 +29,7 @@ void ColorCorrelationMapEncodeDC(const ColorCorrelationMap& map,
AuxOut* aux_out);
struct CfLHeuristics {
- void Init(const Rect& rect);
+ Status Init(const Rect& rect);
void PrepareForThreads(size_t num_threads) {
mem = hwy::AllocateAligned<float>(num_threads * ItemsPerThread());
diff --git a/third_party/jpeg-xl/lib/jxl/enc_cluster.cc b/third_party/jpeg-xl/lib/jxl/enc_cluster.cc
index df1b31ddf7..f7284331d9 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_cluster.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_cluster.cc
@@ -236,7 +236,7 @@ void HistogramReindex(std::vector<Histogram>* out, size_t prev_histograms,
// Clusters similar histograms in 'in' together, the selected histograms are
// placed in 'out', and for each index in 'in', *histogram_symbols will
// indicate which of the 'out' histograms is the best approximation.
-void ClusterHistograms(const HistogramParams params,
+void ClusterHistograms(const HistogramParams& params,
const std::vector<Histogram>& in, size_t max_histograms,
std::vector<Histogram>* out,
std::vector<uint32_t>* histogram_symbols) {
@@ -252,9 +252,9 @@ void ClusterHistograms(const HistogramParams params,
if (prev_histograms == 0 &&
params.clustering == HistogramParams::ClusteringType::kBest) {
- for (size_t i = 0; i < out->size(); i++) {
- (*out)[i].entropy_ =
- ANSPopulationCost((*out)[i].data_.data(), (*out)[i].data_.size());
+ for (auto& histo : *out) {
+ histo.entropy_ =
+ ANSPopulationCost(histo.data_.data(), histo.data_.size());
}
uint32_t next_version = 2;
std::vector<uint32_t> version(out->size(), 1);
@@ -308,9 +308,9 @@ void ClusterHistograms(const HistogramParams params,
(*out)[first].AddHistogram((*out)[second]);
(*out)[first].entropy_ = ANSPopulationCost((*out)[first].data_.data(),
(*out)[first].data_.size());
- for (size_t i = 0; i < renumbering.size(); i++) {
- if (renumbering[i] == second) {
- renumbering[i] = first;
+ for (uint32_t& item : renumbering) {
+ if (item == second) {
+ item = first;
}
}
version[second] = 0;
@@ -338,9 +338,8 @@ void ClusterHistograms(const HistogramParams params,
reverse_renumbering[i] = num_alive - 1;
}
out->resize(num_alive);
- for (size_t i = 0; i < histogram_symbols->size(); i++) {
- (*histogram_symbols)[i] =
- reverse_renumbering[renumbering[(*histogram_symbols)[i]]];
+ for (uint32_t& item : *histogram_symbols) {
+ item = reverse_renumbering[renumbering[item]];
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_cluster.h b/third_party/jpeg-xl/lib/jxl/enc_cluster.h
index 923aaaccfe..7ddc003cf2 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_cluster.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_cluster.h
@@ -15,6 +15,7 @@
#include <vector>
#include "lib/jxl/ans_params.h"
+#include "lib/jxl/base/common.h"
#include "lib/jxl/enc_ans_params.h"
namespace jxl {
@@ -61,8 +62,9 @@ struct Histogram {
static constexpr size_t kRounding = 8;
};
-void ClusterHistograms(HistogramParams params, const std::vector<Histogram>& in,
- size_t max_histograms, std::vector<Histogram>* out,
+void ClusterHistograms(const HistogramParams& params,
+ const std::vector<Histogram>& in, size_t max_histograms,
+ std::vector<Histogram>* out,
std::vector<uint32_t>* histogram_symbols);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_coeff_order.cc b/third_party/jpeg-xl/lib/jxl/enc_coeff_order.cc
index 5be012aa92..49129f5d9e 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_coeff_order.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_coeff_order.cc
@@ -6,21 +6,16 @@
#include <stdint.h>
#include <algorithm>
+#include <cmath>
#include <hwy/aligned_allocator.h>
#include <vector>
-#include "lib/jxl/ans_params.h"
-#include "lib/jxl/base/span.h"
#include "lib/jxl/coeff_order.h"
#include "lib/jxl/coeff_order_fwd.h"
-#include "lib/jxl/dec_ans.h"
-#include "lib/jxl/dec_bit_reader.h"
+#include "lib/jxl/dct_util.h"
#include "lib/jxl/enc_ans.h"
#include "lib/jxl/enc_bit_writer.h"
-#include "lib/jxl/entropy_coder.h"
#include "lib/jxl/lehmer_code.h"
-#include "lib/jxl/modular/encoding/encoding.h"
-#include "lib/jxl/modular/modular_image.h"
namespace jxl {
@@ -240,7 +235,7 @@ void EncodePermutation(const coeff_order_t* JXL_RESTRICT order, size_t skip,
size_t size, BitWriter* writer, int layer,
AuxOut* aux_out) {
std::vector<std::vector<Token>> tokens(1);
- TokenizePermutation(order, skip, size, &tokens[0]);
+ TokenizePermutation(order, skip, size, tokens.data());
std::vector<uint8_t> context_map;
EntropyEncodingData codes;
BuildAndEncodeHistograms(HistogramParams(), kPermutationContexts, tokens,
@@ -280,7 +275,7 @@ void EncodeCoeffOrders(uint16_t used_orders,
if (natural_order_lut.size() < size) natural_order_lut.resize(size);
acs.ComputeNaturalCoeffOrderLut(natural_order_lut.data());
for (size_t c = 0; c < 3; c++) {
- EncodeCoeffOrder(&order[CoeffOrderOffset(ord, c)], acs, &tokens[0],
+ EncodeCoeffOrder(&order[CoeffOrderOffset(ord, c)], acs, tokens.data(),
mem.get(), natural_order_lut);
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_comparator.cc b/third_party/jpeg-xl/lib/jxl/enc_comparator.cc
index 268122af06..3ef6a49b8f 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_comparator.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_comparator.cc
@@ -66,9 +66,10 @@ float ComputeScoreImpl(const ImageBundle& rgb0, const ImageBundle& rgb1,
} // namespace
-float ComputeScore(const ImageBundle& rgb0, const ImageBundle& rgb1,
- Comparator* comparator, const JxlCmsInterface& cms,
- ImageF* diffmap, ThreadPool* pool, bool ignore_alpha) {
+Status ComputeScore(const ImageBundle& rgb0, const ImageBundle& rgb1,
+ Comparator* comparator, const JxlCmsInterface& cms,
+ float* score, ImageF* diffmap, ThreadPool* pool,
+ bool ignore_alpha) {
// Convert to linear sRGB (unless already in that space)
ImageMetadata metadata0 = *rgb0.metadata();
ImageBundle store0(&metadata0);
@@ -83,25 +84,28 @@ float ComputeScore(const ImageBundle& rgb0, const ImageBundle& rgb1,
// No alpha: skip blending, only need a single call to Butteraugli.
if (ignore_alpha || (!rgb0.HasAlpha() && !rgb1.HasAlpha())) {
- return ComputeScoreImpl(*linear_srgb0, *linear_srgb1, comparator, diffmap);
+ *score =
+ ComputeScoreImpl(*linear_srgb0, *linear_srgb1, comparator, diffmap);
+ return true;
}
// Blend on black and white backgrounds
const float black = 0.0f;
- ImageBundle blended_black0 = linear_srgb0->Copy();
- ImageBundle blended_black1 = linear_srgb1->Copy();
+ JXL_ASSIGN_OR_RETURN(ImageBundle blended_black0, linear_srgb0->Copy());
+ JXL_ASSIGN_OR_RETURN(ImageBundle blended_black1, linear_srgb1->Copy());
AlphaBlend(black, &blended_black0);
AlphaBlend(black, &blended_black1);
const float white = 1.0f;
- ImageBundle blended_white0 = linear_srgb0->Copy();
- ImageBundle blended_white1 = linear_srgb1->Copy();
+ JXL_ASSIGN_OR_RETURN(ImageBundle blended_white0, linear_srgb0->Copy());
+ JXL_ASSIGN_OR_RETURN(ImageBundle blended_white1, linear_srgb1->Copy());
AlphaBlend(white, &blended_white0);
AlphaBlend(white, &blended_white1);
- ImageF diffmap_black, diffmap_white;
+ ImageF diffmap_black;
+ ImageF diffmap_white;
const float dist_black = ComputeScoreImpl(blended_black0, blended_black1,
comparator, &diffmap_black);
const float dist_white = ComputeScoreImpl(blended_white0, blended_white1,
@@ -111,7 +115,7 @@ float ComputeScore(const ImageBundle& rgb0, const ImageBundle& rgb1,
if (diffmap != nullptr) {
const size_t xsize = rgb0.xsize();
const size_t ysize = rgb0.ysize();
- *diffmap = ImageF(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(*diffmap, ImageF::Create(xsize, ysize));
for (size_t y = 0; y < ysize; ++y) {
const float* JXL_RESTRICT row_black = diffmap_black.ConstRow(y);
const float* JXL_RESTRICT row_white = diffmap_white.ConstRow(y);
@@ -121,7 +125,8 @@ float ComputeScore(const ImageBundle& rgb0, const ImageBundle& rgb1,
}
}
}
- return std::max(dist_black, dist_white);
+ *score = std::max(dist_black, dist_white);
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_comparator.h b/third_party/jpeg-xl/lib/jxl/enc_comparator.h
index c545ea6111..ee62ab6f28 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_comparator.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_comparator.h
@@ -43,10 +43,10 @@ class Comparator {
// Computes the score given images in any RGB color model, optionally with
// alpha channel.
-float ComputeScore(const ImageBundle& rgb0, const ImageBundle& rgb1,
- Comparator* comparator, const JxlCmsInterface& cms,
- ImageF* diffmap = nullptr, ThreadPool* pool = nullptr,
- bool ignore_alpha = false);
+Status ComputeScore(const ImageBundle& rgb0, const ImageBundle& rgb1,
+ Comparator* comparator, const JxlCmsInterface& cms,
+ float* score, ImageF* diffmap = nullptr,
+ ThreadPool* pool = nullptr, bool ignore_alpha = false);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_context_map.cc b/third_party/jpeg-xl/lib/jxl/enc_context_map.cc
index 6968a6fbae..36efc4e649 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_context_map.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_context_map.cc
@@ -7,6 +7,7 @@
#include "lib/jxl/enc_context_map.h"
+#include <jxl/types.h>
#include <stdint.h>
#include <algorithm>
@@ -18,6 +19,7 @@
#include "lib/jxl/enc_ans.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/entropy_coder.h"
+#include "lib/jxl/fields.h"
#include "lib/jxl/pack_signed.h"
namespace jxl {
@@ -69,16 +71,18 @@ void EncodeContextMap(const std::vector<uint8_t>& context_map,
}
std::vector<uint8_t> transformed_symbols = MoveToFrontTransform(context_map);
- std::vector<std::vector<Token>> tokens(1), mtf_tokens(1);
- for (size_t i = 0; i < context_map.size(); i++) {
- tokens[0].emplace_back(0, context_map[i]);
+ std::vector<std::vector<Token>> tokens(1);
+ std::vector<std::vector<Token>> mtf_tokens(1);
+ for (const uint8_t& ctx : context_map) {
+ tokens[0].emplace_back(0, ctx);
}
- for (size_t i = 0; i < transformed_symbols.size(); i++) {
- mtf_tokens[0].emplace_back(0, transformed_symbols[i]);
+ for (const uint8_t& sym : transformed_symbols) {
+ mtf_tokens[0].emplace_back(0, sym);
}
HistogramParams params;
params.uint_method = HistogramParams::HybridUintMethod::kContextMap;
- size_t ans_cost, mtf_cost;
+ size_t ans_cost;
+ size_t mtf_cost;
{
EntropyEncodingData codes;
std::vector<uint8_t> sink_context_map;
@@ -104,14 +108,14 @@ void EncodeContextMap(const std::vector<uint8_t>& context_map,
BitWriter::Allotment allotment(writer, 3 + entry_bits * context_map.size());
writer->Write(1, 1);
writer->Write(2, entry_bits);
- for (size_t i = 0; i < context_map.size(); i++) {
- writer->Write(entry_bits, context_map[i]);
+ for (uint8_t entry : context_map) {
+ writer->Write(entry_bits, entry);
}
allotment.ReclaimAndCharge(writer, layer, aux_out);
} else {
BitWriter::Allotment allotment(writer, 2 + tokens[0].size() * 24);
writer->Write(1, 0);
- writer->Write(1, use_mtf); // Use/don't use MTF.
+ writer->Write(1, TO_JXL_BOOL(use_mtf)); // Use/don't use MTF.
EntropyEncodingData codes;
std::vector<uint8_t> sink_context_map;
BuildAndEncodeHistograms(params, 1, tokens, &codes, &sink_context_map,
@@ -123,9 +127,9 @@ void EncodeContextMap(const std::vector<uint8_t>& context_map,
void EncodeBlockCtxMap(const BlockCtxMap& block_ctx_map, BitWriter* writer,
AuxOut* aux_out) {
- auto& dct = block_ctx_map.dc_thresholds;
- auto& qft = block_ctx_map.qf_thresholds;
- auto& ctx_map = block_ctx_map.ctx_map;
+ const auto& dct = block_ctx_map.dc_thresholds;
+ const auto& qft = block_ctx_map.qf_thresholds;
+ const auto& ctx_map = block_ctx_map.ctx_map;
BitWriter::Allotment allotment(
writer,
(dct[0].size() + dct[1].size() + dct[2].size() + qft.size()) * 34 + 1 +
diff --git a/third_party/jpeg-xl/lib/jxl/enc_debug_image.cc b/third_party/jpeg-xl/lib/jxl/enc_debug_image.cc
index 261570e690..d67ab7db46 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_debug_image.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_debug_image.cc
@@ -18,32 +18,29 @@ namespace jxl {
namespace {
template <typename From>
-Plane<float> ConvertToFloat(const Plane<From>& from) {
+StatusOr<Image3F> ConvertToFloat(const Image3<From>& from) {
float factor = 1.0f / std::numeric_limits<From>::max();
if (std::is_same<From, double>::value || std::is_same<From, float>::value) {
factor = 1.0f;
}
- Plane<float> to(from.xsize(), from.ysize());
- for (size_t y = 0; y < from.ysize(); ++y) {
- const From* const JXL_RESTRICT row_from = from.Row(y);
- float* const JXL_RESTRICT row_to = to.Row(y);
- for (size_t x = 0; x < from.xsize(); ++x) {
- row_to[x] = row_from[x] * factor;
+ JXL_ASSIGN_OR_RETURN(Image3F to, Image3F::Create(from.xsize(), from.ysize()));
+ for (size_t c = 0; c < 3; ++c) {
+ for (size_t y = 0; y < from.ysize(); ++y) {
+ const From* const JXL_RESTRICT row_from = from.ConstPlaneRow(c, y);
+ float* const JXL_RESTRICT row_to = to.PlaneRow(c, y);
+ for (size_t x = 0; x < from.xsize(); ++x) {
+ row_to[x] = row_from[x] * factor;
+ }
}
}
return to;
}
-template <typename From>
-Image3F ConvertToFloat(const Image3<From>& from) {
- return Image3F(ConvertToFloat(from.Plane(0)), ConvertToFloat(from.Plane(1)),
- ConvertToFloat(from.Plane(2)));
-}
template <typename T>
-void DumpImageT(const CompressParams& cparams, const char* label,
- const ColorEncoding& color_encoding, const Image3<T>& image) {
- if (!cparams.debug_image) return;
- Image3F float_image = ConvertToFloat(image);
+Status DumpImageT(const CompressParams& cparams, const char* label,
+ const ColorEncoding& color_encoding, const Image3<T>& image) {
+ if (!cparams.debug_image) return true;
+ JXL_ASSIGN_OR_RETURN(Image3F float_image, ConvertToFloat(image));
JxlColorEncoding color = color_encoding.ToExternal();
size_t num_pixels = 3 * image.xsize() * image.ysize();
std::vector<uint16_t> pixels(num_pixels);
@@ -53,18 +50,20 @@ void DumpImageT(const CompressParams& cparams, const char* label,
}
JXL_CHECK(ConvertChannelsToExternal(
channels, 3, 16, false, JXL_BIG_ENDIAN, 6 * image.xsize(), nullptr,
- &pixels[0], 2 * num_pixels, PixelCallback(), Orientation::kIdentity));
+ pixels.data(), 2 * num_pixels, PixelCallback(), Orientation::kIdentity));
(*cparams.debug_image)(cparams.debug_image_opaque, label, image.xsize(),
- image.ysize(), &color, &pixels[0]);
+ image.ysize(), &color, pixels.data());
+ return true;
}
template <typename T>
-void DumpPlaneNormalizedT(const CompressParams& cparams, const char* label,
- const Plane<T>& image) {
+Status DumpPlaneNormalizedT(const CompressParams& cparams, const char* label,
+ const Plane<T>& image) {
T min;
T max;
ImageMinMax(image, &min, &max);
- Image3B normalized(image.xsize(), image.ysize());
+ JXL_ASSIGN_OR_RETURN(Image3B normalized,
+ Image3B::Create(image.xsize(), image.ysize()));
for (size_t c = 0; c < 3; ++c) {
float mul = min == max ? 0 : (255.0f / (max - min));
for (size_t y = 0; y < image.ysize(); ++y) {
@@ -75,41 +74,42 @@ void DumpPlaneNormalizedT(const CompressParams& cparams, const char* label,
}
}
}
- DumpImageT(cparams, label, ColorEncoding::SRGB(), normalized);
+ return DumpImageT(cparams, label, ColorEncoding::SRGB(), normalized);
}
} // namespace
-void DumpImage(const CompressParams& cparams, const char* label,
- const Image3<float>& image) {
- DumpImageT(cparams, label, ColorEncoding::SRGB(), image);
+Status DumpImage(const CompressParams& cparams, const char* label,
+ const Image3<float>& image) {
+ return DumpImageT(cparams, label, ColorEncoding::SRGB(), image);
}
-void DumpImage(const CompressParams& cparams, const char* label,
- const Image3<uint8_t>& image) {
- DumpImageT(cparams, label, ColorEncoding::SRGB(), image);
+Status DumpImage(const CompressParams& cparams, const char* label,
+ const Image3<uint8_t>& image) {
+ return DumpImageT(cparams, label, ColorEncoding::SRGB(), image);
}
-void DumpXybImage(const CompressParams& cparams, const char* label,
- const Image3F& image) {
- if (!cparams.debug_image) return;
+Status DumpXybImage(const CompressParams& cparams, const char* label,
+ const Image3F& image) {
+ if (!cparams.debug_image) return true;
- Image3F linear(image.xsize(), image.ysize());
+ JXL_ASSIGN_OR_RETURN(Image3F linear,
+ Image3F::Create(image.xsize(), image.ysize()));
OpsinParams opsin_params;
opsin_params.Init(kDefaultIntensityTarget);
OpsinToLinear(image, Rect(linear), nullptr, &linear, opsin_params);
- DumpImageT(cparams, label, ColorEncoding::LinearSRGB(), linear);
+ return DumpImageT(cparams, label, ColorEncoding::LinearSRGB(), linear);
}
-void DumpPlaneNormalized(const CompressParams& cparams, const char* label,
- const Plane<float>& image) {
- DumpPlaneNormalizedT(cparams, label, image);
+Status DumpPlaneNormalized(const CompressParams& cparams, const char* label,
+ const Plane<float>& image) {
+ return DumpPlaneNormalizedT(cparams, label, image);
}
-void DumpPlaneNormalized(const CompressParams& cparams, const char* label,
- const Plane<uint8_t>& image) {
- DumpPlaneNormalizedT(cparams, label, image);
+Status DumpPlaneNormalized(const CompressParams& cparams, const char* label,
+ const Plane<uint8_t>& image) {
+ return DumpPlaneNormalizedT(cparams, label, image);
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_debug_image.h b/third_party/jpeg-xl/lib/jxl/enc_debug_image.h
index 33799a5f7f..428293f8bc 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_debug_image.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_debug_image.h
@@ -16,16 +16,16 @@
namespace jxl {
-void DumpImage(const CompressParams& cparams, const char* label,
- const Image3<float>& image);
-void DumpImage(const CompressParams& cparams, const char* label,
- const Image3<uint8_t>& image);
-void DumpXybImage(const CompressParams& cparams, const char* label,
- const Image3<float>& image);
-void DumpPlaneNormalized(const CompressParams& cparams, const char* label,
- const Plane<float>& image);
-void DumpPlaneNormalized(const CompressParams& cparams, const char* label,
- const Plane<uint8_t>& image);
+Status DumpImage(const CompressParams& cparams, const char* label,
+ const Image3<float>& image);
+Status DumpImage(const CompressParams& cparams, const char* label,
+ const Image3<uint8_t>& image);
+Status DumpXybImage(const CompressParams& cparams, const char* label,
+ const Image3<float>& image);
+Status DumpPlaneNormalized(const CompressParams& cparams, const char* label,
+ const Plane<float>& image);
+Status DumpPlaneNormalized(const CompressParams& cparams, const char* label,
+ const Plane<uint8_t>& image);
// Used to skip image creation if they won't be written to debug directory.
static inline bool WantDebugOutput(const CompressParams& cparams) {
diff --git a/third_party/jpeg-xl/lib/jxl/enc_detect_dots.cc b/third_party/jpeg-xl/lib/jxl/enc_detect_dots.cc
index 4ee8808766..94e6fefb61 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_detect_dots.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_detect_dots.cc
@@ -26,7 +26,6 @@
#include "lib/jxl/base/status.h"
#include "lib/jxl/convolve.h"
#include "lib/jxl/enc_linalg.h"
-#include "lib/jxl/enc_optimize.h"
#include "lib/jxl/image.h"
#include "lib/jxl/image_ops.h"
@@ -44,14 +43,16 @@ using hwy::HWY_NAMESPACE::Add;
using hwy::HWY_NAMESPACE::Mul;
using hwy::HWY_NAMESPACE::Sub;
-ImageF SumOfSquareDifferences(const Image3F& forig, const Image3F& smooth,
- ThreadPool* pool) {
+StatusOr<ImageF> SumOfSquareDifferences(const Image3F& forig,
+ const Image3F& smooth,
+ ThreadPool* pool) {
const HWY_FULL(float) d;
const auto color_coef0 = Set(d, 0.0f);
const auto color_coef1 = Set(d, 10.0f);
const auto color_coef2 = Set(d, 0.0f);
- ImageF sum_of_squares(forig.xsize(), forig.ysize());
+ JXL_ASSIGN_OR_RETURN(ImageF sum_of_squares,
+ ImageF::Create(forig.xsize(), forig.ysize()));
JXL_CHECK(RunOnPool(
pool, 0, forig.ysize(), ThreadPool::NoInit,
[&](const uint32_t task, size_t thread) {
@@ -142,11 +143,12 @@ const WeightsSeparable5& WeightsSeparable5Gaussian3() {
return weights;
}
-ImageF ComputeEnergyImage(const Image3F& orig, Image3F* smooth,
- ThreadPool* pool) {
+StatusOr<ImageF> ComputeEnergyImage(const Image3F& orig, Image3F* smooth,
+ ThreadPool* pool) {
// Prepare guidance images for dot selection.
- Image3F forig(orig.xsize(), orig.ysize());
- *smooth = Image3F(orig.xsize(), orig.ysize());
+ JXL_ASSIGN_OR_RETURN(Image3F forig,
+ Image3F::Create(orig.xsize(), orig.ysize()));
+ JXL_ASSIGN_OR_RETURN(*smooth, Image3F::Create(orig.xsize(), orig.ysize()));
Rect rect(orig);
const auto& weights1 = WeightsSeparable5Gaussian0_65();
@@ -176,7 +178,7 @@ const size_t kMaxCCSize = 1000;
// Extracts a connected component from a Binary image where seed is part
// of the component
-bool ExtractComponent(ImageF* img, std::vector<Pixel>* pixels,
+bool ExtractComponent(const Rect& rect, ImageF* img, std::vector<Pixel>* pixels,
const Pixel& seed, double threshold) {
static const std::vector<Pixel> neighbors{{1, -1}, {1, 0}, {1, 1}, {0, -1},
{0, 1}, {-1, -1}, {-1, 1}, {1, 0}};
@@ -188,9 +190,9 @@ bool ExtractComponent(ImageF* img, std::vector<Pixel>* pixels,
if (pixels->size() > kMaxCCSize) return false;
for (const Pixel& delta : neighbors) {
Pixel child = current + delta;
- if (child.x >= 0 && static_cast<size_t>(child.x) < img->xsize() &&
- child.y >= 0 && static_cast<size_t>(child.y) < img->ysize()) {
- float* value = &img->Row(child.y)[child.x];
+ if (child.x >= 0 && static_cast<size_t>(child.x) < rect.xsize() &&
+ child.y >= 0 && static_cast<size_t>(child.y) < rect.ysize()) {
+ float* value = &rect.Row(img, child.y)[child.x];
if (*value > threshold) {
*value = 0.0;
q.push_back(child);
@@ -221,7 +223,7 @@ struct ConnectedComponent {
float score;
Pixel mode;
- void CompStats(const ImageF& energy, int extra) {
+ void CompStats(const ImageF& energy, const Rect& rect, int extra) {
maxEnergy = 0.0;
meanEnergy = 0.0;
varEnergy = 0.0;
@@ -234,12 +236,12 @@ struct ConnectedComponent {
for (int sy = -extra; sy < (static_cast<int>(bounds.ysize()) + extra);
sy++) {
int y = sy + static_cast<int>(bounds.y0());
- if (y < 0 || static_cast<size_t>(y) >= energy.ysize()) continue;
- const float* JXL_RESTRICT erow = energy.ConstRow(y);
+ if (y < 0 || static_cast<size_t>(y) >= rect.ysize()) continue;
+ const float* JXL_RESTRICT erow = rect.ConstRow(energy, y);
for (int sx = -extra; sx < (static_cast<int>(bounds.xsize()) + extra);
sx++) {
int x = sx + static_cast<int>(bounds.x0());
- if (x < 0 || static_cast<size_t>(x) >= energy.xsize()) continue;
+ if (x < 0 || static_cast<size_t>(x) >= rect.xsize()) continue;
if (erow[x] > maxEnergy) {
maxEnergy = erow[x];
mode.x = x;
@@ -266,7 +268,10 @@ struct ConnectedComponent {
Rect BoundingRectangle(const std::vector<Pixel>& pixels) {
JXL_ASSERT(!pixels.empty());
- int low_x, high_x, low_y, high_y;
+ int low_x;
+ int high_x;
+ int low_y;
+ int high_y;
low_x = high_x = pixels[0].x;
low_y = high_y = pixels[0].y;
for (const Pixel& p : pixels) {
@@ -278,22 +283,25 @@ Rect BoundingRectangle(const std::vector<Pixel>& pixels) {
return Rect(low_x, low_y, high_x - low_x + 1, high_y - low_y + 1);
}
-std::vector<ConnectedComponent> FindCC(const ImageF& energy, double t_low,
- double t_high, uint32_t maxWindow,
- double minScore) {
+StatusOr<std::vector<ConnectedComponent>> FindCC(const ImageF& energy,
+ const Rect& rect, double t_low,
+ double t_high,
+ uint32_t maxWindow,
+ double minScore) {
const int kExtraRect = 4;
- ImageF img(energy.xsize(), energy.ysize());
+ JXL_ASSIGN_OR_RETURN(ImageF img,
+ ImageF::Create(energy.xsize(), energy.ysize()));
CopyImageTo(energy, &img);
std::vector<ConnectedComponent> ans;
- for (size_t y = 0; y < img.ysize(); y++) {
- float* JXL_RESTRICT row = img.Row(y);
- for (size_t x = 0; x < img.xsize(); x++) {
+ for (size_t y = 0; y < rect.ysize(); y++) {
+ float* JXL_RESTRICT row = rect.Row(&img, y);
+ for (size_t x = 0; x < rect.xsize(); x++) {
if (row[x] > t_high) {
std::vector<Pixel> pixels;
row[x] = 0.0;
bool success = ExtractComponent(
- &img, &pixels, Pixel{static_cast<int>(x), static_cast<int>(y)},
- t_low);
+ rect, &img, &pixels,
+ Pixel{static_cast<int>(x), static_cast<int>(y)}, t_low);
if (!success) continue;
#if JXL_DEBUG_DOT_DETECT
for (size_t i = 0; i < pixels.size(); i++) {
@@ -304,7 +312,7 @@ std::vector<ConnectedComponent> FindCC(const ImageF& energy, double t_low,
Rect bounds = BoundingRectangle(pixels);
if (bounds.xsize() < maxWindow && bounds.ysize() < maxWindow) {
ConnectedComponent cc{bounds, std::move(pixels)};
- cc.CompStats(energy, kExtraRect);
+ cc.CompStats(energy, rect, kExtraRect);
if (cc.score < minScore) continue;
JXL_DEBUG(JXL_DEBUG_DOT_DETECT,
"cc mode: (%d,%d), max: %f, bgMean: %f bgVar: "
@@ -323,12 +331,14 @@ std::vector<ConnectedComponent> FindCC(const ImageF& energy, double t_low,
// TODO(sggonzalez): Adapt this function for the different color spaces or
// remove it if the color space with the best performance does not need it
void ComputeDotLosses(GaussianEllipse* ellipse, const ConnectedComponent& cc,
- const Image3F& img, const Image3F& background) {
+ const Rect& rect, const Image3F& img,
+ const Image3F& background) {
const int rectBounds = 2;
const double kIntensityR = 0.0; // 0.015;
const double kSigmaR = 0.0; // 0.01;
const double kZeroEpsilon = 0.1; // Tolerance to consider a value negative
- double ct = cos(ellipse->angle), st = sin(ellipse->angle);
+ double ct = cos(ellipse->angle);
+ double st = sin(ellipse->angle);
const std::array<double, 3> channelGains{{1.0, 1.0, 1.0}};
int N = 0;
ellipse->l1_loss = 0.0;
@@ -342,15 +352,15 @@ void ComputeDotLosses(GaussianEllipse* ellipse, const ConnectedComponent& cc,
for (int sy = -rectBounds;
sy < (static_cast<int>(cc.bounds.ysize()) + rectBounds); sy++) {
int y = sy + cc.bounds.y0();
- if (y < 0 || static_cast<size_t>(y) >= img.ysize()) continue;
- const float* JXL_RESTRICT row = img.ConstPlaneRow(c, y);
+ if (y < 0 || static_cast<size_t>(y) >= rect.ysize()) continue;
+ const float* JXL_RESTRICT row = rect.ConstPlaneRow(img, c, y);
// bgrow is only used if kOptimizeBackground is false.
// NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
- const float* JXL_RESTRICT bgrow = background.ConstPlaneRow(c, y);
+ const float* JXL_RESTRICT bgrow = rect.ConstPlaneRow(background, c, y);
for (int sx = -rectBounds;
sx < (static_cast<int>(cc.bounds.xsize()) + rectBounds); sx++) {
int x = sx + cc.bounds.x0();
- if (x < 0 || static_cast<size_t>(x) >= img.xsize()) continue;
+ if (x < 0 || static_cast<size_t>(x) >= rect.xsize()) continue;
double target = row[x];
double dotDelta = DotGaussianModel(
x - ellipse->x, y - ellipse->y, ct, st, ellipse->sigma_x,
@@ -385,9 +395,8 @@ void ComputeDotLosses(GaussianEllipse* ellipse, const ConnectedComponent& cc,
ellipse->ridge_loss = ellipse->l2_loss + ridgeTerm;
}
-GaussianEllipse FitGaussianFast(const ConnectedComponent& cc,
- const ImageF& energy, const Image3F& img,
- const Image3F& background) {
+GaussianEllipse FitGaussianFast(const ConnectedComponent& cc, const Rect& rect,
+ const Image3F& img, const Image3F& background) {
constexpr bool leastSqIntensity = true;
constexpr double kEpsilon = 1e-6;
GaussianEllipse ans;
@@ -405,18 +414,18 @@ GaussianEllipse FitGaussianFast(const ConnectedComponent& cc,
"%" PRIuS " %" PRIuS " %" PRIuS " %" PRIuS "\n", cc.bounds.x0(),
cc.bounds.y0(), cc.bounds.xsize(), cc.bounds.ysize());
for (int c = 0; c < 3; c++) {
- color[c] = img.ConstPlaneRow(c, cc.mode.y)[cc.mode.x] -
- background.ConstPlaneRow(c, cc.mode.y)[cc.mode.x];
+ color[c] = rect.ConstPlaneRow(img, c, cc.mode.y)[cc.mode.x] -
+ rect.ConstPlaneRow(background, c, cc.mode.y)[cc.mode.x];
}
double sign = (color[1] > 0) ? 1 : -1;
for (int sy = -kRectBounds; sy <= kRectBounds; sy++) {
int y = sy + cc.mode.y;
- if (y < 0 || static_cast<size_t>(y) >= energy.ysize()) continue;
- const float* JXL_RESTRICT row = img.ConstPlaneRow(1, y);
- const float* JXL_RESTRICT bgrow = background.ConstPlaneRow(1, y);
+ if (y < 0 || static_cast<size_t>(y) >= rect.ysize()) continue;
+ const float* JXL_RESTRICT row = rect.ConstPlaneRow(img, 1, y);
+ const float* JXL_RESTRICT bgrow = rect.ConstPlaneRow(background, 1, y);
for (int sx = -kRectBounds; sx <= kRectBounds; sx++) {
int x = sx + cc.mode.x;
- if (x < 0 || static_cast<size_t>(x) >= energy.xsize()) continue;
+ if (x < 0 || static_cast<size_t>(x) >= rect.xsize()) continue;
double w = std::max(kEpsilon, sign * (row[x] - bgrow[x]));
sum += w;
@@ -426,7 +435,7 @@ GaussianEllipse FitGaussianFast(const ConnectedComponent& cc,
m2[1] += w * x * y;
m2[2] += w * y * y;
for (int c = 0; c < 3; c++) {
- bgColor[c] += background.ConstPlaneRow(c, y)[x];
+ bgColor[c] += rect.ConstPlaneRow(background, c, y)[x];
}
N++;
}
@@ -450,14 +459,16 @@ GaussianEllipse FitGaussianFast(const ConnectedComponent& cc,
ans.intensity[j] = kScaleMult[j] * color[j];
}
- ImageD Sigma(2, 2), D(1, 2), U(2, 2);
- Sigma.Row(0)[0] = m2[0] - m1[0] * m1[0];
- Sigma.Row(1)[1] = m2[2] - m1[1] * m1[1];
- Sigma.Row(0)[1] = Sigma.Row(1)[0] = m2[1] - m1[0] * m1[1];
- ConvertToDiagonal(Sigma, &D, &U);
- const double* JXL_RESTRICT d = D.ConstRow(0);
- const double* JXL_RESTRICT u = U.ConstRow(1);
- int p1 = 0, p2 = 1;
+ Matrix2x2 Sigma;
+ Vector2 d;
+ Matrix2x2 U;
+ Sigma[0][0] = m2[0] - m1[0] * m1[0];
+ Sigma[1][1] = m2[2] - m1[1] * m1[1];
+ Sigma[0][1] = Sigma[1][0] = m2[1] - m1[0] * m1[1];
+ ConvertToDiagonal(Sigma, d, U);
+ Vector2& u = U[1];
+ int p1 = 0;
+ int p2 = 1;
if (d[0] < d[1]) std::swap(p1, p2);
ans.sigma_x = kSigmaMult * d[p1];
ans.sigma_y = kSigmaMult * d[p2];
@@ -466,7 +477,8 @@ GaussianEllipse FitGaussianFast(const ConnectedComponent& cc,
ans.bgColor = bgColor;
if (leastSqIntensity) {
GaussianEllipse* ellipse = &ans;
- double ct = cos(ans.angle), st = sin(ans.angle);
+ double ct = cos(ans.angle);
+ double st = sin(ans.angle);
// Estimate intensity with least squares (fixed background)
for (int c = 0; c < 3; c++) {
double gg = 0.0;
@@ -474,11 +486,11 @@ GaussianEllipse FitGaussianFast(const ConnectedComponent& cc,
int yc = static_cast<int>(cc.mode.y);
int xc = static_cast<int>(cc.mode.x);
for (int y = yc - kRectBounds; y <= yc + kRectBounds; y++) {
- if (y < 0 || static_cast<size_t>(y) >= img.ysize()) continue;
- const float* JXL_RESTRICT row = img.ConstPlaneRow(c, y);
- const float* JXL_RESTRICT bgrow = background.ConstPlaneRow(c, y);
+ if (y < 0 || static_cast<size_t>(y) >= rect.ysize()) continue;
+ const float* JXL_RESTRICT row = rect.ConstPlaneRow(img, c, y);
+ const float* JXL_RESTRICT bgrow = rect.ConstPlaneRow(background, c, y);
for (int x = xc - kRectBounds; x <= xc + kRectBounds; x++) {
- if (x < 0 || static_cast<size_t>(x) >= img.xsize()) continue;
+ if (x < 0 || static_cast<size_t>(x) >= rect.xsize()) continue;
double target = row[x] - bgrow[x];
double gaussian =
DotGaussianModel(x - ellipse->x, y - ellipse->y, ct, st,
@@ -490,13 +502,13 @@ GaussianEllipse FitGaussianFast(const ConnectedComponent& cc,
ans.intensity[c] = gd / (gg + 1e-6); // Regularized least squares
}
}
- ComputeDotLosses(&ans, cc, img, background);
+ ComputeDotLosses(&ans, cc, rect, img, background);
return ans;
}
-GaussianEllipse FitGaussian(const ConnectedComponent& cc, const ImageF& energy,
+GaussianEllipse FitGaussian(const ConnectedComponent& cc, const Rect& rect,
const Image3F& img, const Image3F& background) {
- auto ellipse = FitGaussianFast(cc, energy, img, background);
+ auto ellipse = FitGaussianFast(cc, rect, img, background);
if (ellipse.sigma_x < ellipse.sigma_y) {
std::swap(ellipse.sigma_x, ellipse.sigma_y);
ellipse.angle += kPi / 2.0;
@@ -522,14 +534,16 @@ GaussianEllipse FitGaussian(const ConnectedComponent& cc, const ImageF& energy,
} // namespace
-std::vector<PatchInfo> DetectGaussianEllipses(
- const Image3F& opsin, const GaussianDetectParams& params,
+StatusOr<std::vector<PatchInfo>> DetectGaussianEllipses(
+ const Image3F& opsin, const Rect& rect, const GaussianDetectParams& params,
const EllipseQuantParams& qParams, ThreadPool* pool) {
std::vector<PatchInfo> dots;
- Image3F smooth(opsin.xsize(), opsin.ysize());
- ImageF energy = ComputeEnergyImage(opsin, &smooth, pool);
- std::vector<ConnectedComponent> components = FindCC(
- energy, params.t_low, params.t_high, params.maxWinSize, params.minScore);
+ JXL_ASSIGN_OR_RETURN(Image3F smooth,
+ Image3F::Create(opsin.xsize(), opsin.ysize()));
+ JXL_ASSIGN_OR_RETURN(ImageF energy, ComputeEnergyImage(opsin, &smooth, pool));
+ JXL_ASSIGN_OR_RETURN(std::vector<ConnectedComponent> components,
+ FindCC(energy, rect, params.t_low, params.t_high,
+ params.maxWinSize, params.minScore));
size_t numCC =
std::min(params.maxCC, (components.size() * params.percCC) / 100);
if (components.size() > numCC) {
@@ -541,11 +555,11 @@ std::vector<PatchInfo> DetectGaussianEllipses(
components.erase(components.begin() + numCC, components.end());
}
for (const auto& cc : components) {
- GaussianEllipse ellipse = FitGaussian(cc, energy, opsin, smooth);
+ GaussianEllipse ellipse = FitGaussian(cc, rect, opsin, smooth);
if (ellipse.x < 0.0 ||
- std::ceil(ellipse.x) >= static_cast<double>(opsin.xsize()) ||
+ std::ceil(ellipse.x) >= static_cast<double>(rect.xsize()) ||
ellipse.y < 0.0 ||
- std::ceil(ellipse.y) >= static_cast<double>(opsin.ysize())) {
+ std::ceil(ellipse.y) >= static_cast<double>(rect.ysize())) {
continue;
}
if (ellipse.neg_pixels > params.maxNegPixels) continue;
@@ -573,8 +587,8 @@ std::vector<PatchInfo> DetectGaussianEllipses(
for (size_t x = 0; x < patch.xsize; x++) {
for (size_t c = 0; c < 3; c++) {
patch.fpixels[c][y * patch.xsize + x] =
- opsin.ConstPlaneRow(c, y0 + y)[x0 + x] -
- smooth.ConstPlaneRow(c, y0 + y)[x0 + x];
+ rect.ConstPlaneRow(opsin, c, y0 + y)[x0 + x] -
+ rect.ConstPlaneRow(smooth, c, y0 + y)[x0 + x];
}
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_detect_dots.h b/third_party/jpeg-xl/lib/jxl/enc_detect_dots.h
index c3071d9a2f..59def59f8f 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_detect_dots.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_detect_dots.h
@@ -14,7 +14,6 @@
#include <vector>
#include "lib/jxl/base/data_parallel.h"
-#include "lib/jxl/dec_patch_dictionary.h"
#include "lib/jxl/enc_patch_dictionary.h"
#include "lib/jxl/image.h"
@@ -58,8 +57,8 @@ struct EllipseQuantParams {
};
// Detects dots in XYB image.
-std::vector<PatchInfo> DetectGaussianEllipses(
- const Image3F& opsin, const GaussianDetectParams& params,
+StatusOr<std::vector<PatchInfo>> DetectGaussianEllipses(
+ const Image3F& opsin, const Rect& rect, const GaussianDetectParams& params,
const EllipseQuantParams& qParams, ThreadPool* pool);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.cc b/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.cc
index a5b1af63b2..7d76ba9002 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.cc
@@ -9,17 +9,12 @@
#include <string.h>
#include <array>
-#include <utility>
#include "lib/jxl/base/override.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
-#include "lib/jxl/dec_bit_reader.h"
-#include "lib/jxl/dec_xyb.h"
-#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/enc_detect_dots.h"
#include "lib/jxl/enc_params.h"
-#include "lib/jxl/enc_xyb.h"
#include "lib/jxl/image.h"
namespace jxl {
@@ -39,10 +34,9 @@ const std::array<double, 3> kEllipseMaxIntensity{{0.05, 1.0, 0.4}};
const std::array<size_t, 3> kEllipseIntensityQ{{10, 36, 10}};
} // namespace
-std::vector<PatchInfo> FindDotDictionary(const CompressParams& cparams,
- const Image3F& opsin,
- const ColorCorrelationMap& cmap,
- ThreadPool* pool) {
+StatusOr<std::vector<PatchInfo>> FindDotDictionary(
+ const CompressParams& cparams, const Image3F& opsin, const Rect& rect,
+ const ColorCorrelationMap& cmap, ThreadPool* pool) {
if (ApplyOverride(cparams.dots,
cparams.butteraugli_distance >= kMinButteraugliForDots)) {
GaussianDetectParams ellipse_params;
@@ -58,14 +52,15 @@ std::vector<PatchInfo> FindDotDictionary(const CompressParams& cparams,
ellipse_params.maxCC = 100;
ellipse_params.percCC = 100;
EllipseQuantParams qParams{
- opsin.xsize(), opsin.ysize(), kEllipsePosQ,
+ rect.xsize(), rect.ysize(), kEllipsePosQ,
kEllipseMinSigma, kEllipseMaxSigma, kEllipseSigmaQ,
kEllipseAngleQ, kEllipseMinIntensity, kEllipseMaxIntensity,
kEllipseIntensityQ, kEllipsePosQ <= 5, cmap.YtoXRatio(0),
cmap.YtoBRatio(0)};
- return DetectGaussianEllipses(opsin, ellipse_params, qParams, pool);
+ return DetectGaussianEllipses(opsin, rect, ellipse_params, qParams, pool);
}
- return {};
+ std::vector<PatchInfo> nothing;
+ return nothing;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.h b/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.h
index 2ba4393f30..d348fb73b8 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.h
@@ -15,19 +15,15 @@
#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
-#include "lib/jxl/dec_bit_reader.h"
-#include "lib/jxl/dec_patch_dictionary.h"
-#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/enc_patch_dictionary.h"
#include "lib/jxl/image.h"
namespace jxl {
-std::vector<PatchInfo> FindDotDictionary(const CompressParams& cparams,
- const Image3F& opsin,
- const ColorCorrelationMap& cmap,
- ThreadPool* pool);
+StatusOr<std::vector<PatchInfo>> FindDotDictionary(
+ const CompressParams& cparams, const Image3F& opsin, const Rect& rect,
+ const ColorCorrelationMap& cmap, ThreadPool* pool);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.cc b/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.cc
index 07601a2221..b71bb07bc9 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.cc
@@ -90,8 +90,8 @@ int32_t NumNonZeroExceptLLF(const size_t cx, const size_t cy,
}
// We want area - sum_zero, add because neg_sum_zero is already negated.
- const int32_t nzeros =
- int32_t(cx * cy * kDCTBlockSize) + GetLane(SumOfLanes(di, neg_sum_zero));
+ const int32_t nzeros = static_cast<int32_t>(cx * cy * kDCTBlockSize) +
+ GetLane(SumOfLanes(di, neg_sum_zero));
const int32_t shifted_nzeros = static_cast<int32_t>(
(nzeros + covered_blocks - 1) >> log2_covered_blocks);
@@ -139,8 +139,8 @@ int32_t NumNonZero8x8ExceptDC(const int32_t* JXL_RESTRICT block,
}
// We want 64 - sum_zero, add because neg_sum_zero is already negated.
- const int32_t nzeros =
- int32_t(kDCTBlockSize) + GetLane(SumOfLanes(di, neg_sum_zero));
+ const int32_t nzeros = static_cast<int32_t>(kDCTBlockSize) +
+ GetLane(SumOfLanes(di, neg_sum_zero));
*nzeros_pos = nzeros;
@@ -157,7 +157,7 @@ void TokenizeCoefficients(const coeff_order_t* JXL_RESTRICT orders,
const Rect& rect,
const int32_t* JXL_RESTRICT* JXL_RESTRICT ac_rows,
const AcStrategyImage& ac_strategy,
- YCbCrChromaSubsampling cs,
+ const YCbCrChromaSubsampling& cs,
Image3I* JXL_RESTRICT tmp_num_nzeroes,
std::vector<Token>* JXL_RESTRICT output,
const ImageB& qdc, const ImageI& qf,
@@ -236,7 +236,7 @@ void TokenizeCoefficients(const coeff_order_t* JXL_RESTRICT orders,
log2_covered_blocks, prev);
uint32_t u_coeff = PackSigned(coeff);
output->emplace_back(ctx, u_coeff);
- prev = coeff != 0;
+ prev = (coeff != 0) ? 1 : 0;
nzeros -= prev;
}
JXL_DASSERT(nzeros == 0);
@@ -258,14 +258,14 @@ void TokenizeCoefficients(const coeff_order_t* JXL_RESTRICT orders,
const Rect& rect,
const int32_t* JXL_RESTRICT* JXL_RESTRICT ac_rows,
const AcStrategyImage& ac_strategy,
- YCbCrChromaSubsampling cs,
+ const YCbCrChromaSubsampling& cs,
Image3I* JXL_RESTRICT tmp_num_nzeroes,
std::vector<Token>* JXL_RESTRICT output,
const ImageB& qdc, const ImageI& qf,
const BlockCtxMap& block_ctx_map) {
- return HWY_DYNAMIC_DISPATCH(TokenizeCoefficients)(
- orders, rect, ac_rows, ac_strategy, cs, tmp_num_nzeroes, output, qdc, qf,
- block_ctx_map);
+ HWY_DYNAMIC_DISPATCH(TokenizeCoefficients)
+ (orders, rect, ac_rows, ac_strategy, cs, tmp_num_nzeroes, output, qdc, qf,
+ block_ctx_map);
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.h b/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.h
index 7dfc71c726..6df3e8e770 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.h
@@ -35,7 +35,7 @@ void TokenizeCoefficients(const coeff_order_t* JXL_RESTRICT orders,
const Rect& rect,
const int32_t* JXL_RESTRICT* JXL_RESTRICT ac_rows,
const AcStrategyImage& ac_strategy,
- YCbCrChromaSubsampling cs,
+ const YCbCrChromaSubsampling& cs,
Image3I* JXL_RESTRICT tmp_num_nzeroes,
std::vector<Token>* JXL_RESTRICT output,
const ImageB& qdc, const ImageI& qf,
diff --git a/third_party/jpeg-xl/lib/jxl/enc_external_image.cc b/third_party/jpeg-xl/lib/jxl/enc_external_image.cc
index 680323e79a..90e4937e7b 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_external_image.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_external_image.cc
@@ -8,14 +8,9 @@
#include <jxl/types.h>
#include <string.h>
-#include <algorithm>
-#include <array>
#include <atomic>
-#include <functional>
#include <utility>
-#include <vector>
-#include "lib/jxl/alpha.h"
#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/float.h"
@@ -114,7 +109,7 @@ Status ConvertFromExternalNoSizeCheck(const uint8_t* data, size_t xsize,
color_channels, format.num_channels);
}
- Image3F color(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(Image3F color, Image3F::Create(xsize, ysize));
for (size_t c = 0; c < color_channels; ++c) {
JXL_RETURN_IF_ERROR(ConvertFromExternalNoSizeCheck(
data, xsize, ysize, stride, bits_per_sample, format, c, pool,
@@ -129,7 +124,7 @@ Status ConvertFromExternalNoSizeCheck(const uint8_t* data, size_t xsize,
// Passing an interleaved image with an alpha channel to an image that doesn't
// have alpha channel just discards the passed alpha channel.
if (has_alpha && ib->HasAlpha()) {
- ImageF alpha(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF alpha, ImageF::Create(xsize, ysize));
JXL_RETURN_IF_ERROR(ConvertFromExternalNoSizeCheck(
data, xsize, ysize, stride, bits_per_sample, format,
format.num_channels - 1, pool, &alpha));
@@ -137,7 +132,7 @@ Status ConvertFromExternalNoSizeCheck(const uint8_t* data, size_t xsize,
} else if (!has_alpha && ib->HasAlpha()) {
// if alpha is not passed, but it is expected, then assume
// it is all-opaque
- ImageF alpha(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF alpha, ImageF::Create(xsize, ysize));
FillImage(1.0f, &alpha);
ib->SetAlpha(std::move(alpha));
}
@@ -184,7 +179,7 @@ Status ConvertFromExternal(Span<const uint8_t> bytes, size_t xsize,
color_channels, format.num_channels);
}
- Image3F color(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(Image3F color, Image3F::Create(xsize, ysize));
for (size_t c = 0; c < color_channels; ++c) {
JXL_RETURN_IF_ERROR(ConvertFromExternal(bytes.data(), bytes.size(), xsize,
ysize, bits_per_sample, format, c,
@@ -199,7 +194,7 @@ Status ConvertFromExternal(Span<const uint8_t> bytes, size_t xsize,
// Passing an interleaved image with an alpha channel to an image that doesn't
// have alpha channel just discards the passed alpha channel.
if (has_alpha && ib->HasAlpha()) {
- ImageF alpha(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF alpha, ImageF::Create(xsize, ysize));
JXL_RETURN_IF_ERROR(ConvertFromExternal(
bytes.data(), bytes.size(), xsize, ysize, bits_per_sample, format,
format.num_channels - 1, pool, &alpha));
@@ -207,7 +202,7 @@ Status ConvertFromExternal(Span<const uint8_t> bytes, size_t xsize,
} else if (!has_alpha && ib->HasAlpha()) {
// if alpha is not passed, but it is expected, then assume
// it is all-opaque
- ImageF alpha(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF alpha, ImageF::Create(xsize, ysize));
FillImage(1.0f, &alpha);
ib->SetAlpha(std::move(alpha));
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc b/third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc
index b32d2478e0..58d0d00eaa 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc
@@ -331,6 +331,8 @@ struct PrefixCode {
uint8_t* min_limit,
uint8_t* max_limit,
uint8_t* nbits) {
+ assert(precision < 15);
+ assert(n <= kMaxNumSymbols);
std::vector<T> dynp(((1U << precision) + 1) * (n + 1), infty);
auto d = [&](size_t sym, size_t off) -> T& {
return dynp[sym * ((1 << precision) + 1) + off];
@@ -428,10 +430,11 @@ struct PrefixCode {
}
// Invalid code, used to construct arrays.
- PrefixCode() {}
+ PrefixCode() = default;
template <typename BitDepth>
- PrefixCode(BitDepth, uint64_t* raw_counts, uint64_t* lz77_counts) {
+ PrefixCode(BitDepth /* bitdepth */, uint64_t* raw_counts,
+ uint64_t* lz77_counts) {
// "merge" together all the lz77 counts in a single symbol for the level 1
// table (containing just the raw symbols, up to length 7).
uint64_t level1_counts[kNumRawSymbols + 1];
@@ -1317,7 +1320,7 @@ struct Mask32 {
SIMDVec32 IfThenElse(const SIMDVec32& if_true, const SIMDVec32& if_false);
size_t CountPrefix() const {
return CtzNonZero(~static_cast<uint64_t>(
- (uint8_t)_mm256_movemask_ps(_mm256_castsi256_ps(mask))));
+ static_cast<uint8_t>(_mm256_movemask_ps(_mm256_castsi256_ps(mask)))));
}
};
@@ -1414,8 +1417,8 @@ struct Mask16 {
return Mask16{_mm256_and_si256(mask, oth.mask)};
}
size_t CountPrefix() const {
- return CtzNonZero(
- ~static_cast<uint64_t>((uint32_t)_mm256_movemask_epi8(mask))) /
+ return CtzNonZero(~static_cast<uint64_t>(
+ static_cast<uint32_t>(_mm256_movemask_epi8(mask)))) /
2;
}
};
@@ -3151,9 +3154,9 @@ void StoreYCoCg(SIMDVec16 r, SIMDVec16 g, SIMDVec16 b, int16_t* y, int16_t* co,
SIMDVec16 tmp = b.Add(co_v.SignedShiftRight<1>());
SIMDVec16 cg_v = g.Sub(tmp);
SIMDVec16 y_v = tmp.Add(cg_v.SignedShiftRight<1>());
- y_v.Store((uint16_t*)y);
- co_v.Store((uint16_t*)co);
- cg_v.Store((uint16_t*)cg);
+ y_v.Store(reinterpret_cast<uint16_t*>(y));
+ co_v.Store(reinterpret_cast<uint16_t*>(co));
+ cg_v.Store(reinterpret_cast<uint16_t*>(cg));
}
void StoreYCoCg(SIMDVec16 r, SIMDVec16 g, SIMDVec16 b, int32_t* y, int32_t* co,
@@ -3169,12 +3172,12 @@ void StoreYCoCg(SIMDVec16 r, SIMDVec16 g, SIMDVec16 b, int32_t* y, int32_t* co,
SIMDVec32 tmp_hi = b_up.hi.Add(co_hi_v.SignedShiftRight<1>());
SIMDVec32 cg_hi_v = g_up.hi.Sub(tmp_hi);
SIMDVec32 y_hi_v = tmp_hi.Add(cg_hi_v.SignedShiftRight<1>());
- y_lo_v.Store((uint32_t*)y);
- co_lo_v.Store((uint32_t*)co);
- cg_lo_v.Store((uint32_t*)cg);
- y_hi_v.Store((uint32_t*)y + SIMDVec32::kLanes);
- co_hi_v.Store((uint32_t*)co + SIMDVec32::kLanes);
- cg_hi_v.Store((uint32_t*)cg + SIMDVec32::kLanes);
+ y_lo_v.Store(reinterpret_cast<uint32_t*>(y));
+ co_lo_v.Store(reinterpret_cast<uint32_t*>(co));
+ cg_lo_v.Store(reinterpret_cast<uint32_t*>(cg));
+ y_hi_v.Store(reinterpret_cast<uint32_t*>(y) + SIMDVec32::kLanes);
+ co_hi_v.Store(reinterpret_cast<uint32_t*>(co) + SIMDVec32::kLanes);
+ cg_hi_v.Store(reinterpret_cast<uint32_t*>(cg) + SIMDVec32::kLanes);
}
#endif
@@ -3573,8 +3576,7 @@ void PrepareDCGlobalPalette(bool is_single_group, size_t width, size_t height,
int16_t p[4][32 + 1024] = {};
uint8_t prgba[4];
size_t i = 0;
- size_t have_zero = 0;
- if (palette[pcolors - 1] == 0) have_zero = 1;
+ size_t have_zero = 1;
for (; i < pcolors; i++) {
memcpy(prgba, &palette[i], 4);
p[0][16 + i + have_zero] = prgba[0];
@@ -3735,10 +3737,13 @@ JxlFastLosslessFrameState* LLPrepare(JxlChunkedFrameInputSource input,
const void* buffer =
input.get_color_channel_data_at(input.opaque, x0, y0, xs, ys, &stride);
auto rgba = reinterpret_cast<const unsigned char*>(buffer);
- int y_begin = std::max<int>(0, ys - 2 * effort) / 2;
- int y_count = std::min<int>(num_rows, y0 + ys - y_begin - 1);
+ int y_begin_group =
+ std::max<ssize_t>(
+ 0, static_cast<ssize_t>(ys) - static_cast<ssize_t>(num_rows)) /
+ 2;
+ int y_count = std::min<int>(num_rows, ys - y_begin_group);
int x_max = xs / kChunkSize * kChunkSize;
- CollectSamples(rgba, 0, y_begin, x_max, stride, y_count, raw_counts,
+ CollectSamples(rgba, 0, y_begin_group, x_max, stride, y_count, raw_counts,
lz77_counts, onegroup, !collided, bitdepth, nb_chans,
big_endian, lookup.data());
input.release_buffer(input.opaque, buffer);
@@ -4020,7 +4025,7 @@ namespace default_implementation {
#else // FJXL_ENABLE_NEON
namespace default_implementation {
-#include "lib/jxl/enc_fast_lossless.cc"
+#include "lib/jxl/enc_fast_lossless.cc" // NOLINT
}
#if FJXL_ENABLE_AVX2
@@ -4039,7 +4044,7 @@ namespace default_implementation {
namespace AVX2 {
#define FJXL_AVX2
-#include "lib/jxl/enc_fast_lossless.cc"
+#include "lib/jxl/enc_fast_lossless.cc" // NOLINT
#undef FJXL_AVX2
} // namespace AVX2
@@ -4174,18 +4179,20 @@ void JxlFastLosslessProcessFrame(
__builtin_cpu_supports("avx512vbmi") &&
__builtin_cpu_supports("avx512bw") && __builtin_cpu_supports("avx512f") &&
__builtin_cpu_supports("avx512vl")) {
- return AVX512::JxlFastLosslessProcessFrameImpl(
- frame_state, is_last, runner_opaque, runner, output_processor);
+ AVX512::JxlFastLosslessProcessFrameImpl(frame_state, is_last, runner_opaque,
+ runner, output_processor);
+ return;
}
#endif
#if FJXL_ENABLE_AVX2
if (__builtin_cpu_supports("avx2")) {
- return AVX2::JxlFastLosslessProcessFrameImpl(
- frame_state, is_last, runner_opaque, runner, output_processor);
+ AVX2::JxlFastLosslessProcessFrameImpl(frame_state, is_last, runner_opaque,
+ runner, output_processor);
+ return;
}
#endif
- return default_implementation::JxlFastLosslessProcessFrameImpl(
+ default_implementation::JxlFastLosslessProcessFrameImpl(
frame_state, is_last, runner_opaque, runner, output_processor);
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_fields.cc b/third_party/jpeg-xl/lib/jxl/enc_fields.cc
index dc0cbb7913..fa513297fd 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_fields.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_fields.cc
@@ -74,7 +74,8 @@ class WriteVisitor : public VisitorBase {
Status Bundle::Write(const Fields& fields, BitWriter* writer, size_t layer,
AuxOut* aux_out) {
- size_t extension_bits, total_bits;
+ size_t extension_bits;
+ size_t total_bits;
JXL_RETURN_IF_ERROR(Bundle::CanEncode(fields, &extension_bits, &total_bits));
BitWriter::Allotment allotment(writer, total_bits);
@@ -173,7 +174,8 @@ Status F16Coder::Write(float value, BitWriter* JXL_RESTRICT writer) {
return true;
}
- uint32_t biased_exp16, mantissa16;
+ uint32_t biased_exp16;
+ uint32_t mantissa16;
// exp = [-24, -15] => subnormal
if (JXL_UNLIKELY(exp < -14)) {
diff --git a/third_party/jpeg-xl/lib/jxl/enc_frame.cc b/third_party/jpeg-xl/lib/jxl/enc_frame.cc
index aae59c49a6..8587e1aed2 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_frame.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_frame.cc
@@ -12,13 +12,13 @@
#include <array>
#include <atomic>
#include <cmath>
-#include <limits>
+#include <memory>
#include <numeric>
+#include <utility>
#include <vector>
#include "lib/jxl/ac_context.h"
#include "lib/jxl/ac_strategy.h"
-#include "lib/jxl/ans_params.h"
#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
@@ -31,7 +31,6 @@
#include "lib/jxl/coeff_order_fwd.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/common.h" // kMaxNumPasses
-#include "lib/jxl/compressed_dc.h"
#include "lib/jxl/dct_util.h"
#include "lib/jxl/dec_external_image.h"
#include "lib/jxl/enc_ac_strategy.h"
@@ -47,7 +46,6 @@
#include "lib/jxl/enc_entropy_coder.h"
#include "lib/jxl/enc_external_image.h"
#include "lib/jxl/enc_fields.h"
-#include "lib/jxl/enc_gaborish.h"
#include "lib/jxl/enc_group.h"
#include "lib/jxl/enc_heuristics.h"
#include "lib/jxl/enc_modular.h"
@@ -285,7 +283,8 @@ Status LoopFilterFromParams(const CompressParams& cparams, bool streaming_mode,
if (frame_header->encoding == FrameEncoding::kModular &&
!cparams.IsLossless()) {
// TODO(veluca): this formula is nonsense.
- loop_filter->epf_sigma_for_modular = cparams.butteraugli_distance;
+ loop_filter->epf_sigma_for_modular =
+ std::max(cparams.butteraugli_distance, 1.0f);
}
if (frame_header->encoding == FrameEncoding::kModular &&
cparams.lossy_palette) {
@@ -539,7 +538,7 @@ struct PixelStatsForChromacityAdjustment {
float dx = 0;
float db = 0;
float exposed_blue = 0;
- float CalcPlane(const ImageF* JXL_RESTRICT plane, const Rect& rect) const {
+ static float CalcPlane(const ImageF* JXL_RESTRICT plane, const Rect& rect) {
float xmax = 0;
float ymax = 0;
for (size_t ty = 1; ty < rect.ysize(); ++ty) {
@@ -583,7 +582,7 @@ struct PixelStatsForChromacityAdjustment {
dx = CalcPlane(&opsin->Plane(0), rect);
CalcExposedBlue(&opsin->Plane(1), &opsin->Plane(2), rect);
}
- int HowMuchIsXChannelPixelized() {
+ int HowMuchIsXChannelPixelized() const {
if (dx >= 0.03) {
return 2;
}
@@ -592,7 +591,7 @@ struct PixelStatsForChromacityAdjustment {
}
return 0;
}
- int HowMuchIsBChannelPixelized() {
+ int HowMuchIsBChannelPixelized() const {
int add = exposed_blue >= 0.13 ? 1 : 0;
if (db > 0.38) {
return 2 + add;
@@ -682,12 +681,12 @@ void ComputeNoiseParams(const CompressParams& cparams, bool streaming_mode,
}
}
-void DownsampleColorChannels(const CompressParams& cparams,
- const FrameHeader& frame_header,
- bool color_is_jpeg, Image3F* opsin) {
+Status DownsampleColorChannels(const CompressParams& cparams,
+ const FrameHeader& frame_header,
+ bool color_is_jpeg, Image3F* opsin) {
if (color_is_jpeg || frame_header.upsampling == 1 ||
cparams.already_downsampled) {
- return;
+ return true;
}
if (frame_header.encoding == FrameEncoding::kVarDCT &&
frame_header.upsampling == 2) {
@@ -698,16 +697,18 @@ void DownsampleColorChannels(const CompressParams& cparams,
// TODO(lode): DownsampleImage2_Iterative is currently too slow to
// be used for squirrel, make it faster, and / or enable it only for
// kitten.
- DownsampleImage2_Iterative(opsin);
+ JXL_RETURN_IF_ERROR(DownsampleImage2_Iterative(opsin));
} else {
- DownsampleImage2_Sharper(opsin);
+ JXL_RETURN_IF_ERROR(DownsampleImage2_Sharper(opsin));
}
} else {
- DownsampleImage(opsin, frame_header.upsampling);
+ JXL_ASSIGN_OR_RETURN(*opsin,
+ DownsampleImage(*opsin, frame_header.upsampling));
}
if (frame_header.encoding == FrameEncoding::kVarDCT) {
PadImageToBlockMultipleInPlace(opsin);
}
+ return true;
}
template <typename V, typename R>
@@ -741,14 +742,17 @@ Status ComputeJPEGTranscodingData(const jpeg::JPEGData& jpeg_data,
const size_t ysize_blocks = frame_dim.ysize_blocks;
// no-op chroma from luma
- shared.cmap = ColorCorrelationMap(xsize, ysize, false);
+ JXL_ASSIGN_OR_RETURN(shared.cmap,
+ ColorCorrelationMap::Create(xsize, ysize, false));
shared.ac_strategy.FillDCT8();
- FillImage(uint8_t(0), &shared.epf_sharpness);
+ FillImage(static_cast<uint8_t>(0), &shared.epf_sharpness);
enc_state->coeffs.clear();
while (enc_state->coeffs.size() < enc_state->passes.size()) {
- enc_state->coeffs.emplace_back(make_unique<ACImageT<int32_t>>(
- kGroupDim * kGroupDim, frame_dim.num_groups));
+ JXL_ASSIGN_OR_RETURN(
+ std::unique_ptr<ACImageT<int32_t>> coeffs,
+ ACImageT<int32_t>::Make(kGroupDim * kGroupDim, frame_dim.num_groups));
+ enc_state->coeffs.emplace_back(std::move(coeffs));
}
// convert JPEG quantization table to a Quantizer object
@@ -779,7 +783,8 @@ Status ComputeJPEGTranscodingData(const jpeg::JPEGData& jpeg_data,
1.0f / dcquantization[2]};
qe[AcStrategy::Type::DCT] = QuantEncoding::RAW(qt);
- DequantMatricesSetCustom(&shared.matrices, qe, enc_modular);
+ JXL_RETURN_IF_ERROR(
+ DequantMatricesSetCustom(&shared.matrices, qe, enc_modular));
// Ensure that InvGlobalScale() is 1.
shared.quantizer = Quantizer(&shared.matrices, 1, kGlobalScaleDenom);
@@ -844,7 +849,8 @@ Status ComputeJPEGTranscodingData(const jpeg::JPEGData& jpeg_data,
kScale * row_s[x * kDCTBlockSize + coeffpos] +
(kOffset - kBase * kScale) * scaled_m;
if (std::abs(scaled_m) > 1e-8f) {
- float from, to;
+ float from;
+ float to;
if (scaled_m > 0) {
from = (scaled_s - kZeroThresh) / scaled_m;
to = (scaled_s + kZeroThresh) / scaled_m;
@@ -889,7 +895,7 @@ Status ComputeJPEGTranscodingData(const jpeg::JPEGData& jpeg_data,
}
}
- Image3F dc = Image3F(xsize_blocks, ysize_blocks);
+ JXL_ASSIGN_OR_RETURN(Image3F dc, Image3F::Create(xsize_blocks, ysize_blocks));
if (!frame_header.chroma_subsampling.Is444()) {
ZeroFillImage(&dc);
for (auto& coeff : enc_state->coeffs) {
@@ -944,7 +950,7 @@ Status ComputeJPEGTranscodingData(const jpeg::JPEGData& jpeg_data,
idc = inputjpeg[base] + 1024 / qt[c * 64];
}
dc_counts[c][std::min(static_cast<uint32_t>(idc + 1024),
- uint32_t(2047))]++;
+ static_cast<uint32_t>(2047))]++;
total_dc[c]++;
fdc[bx >> hshift] = idc * dcquantization_r[c];
if (c == 1 || !enc_state->cparams.force_cfl_jpeg_recompression ||
@@ -1024,18 +1030,27 @@ Status ComputeJPEGTranscodingData(const jpeg::JPEGData& jpeg_data,
*std::max_element(ctx_map.begin(), ctx_map.end()) + 1;
// disable DC frame for now
+ std::atomic<bool> has_error{false};
auto compute_dc_coeffs = [&](const uint32_t group_index,
size_t /* thread */) {
+ if (has_error) return;
const Rect r = enc_state->shared.frame_dim.DCGroupRect(group_index);
- enc_modular->AddVarDCTDC(frame_header, dc, r, group_index,
- /*nl_dc=*/false, enc_state,
- /*jpeg_transcode=*/true);
- enc_modular->AddACMetadata(r, group_index, /*jpeg_transcode=*/true,
- enc_state);
+ if (!enc_modular->AddVarDCTDC(frame_header, dc, r, group_index,
+ /*nl_dc=*/false, enc_state,
+ /*jpeg_transcode=*/true)) {
+ has_error = true;
+ return;
+ }
+ if (!enc_modular->AddACMetadata(r, group_index, /*jpeg_transcode=*/true,
+ enc_state)) {
+ has_error = true;
+ return;
+ }
};
JXL_RETURN_IF_ERROR(RunOnPool(pool, 0, shared.frame_dim.num_dc_groups,
ThreadPool::NoInit, compute_dc_coeffs,
"Compute DC coeffs"));
+ if (has_error) return JXL_FAILURE("Compute DC coeffs failed");
return true;
}
@@ -1077,10 +1092,12 @@ void ComputeAllCoeffOrders(PassesEncoderState& enc_state,
// Working area for TokenizeCoefficients (per-group!)
struct EncCache {
// Allocates memory when first called.
- void InitOnce() {
+ Status InitOnce() {
if (num_nzeroes.xsize() == 0) {
- num_nzeroes = Image3I(kGroupDimInBlocks, kGroupDimInBlocks);
+ JXL_ASSIGN_OR_RETURN(
+ num_nzeroes, Image3I::Create(kGroupDimInBlocks, kGroupDimInBlocks));
}
+ return true;
}
// TokenizeCoefficients
Image3I num_nzeroes;
@@ -1095,8 +1112,10 @@ Status TokenizeAllCoefficients(const FrameHeader& frame_header,
group_caches.resize(num_threads);
return true;
};
+ std::atomic<bool> has_error{false};
const auto tokenize_group = [&](const uint32_t group_index,
const size_t thread) {
+ if (has_error) return;
// Tokenize coefficients.
const Rect rect = shared.frame_dim.BlockGroupRect(group_index);
for (size_t idx_pass = 0; idx_pass < enc_state->passes.size(); idx_pass++) {
@@ -1107,7 +1126,10 @@ Status TokenizeAllCoefficients(const FrameHeader& frame_header,
enc_state->coeffs[idx_pass]->PlaneRow(2, group_index, 0).ptr32,
};
// Ensure group cache is initialized.
- group_caches[thread].InitOnce();
+ if (!group_caches[thread].InitOnce()) {
+ has_error = true;
+ return;
+ }
TokenizeCoefficients(
&shared.coeff_orders[idx_pass * shared.coeff_order_size], rect,
ac_rows, shared.ac_strategy, frame_header.chroma_subsampling,
@@ -1116,8 +1138,11 @@ Status TokenizeAllCoefficients(const FrameHeader& frame_header,
shared.raw_quant_field, shared.block_ctx_map);
}
};
- return RunOnPool(pool, 0, shared.frame_dim.num_groups, tokenize_group_init,
- tokenize_group, "TokenizeGroup");
+ JXL_RETURN_IF_ERROR(RunOnPool(pool, 0, shared.frame_dim.num_groups,
+ tokenize_group_init, tokenize_group,
+ "TokenizeGroup"));
+ if (has_error) return JXL_FAILURE("TokenizeGroup failed");
+ return true;
}
Status EncodeGlobalDCInfo(const PassesSharedState& shared, BitWriter* writer,
@@ -1208,10 +1233,13 @@ Status EncodeGroups(const FrameHeader& frame_header,
const size_t num_groups = frame_dim.num_groups;
const size_t num_passes = enc_state->progressive_splitter.GetNumPasses();
const size_t global_ac_index = frame_dim.num_dc_groups + 1;
- const bool is_small_image = frame_dim.num_groups == 1 && num_passes == 1;
-
- group_codes->resize(
- NumTocEntries(num_groups, frame_dim.num_dc_groups, num_passes));
+ const bool is_small_image =
+ !enc_state->streaming_mode && num_groups == 1 && num_passes == 1;
+ const size_t num_toc_entries =
+ is_small_image ? 1
+ : AcGroupIndex(0, 0, num_groups, frame_dim.num_dc_groups) +
+ num_groups * num_passes;
+ group_codes->resize(num_toc_entries);
const auto get_output = [&](const size_t index) {
return &(*group_codes)[is_small_image ? 0 : index];
@@ -1308,35 +1336,48 @@ Status EncodeGroups(const FrameHeader& frame_header,
enc_state, get_output(global_ac_index), enc_modular, aux_out));
}
- std::atomic<int> num_errors{0};
+ std::atomic<bool> has_error{false};
const auto process_group = [&](const uint32_t group_index,
const size_t thread) {
+ if (has_error) return;
AuxOut* my_aux_out = aux_outs[thread].get();
+ size_t ac_group_id =
+ enc_state->streaming_mode
+ ? enc_modular->ComputeStreamingAbsoluteAcGroupId(
+ enc_state->dc_group_index, group_index, shared.frame_dim)
+ : group_index;
+
for (size_t i = 0; i < num_passes; i++) {
+ JXL_DEBUG_V(2, "Encoding AC group %u [abs %" PRIuS "] pass %" PRIuS,
+ group_index, ac_group_id, i);
if (frame_header.encoding == FrameEncoding::kVarDCT) {
if (!EncodeGroupTokenizedCoefficients(
group_index, i, enc_state->histogram_idx[group_index],
*enc_state, ac_group_code(i, group_index), my_aux_out)) {
- num_errors.fetch_add(1, std::memory_order_relaxed);
+ has_error = true;
return;
}
}
// Write all modular encoded data (color?, alpha, depth, extra channels)
if (!enc_modular->EncodeStream(
ac_group_code(i, group_index), my_aux_out, kLayerModularAcGroup,
- ModularStreamId::ModularAC(group_index, i))) {
- num_errors.fetch_add(1, std::memory_order_relaxed);
+ ModularStreamId::ModularAC(ac_group_id, i))) {
+ has_error = true;
return;
}
+ JXL_DEBUG_V(2,
+ "AC group %u [abs %" PRIuS "] pass %" PRIuS
+ " encoded size is %" PRIuS " bits",
+ group_index, ac_group_id, i,
+ ac_group_code(i, group_index)->BitsWritten());
}
};
JXL_RETURN_IF_ERROR(RunOnPool(pool, 0, num_groups, resize_aux_outs,
process_group, "EncodeGroupCoefficients"));
-
+ if (has_error) return JXL_FAILURE("EncodeGroupCoefficients failed");
// Resizing aux_outs to 0 also Assimilates the array.
static_cast<void>(resize_aux_outs(0));
- JXL_RETURN_IF_ERROR(num_errors.load(std::memory_order_relaxed) == 0);
for (BitWriter& bw : *group_codes) {
BitWriter::Allotment allotment(&bw, 8);
@@ -1360,29 +1401,39 @@ Status ComputeEncodingData(
PassesSharedState& shared = enc_state.shared;
shared.metadata = metadata;
if (enc_state.streaming_mode) {
- shared.frame_dim.Set(xsize, ysize, /*group_size_shift=*/1,
- /*maxhshift=*/0, /*maxvshift=*/0,
- /*modular_mode=*/false, /*upsampling=*/1);
+ shared.frame_dim.Set(
+ xsize, ysize, frame_header.group_size_shift,
+ /*max_hshift=*/0, /*max_vshift=*/0,
+ mutable_frame_header.encoding == FrameEncoding::kModular,
+ /*upsampling=*/1);
} else {
shared.frame_dim = frame_header.ToFrameDimensions();
}
shared.image_features.patches.SetPassesSharedState(&shared);
const FrameDimensions& frame_dim = shared.frame_dim;
- shared.ac_strategy =
- AcStrategyImage(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
- shared.raw_quant_field =
- ImageI(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
- shared.epf_sharpness = ImageB(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
- shared.cmap = ColorCorrelationMap(frame_dim.xsize, frame_dim.ysize);
+ JXL_ASSIGN_OR_RETURN(
+ shared.ac_strategy,
+ AcStrategyImage::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
+ JXL_ASSIGN_OR_RETURN(
+ shared.raw_quant_field,
+ ImageI::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
+ JXL_ASSIGN_OR_RETURN(
+ shared.epf_sharpness,
+ ImageB::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
+ JXL_ASSIGN_OR_RETURN(shared.cmap, ColorCorrelationMap::Create(
+ frame_dim.xsize, frame_dim.ysize));
shared.coeff_order_size = kCoeffOrderMaxSize;
if (frame_header.encoding == FrameEncoding::kVarDCT) {
shared.coeff_orders.resize(frame_header.passes.num_passes *
kCoeffOrderMaxSize);
}
- shared.quant_dc = ImageB(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
- shared.dc_storage = Image3F(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
+ JXL_ASSIGN_OR_RETURN(shared.quant_dc, ImageB::Create(frame_dim.xsize_blocks,
+ frame_dim.ysize_blocks));
+ JXL_ASSIGN_OR_RETURN(
+ shared.dc_storage,
+ Image3F::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
shared.dc = &shared.dc_storage;
const size_t num_extra_channels = metadata->m.num_extra_channels;
@@ -1397,16 +1448,19 @@ Status ComputeEncodingData(
// computing inverse Gaborish and adaptive quantization map.
int max_border = enc_state.streaming_mode ? kBlockDim : 0;
Rect frame_rect(0, 0, frame_data.xsize, frame_data.ysize);
- Rect patch_rect = Rect(x0, y0, xsize, ysize).Extend(max_border, frame_rect);
+ Rect frame_area_rect = Rect(x0, y0, xsize, ysize);
+ Rect patch_rect = frame_area_rect.Extend(max_border, frame_rect);
JXL_ASSERT(patch_rect.IsInside(frame_rect));
// Allocating a large enough image avoids a copy when padding.
- Image3F color(RoundUpToBlockDim(patch_rect.xsize()),
- RoundUpToBlockDim(patch_rect.ysize()));
+ JXL_ASSIGN_OR_RETURN(Image3F color,
+ Image3F::Create(RoundUpToBlockDim(patch_rect.xsize()),
+ RoundUpToBlockDim(patch_rect.ysize())));
color.ShrinkTo(patch_rect.xsize(), patch_rect.ysize());
std::vector<ImageF> extra_channels(num_extra_channels);
for (auto& extra_channel : extra_channels) {
- extra_channel = jxl::ImageF(patch_rect.xsize(), patch_rect.ysize());
+ JXL_ASSIGN_OR_RETURN(
+ extra_channel, ImageF::Create(patch_rect.xsize(), patch_rect.ysize()));
}
ImageF* alpha = alpha_eci ? &extra_channels[alpha_idx] : nullptr;
ImageF* black = black_eci ? &extra_channels[black_idx] : nullptr;
@@ -1432,7 +1486,9 @@ Status ComputeEncodingData(
frame_info.ib_needs_color_transform) {
if (frame_header.encoding == FrameEncoding::kVarDCT &&
cparams.speed_tier <= SpeedTier::kKitten) {
- linear_storage = Image3F(patch_rect.xsize(), patch_rect.ysize());
+ JXL_ASSIGN_OR_RETURN(
+ linear_storage,
+ Image3F::Create(patch_rect.xsize(), patch_rect.ysize()));
linear = &linear_storage;
}
ToXYB(c_enc, metadata->m.IntensityTarget(), black, pool, &color, cms,
@@ -1446,7 +1502,7 @@ Status ComputeEncodingData(
bool lossless = cparams.IsLossless();
if (alpha && !alpha_eci->alpha_associated &&
frame_header.frame_type == FrameType::kRegularFrame &&
- !ApplyOverride(cparams.keep_invisible, lossless) &&
+ !ApplyOverride(cparams.keep_invisible, true) &&
cparams.ec_resampling == cparams.resampling) {
// simplify invisible pixels
SimplifyInvisible(&color, *alpha, lossless);
@@ -1467,15 +1523,17 @@ Status ComputeEncodingData(
&mutable_frame_header);
}
- ComputeNoiseParams(cparams, enc_state.streaming_mode, !!jpeg_data, color,
+ bool has_jpeg_data = (jpeg_data != nullptr);
+ ComputeNoiseParams(cparams, enc_state.streaming_mode, has_jpeg_data, color,
frame_dim, &mutable_frame_header,
&shared.image_features.noise_params);
- DownsampleColorChannels(cparams, frame_header, !!jpeg_data, &color);
+ JXL_RETURN_IF_ERROR(
+ DownsampleColorChannels(cparams, frame_header, has_jpeg_data, &color));
if (cparams.ec_resampling != 1 && !cparams.already_downsampled) {
for (ImageF& ec : extra_channels) {
- DownsampleImage(&ec, cparams.ec_resampling);
+ JXL_ASSIGN_OR_RETURN(ec, DownsampleImage(ec, cparams.ec_resampling));
}
}
@@ -1505,15 +1563,21 @@ Status ComputeEncodingData(
TokenizeAllCoefficients(frame_header, pool, &enc_state));
}
+ if (cparams.modular_mode || !extra_channels.empty()) {
+ JXL_RETURN_IF_ERROR(enc_modular.ComputeEncodingData(
+ frame_header, metadata->m, &color, extra_channels, group_rect,
+ frame_dim, frame_area_rect, &enc_state, cms, pool, aux_out,
+ /*do_color=*/cparams.modular_mode));
+ }
+
if (!enc_state.streaming_mode) {
- if (cparams.modular_mode || !extra_channels.empty()) {
- JXL_RETURN_IF_ERROR(enc_modular.ComputeEncodingData(
- frame_header, metadata->m, &color, extra_channels, &enc_state, cms,
- pool, aux_out, /*do_color=*/cparams.modular_mode));
+ if (cparams.speed_tier < SpeedTier::kTortoise ||
+ !cparams.ModularPartIsLossless() || cparams.responsive ||
+ !cparams.custom_fixed_tree.empty()) {
+ // Use local trees if doing lossless modular, unless at very slow speeds.
+ JXL_RETURN_IF_ERROR(enc_modular.ComputeTree(pool));
+ JXL_RETURN_IF_ERROR(enc_modular.ComputeTokens(pool));
}
- JXL_RETURN_IF_ERROR(enc_modular.ComputeTree(pool));
- JXL_RETURN_IF_ERROR(enc_modular.ComputeTokens(pool));
-
mutable_frame_header.UpdateFlag(shared.image_features.patches.HasAny(),
FrameHeader::kPatches);
mutable_frame_header.UpdateFlag(shared.image_features.splines.HasAny(),
@@ -1526,6 +1590,7 @@ Status ComputeEncodingData(
const size_t group_index = enc_state.dc_group_index;
enc_modular.ClearStreamData(ModularStreamId::VarDCTDC(group_index));
enc_modular.ClearStreamData(ModularStreamId::ACMetadata(group_index));
+ enc_modular.ClearModularStreamData();
}
return true;
}
@@ -1614,49 +1679,58 @@ bool CanDoStreamingEncoding(const CompressParams& cparams,
const FrameInfo& frame_info,
const CodecMetadata& metadata,
const JxlEncoderChunkedFrameAdapter& frame_data) {
- if (frame_data.IsJPEG()) {
- return false;
- }
- if (cparams.noise == Override::kOn || cparams.patches == Override::kOn) {
+ if (cparams.buffering == 0) {
return false;
}
- if (cparams.progressive_dc != 0 || frame_info.dc_level != 0) {
- return false;
+ if (cparams.buffering == -1) {
+ if (cparams.speed_tier < SpeedTier::kTortoise) return false;
+ if (cparams.speed_tier < SpeedTier::kSquirrel &&
+ cparams.butteraugli_distance > 0.5f) {
+ return false;
+ }
+ if (cparams.speed_tier == SpeedTier::kSquirrel &&
+ cparams.butteraugli_distance >= 3.f) {
+ return false;
+ }
}
- if (cparams.resampling != 1 || cparams.ec_resampling != 1) {
+
+ // TODO(veluca): handle different values of `buffering`.
+ if (frame_data.xsize <= 2048 && frame_data.ysize <= 2048) {
return false;
}
- if (cparams.max_error_mode) {
+ if (frame_data.IsJPEG()) {
return false;
}
- if (cparams.color_transform != ColorTransform::kXYB) {
+ if (cparams.noise == Override::kOn || cparams.patches == Override::kOn) {
return false;
}
- if (cparams.modular_mode) {
+ if (cparams.progressive_dc != 0 || frame_info.dc_level != 0) {
return false;
}
- if (metadata.m.num_extra_channels > 0) {
+ if (cparams.resampling != 1 || cparams.ec_resampling != 1) {
return false;
}
- if (cparams.buffering == 0) {
+ if (cparams.max_error_mode) {
return false;
}
- if (cparams.buffering == 1 && frame_data.xsize <= 2048 &&
- frame_data.ysize <= 2048) {
- return false;
+ if (!cparams.ModularPartIsLossless() || cparams.responsive > 0) {
+ if (metadata.m.num_extra_channels > 0 || cparams.modular_mode) {
+ return false;
+ }
}
- if (frame_data.xsize <= 256 && frame_data.ysize <= 256) {
+ ColorTransform ok_color_transform =
+ cparams.modular_mode ? ColorTransform::kNone : ColorTransform::kXYB;
+ if (cparams.color_transform != ok_color_transform) {
return false;
}
return true;
}
void ComputePermutationForStreaming(size_t xsize, size_t ysize,
- size_t num_passes,
+ size_t group_size, size_t num_passes,
std::vector<coeff_order_t>& permutation,
std::vector<size_t>& dc_group_order) {
// This is only valid in VarDCT mode, otherwise there can be group shift.
- const size_t group_size = 256;
const size_t dc_group_size = group_size * kBlockDim;
const size_t group_xsize = DivCeil(xsize, group_size);
const size_t group_ysize = DivCeil(ysize, group_size);
@@ -1794,7 +1868,7 @@ void RemoveUnusedHistograms(std::vector<uint8_t>& context_map,
for (uint8_t histo_idx : inv_remap) {
new_codes.encoding_info.emplace_back(
std::move(codes.encoding_info[histo_idx]));
- new_codes.uint_config.emplace_back(std::move(codes.uint_config[histo_idx]));
+ new_codes.uint_config.emplace_back(codes.uint_config[histo_idx]);
new_codes.encoded_histograms.emplace_back(
std::move(codes.encoded_histograms[histo_idx]));
}
@@ -1864,14 +1938,13 @@ Status EncodeFrameStreaming(const CompressParams& cparams,
frame_info, jpeg_data.get(), true,
&frame_header));
const size_t num_passes = enc_state.progressive_splitter.GetNumPasses();
- ModularFrameEncoder enc_modular(frame_header, cparams);
+ ModularFrameEncoder enc_modular(frame_header, cparams, true);
std::vector<coeff_order_t> permutation;
std::vector<size_t> dc_group_order;
- ComputePermutationForStreaming(frame_data.xsize, frame_data.ysize, num_passes,
- permutation, dc_group_order);
+ size_t group_size = frame_header.ToFrameDimensions().group_dim;
+ ComputePermutationForStreaming(frame_data.xsize, frame_data.ysize, group_size,
+ num_passes, permutation, dc_group_order);
enc_state.shared.num_histograms = dc_group_order.size();
- // This is only valid in VarDCT mode, otherwise there can be group shift.
- size_t group_size = 256;
size_t dc_group_size = group_size * kBlockDim;
size_t dc_group_xsize = DivCeil(frame_data.xsize, dc_group_size);
size_t min_dc_global_size = 0;
@@ -1898,8 +1971,7 @@ Status EncodeFrameStreaming(const CompressParams& cparams,
enc_state.streaming_mode = true;
enc_state.initialize_global_state = (i == 0);
enc_state.dc_group_index = dc_ix;
- enc_state.histogram_idx =
- std::vector<uint8_t>(group_xsize * group_ysize, i);
+ enc_state.histogram_idx = std::vector<size_t>(group_xsize * group_ysize, i);
std::vector<BitWriter> group_codes;
JXL_RETURN_IF_ERROR(ComputeEncodingData(
cparams, frame_info, metadata, frame_data, jpeg_data.get(), x0, y0,
@@ -1931,9 +2003,13 @@ Status EncodeFrameStreaming(const CompressParams& cparams,
JXL_RETURN_IF_ERROR(
OutputGroups(std::move(group_codes), &group_sizes, output_processor));
}
- JXL_RETURN_IF_ERROR(OutputAcGlobal(enc_state,
- frame_header.ToFrameDimensions(),
- &group_sizes, output_processor, aux_out));
+ if (frame_header.encoding == FrameEncoding::kVarDCT) {
+ JXL_RETURN_IF_ERROR(
+ OutputAcGlobal(enc_state, frame_header.ToFrameDimensions(),
+ &group_sizes, output_processor, aux_out));
+ } else {
+ group_sizes.push_back(0);
+ }
JXL_ASSERT(group_sizes.size() == permutation.size());
size_t end_pos = output_processor->CurrentPosition();
output_processor->Seek(start_pos);
@@ -1975,7 +2051,7 @@ Status EncodeFrameOneShot(const CompressParams& cparams,
frame_info, jpeg_data.get(), false,
&frame_header));
const size_t num_passes = enc_state.progressive_splitter.GetNumPasses();
- ModularFrameEncoder enc_modular(frame_header, cparams);
+ ModularFrameEncoder enc_modular(frame_header, cparams, false);
JXL_RETURN_IF_ERROR(ComputeEncodingData(
cparams, frame_info, metadata, frame_data, jpeg_data.get(), 0, 0,
frame_data.xsize, frame_data.ysize, cms, pool, frame_header, enc_modular,
@@ -2008,15 +2084,21 @@ Status EncodeFrame(const CompressParams& cparams_orig,
JxlEncoderOutputProcessorWrapper* output_processor,
AuxOut* aux_out) {
CompressParams cparams = cparams_orig;
- if (cparams.speed_tier == SpeedTier::kGlacier && !cparams.IsLossless()) {
- cparams.speed_tier = SpeedTier::kTortoise;
+ if (cparams.speed_tier == SpeedTier::kTectonicPlate &&
+ !cparams.IsLossless()) {
+ cparams.speed_tier = SpeedTier::kGlacier;
+ }
+ // Lightning mode is handled externally, so switch to Thunder mode to handle
+ // potentially weird cases.
+ if (cparams.speed_tier == SpeedTier::kLightning) {
+ cparams.speed_tier = SpeedTier::kThunder;
}
- if (cparams.speed_tier == SpeedTier::kGlacier) {
+ if (cparams.speed_tier == SpeedTier::kTectonicPlate) {
std::vector<CompressParams> all_params;
std::vector<size_t> size;
CompressParams cparams_attempt = cparams_orig;
- cparams_attempt.speed_tier = SpeedTier::kTortoise;
+ cparams_attempt.speed_tier = SpeedTier::kGlacier;
cparams_attempt.options.max_properties = 4;
for (float x : {0.0f, 80.f}) {
@@ -2027,8 +2109,9 @@ Status EncodeFrame(const CompressParams& cparams_orig,
// modular headers.
for (int K : {0, 1 << 10, 70000}) {
cparams_attempt.palette_colors = K;
- for (int tree_mode : {-1, (int)ModularOptions::TreeMode::kNoWP,
- (int)ModularOptions::TreeMode::kDefault}) {
+ for (int tree_mode :
+ {-1, static_cast<int>(ModularOptions::TreeMode::kNoWP),
+ static_cast<int>(ModularOptions::TreeMode::kDefault)}) {
if (tree_mode == -1) {
// LZ77 only
cparams_attempt.options.nb_repeats = 0;
@@ -2054,11 +2137,12 @@ Status EncodeFrame(const CompressParams& cparams_orig,
size.resize(all_params.size());
- std::atomic<int> num_errors{0};
+ std::atomic<bool> has_error{false};
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, all_params.size(), ThreadPool::NoInit,
[&](size_t task, size_t) {
+ if (has_error) return;
std::vector<uint8_t> output(64);
uint8_t* next_out = output.data();
size_t avail_out = output.size();
@@ -2066,13 +2150,13 @@ Status EncodeFrame(const CompressParams& cparams_orig,
local_output.SetAvailOut(&next_out, &avail_out);
if (!EncodeFrame(all_params[task], frame_info, metadata, frame_data,
cms, nullptr, &local_output, aux_out)) {
- num_errors.fetch_add(1, std::memory_order_relaxed);
+ has_error = true;
return;
}
size[task] = local_output.CurrentPosition();
},
- "Compress kGlacier"));
- JXL_RETURN_IF_ERROR(num_errors.load(std::memory_order_relaxed) == 0);
+ "Compress kTectonicPlate"));
+ if (has_error) return JXL_FAILURE("Compress kTectonicPlate failed");
size_t best_idx = 0;
for (size_t i = 1; i < all_params.size(); i++) {
@@ -2156,7 +2240,7 @@ Status EncodeFrame(const CompressParams& cparams_orig,
size_t stride = ib.xsize() * num_channels * 4;
color.resize(ib.ysize() * stride);
JXL_RETURN_IF_ERROR(ConvertToExternal(
- ib, /*bites_per_sample=*/32, /*float_out=*/true, num_channels,
+ ib, /*bits_per_sample=*/32, /*float_out=*/true, num_channels,
JXL_NATIVE_ENDIAN, stride, pool, color.data(), color.size(),
/*out_callback=*/{}, Orientation::kIdentity));
JxlPixelFormat format{num_channels, JXL_TYPE_FLOAT, JXL_NATIVE_ENDIAN, 0};
@@ -2169,7 +2253,7 @@ Status EncodeFrame(const CompressParams& cparams_orig,
const ImageF* channel = &ib.extra_channels()[ec];
JXL_RETURN_IF_ERROR(ConvertChannelsToExternal(
&channel, 1,
- /*bites_per_sample=*/32,
+ /*bits_per_sample=*/32,
/*float_out=*/true, JXL_NATIVE_ENDIAN, ec_stride, pool, ec_data.data(),
ec_data.size(), /*out_callback=*/{}, Orientation::kIdentity));
frame_data.SetFromBuffer(1 + ec, ec_data.data(), ec_data.size(), ec_format);
diff --git a/third_party/jpeg-xl/lib/jxl/enc_frame.h b/third_party/jpeg-xl/lib/jxl/enc_frame.h
index c6db64ee4e..a5b74cc648 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_frame.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_frame.h
@@ -57,7 +57,7 @@ struct FrameInfo {
// Corresponds to BlendingInfo::source from the FrameHeader.
size_t source = 1;
// Corresponds to BlendingInfo::clamp from the FrameHeader.
- size_t clamp = 1;
+ bool clamp = true;
// Corresponds to BlendingInfo::alpha_channel from the FrameHeader, or set to
// -1 to automatically choose it as the index of the first extra channel of
// type alpha.
diff --git a/third_party/jpeg-xl/lib/jxl/enc_gaborish.cc b/third_party/jpeg-xl/lib/jxl/enc_gaborish.cc
index 3f2ee32afd..7467a4d669 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_gaborish.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_gaborish.cc
@@ -15,8 +15,8 @@
namespace jxl {
-void GaborishInverse(Image3F* in_out, const Rect& rect, float mul[3],
- ThreadPool* pool) {
+Status GaborishInverse(Image3F* in_out, const Rect& rect, const float mul[3],
+ ThreadPool* pool) {
WeightsSymmetric5 weights[3];
// Only an approximation. One or even two 3x3, and rank-1 (separable) 5x5
// are insufficient. The numbers here have been obtained by butteraugli
@@ -47,7 +47,9 @@ void GaborishInverse(Image3F* in_out, const Rect& rect, float mul[3],
// Note that we cannot *allocate* a plane, as doing so might cause Image3F to
// have planes of different stride. Instead, we copy one plane in a temporary
// image and reuse the existing planes of the in/out image.
- ImageF temp(in_out->Plane(2).xsize(), in_out->Plane(2).ysize());
+ ImageF temp;
+ JXL_ASSIGN_OR_RETURN(
+ temp, ImageF::Create(in_out->Plane(2).xsize(), in_out->Plane(2).ysize()));
CopyImageTo(in_out->Plane(2), &temp);
Rect xrect = rect.Extend(3, Rect(*in_out));
Symmetric5(in_out->Plane(0), xrect, weights[0], pool, &in_out->Plane(2),
@@ -59,6 +61,7 @@ void GaborishInverse(Image3F* in_out, const Rect& rect, float mul[3],
in_out->Plane(0).Swap(in_out->Plane(1));
// 2 1 0
in_out->Plane(0).Swap(in_out->Plane(2));
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_gaborish.h b/third_party/jpeg-xl/lib/jxl/enc_gaborish.h
index ece4959f36..041edcec96 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_gaborish.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_gaborish.h
@@ -9,6 +9,7 @@
// Linear smoothing (3x3 convolution) for deblocking without too much blur.
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/image.h"
namespace jxl {
@@ -16,8 +17,8 @@ namespace jxl {
// Used in encoder to reduce the impact of the decoder's smoothing.
// This is not exact. Works in-place to reduce memory use.
// The input is typically in XYB space.
-void GaborishInverse(Image3F* in_out, const Rect& rect, float mul[3],
- ThreadPool* pool);
+Status GaborishInverse(Image3F* in_out, const Rect& rect, const float mul[3],
+ ThreadPool* pool);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_gaborish_test.cc b/third_party/jpeg-xl/lib/jxl/enc_gaborish_test.cc
index 426f08ecb0..0d173c5eb8 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_gaborish_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_gaborish_test.cc
@@ -5,6 +5,8 @@
#include "lib/jxl/enc_gaborish.h"
+#include <jxl/types.h>
+
#include <hwy/base.h>
#include "lib/jxl/base/compiler_specific.h"
@@ -40,7 +42,7 @@ void ConvolveGaborish(const ImageF& in, float weight1, float weight2,
}
void TestRoundTrip(const Image3F& in, float max_l1) {
- Image3F fwd(in.xsize(), in.ysize());
+ JXL_ASSIGN_OR_DIE(Image3F fwd, Image3F::Create(in.xsize(), in.ysize()));
ThreadPool* null_pool = nullptr;
ConvolveGaborish(in.Plane(0), 0, 0, null_pool, &fwd.Plane(0));
ConvolveGaborish(in.Plane(1), 0, 0, null_pool, &fwd.Plane(1));
@@ -51,20 +53,20 @@ void TestRoundTrip(const Image3F& in, float max_l1) {
w,
w,
};
- GaborishInverse(&fwd, Rect(fwd), weights, null_pool);
+ JXL_CHECK(GaborishInverse(&fwd, Rect(fwd), weights, null_pool));
JXL_ASSERT_OK(VerifyRelativeError(in, fwd, max_l1, 1E-4f, _));
}
TEST(GaborishTest, TestZero) {
- Image3F in(20, 20);
+ JXL_ASSIGN_OR_DIE(Image3F in, Image3F::Create(20, 20));
ZeroFillImage(&in);
TestRoundTrip(in, 0.0f);
}
// Disabled: large difference.
-#if 0
+#if JXL_FALSE
TEST(GaborishTest, TestDirac) {
- Image3F in(20, 20);
+ JXL_ASSIGN_OR_DIE(Image3F in, Image3F::Create(20, 20));
ZeroFillImage(&in);
in.PlaneRow(1, 10)[10] = 10.0f;
TestRoundTrip(in, 0.26f);
@@ -72,7 +74,7 @@ TEST(GaborishTest, TestDirac) {
#endif
TEST(GaborishTest, TestFlat) {
- Image3F in(20, 20);
+ JXL_ASSIGN_OR_DIE(Image3F in, Image3F::Create(20, 20));
FillImage(1.0f, &in);
TestRoundTrip(in, 1E-5f);
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_group.cc b/third_party/jpeg-xl/lib/jxl/enc_group.cc
index 09bab534c9..1967fdaba9 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_group.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_group.cc
@@ -286,10 +286,11 @@ void AdjustQuantBlockAC(const Quantizer& quantizer, size_t c,
{
// Reduce quant in highly active areas.
int32_t div = (xsize * ysize);
- int32_t activity = (hfNonZeros[0] + div / 2) / div;
+ int32_t activity = (static_cast<int32_t>(hfNonZeros[0]) + div / 2) / div;
int32_t orig_qp_limit = std::max(4, *quant / 2);
for (int i = 1; i < 4; ++i) {
- activity = std::min<int32_t>(activity, (hfNonZeros[i] + div / 2) / div);
+ activity = std::min(
+ activity, (static_cast<int32_t>(hfNonZeros[i]) + div / 2) / div);
}
if (activity >= 15) {
activity = 15;
@@ -316,7 +317,7 @@ void QuantizeRoundtripYBlockAC(PassesEncoderState* enc_state, const size_t size,
float* JXL_RESTRICT inout,
int32_t* JXL_RESTRICT quantized) {
float thres_y[4] = {0.58f, 0.64f, 0.64f, 0.64f};
- {
+ if (enc_state->cparams.speed_tier <= SpeedTier::kHare) {
int32_t max_quant = 0;
int quant_orig = *quant;
float val[3] = {enc_state->x_qm_multiplier, 1.0f,
@@ -337,6 +338,11 @@ void QuantizeRoundtripYBlockAC(PassesEncoderState* enc_state, const size_t size,
max_quant = std::max(*quant, max_quant);
}
*quant = max_quant;
+ } else {
+ thres_y[0] = 0.56;
+ thres_y[1] = 0.62;
+ thres_y[2] = 0.62;
+ thres_y[3] = 0.62;
}
QuantizeBlockAC(quantizer, error_diffusion, 1, 1.0f, quant_kind, xsize, ysize,
@@ -507,8 +513,8 @@ namespace jxl {
HWY_EXPORT(ComputeCoefficients);
void ComputeCoefficients(size_t group_idx, PassesEncoderState* enc_state,
const Image3F& opsin, const Rect& rect, Image3F* dc) {
- return HWY_DYNAMIC_DISPATCH(ComputeCoefficients)(group_idx, enc_state, opsin,
- rect, dc);
+ HWY_DYNAMIC_DISPATCH(ComputeCoefficients)
+ (group_idx, enc_state, opsin, rect, dc);
}
Status EncodeGroupTokenizedCoefficients(size_t group_idx, size_t pass_idx,
diff --git a/third_party/jpeg-xl/lib/jxl/enc_heuristics.cc b/third_party/jpeg-xl/lib/jxl/enc_heuristics.cc
index 9d6bf11184..685558ac7c 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_heuristics.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_heuristics.cc
@@ -149,8 +149,10 @@ void FindBestBlockEntropyModel(const CompressParams& cparams, const ImageI& rqf,
std::vector<uint8_t> remap((qft.size() + 1) * kNumOrders);
std::iota(remap.begin(), remap.end(), 0);
std::vector<uint8_t> clusters(remap);
- size_t nb_clusters = Clamp1((int)(tot / size_for_ctx_model / 2), 2, 9);
- size_t nb_clusters_chroma = Clamp1((int)(tot / size_for_ctx_model / 3), 1, 5);
+ size_t nb_clusters =
+ Clamp1(static_cast<int>(tot / size_for_ctx_model / 2), 2, 9);
+ size_t nb_clusters_chroma =
+ Clamp1(static_cast<int>(tot / size_for_ctx_model / 3), 1, 5);
// This is O(n^2 log n), but n is small.
while (clusters.size() > nb_clusters) {
std::sort(clusters.begin(), clusters.end(),
@@ -181,8 +183,8 @@ void FindBestBlockEntropyModel(const CompressParams& cparams, const ImageI& rqf,
// for chroma, only use up to nb_clusters_chroma separate block contexts
// (those for the biggest clusters)
for (size_t i = remap.size(); i < remap.size() * 3; i++) {
- ctx_map[i] = num + Clamp1((int)remap[i % remap.size()], 0,
- (int)nb_clusters_chroma - 1);
+ ctx_map[i] = num + Clamp1(static_cast<int>(remap[i % remap.size()]), 0,
+ static_cast<int>(nb_clusters_chroma) - 1);
}
block_ctx_map->num_ctxs =
*std::max_element(ctx_map.begin(), ctx_map.end()) + 1;
@@ -190,9 +192,9 @@ void FindBestBlockEntropyModel(const CompressParams& cparams, const ImageI& rqf,
namespace {
-void FindBestDequantMatrices(const CompressParams& cparams,
- ModularFrameEncoder* modular_frame_encoder,
- DequantMatrices* dequant_matrices) {
+Status FindBestDequantMatrices(const CompressParams& cparams,
+ ModularFrameEncoder* modular_frame_encoder,
+ DequantMatrices* dequant_matrices) {
// TODO(veluca): quant matrices for no-gaborish.
// TODO(veluca): heuristics for in-bitstream quant tables.
*dequant_matrices = DequantMatrices();
@@ -204,13 +206,14 @@ void FindBestDequantMatrices(const CompressParams& cparams,
DctQuantWeightParams dct_params(weights);
std::vector<QuantEncoding> encodings(DequantMatrices::kNum,
QuantEncoding::DCT(dct_params));
- DequantMatricesSetCustom(dequant_matrices, encodings,
- modular_frame_encoder);
+ JXL_RETURN_IF_ERROR(DequantMatricesSetCustom(dequant_matrices, encodings,
+ modular_frame_encoder));
float dc_weights[3] = {1.0f / cparams.max_error[0],
1.0f / cparams.max_error[1],
1.0f / cparams.max_error[2]};
DequantMatricesSetCustomDC(dequant_matrices, dc_weights);
}
+ return true;
}
void StoreMin2(const float v, float& min1, float& min2) {
@@ -226,9 +229,9 @@ void StoreMin2(const float v, float& min1, float& min2) {
void CreateMask(const ImageF& image, ImageF& mask) {
for (size_t y = 0; y < image.ysize(); y++) {
- auto* row_n = y > 0 ? image.Row(y - 1) : image.Row(y);
- auto* row_in = image.Row(y);
- auto* row_s = y + 1 < image.ysize() ? image.Row(y + 1) : image.Row(y);
+ const auto* row_n = y > 0 ? image.Row(y - 1) : image.Row(y);
+ const auto* row_in = image.Row(y);
+ const auto* row_s = y + 1 < image.ysize() ? image.Row(y + 1) : image.Row(y);
auto* row_out = mask.Row(y);
for (size_t x = 0; x < image.xsize(); x++) {
// Center, west, east, north, south values and their absolute difference
@@ -258,7 +261,7 @@ void CreateMask(const ImageF& image, ImageF& mask) {
// by the decoder. Ringing is slightly reduced by clamping the values of the
// resulting pixels within certain bounds of a small region in the original
// image.
-void DownsampleImage2_Sharper(const ImageF& input, ImageF* output) {
+Status DownsampleImage2_Sharper(const ImageF& input, ImageF* output) {
const int64_t kernelx = 12;
const int64_t kernely = 12;
@@ -315,11 +318,12 @@ void DownsampleImage2_Sharper(const ImageF& input, ImageF* output) {
int64_t xsize = input.xsize();
int64_t ysize = input.ysize();
- ImageF box_downsample(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF box_downsample, ImageF::Create(xsize, ysize));
CopyImageTo(input, &box_downsample);
- DownsampleImage(&box_downsample, 2);
+ JXL_ASSIGN_OR_RETURN(box_downsample, DownsampleImage(box_downsample, 2));
- ImageF mask(box_downsample.xsize(), box_downsample.ysize());
+ JXL_ASSIGN_OR_RETURN(ImageF mask, ImageF::Create(box_downsample.xsize(),
+ box_downsample.ysize()));
CreateMask(box_downsample, mask);
for (size_t y = 0; y < output->ysize(); y++) {
@@ -379,50 +383,54 @@ void DownsampleImage2_Sharper(const ImageF& input, ImageF* output) {
}
}
}
+ return true;
}
} // namespace
-void DownsampleImage2_Sharper(Image3F* opsin) {
+Status DownsampleImage2_Sharper(Image3F* opsin) {
// Allocate extra space to avoid a reallocation when padding.
- Image3F downsampled(DivCeil(opsin->xsize(), 2) + kBlockDim,
- DivCeil(opsin->ysize(), 2) + kBlockDim);
+ JXL_ASSIGN_OR_RETURN(Image3F downsampled,
+ Image3F::Create(DivCeil(opsin->xsize(), 2) + kBlockDim,
+ DivCeil(opsin->ysize(), 2) + kBlockDim));
downsampled.ShrinkTo(downsampled.xsize() - kBlockDim,
downsampled.ysize() - kBlockDim);
for (size_t c = 0; c < 3; c++) {
- DownsampleImage2_Sharper(opsin->Plane(c), &downsampled.Plane(c));
+ JXL_RETURN_IF_ERROR(
+ DownsampleImage2_Sharper(opsin->Plane(c), &downsampled.Plane(c)));
}
*opsin = std::move(downsampled);
+ return true;
}
namespace {
// The default upsampling kernels used by Upsampler in the decoder.
-static const constexpr int64_t kSize = 5;
+const constexpr int64_t kSize = 5;
-static const float kernel00[25] = {
+const float kernel00[25] = {
-0.01716200f, -0.03452303f, -0.04022174f, -0.02921014f, -0.00624645f,
-0.03452303f, 0.14111091f, 0.28896755f, 0.00278718f, -0.01610267f,
-0.04022174f, 0.28896755f, 0.56661550f, 0.03777607f, -0.01986694f,
-0.02921014f, 0.00278718f, 0.03777607f, -0.03144731f, -0.01185068f,
-0.00624645f, -0.01610267f, -0.01986694f, -0.01185068f, -0.00213539f,
};
-static const float kernel01[25] = {
+const float kernel01[25] = {
-0.00624645f, -0.01610267f, -0.01986694f, -0.01185068f, -0.00213539f,
-0.02921014f, 0.00278718f, 0.03777607f, -0.03144731f, -0.01185068f,
-0.04022174f, 0.28896755f, 0.56661550f, 0.03777607f, -0.01986694f,
-0.03452303f, 0.14111091f, 0.28896755f, 0.00278718f, -0.01610267f,
-0.01716200f, -0.03452303f, -0.04022174f, -0.02921014f, -0.00624645f,
};
-static const float kernel10[25] = {
+const float kernel10[25] = {
-0.00624645f, -0.02921014f, -0.04022174f, -0.03452303f, -0.01716200f,
-0.01610267f, 0.00278718f, 0.28896755f, 0.14111091f, -0.03452303f,
-0.01986694f, 0.03777607f, 0.56661550f, 0.28896755f, -0.04022174f,
-0.01185068f, -0.03144731f, 0.03777607f, 0.00278718f, -0.02921014f,
-0.00213539f, -0.01185068f, -0.01986694f, -0.01610267f, -0.00624645f,
};
-static const float kernel11[25] = {
+const float kernel11[25] = {
-0.00213539f, -0.01185068f, -0.01986694f, -0.01610267f, -0.00624645f,
-0.01185068f, -0.03144731f, 0.03777607f, 0.00278718f, -0.02921014f,
-0.01986694f, 0.03777607f, 0.56661550f, 0.28896755f, -0.04022174f,
@@ -435,14 +443,14 @@ static const float kernel11[25] = {
// TODO(lode): use Upsampler instead. However, it requires pre-initialization
// and padding on the left side of the image which requires refactoring the
// other code using this.
-static void UpsampleImage(const ImageF& input, ImageF* output) {
+void UpsampleImage(const ImageF& input, ImageF* output) {
int64_t xsize = input.xsize();
int64_t ysize = input.ysize();
int64_t xsize2 = output->xsize();
int64_t ysize2 = output->ysize();
for (int64_t y = 0; y < ysize2; y++) {
for (int64_t x = 0; x < xsize2; x++) {
- auto kernel = kernel00;
+ const auto* kernel = kernel00;
if ((x & 1) && (y & 1)) {
kernel = kernel11;
} else if (x & 1) {
@@ -492,7 +500,7 @@ static void UpsampleImage(const ImageF& input, ImageF* output) {
// Returns the derivative of Upsampler, with respect to input pixel x2, y2, to
// output pixel x, y (ignoring the clamping).
float UpsamplerDeriv(int64_t x2, int64_t y2, int64_t x, int64_t y) {
- auto kernel = kernel00;
+ const auto* kernel = kernel00;
if ((x & 1) && (y & 1)) {
kernel = kernel11;
} else if (x & 1) {
@@ -597,11 +605,9 @@ void ReduceRinging(const ImageF& initial, const ImageF& mask, ImageF& down) {
float max = initial.Row(y)[x];
for (int64_t yi = -1; yi < 2; yi++) {
for (int64_t xi = -1; xi < 2; xi++) {
- int64_t x2 = (int64_t)x + xi;
- int64_t y2 = (int64_t)y + yi;
- if (x2 < 0 || y2 < 0 || x2 >= (int64_t)xsize2 ||
- y2 >= (int64_t)ysize2)
- continue;
+ int64_t x2 = static_cast<int64_t>(x) + xi;
+ int64_t y2 = static_cast<int64_t>(y) + yi;
+ if (x2 < 0 || y2 < 0 || x2 >= xsize2 || y2 >= ysize2) continue;
min = std::min<float>(min, initial.Row(y2)[x2]);
max = std::max<float>(max, initial.Row(y2)[x2]);
}
@@ -625,32 +631,35 @@ void ReduceRinging(const ImageF& initial, const ImageF& mask, ImageF& down) {
}
// TODO(lode): move this to a separate file enc_downsample.cc
-void DownsampleImage2_Iterative(const ImageF& orig, ImageF* output) {
+Status DownsampleImage2_Iterative(const ImageF& orig, ImageF* output) {
int64_t xsize = orig.xsize();
int64_t ysize = orig.ysize();
int64_t xsize2 = DivCeil(orig.xsize(), 2);
int64_t ysize2 = DivCeil(orig.ysize(), 2);
- ImageF box_downsample(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF box_downsample, ImageF::Create(xsize, ysize));
CopyImageTo(orig, &box_downsample);
- DownsampleImage(&box_downsample, 2);
- ImageF mask(box_downsample.xsize(), box_downsample.ysize());
+ JXL_ASSIGN_OR_RETURN(box_downsample, DownsampleImage(box_downsample, 2));
+ JXL_ASSIGN_OR_RETURN(ImageF mask, ImageF::Create(box_downsample.xsize(),
+ box_downsample.ysize()));
CreateMask(box_downsample, mask);
output->ShrinkTo(xsize2, ysize2);
// Initial result image using the sharper downsampling.
// Allocate extra space to avoid a reallocation when padding.
- ImageF initial(DivCeil(orig.xsize(), 2) + kBlockDim,
- DivCeil(orig.ysize(), 2) + kBlockDim);
+ JXL_ASSIGN_OR_RETURN(ImageF initial,
+ ImageF::Create(DivCeil(orig.xsize(), 2) + kBlockDim,
+ DivCeil(orig.ysize(), 2) + kBlockDim));
initial.ShrinkTo(initial.xsize() - kBlockDim, initial.ysize() - kBlockDim);
- DownsampleImage2_Sharper(orig, &initial);
+ JXL_RETURN_IF_ERROR(DownsampleImage2_Sharper(orig, &initial));
- ImageF down(initial.xsize(), initial.ysize());
+ JXL_ASSIGN_OR_RETURN(ImageF down,
+ ImageF::Create(initial.xsize(), initial.ysize()));
CopyImageTo(initial, &down);
- ImageF up(xsize, ysize);
- ImageF corr(xsize, ysize);
- ImageF corr2(xsize2, ysize2);
+ JXL_ASSIGN_OR_RETURN(ImageF up, ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_RETURN(ImageF corr, ImageF::Create(xsize, ysize));
+ JXL_ASSIGN_OR_RETURN(ImageF corr2, ImageF::Create(xsize2, ysize2));
// In the weights map, relatively higher values will allow less ringing but
// also less sharpness. With all constant values, it optimizes equally
@@ -659,25 +668,25 @@ void DownsampleImage2_Iterative(const ImageF& orig, ImageF* output) {
// TODO(lode): Make use of the weights field for anti-ringing and clamping,
// the values are all set to 1 for now, but it is intended to be used for
// reducing ringing based on the mask, and taking clamping into account.
- ImageF weights(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(ImageF weights, ImageF::Create(xsize, ysize));
for (size_t y = 0; y < weights.ysize(); y++) {
auto* row = weights.Row(y);
for (size_t x = 0; x < weights.xsize(); x++) {
row[x] = 1;
}
}
- ImageF weights2(xsize2, ysize2);
+ JXL_ASSIGN_OR_RETURN(ImageF weights2, ImageF::Create(xsize2, ysize2));
AntiUpsample(weights, &weights2);
const size_t num_it = 3;
for (size_t it = 0; it < num_it; ++it) {
UpsampleImage(down, &up);
- corr = LinComb<float>(1, orig, -1, up);
+ JXL_ASSIGN_OR_RETURN(corr, LinComb<float>(1, orig, -1, up));
ElwiseMul(corr, weights, &corr);
AntiUpsample(corr, &corr2);
ElwiseDiv(corr2, weights2, &corr2);
- down = LinComb<float>(1, down, 1, corr2);
+ JXL_ASSIGN_OR_RETURN(down, LinComb<float>(1, down, 1, corr2));
}
ReduceRinging(initial, mask, down);
@@ -690,32 +699,40 @@ void DownsampleImage2_Iterative(const ImageF& orig, ImageF* output) {
output->Row(y)[x] = v;
}
}
+ return true;
}
} // namespace
-void DownsampleImage2_Iterative(Image3F* opsin) {
+Status DownsampleImage2_Iterative(Image3F* opsin) {
// Allocate extra space to avoid a reallocation when padding.
- Image3F downsampled(DivCeil(opsin->xsize(), 2) + kBlockDim,
- DivCeil(opsin->ysize(), 2) + kBlockDim);
+ JXL_ASSIGN_OR_RETURN(Image3F downsampled,
+ Image3F::Create(DivCeil(opsin->xsize(), 2) + kBlockDim,
+ DivCeil(opsin->ysize(), 2) + kBlockDim));
downsampled.ShrinkTo(downsampled.xsize() - kBlockDim,
downsampled.ysize() - kBlockDim);
- Image3F rgb(opsin->xsize(), opsin->ysize());
+ JXL_ASSIGN_OR_RETURN(Image3F rgb,
+ Image3F::Create(opsin->xsize(), opsin->ysize()));
OpsinParams opsin_params; // TODO(user): use the ones that are actually used
opsin_params.Init(kDefaultIntensityTarget);
OpsinToLinear(*opsin, Rect(rgb), nullptr, &rgb, opsin_params);
- ImageF mask(opsin->xsize(), opsin->ysize());
+ JXL_ASSIGN_OR_RETURN(ImageF mask,
+ ImageF::Create(opsin->xsize(), opsin->ysize()));
ButteraugliParams butter_params;
- ButteraugliComparator butter(rgb, butter_params);
- butter.Mask(&mask);
- ImageF mask_fuzzy(opsin->xsize(), opsin->ysize());
+ JXL_ASSIGN_OR_RETURN(std::unique_ptr<ButteraugliComparator> butter,
+ ButteraugliComparator::Make(rgb, butter_params));
+ JXL_RETURN_IF_ERROR(butter->Mask(&mask));
+ JXL_ASSIGN_OR_RETURN(ImageF mask_fuzzy,
+ ImageF::Create(opsin->xsize(), opsin->ysize()));
for (size_t c = 0; c < 3; c++) {
- DownsampleImage2_Iterative(opsin->Plane(c), &downsampled.Plane(c));
+ JXL_RETURN_IF_ERROR(
+ DownsampleImage2_Iterative(opsin->Plane(c), &downsampled.Plane(c)));
}
*opsin = std::move(downsampled);
+ return true;
}
Status LossyFrameHeuristics(const FrameHeader& frame_header,
@@ -739,10 +756,11 @@ Status LossyFrameHeuristics(const FrameHeader& frame_header,
BlockCtxMap& block_ctx_map = shared.block_ctx_map;
// Find and subtract splines.
+ if (cparams.custom_splines.HasAny()) {
+ image_features.splines = cparams.custom_splines;
+ }
if (!streaming_mode && cparams.speed_tier <= SpeedTier::kSquirrel) {
- if (cparams.custom_splines.HasAny()) {
- image_features.splines = cparams.custom_splines;
- } else {
+ if (!cparams.custom_splines.HasAny()) {
image_features.splines = FindSplines(*opsin);
}
JXL_RETURN_IF_ERROR(image_features.splines.InitializeDrawCache(
@@ -754,7 +772,8 @@ Status LossyFrameHeuristics(const FrameHeader& frame_header,
if (!streaming_mode &&
ApplyOverride(cparams.patches,
cparams.speed_tier <= SpeedTier::kSquirrel)) {
- FindBestPatchDictionary(*opsin, enc_state, cms, pool, aux_out);
+ JXL_RETURN_IF_ERROR(
+ FindBestPatchDictionary(*opsin, enc_state, cms, pool, aux_out));
PatchDictionaryEncoder::SubtractFrom(image_features.patches, opsin);
}
@@ -791,10 +810,12 @@ Status LossyFrameHeuristics(const FrameHeader& frame_header,
// on simple heuristics in FindBestAcStrategy, or set a constant for Falcon
// mode.
if (cparams.speed_tier > SpeedTier::kHare) {
- initial_quant_field =
- ImageF(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
- initial_quant_masking =
- ImageF(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
+ JXL_ASSIGN_OR_RETURN(
+ initial_quant_field,
+ ImageF::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
+ JXL_ASSIGN_OR_RETURN(
+ initial_quant_masking,
+ ImageF::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
float q = 0.79 / cparams.butteraugli_distance;
FillImage(q, &initial_quant_field);
FillImage(1.0f / (q + 0.001f), &initial_quant_masking);
@@ -805,9 +826,11 @@ Status LossyFrameHeuristics(const FrameHeader& frame_header,
if (!frame_header.loop_filter.gab) {
butteraugli_distance_for_iqf *= 0.73f;
}
- initial_quant_field = InitialQuantField(
- butteraugli_distance_for_iqf, *opsin, rect, pool, 1.0f,
- &initial_quant_masking, &initial_quant_masking1x1);
+ JXL_ASSIGN_OR_RETURN(
+ initial_quant_field,
+ InitialQuantField(butteraugli_distance_for_iqf, *opsin, rect, pool,
+ 1.0f, &initial_quant_masking,
+ &initial_quant_masking1x1));
float q = 0.39 / cparams.butteraugli_distance;
quantizer.ComputeGlobalScaleAndQuant(quant_dc, q, 0);
}
@@ -822,18 +845,21 @@ Status LossyFrameHeuristics(const FrameHeader& frame_header,
0.99406123118127299f,
0.99719338015886894f,
};
- GaborishInverse(opsin, rect, weight, pool);
+ JXL_RETURN_IF_ERROR(GaborishInverse(opsin, rect, weight, pool));
}
if (initialize_global_state) {
- FindBestDequantMatrices(cparams, modular_frame_encoder, &matrices);
+ JXL_RETURN_IF_ERROR(
+ FindBestDequantMatrices(cparams, modular_frame_encoder, &matrices));
}
- cfl_heuristics.Init(rect);
+ JXL_RETURN_IF_ERROR(cfl_heuristics.Init(rect));
acs_heuristics.Init(*opsin, rect, initial_quant_field, initial_quant_masking,
initial_quant_masking1x1, &matrices);
+ std::atomic<bool> has_error{false};
auto process_tile = [&](const uint32_t tid, const size_t thread) {
+ if (has_error) return;
size_t n_enc_tiles = DivCeil(frame_dim.xsize_blocks, kEncTileDimInBlocks);
size_t tx = tid % n_enc_tiles;
size_t ty = tid / n_enc_tiles;
@@ -856,13 +882,16 @@ Status LossyFrameHeuristics(const FrameHeader& frame_header,
}
// Choose block sizes.
- acs_heuristics.ProcessRect(r, cmap, &ac_strategy);
+ acs_heuristics.ProcessRect(r, cmap, &ac_strategy, thread);
// Choose amount of post-processing smoothing.
// TODO(veluca): should this go *after* AdjustQuantField?
- ar_heuristics.RunRect(cparams, frame_header, r, *opsin, rect,
- initial_quant_field, ac_strategy, &epf_sharpness,
- thread);
+ if (!ar_heuristics.RunRect(cparams, frame_header, r, *opsin, rect,
+ initial_quant_field, ac_strategy, &epf_sharpness,
+ thread)) {
+ has_error = true;
+ return;
+ }
// Always set the initial quant field, so we can compute the CfL map with
// more accuracy. The initial quant field might change in slower modes, but
@@ -884,18 +913,21 @@ Status LossyFrameHeuristics(const FrameHeader& frame_header,
DivCeil(frame_dim.xsize_blocks, kEncTileDimInBlocks) *
DivCeil(frame_dim.ysize_blocks, kEncTileDimInBlocks),
[&](const size_t num_threads) {
+ acs_heuristics.PrepareForThreads(num_threads);
ar_heuristics.PrepareForThreads(num_threads);
cfl_heuristics.PrepareForThreads(num_threads);
return true;
},
process_tile, "Enc Heuristics"));
+ if (has_error) return JXL_FAILURE("Enc Heuristics failed");
- acs_heuristics.Finalize(frame_dim, ac_strategy, aux_out);
+ JXL_RETURN_IF_ERROR(acs_heuristics.Finalize(frame_dim, ac_strategy, aux_out));
// Refine quantization levels.
if (!streaming_mode) {
- FindBestQuantizer(frame_header, original_pixels, *opsin,
- initial_quant_field, enc_state, cms, pool, aux_out);
+ JXL_RETURN_IF_ERROR(FindBestQuantizer(frame_header, original_pixels, *opsin,
+ initial_quant_field, enc_state, cms,
+ pool, aux_out));
}
// Choose a context model that depends on the amount of quantization for AC.
diff --git a/third_party/jpeg-xl/lib/jxl/enc_heuristics.h b/third_party/jpeg-xl/lib/jxl/enc_heuristics.h
index 14cb596387..0dd93e4288 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_heuristics.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_heuristics.h
@@ -38,8 +38,8 @@ Status LossyFrameHeuristics(const FrameHeader& frame_header,
void FindBestBlockEntropyModel(PassesEncoderState& enc_state);
-void DownsampleImage2_Iterative(Image3F* output);
-void DownsampleImage2_Sharper(Image3F* opsin);
+Status DownsampleImage2_Iterative(Image3F* opsin);
+Status DownsampleImage2_Sharper(Image3F* opsin);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_huffman.cc b/third_party/jpeg-xl/lib/jxl/enc_huffman.cc
index 3eab2c218a..6af92f6ed5 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_huffman.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_huffman.cc
@@ -70,6 +70,7 @@ void StoreHuffmanTreeToBitMask(const size_t huffman_tree_size,
for (size_t i = 0; i < huffman_tree_size; ++i) {
size_t ix = huffman_tree[i];
writer->Write(code_length_bitdepth[ix], code_length_bitdepth_symbols[ix]);
+ JXL_ASSERT(ix <= 17);
// Extra bits
switch (ix) {
case 16:
@@ -78,6 +79,9 @@ void StoreHuffmanTreeToBitMask(const size_t huffman_tree_size,
case 17:
writer->Write(3, huffman_tree_extra_bits[i]);
break;
+ default:
+ // no-op
+ break;
}
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_huffman_tree.cc b/third_party/jpeg-xl/lib/jxl/enc_huffman_tree.cc
index 5c40dea770..82ae4bccc7 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_huffman_tree.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_huffman_tree.cc
@@ -85,7 +85,8 @@ void CreateHuffmanTree(const uint32_t* data, const size_t length,
size_t i = 0; // Points to the next leaf node.
size_t j = n + 1; // Points to the next non-leaf node.
for (size_t k = n - 1; k != 0; --k) {
- size_t left, right;
+ size_t left;
+ size_t right;
if (tree[i].total_count <= tree[j].total_count) {
left = i;
++i;
@@ -112,7 +113,7 @@ void CreateHuffmanTree(const uint32_t* data, const size_t length,
tree.push_back(sentinel);
}
JXL_DASSERT(tree.size() == 2 * n + 1);
- SetDepth(tree[2 * n - 1], &tree[0], depth, 0);
+ SetDepth(tree[2 * n - 1], tree.data(), depth, 0);
// We need to pack the Huffman tree in tree_limit bits.
// If this was not successful, add fake entities to the lowest values
diff --git a/third_party/jpeg-xl/lib/jxl/enc_icc_codec.cc b/third_party/jpeg-xl/lib/jxl/enc_icc_codec.cc
index 8e92fe3452..a29fb3f299 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_icc_codec.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_icc_codec.cc
@@ -13,6 +13,7 @@
#include <vector>
#include "lib/jxl/base/byte_order.h"
+#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/enc_ans.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/fields.h"
@@ -36,7 +37,8 @@ void Unshuffle(uint8_t* data, size_t size, size_t width) {
size_t height = (size + width - 1) / width; // amount of rows of input
PaddedBytes result(size);
// i = input index, j output index
- size_t s = 0, j = 0;
+ size_t s = 0;
+ size_t j = 0;
for (size_t i = 0; i < size; i++) {
result[j] = data[i];
j += height;
@@ -71,7 +73,7 @@ Status PredictAndShuffle(size_t stride, size_t width, int order, size_t num,
return true;
}
-static inline void EncodeVarInt(uint64_t value, PaddedBytes* data) {
+inline void EncodeVarInt(uint64_t value, PaddedBytes* data) {
size_t pos = data->size();
data->resize(data->size() + 9);
size_t output_size = data->size();
@@ -83,13 +85,13 @@ static inline void EncodeVarInt(uint64_t value, PaddedBytes* data) {
// TODO(eustas): should it be `<` ?
JXL_CHECK(pos <= output_size);
// |128: Set the next byte flag
- output[pos++] = ((uint8_t)(value & 127)) | 128;
+ output[pos++] = (static_cast<uint8_t>(value & 127)) | 128;
// Remove the seven bits we just wrote
value >>= 7;
}
// TODO(eustas): should it be `<` ?
JXL_CHECK(pos <= output_size);
- output[pos++] = ((uint8_t)value) & 127;
+ output[pos++] = static_cast<uint8_t>(value & 127);
data->resize(pos);
}
@@ -235,7 +237,9 @@ Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result) {
// allowed for tagged elements to overlap, e.g. the curve for R, G and B could
// all point to the same one.
Tag tag;
- size_t tagstart = 0, tagsize = 0, clutstart = 0;
+ size_t tagstart = 0;
+ size_t tagsize = 0;
+ size_t clutstart = 0;
// Should always check tag_sane before doing math with tagsize.
const auto tag_sane = [&tagsize]() {
@@ -292,7 +296,9 @@ Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result) {
commands_add.push_back(kCommandTypeStartFirst + 5);
pos += 8;
commands_add.push_back(kCommandPredict);
- int order = 1, width = 2, stride = width;
+ int order = 1;
+ int width = 2;
+ int stride = width;
commands_add.push_back((order << 2) | (width - 1));
EncodeVarInt(num, &commands_add);
JXL_RETURN_IF_ERROR(PredictAndShuffle(stride, width, order, num, icc,
@@ -310,7 +316,9 @@ Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result) {
pos += 12;
last1 = pos;
commands_add.push_back(kCommandPredict);
- int order = 1, width = 2, stride = width;
+ int order = 1;
+ int width = 2;
+ int stride = width;
commands_add.push_back((order << 2) | (width - 1));
EncodeVarInt(num, &commands_add);
JXL_RETURN_IF_ERROR(PredictAndShuffle(stride, width, order, num, icc,
@@ -352,7 +360,9 @@ Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result) {
if (commands_add.empty() && data_add.empty() && tag == kGbd_Tag &&
tag_sane() && pos == tagstart + 8 && pos + tagsize - 8 <= size &&
pos > 16) {
- size_t width = 4, order = 0, stride = width;
+ size_t width = 4;
+ size_t order = 0;
+ size_t stride = width;
size_t num = tagsize - 8;
uint8_t flags = (order << 2) | (width - 1) | (stride == width ? 0 : 16);
commands_add.push_back(kCommandPredict);
diff --git a/third_party/jpeg-xl/lib/jxl/enc_icc_codec.h b/third_party/jpeg-xl/lib/jxl/enc_icc_codec.h
index 224c2e5316..a99e11b19c 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_icc_codec.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_icc_codec.h
@@ -15,7 +15,6 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/enc_bit_writer.h"
namespace jxl {
@@ -27,9 +26,6 @@ class PaddedBytes;
Status WriteICC(const std::vector<uint8_t>& icc, BitWriter* JXL_RESTRICT writer,
size_t layer, AuxOut* JXL_RESTRICT aux_out);
-// Exposed only for testing
-Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result);
-
} // namespace jxl
#endif // LIB_JXL_ENC_ICC_CODEC_H_
diff --git a/third_party/jpeg-xl/lib/jxl/enc_image_bundle.cc b/third_party/jpeg-xl/lib/jxl/enc_image_bundle.cc
index 1b41361320..044f763363 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_image_bundle.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_image_bundle.cc
@@ -8,13 +8,10 @@
#include <jxl/cms_interface.h>
#include <atomic>
-#include <limits>
#include <utility>
-#include "lib/jxl/alpha.h"
-#include "lib/jxl/base/byte_order.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
-#include "lib/jxl/fields.h"
#include "lib/jxl/image_bundle.h"
namespace jxl {
@@ -30,11 +27,11 @@ Status ApplyColorTransform(const ColorEncoding& c_current,
JXL_CHECK(c_current.IsGray() == c_desired.IsGray());
bool is_gray = c_current.IsGray();
if (out->xsize() < rect.xsize() || out->ysize() < rect.ysize()) {
- *out = Image3F(rect.xsize(), rect.ysize());
+ JXL_ASSIGN_OR_RETURN(*out, Image3F::Create(rect.xsize(), rect.ysize()));
} else {
out->ShrinkTo(rect.xsize(), rect.ysize());
}
- std::atomic<bool> ok{true};
+ std::atomic<bool> has_error{false};
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, rect.ysize(),
[&](const size_t num_threads) {
@@ -42,6 +39,7 @@ Status ApplyColorTransform(const ColorEncoding& c_current,
rect.xsize(), num_threads);
},
[&](const uint32_t y, const size_t thread) {
+ if (has_error) return;
float* mutable_src_buf = c_transform.BufSrc(thread);
const float* src_buf = mutable_src_buf;
// Interleave input.
@@ -49,7 +47,7 @@ Status ApplyColorTransform(const ColorEncoding& c_current,
src_buf = rect.ConstPlaneRow(color, 0, y);
} else if (c_current.IsCMYK()) {
if (!black) {
- ok.store(false);
+ has_error = true;
return;
}
const float* JXL_RESTRICT row_in0 = rect.ConstPlaneRow(color, 0, y);
@@ -74,8 +72,8 @@ Status ApplyColorTransform(const ColorEncoding& c_current,
}
}
float* JXL_RESTRICT dst_buf = c_transform.BufDst(thread);
- if (!c_transform.Run(thread, src_buf, dst_buf)) {
- ok.store(false);
+ if (!c_transform.Run(thread, src_buf, dst_buf, rect.xsize())) {
+ has_error = true;
return;
}
float* JXL_RESTRICT row_out0 = out->PlaneRow(0, y);
@@ -97,7 +95,8 @@ Status ApplyColorTransform(const ColorEncoding& c_current,
}
},
"Colorspace transform"));
- return ok.load();
+ if (has_error) return JXL_FAILURE("Colorspace transform failed");
+ return true;
}
namespace {
@@ -133,7 +132,8 @@ Status TransformIfNeeded(const ImageBundle& in, const ColorEncoding& c_desired,
}
// TODO(janwas): avoid copying via createExternal+copyBackToIO
// instead of copy+createExternal+copyBackToIO
- Image3F color(in.color().xsize(), in.color().ysize());
+ JXL_ASSIGN_OR_RETURN(Image3F color,
+ Image3F::Create(in.color().xsize(), in.color().ysize()));
CopyImageTo(in.color(), &color);
store->SetFromImage(std::move(color), in.c_current());
@@ -141,7 +141,8 @@ Status TransformIfNeeded(const ImageBundle& in, const ColorEncoding& c_desired,
if (in.HasExtraChannels()) {
std::vector<ImageF> extra_channels;
for (const ImageF& extra_channel : in.extra_channels()) {
- ImageF ec(extra_channel.xsize(), extra_channel.ysize());
+ JXL_ASSIGN_OR_RETURN(ImageF ec, ImageF::Create(extra_channel.xsize(),
+ extra_channel.ysize()));
CopyImageTo(extra_channel, &ec);
extra_channels.emplace_back(std::move(ec));
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_linalg.cc b/third_party/jpeg-xl/lib/jxl/enc_linalg.cc
index fe2090a909..452c17f4e8 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_linalg.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_linalg.cc
@@ -7,46 +7,43 @@
#include <cmath>
-#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/status.h"
namespace jxl {
-void ConvertToDiagonal(const ImageD& A, ImageD* const JXL_RESTRICT diag,
- ImageD* const JXL_RESTRICT U) {
+void ConvertToDiagonal(const Matrix2x2& A, Vector2& diag, Matrix2x2& U) {
#if JXL_ENABLE_ASSERT
- JXL_ASSERT(A.xsize() == 2);
- JXL_ASSERT(A.ysize() == 2);
- JXL_ASSERT(std::abs(A.Row(0)[1] - A.Row(1)[0]) < 1e-15);
+ // Check A is symmetric.
+ JXL_ASSERT(std::abs(A[0][1] - A[1][0]) < 1e-15);
#endif
- if (std::abs(A.ConstRow(0)[1]) < 1e-15) {
+ if (std::abs(A[0][1]) < 1e-15) {
// Already diagonal.
- diag->Row(0)[0] = A.ConstRow(0)[0];
- diag->Row(0)[1] = A.ConstRow(1)[1];
- U->Row(0)[0] = U->Row(1)[1] = 1.0;
- U->Row(0)[1] = U->Row(1)[0] = 0.0;
+ diag[0] = A[0][0];
+ diag[1] = A[1][1];
+ U[0][0] = U[1][1] = 1.0;
+ U[0][1] = U[1][0] = 0.0;
return;
}
- double b = -(A.Row(0)[0] + A.Row(1)[1]);
- double c = A.Row(0)[0] * A.Row(1)[1] - A.Row(0)[1] * A.Row(0)[1];
+ double b = -(A[0][0] + A[1][1]);
+ double c = A[0][0] * A[1][1] - A[0][1] * A[0][1];
double d = b * b - 4.0 * c;
double sqd = std::sqrt(d);
double l1 = (-b - sqd) * 0.5;
double l2 = (-b + sqd) * 0.5;
- double v1[2] = {A.Row(0)[0] - l1, A.Row(1)[0]};
+ Vector2 v1 = {A[0][0] - l1, A[1][0]};
double v1n = 1.0 / std::hypot(v1[0], v1[1]);
v1[0] = v1[0] * v1n;
v1[1] = v1[1] * v1n;
- diag->Row(0)[0] = l1;
- diag->Row(0)[1] = l2;
+ diag[0] = l1;
+ diag[1] = l2;
- U->Row(0)[0] = v1[1];
- U->Row(0)[1] = -v1[0];
- U->Row(1)[0] = v1[0];
- U->Row(1)[1] = v1[1];
+ U[0][0] = v1[1];
+ U[0][1] = -v1[0];
+ U[1][0] = v1[0];
+ U[1][1] = v1[1];
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_linalg.h b/third_party/jpeg-xl/lib/jxl/enc_linalg.h
index 791770d5d4..b9a36c7ca1 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_linalg.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_linalg.h
@@ -8,16 +8,16 @@
// Linear algebra.
-#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/image.h"
+#include <array>
namespace jxl {
-using ImageD = Plane<double>;
+typedef std::array<double, 2> Vector2;
+// NB: matrix2x2[row][column]
+typedef std::array<Vector2, 2> Matrix2x2;
// A is symmetric, U is orthogonal, and A = U * Diagonal(diag) * Transpose(U).
-void ConvertToDiagonal(const ImageD& A, ImageD* JXL_RESTRICT diag,
- ImageD* JXL_RESTRICT U);
+void ConvertToDiagonal(const Matrix2x2& A, Vector2& diag, Matrix2x2& U);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_linalg_test.cc b/third_party/jpeg-xl/lib/jxl/enc_linalg_test.cc
index 967b9a3afb..c02f009ca7 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_linalg_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_linalg_test.cc
@@ -5,110 +5,78 @@
#include "lib/jxl/enc_linalg.h"
-#include "lib/jxl/image_test_utils.h"
+#include "lib/jxl/base/random.h"
#include "lib/jxl/testing.h"
namespace jxl {
namespace {
-ImageD Identity(const size_t N) {
- ImageD out(N, N);
- for (size_t i = 0; i < N; ++i) {
- double* JXL_RESTRICT row = out.Row(i);
- std::fill(row, row + N, 0);
- row[i] = 1.0;
- }
- return out;
-}
+Matrix2x2 Diagonal(const Vector2& d) { return {{{d[0], 0.0}, {0.0, d[1]}}}; }
-ImageD Diagonal(const ImageD& d) {
- JXL_ASSERT(d.ysize() == 1);
- ImageD out(d.xsize(), d.xsize());
- const double* JXL_RESTRICT row_diag = d.Row(0);
- for (size_t k = 0; k < d.xsize(); ++k) {
- double* JXL_RESTRICT row_out = out.Row(k);
- std::fill(row_out, row_out + d.xsize(), 0.0);
- row_out[k] = row_diag[k];
- }
- return out;
-}
+Matrix2x2 Identity() { return Diagonal({1.0, 1.0}); }
-ImageD MatMul(const ImageD& A, const ImageD& B) {
- JXL_ASSERT(A.ysize() == B.xsize());
- ImageD out(A.xsize(), B.ysize());
- for (size_t y = 0; y < B.ysize(); ++y) {
- const double* const JXL_RESTRICT row_b = B.Row(y);
- double* const JXL_RESTRICT row_out = out.Row(y);
- for (size_t x = 0; x < A.xsize(); ++x) {
- row_out[x] = 0.0;
- for (size_t k = 0; k < B.xsize(); ++k) {
- row_out[x] += A.Row(k)[x] * row_b[k];
- }
+Matrix2x2 MatMul(const Matrix2x2& A, const Matrix2x2& B) {
+ Matrix2x2 out;
+ for (size_t y = 0; y < 2; ++y) {
+ for (size_t x = 0; x < 2; ++x) {
+ out[y][x] = A[0][x] * B[y][0] + A[1][x] * B[y][1];
}
}
return out;
}
-ImageD Transpose(const ImageD& A) {
- ImageD out(A.ysize(), A.xsize());
- for (size_t x = 0; x < A.xsize(); ++x) {
- double* const JXL_RESTRICT row_out = out.Row(x);
- for (size_t y = 0; y < A.ysize(); ++y) {
- row_out[y] = A.Row(y)[x];
- }
- }
- return out;
+Matrix2x2 Transpose(const Matrix2x2& A) {
+ return {{{A[0][0], A[1][0]}, {A[0][1], A[1][1]}}};
}
-ImageD RandomSymmetricMatrix(const size_t N, Rng& rng, const double vmin,
- const double vmax) {
- ImageD A(N, N);
- GenerateImage(rng, &A, vmin, vmax);
- for (size_t i = 0; i < N; ++i) {
- for (size_t j = 0; j < i; ++j) {
- A.Row(j)[i] = A.Row(i)[j];
- }
- }
+Matrix2x2 RandomSymmetricMatrix(Rng& rng, const double vmin,
+ const double vmax) {
+ Matrix2x2 A;
+ A[0][0] = rng.UniformF(vmin, vmax);
+ A[0][1] = A[1][0] = rng.UniformF(vmin, vmax);
+ A[1][1] = rng.UniformF(vmin, vmax);
return A;
}
-void VerifyMatrixEqual(const ImageD& A, const ImageD& B, const double eps) {
- ASSERT_EQ(A.xsize(), B.xsize());
- ASSERT_EQ(A.ysize(), B.ysize());
- for (size_t y = 0; y < A.ysize(); ++y) {
- for (size_t x = 0; x < A.xsize(); ++x) {
- ASSERT_NEAR(A.Row(y)[x], B.Row(y)[x], eps);
+void VerifyMatrixEqual(const Matrix2x2& A, const Matrix2x2& B,
+ const double eps) {
+ for (size_t y = 0; y < 2; ++y) {
+ for (size_t x = 0; x < 2; ++x) {
+ ASSERT_NEAR(A[y][x], B[y][x], eps);
}
}
}
-void VerifyOrthogonal(const ImageD& A, const double eps) {
- VerifyMatrixEqual(Identity(A.xsize()), MatMul(Transpose(A), A), eps);
+void VerifyOrthogonal(const Matrix2x2& A, const double eps) {
+ VerifyMatrixEqual(Identity(), MatMul(Transpose(A), A), eps);
}
TEST(LinAlgTest, ConvertToDiagonal) {
{
- ImageD I = Identity(2);
- ImageD U(2, 2), d(2, 1);
- ConvertToDiagonal(I, &d, &U);
+ Matrix2x2 I = Identity();
+ Matrix2x2 U;
+ Vector2 d;
+ ConvertToDiagonal(I, d, U);
VerifyMatrixEqual(I, U, 1e-15);
for (size_t k = 0; k < 2; ++k) {
- ASSERT_NEAR(d.Row(0)[k], 1.0, 1e-15);
+ ASSERT_NEAR(d[k], 1.0, 1e-15);
}
}
{
- ImageD A = Identity(2);
- A.Row(0)[1] = A.Row(1)[0] = 2.0;
- ImageD U(2, 2), d(2, 1);
- ConvertToDiagonal(A, &d, &U);
+ Matrix2x2 A = Identity();
+ A[0][1] = A[1][0] = 2.0;
+ Matrix2x2 U;
+ Vector2 d;
+ ConvertToDiagonal(A, d, U);
VerifyOrthogonal(U, 1e-12);
VerifyMatrixEqual(A, MatMul(U, MatMul(Diagonal(d), Transpose(U))), 1e-12);
}
Rng rng(0);
for (size_t i = 0; i < 100; ++i) {
- ImageD A = RandomSymmetricMatrix(2, rng, -1.0, 1.0);
- ImageD U(2, 2), d(2, 1);
- ConvertToDiagonal(A, &d, &U);
+ Matrix2x2 A = RandomSymmetricMatrix(rng, -1.0, 1.0);
+ Matrix2x2 U;
+ Vector2 d;
+ ConvertToDiagonal(A, d, U);
VerifyOrthogonal(U, 1e-12);
VerifyMatrixEqual(A, MatMul(U, MatMul(Diagonal(d), Transpose(U))), 1e-12);
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_modular.cc b/third_party/jpeg-xl/lib/jxl/enc_modular.cc
index b8366953b7..dbd62d4a01 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_modular.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_modular.cc
@@ -10,8 +10,8 @@
#include <array>
#include <atomic>
+#include <cstdint>
#include <limits>
-#include <queue>
#include <utility>
#include <vector>
@@ -28,9 +28,9 @@
#include "lib/jxl/enc_params.h"
#include "lib/jxl/enc_patch_dictionary.h"
#include "lib/jxl/enc_quant_weights.h"
+#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/frame_header.h"
#include "lib/jxl/modular/encoding/context_predict.h"
-#include "lib/jxl/modular/encoding/enc_debug_tree.h"
#include "lib/jxl/modular/encoding/enc_encoding.h"
#include "lib/jxl/modular/encoding/encoding.h"
#include "lib/jxl/modular/encoding/ma_common.h"
@@ -38,7 +38,7 @@
#include "lib/jxl/modular/options.h"
#include "lib/jxl/modular/transform/enc_transform.h"
#include "lib/jxl/pack_signed.h"
-#include "lib/jxl/toc.h"
+#include "modular/options.h"
namespace jxl {
@@ -48,15 +48,15 @@ namespace {
// Squeeze default quantization factors
// these quantization factors are for -Q 50 (other qualities simply scale the
// factors; things are rounded down and obviously cannot get below 1)
-static const float squeeze_quality_factor =
+const float squeeze_quality_factor =
0.35; // for easy tweaking of the quality range (decrease this number for
// higher quality)
-static const float squeeze_luma_factor =
+const float squeeze_luma_factor =
1.1; // for easy tweaking of the balance between luma (or anything
// non-chroma) and chroma (decrease this number for higher quality
// luma)
-static const float squeeze_quality_factor_xyb = 2.4f;
-static const float squeeze_xyb_qtable[3][16] = {
+const float squeeze_quality_factor_xyb = 2.4f;
+const float squeeze_xyb_qtable[3][16] = {
{163.84, 81.92, 40.96, 20.48, 10.24, 5.12, 2.56, 1.28, 0.64, 0.32, 0.16,
0.08, 0.04, 0.02, 0.01, 0.005}, // Y
{1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5, 0.5, 0.5, 0.5,
@@ -65,12 +65,12 @@ static const float squeeze_xyb_qtable[3][16] = {
0.5}, // B-Y
};
-static const float squeeze_luma_qtable[16] = {
- 163.84, 81.92, 40.96, 20.48, 10.24, 5.12, 2.56, 1.28,
- 0.64, 0.32, 0.16, 0.08, 0.04, 0.02, 0.01, 0.005};
+const float squeeze_luma_qtable[16] = {163.84, 81.92, 40.96, 20.48, 10.24, 5.12,
+ 2.56, 1.28, 0.64, 0.32, 0.16, 0.08,
+ 0.04, 0.02, 0.01, 0.005};
// for 8-bit input, the range of YCoCg chroma is -255..255 so basically this
// does 4:2:0 subsampling (two most fine grained layers get quantized away)
-static const float squeeze_chroma_qtable[16] = {
+const float squeeze_chroma_qtable[16] = {
1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5, 0.5, 0.5, 0.5, 0.5};
// Merges the trees in `trees` using nodes that decide on stream_id, as defined
@@ -139,10 +139,12 @@ Status float_to_int(const float* const row_in, pixel_type* const row_out,
}
if (bits == 32 && fp) {
JXL_ASSERT(exp_bits == 8);
- memcpy((void*)row_out, (const void*)row_in, 4 * xsize);
+ memcpy(static_cast<void*>(row_out), static_cast<const void*>(row_in),
+ 4 * xsize);
return true;
}
+ JXL_ASSERT(bits > 0);
int exp_bias = (1 << (exp_bits - 1)) - 1;
int max_exp = (1 << exp_bits) - 1;
uint32_t sign = (1u << (bits - 1));
@@ -186,14 +188,144 @@ Status float_to_int(const float* const row_in, pixel_type* const row_out,
f = (signbit ? sign : 0);
f |= (exp << mant_bits);
f |= mantissa;
- row_out[x] = (pixel_type)f;
+ row_out[x] = static_cast<pixel_type>(f);
}
return true;
}
+
+float EstimateWPCost(const Image& img, size_t i) {
+ size_t extra_bits = 0;
+ float histo_cost = 0;
+ HybridUintConfig config;
+ int32_t cutoffs[] = {-500, -392, -255, -191, -127, -95, -63, -47, -31,
+ -23, -15, -11, -7, -4, -3, -1, 0, 1,
+ 3, 5, 7, 11, 15, 23, 31, 47, 63,
+ 95, 127, 191, 255, 392, 500};
+ constexpr size_t nc = sizeof(cutoffs) / sizeof(*cutoffs) + 1;
+ Histogram histo[nc] = {};
+ weighted::Header wp_header;
+ PredictorMode(i, &wp_header);
+ for (const Channel& ch : img.channel) {
+ const intptr_t onerow = ch.plane.PixelsPerRow();
+ weighted::State wp_state(wp_header, ch.w, ch.h);
+ Properties properties(1);
+ for (size_t y = 0; y < ch.h; y++) {
+ const pixel_type* JXL_RESTRICT r = ch.Row(y);
+ for (size_t x = 0; x < ch.w; x++) {
+ size_t offset = 0;
+ pixel_type_w left = (x ? r[x - 1] : y ? *(r + x - onerow) : 0);
+ pixel_type_w top = (y ? *(r + x - onerow) : left);
+ pixel_type_w topleft = (x && y ? *(r + x - 1 - onerow) : left);
+ pixel_type_w topright =
+ (x + 1 < ch.w && y ? *(r + x + 1 - onerow) : top);
+ pixel_type_w toptop = (y > 1 ? *(r + x - onerow - onerow) : top);
+ pixel_type guess = wp_state.Predict</*compute_properties=*/true>(
+ x, y, ch.w, top, left, topright, topleft, toptop, &properties,
+ offset);
+ size_t ctx = 0;
+ for (int c : cutoffs) {
+ ctx += (c >= properties[0]) ? 1 : 0;
+ }
+ pixel_type res = r[x] - guess;
+ uint32_t token;
+ uint32_t nbits;
+ uint32_t bits;
+ config.Encode(PackSigned(res), &token, &nbits, &bits);
+ histo[ctx].Add(token);
+ extra_bits += nbits;
+ wp_state.UpdateErrors(r[x], x, y, ch.w);
+ }
+ }
+ for (auto& h : histo) {
+ histo_cost += h.ShannonEntropy();
+ h.Clear();
+ }
+ }
+ return histo_cost + extra_bits;
+}
+
+float EstimateCost(const Image& img) {
+ // TODO(veluca): consider SIMDfication of this code.
+ size_t extra_bits = 0;
+ float histo_cost = 0;
+ HybridUintConfig config;
+ uint32_t cutoffs[] = {0, 1, 3, 5, 7, 11, 15, 23, 31,
+ 47, 63, 95, 127, 191, 255, 392, 500};
+ constexpr size_t nc = sizeof(cutoffs) / sizeof(*cutoffs) + 1;
+ Histogram histo[nc] = {};
+ for (const Channel& ch : img.channel) {
+ const intptr_t onerow = ch.plane.PixelsPerRow();
+ for (size_t y = 0; y < ch.h; y++) {
+ const pixel_type* JXL_RESTRICT r = ch.Row(y);
+ for (size_t x = 0; x < ch.w; x++) {
+ pixel_type_w left = (x ? r[x - 1] : y ? *(r + x - onerow) : 0);
+ pixel_type_w top = (y ? *(r + x - onerow) : left);
+ pixel_type_w topleft = (x && y ? *(r + x - 1 - onerow) : left);
+ size_t maxdiff = std::max(std::max(left, top), topleft) -
+ std::min(std::min(left, top), topleft);
+ size_t ctx = 0;
+ for (uint32_t c : cutoffs) {
+ ctx += (c > maxdiff) ? 1 : 0;
+ }
+ pixel_type res = r[x] - ClampedGradient(top, left, topleft);
+ uint32_t token;
+ uint32_t nbits;
+ uint32_t bits;
+ config.Encode(PackSigned(res), &token, &nbits, &bits);
+ histo[ctx].Add(token);
+ extra_bits += nbits;
+ }
+ }
+ for (auto& h : histo) {
+ histo_cost += h.ShannonEntropy();
+ h.Clear();
+ }
+ }
+ return histo_cost + extra_bits;
+}
+
+bool do_transform(Image& image, const Transform& tr,
+ const weighted::Header& wp_header,
+ jxl::ThreadPool* pool = nullptr, bool force_jxlart = false) {
+ Transform t = tr;
+ bool did_it = true;
+ if (force_jxlart) {
+ if (!t.MetaApply(image)) return false;
+ } else {
+ did_it = TransformForward(t, image, wp_header, pool);
+ }
+ if (did_it) image.transform.push_back(t);
+ return did_it;
+}
+
+bool maybe_do_transform(Image& image, const Transform& tr,
+ const CompressParams& cparams,
+ const weighted::Header& wp_header,
+ jxl::ThreadPool* pool = nullptr,
+ bool force_jxlart = false) {
+ if (force_jxlart || cparams.speed_tier >= SpeedTier::kSquirrel) {
+ return do_transform(image, tr, wp_header, pool, force_jxlart);
+ }
+ float cost_before = EstimateCost(image);
+ bool did_it = do_transform(image, tr, wp_header, pool);
+ if (did_it) {
+ float cost_after = EstimateCost(image);
+ JXL_DEBUG_V(7, "Cost before: %f cost after: %f", cost_before, cost_after);
+ if (cost_after > cost_before) {
+ Transform t = image.transform.back();
+ JXL_RETURN_IF_ERROR(t.Inverse(image, wp_header, pool));
+ image.transform.pop_back();
+ did_it = false;
+ }
+ }
+ return did_it;
+}
+
} // namespace
ModularFrameEncoder::ModularFrameEncoder(const FrameHeader& frame_header,
- const CompressParams& cparams_orig)
+ const CompressParams& cparams_orig,
+ bool streaming_mode)
: frame_dim_(frame_header.ToFrameDimensions()), cparams_(cparams_orig) {
size_t num_streams =
ModularStreamId::Num(frame_dim_, frame_header.passes.num_passes);
@@ -253,10 +385,16 @@ ModularFrameEncoder::ModularFrameEncoder(const FrameHeader& frame_header,
// Same, but for the non-Squeeze case.
prop_order = {0, 1, 15, 9, 10, 11, 12, 13, 14, 2, 3, 4, 5, 6, 7, 8};
// if few groups, don't use group as a property
- if (num_streams < 30 && cparams_.speed_tier > SpeedTier::kTortoise) {
+ if (num_streams < 30 && cparams_.speed_tier > SpeedTier::kTortoise &&
+ cparams_orig.ModularPartIsLossless()) {
prop_order.erase(prop_order.begin() + 1);
}
}
+ int max_properties = std::min<int>(
+ cparams_.options.max_properties,
+ static_cast<int>(
+ frame_header.nonserialized_metadata->m.num_extra_channels) +
+ (frame_header.encoding == FrameEncoding::kModular ? 2 : -1));
switch (cparams_.speed_tier) {
case SpeedTier::kHare:
cparams_.options.splitting_heuristics_properties.assign(
@@ -278,6 +416,7 @@ ModularFrameEncoder::ModularFrameEncoder(const FrameHeader& frame_header,
prop_order.begin(), prop_order.begin() + 10);
cparams_.options.max_property_values = 96;
break;
+ case SpeedTier::kGlacier:
case SpeedTier::kTortoise:
cparams_.options.splitting_heuristics_properties = prop_order;
cparams_.options.max_property_values = 256;
@@ -290,24 +429,36 @@ ModularFrameEncoder::ModularFrameEncoder(const FrameHeader& frame_header,
}
if (cparams_.speed_tier > SpeedTier::kTortoise) {
// Gradient in previous channels.
- for (int i = 0; i < cparams_.options.max_properties; i++) {
+ for (int i = 0; i < max_properties; i++) {
cparams_.options.splitting_heuristics_properties.push_back(
kNumNonrefProperties + i * 4 + 3);
}
} else {
// All the extra properties in Tortoise mode.
- for (int i = 0; i < cparams_.options.max_properties * 4; i++) {
+ for (int i = 0; i < max_properties * 4; i++) {
cparams_.options.splitting_heuristics_properties.push_back(
kNumNonrefProperties + i);
}
}
}
- if (cparams_.options.predictor == static_cast<Predictor>(-1)) {
+ if ((cparams_.options.predictor == Predictor::Average0 ||
+ cparams_.options.predictor == Predictor::Average1 ||
+ cparams_.options.predictor == Predictor::Average2 ||
+ cparams_.options.predictor == Predictor::Average3 ||
+ cparams_.options.predictor == Predictor::Average4 ||
+ cparams_.options.predictor == Predictor::Weighted) &&
+ !cparams_.ModularPartIsLossless()) {
+ // Lossy + Average/Weighted predictors does not work, so switch to default
+ // predictors.
+ cparams_.options.predictor = kUndefinedPredictor;
+ }
+
+ if (cparams_.options.predictor == kUndefinedPredictor) {
// no explicit predictor(s) given, set a good default
- if ((cparams_.speed_tier <= SpeedTier::kTortoise ||
+ if ((cparams_.speed_tier <= SpeedTier::kGlacier ||
cparams_.modular_mode == false) &&
- cparams_.IsLossless() && cparams_.responsive == false) {
+ cparams_.IsLossless() && cparams_.responsive == JXL_FALSE) {
// TODO(veluca): allow all predictors that don't break residual
// multipliers in lossy mode.
cparams_.options.predictor = Predictor::Variable;
@@ -354,48 +505,54 @@ ModularFrameEncoder::ModularFrameEncoder(const FrameHeader& frame_header,
// TODO(veluca): figure out how to use different predictor sets per channel.
stream_options_.resize(num_streams, cparams_.options);
-}
-bool do_transform(Image& image, const Transform& tr,
- const weighted::Header& wp_header,
- jxl::ThreadPool* pool = nullptr, bool force_jxlart = false) {
- Transform t = tr;
- bool did_it = true;
- if (force_jxlart) {
- if (!t.MetaApply(image)) return false;
- } else {
- did_it = TransformForward(t, image, wp_header, pool);
+ stream_options_[0] = cparams_.options;
+ if (cparams_.speed_tier == SpeedTier::kFalcon) {
+ stream_options_[0].tree_kind = ModularOptions::TreeKind::kWPFixedDC;
+ } else if (cparams_.speed_tier == SpeedTier::kThunder) {
+ stream_options_[0].tree_kind = ModularOptions::TreeKind::kGradientFixedDC;
}
- if (did_it) image.transform.push_back(t);
- return did_it;
+ stream_options_[0].histogram_params =
+ HistogramParams::ForModular(cparams_, {}, streaming_mode);
}
Status ModularFrameEncoder::ComputeEncodingData(
const FrameHeader& frame_header, const ImageMetadata& metadata,
Image3F* JXL_RESTRICT color, const std::vector<ImageF>& extra_channels,
- PassesEncoderState* JXL_RESTRICT enc_state, const JxlCmsInterface& cms,
- ThreadPool* pool, AuxOut* aux_out, bool do_color) {
+ const Rect& group_rect, const FrameDimensions& patch_dim,
+ const Rect& frame_area_rect, PassesEncoderState* JXL_RESTRICT enc_state,
+ const JxlCmsInterface& cms, ThreadPool* pool, AuxOut* aux_out,
+ bool do_color) {
JXL_DEBUG_V(6, "Computing modular encoding data for frame %s",
frame_header.DebugString().c_str());
- if (do_color && frame_header.loop_filter.gab) {
+ bool groupwise = enc_state->streaming_mode;
+
+ if (do_color && frame_header.loop_filter.gab && !groupwise) {
float w = 0.9908511000000001f;
float weights[3] = {w, w, w};
- GaborishInverse(color, Rect(*color), weights, pool);
+ JXL_RETURN_IF_ERROR(GaborishInverse(color, Rect(*color), weights, pool));
}
if (do_color && metadata.bit_depth.bits_per_sample <= 16 &&
cparams_.speed_tier < SpeedTier::kCheetah &&
- cparams_.decoding_speed_tier < 2) {
- FindBestPatchDictionary(*color, enc_state, cms, nullptr, aux_out,
- cparams_.color_transform == ColorTransform::kXYB);
+ cparams_.decoding_speed_tier < 2 && !groupwise) {
+ JXL_RETURN_IF_ERROR(FindBestPatchDictionary(
+ *color, enc_state, cms, nullptr, aux_out,
+ cparams_.color_transform == ColorTransform::kXYB));
PatchDictionaryEncoder::SubtractFrom(
enc_state->shared.image_features.patches, color);
}
+ if (cparams_.custom_splines.HasAny()) {
+ PassesSharedState& shared = enc_state->shared;
+ ImageFeatures& image_features = shared.image_features;
+ image_features.splines = cparams_.custom_splines;
+ }
+
// Convert ImageBundle to modular Image object
- const size_t xsize = frame_dim_.xsize;
- const size_t ysize = frame_dim_.ysize;
+ const size_t xsize = patch_dim.xsize;
+ const size_t ysize = patch_dim.ysize;
int nb_chans = 3;
if (metadata.color_encoding.IsGray() &&
@@ -423,7 +580,9 @@ Status ModularFrameEncoder::ComputeEncodingData(
int max_bitdepth =
do_color ? metadata.bit_depth.bits_per_sample + (fp ? 0 : 1) : 0;
Image& gi = stream_images_[0];
- gi = Image(xsize, ysize, metadata.bit_depth.bits_per_sample, nb_chans);
+ JXL_ASSIGN_OR_RETURN(
+ gi, Image::Create(xsize, ysize, metadata.bit_depth.bits_per_sample,
+ nb_chans));
int c = 0;
if (cparams_.color_transform == ColorTransform::kXYB &&
cparams_.modular_mode == true) {
@@ -478,17 +637,21 @@ Status ModularFrameEncoder::ComputeEncodingData(
gi.channel[c_out].vshift = frame_header.chroma_subsampling.VShift(c);
size_t xsize_shifted = DivCeil(xsize, 1 << gi.channel[c_out].hshift);
size_t ysize_shifted = DivCeil(ysize, 1 << gi.channel[c_out].vshift);
- gi.channel[c_out].shrink(xsize_shifted, ysize_shifted);
+ JXL_RETURN_IF_ERROR(
+ gi.channel[c_out].shrink(xsize_shifted, ysize_shifted));
std::atomic<bool> has_error{false};
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, ysize_shifted, ThreadPool::NoInit,
[&](const int task, const int thread) {
+ if (has_error) return;
const size_t y = task;
- const float* const JXL_RESTRICT row_in = color->PlaneRow(c, y);
+ const float* const JXL_RESTRICT row_in =
+ color->PlaneRow(c, y + group_rect.y0()) + group_rect.x0();
pixel_type* const JXL_RESTRICT row_out = gi.channel[c_out].Row(y);
if (!float_to_int(row_in, row_out, xsize_shifted, bits, exp_bits,
fp, factor)) {
has_error = true;
+ return;
};
},
"float2int"));
@@ -505,8 +668,9 @@ Status ModularFrameEncoder::ComputeEncodingData(
for (size_t ec = 0; ec < extra_channels.size(); ec++, c++) {
const ExtraChannelInfo& eci = metadata.extra_channel_info[ec];
size_t ecups = frame_header.extra_channel_upsampling[ec];
- gi.channel[c].shrink(DivCeil(frame_dim_.xsize_upsampled, ecups),
- DivCeil(frame_dim_.ysize_upsampled, ecups));
+ JXL_RETURN_IF_ERROR(
+ gi.channel[c].shrink(DivCeil(patch_dim.xsize_upsampled, ecups),
+ DivCeil(patch_dim.ysize_upsampled, ecups)));
gi.channel[c].hshift = gi.channel[c].vshift =
CeilLog2Nonzero(ecups) - CeilLog2Nonzero(frame_header.upsampling);
@@ -519,12 +683,15 @@ Status ModularFrameEncoder::ComputeEncodingData(
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, gi.channel[c].plane.ysize(), ThreadPool::NoInit,
[&](const int task, const int thread) {
+ if (has_error) return;
const size_t y = task;
- const float* const JXL_RESTRICT row_in = extra_channels[ec].Row(y);
+ const float* const JXL_RESTRICT row_in =
+ extra_channels[ec].Row(y + group_rect.y0()) + group_rect.x0();
pixel_type* const JXL_RESTRICT row_out = gi.channel[c].Row(y);
if (!float_to_int(row_in, row_out, gi.channel[c].plane.xsize(), bits,
exp_bits, fp, factor)) {
has_error = true;
+ return;
};
},
"float2int"));
@@ -533,11 +700,12 @@ Status ModularFrameEncoder::ComputeEncodingData(
JXL_ASSERT(c == nb_chans);
int level_max_bitdepth = (cparams_.level == 5 ? 16 : 32);
- if (max_bitdepth > level_max_bitdepth)
+ if (max_bitdepth > level_max_bitdepth) {
return JXL_FAILURE(
"Bitdepth too high for level %i (need %i bits, have only %i in this "
"level)",
cparams_.level, max_bitdepth, level_max_bitdepth);
+ }
// Set options and apply transformations
if (!cparams_.ModularPartIsLossless()) {
@@ -553,14 +721,14 @@ Status ModularFrameEncoder::ComputeEncodingData(
}
// Global palette
- if (cparams_.palette_colors != 0 || cparams_.lossy_palette) {
+ if ((cparams_.palette_colors != 0 || cparams_.lossy_palette) && !groupwise) {
// all-channel palette (e.g. RGBA)
if (gi.channel.size() - gi.nb_meta_channels > 1) {
Transform maybe_palette(TransformId::kPalette);
maybe_palette.begin_c = gi.nb_meta_channels;
maybe_palette.num_c = gi.channel.size() - gi.nb_meta_channels;
- maybe_palette.nb_colors =
- std::min((int)(xsize * ysize / 2), std::abs(cparams_.palette_colors));
+ maybe_palette.nb_colors = std::min(static_cast<int>(xsize * ysize / 2),
+ std::abs(cparams_.palette_colors));
maybe_palette.ordered_palette = cparams_.palette_colors >= 0;
maybe_palette.lossy_palette =
(cparams_.lossy_palette && maybe_palette.num_c == 3);
@@ -569,8 +737,8 @@ Status ModularFrameEncoder::ComputeEncodingData(
}
// TODO(veluca): use a custom weighted header if using the weighted
// predictor.
- do_transform(gi, maybe_palette, weighted::Header(), pool,
- cparams_.options.zero_tokens);
+ maybe_do_transform(gi, maybe_palette, cparams_, weighted::Header(), pool,
+ cparams_.options.zero_tokens);
}
// all-minus-one-channel palette (RGB with separate alpha, or CMY with
// separate K)
@@ -578,20 +746,20 @@ Status ModularFrameEncoder::ComputeEncodingData(
Transform maybe_palette_3(TransformId::kPalette);
maybe_palette_3.begin_c = gi.nb_meta_channels;
maybe_palette_3.num_c = gi.channel.size() - gi.nb_meta_channels - 1;
- maybe_palette_3.nb_colors =
- std::min((int)(xsize * ysize / 3), std::abs(cparams_.palette_colors));
+ maybe_palette_3.nb_colors = std::min(static_cast<int>(xsize * ysize / 3),
+ std::abs(cparams_.palette_colors));
maybe_palette_3.ordered_palette = cparams_.palette_colors >= 0;
maybe_palette_3.lossy_palette = cparams_.lossy_palette;
if (maybe_palette_3.lossy_palette) {
maybe_palette_3.predictor = delta_pred_;
}
- do_transform(gi, maybe_palette_3, weighted::Header(), pool,
- cparams_.options.zero_tokens);
+ maybe_do_transform(gi, maybe_palette_3, cparams_, weighted::Header(),
+ pool, cparams_.options.zero_tokens);
}
}
// Global channel palette
- if (cparams_.channel_colors_pre_transform_percent > 0 &&
+ if (!groupwise && cparams_.channel_colors_pre_transform_percent > 0 &&
!cparams_.lossy_palette &&
(cparams_.speed_tier <= SpeedTier::kThunder ||
(do_color && metadata.bit_depth.bits_per_sample > 8))) {
@@ -600,9 +768,10 @@ Status ModularFrameEncoder::ComputeEncodingData(
int orig_bitdepth = max_bitdepth;
max_bitdepth = 0;
for (size_t i = 0; i < nb_channels; i++) {
- int32_t min, max;
+ int32_t min;
+ int32_t max;
compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max);
- int64_t colors = (int64_t)max - min + 1;
+ int64_t colors = static_cast<int64_t>(max) - min + 1;
JXL_DEBUG_V(10, "Channel %" PRIuS ": range=%i..%i", i, min, max);
Transform maybe_palette_1(TransformId::kPalette);
maybe_palette_1.begin_c = i + gi.nb_meta_channels;
@@ -612,9 +781,11 @@ Status ModularFrameEncoder::ComputeEncodingData(
// (but only if the channel palette is less than 6% the size of the
// image itself)
maybe_palette_1.nb_colors = std::min(
- (int)(xsize * ysize / 16),
- (int)(cparams_.channel_colors_pre_transform_percent / 100. * colors));
- if (do_transform(gi, maybe_palette_1, weighted::Header(), pool)) {
+ static_cast<int>(xsize * ysize / 16),
+ static_cast<int>(cparams_.channel_colors_pre_transform_percent /
+ 100. * colors));
+ if (maybe_do_transform(gi, maybe_palette_1, cparams_, weighted::Header(),
+ pool)) {
// effective bit depth is lower, adjust quantization accordingly
compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max);
if (max < maxval) maxval = max;
@@ -646,8 +817,28 @@ Status ModularFrameEncoder::ComputeEncodingData(
}
}
+ if (cparams_.move_to_front_from_channel > 0) {
+ for (size_t tgt = 0;
+ tgt + cparams_.move_to_front_from_channel < gi.channel.size(); tgt++) {
+ size_t pos = cparams_.move_to_front_from_channel;
+ while (pos > 0) {
+ Transform move(TransformId::kRCT);
+ if (pos == 1) {
+ move.begin_c = tgt;
+ move.rct_type = 28; // RGB -> GRB
+ pos -= 1;
+ } else {
+ move.begin_c = tgt + pos - 2;
+ move.rct_type = 14; // RGB -> BRG
+ pos -= 2;
+ }
+ do_transform(gi, move, weighted::Header(), pool);
+ }
+ }
+ }
+
// don't do squeeze if we don't have some spare bits
- if (cparams_.responsive && !gi.channel.empty() &&
+ if (!groupwise && cparams_.responsive && !gi.channel.empty() &&
max_bitdepth + 2 < level_max_bitdepth) {
Transform t(TransformId::kSqueeze);
do_transform(gi, t, weighted::Header(), pool);
@@ -674,8 +865,8 @@ Status ModularFrameEncoder::ComputeEncodingData(
bitdepth_correction = maxval / 255.f;
}
std::vector<float> quantizers;
- float dist = cparams_.butteraugli_distance;
for (size_t i = 0; i < 3; i++) {
+ float dist = cparams_.butteraugli_distance;
quantizers.push_back(quantizer * dist * bitdepth_correction);
}
for (size_t i = 0; i < extra_channels.size(); i++) {
@@ -683,6 +874,7 @@ Status ModularFrameEncoder::ComputeEncodingData(
metadata.extra_channel_info[i].bit_depth.bits_per_sample;
pixel_type ec_maxval = ec_bitdepth < 32 ? (1u << ec_bitdepth) - 1 : 0;
bitdepth_correction = ec_maxval / 255.f;
+ float dist = 0;
if (i < cparams_.ec_distance.size()) dist = cparams_.ec_distance[i];
if (dist < 0) dist = cparams_.butteraugli_distance;
quantizers.push_back(quantizer * dist * bitdepth_correction);
@@ -722,57 +914,57 @@ Status ModularFrameEncoder::ComputeEncodingData(
}
// Fill other groups.
- struct GroupParams {
- Rect rect;
- int minShift;
- int maxShift;
- ModularStreamId id;
- };
- std::vector<GroupParams> stream_params;
-
- stream_options_[0] = cparams_.options;
-
// DC
- for (size_t group_id = 0; group_id < frame_dim_.num_dc_groups; group_id++) {
- const size_t gx = group_id % frame_dim_.xsize_dc_groups;
- const size_t gy = group_id / frame_dim_.xsize_dc_groups;
- const Rect rect(gx * frame_dim_.dc_group_dim, gy * frame_dim_.dc_group_dim,
- frame_dim_.dc_group_dim, frame_dim_.dc_group_dim);
+ for (size_t group_id = 0; group_id < patch_dim.num_dc_groups; group_id++) {
+ const size_t rgx = group_id % patch_dim.xsize_dc_groups;
+ const size_t rgy = group_id / patch_dim.xsize_dc_groups;
+ const Rect rect(rgx * patch_dim.dc_group_dim, rgy * patch_dim.dc_group_dim,
+ patch_dim.dc_group_dim, patch_dim.dc_group_dim);
+ size_t gx = rgx + frame_area_rect.x0() / 2048;
+ size_t gy = rgy + frame_area_rect.y0() / 2048;
+ size_t real_group_id = gy * frame_dim_.xsize_dc_groups + gx;
// minShift==3 because (frame_dim.dc_group_dim >> 3) == frame_dim.group_dim
// maxShift==1000 is infinity
- stream_params.push_back(
- GroupParams{rect, 3, 1000, ModularStreamId::ModularDC(group_id)});
+ stream_params_.push_back(
+ GroupParams{rect, 3, 1000, ModularStreamId::ModularDC(real_group_id)});
}
// AC global -> nothing.
// AC
- for (size_t group_id = 0; group_id < frame_dim_.num_groups; group_id++) {
- const size_t gx = group_id % frame_dim_.xsize_groups;
- const size_t gy = group_id / frame_dim_.xsize_groups;
- const Rect mrect(gx * frame_dim_.group_dim, gy * frame_dim_.group_dim,
- frame_dim_.group_dim, frame_dim_.group_dim);
+ for (size_t group_id = 0; group_id < patch_dim.num_groups; group_id++) {
+ const size_t rgx = group_id % patch_dim.xsize_groups;
+ const size_t rgy = group_id / patch_dim.xsize_groups;
+ const Rect mrect(rgx * patch_dim.group_dim, rgy * patch_dim.group_dim,
+ patch_dim.group_dim, patch_dim.group_dim);
+ size_t gx = rgx + frame_area_rect.x0() / (frame_dim_.group_dim);
+ size_t gy = rgy + frame_area_rect.y0() / (frame_dim_.group_dim);
+ size_t real_group_id = gy * frame_dim_.xsize_groups + gx;
for (size_t i = 0; i < enc_state->progressive_splitter.GetNumPasses();
i++) {
- int maxShift, minShift;
+ int maxShift;
+ int minShift;
frame_header.passes.GetDownsamplingBracket(i, minShift, maxShift);
- stream_params.push_back(GroupParams{
- mrect, minShift, maxShift, ModularStreamId::ModularAC(group_id, i)});
+ stream_params_.push_back(
+ GroupParams{mrect, minShift, maxShift,
+ ModularStreamId::ModularAC(real_group_id, i)});
}
}
// if there's only one group, everything ends up in GlobalModular
// in that case, also try RCTs/WP params for the one group
- if (stream_params.size() == 2) {
- stream_params.push_back(GroupParams{Rect(0, 0, xsize, ysize), 0, 1000,
- ModularStreamId::Global()});
+ if (stream_params_.size() == 2) {
+ stream_params_.push_back(GroupParams{Rect(0, 0, xsize, ysize), 0, 1000,
+ ModularStreamId::Global()});
}
gi_channel_.resize(stream_images_.size());
JXL_RETURN_IF_ERROR(RunOnPool(
- pool, 0, stream_params.size(), ThreadPool::NoInit,
+ pool, 0, stream_params_.size(), ThreadPool::NoInit,
[&](const uint32_t i, size_t /* thread */) {
- stream_options_[stream_params[i].id.ID(frame_dim_)] = cparams_.options;
+ size_t stream = stream_params_[i].id.ID(frame_dim_);
+ stream_options_[stream] = stream_options_[0];
JXL_CHECK(PrepareStreamParams(
- stream_params[i].rect, cparams_, stream_params[i].minShift,
- stream_params[i].maxShift, stream_params[i].id, do_color));
+ stream_params_[i].rect, cparams_, stream_params_[i].minShift,
+ stream_params_[i].maxShift, stream_params_[i].id, do_color,
+ groupwise));
},
"ChooseParams"));
{
@@ -821,7 +1013,7 @@ Status ModularFrameEncoder::ComputeTree(ThreadPool* pool) {
StaticPropRange range;
range[0] = {{i, i + 1}};
range[1] = {{stream_id, stream_id + 1}};
- multiplier_info.push_back({range, (uint32_t)q});
+ multiplier_info.push_back({range, static_cast<uint32_t>(q)});
} else {
// Previous channel in the same group had the same quantization
// factor. Don't provide two different ranges, as that creates
@@ -922,11 +1114,10 @@ Status ModularFrameEncoder::ComputeTree(ThreadPool* pool) {
StaticPropRange range;
range[0] = {{0, max_c}};
range[1] = {{start, stop}};
- auto local_multiplier_info = multiplier_info;
tree_samples.PreQuantizeProperties(
- range, local_multiplier_info, group_pixel_count,
- channel_pixel_count, pixel_samples, diff_samples,
+ range, multiplier_info, group_pixel_count, channel_pixel_count,
+ pixel_samples, diff_samples,
stream_options_[start].max_property_values);
for (size_t i = start; i < stop; i++) {
JXL_CHECK(ModularGenericCompress(
@@ -937,7 +1128,7 @@ Status ModularFrameEncoder::ComputeTree(ThreadPool* pool) {
// TODO(veluca): parallelize more.
trees[chunk] =
LearnTree(std::move(tree_samples), total_pixels,
- stream_options_[start], local_multiplier_info, range);
+ stream_options_[start], multiplier_info, range);
},
"LearnTrees"));
if (invalid_force_wp.test_and_set(std::memory_order_acq_rel)) {
@@ -966,7 +1157,7 @@ Status ModularFrameEncoder::ComputeTree(ThreadPool* pool) {
tree_tokens_.resize(1);
tree_tokens_[0].clear();
Tree decoded_tree;
- TokenizeTree(tree_, &tree_tokens_[0], &decoded_tree);
+ TokenizeTree(tree_, tree_tokens_.data(), &decoded_tree);
JXL_ASSERT(tree_.size() == decoded_tree.size());
tree_ = std::move(decoded_tree);
@@ -1019,46 +1210,8 @@ Status ModularFrameEncoder::EncodeGlobalInfo(bool streaming_mode,
allotment.ReclaimAndCharge(writer, kLayerModularTree, aux_out);
// Write tree
- HistogramParams params;
- if (cparams_.speed_tier > SpeedTier::kKitten) {
- params.clustering = HistogramParams::ClusteringType::kFast;
- params.ans_histogram_strategy =
- cparams_.speed_tier > SpeedTier::kThunder
- ? HistogramParams::ANSHistogramStrategy::kFast
- : HistogramParams::ANSHistogramStrategy::kApproximate;
- params.lz77_method =
- cparams_.decoding_speed_tier >= 3 && cparams_.modular_mode
- ? (cparams_.speed_tier >= SpeedTier::kFalcon
- ? HistogramParams::LZ77Method::kRLE
- : HistogramParams::LZ77Method::kLZ77)
- : HistogramParams::LZ77Method::kNone;
- // Near-lossless DC, as well as modular mode, require choosing hybrid uint
- // more carefully.
- if ((!extra_dc_precision.empty() && extra_dc_precision[0] != 0) ||
- (cparams_.modular_mode && cparams_.speed_tier < SpeedTier::kCheetah)) {
- params.uint_method = HistogramParams::HybridUintMethod::kFast;
- } else {
- params.uint_method = HistogramParams::HybridUintMethod::kNone;
- }
- } else if (cparams_.speed_tier <= SpeedTier::kTortoise) {
- params.lz77_method = HistogramParams::LZ77Method::kOptimal;
- } else {
- params.lz77_method = HistogramParams::LZ77Method::kLZ77;
- }
- if (cparams_.decoding_speed_tier >= 1) {
- params.max_histograms = 12;
- }
- if (cparams_.decoding_speed_tier >= 1 && cparams_.responsive) {
- params.lz77_method = cparams_.speed_tier >= SpeedTier::kCheetah
- ? HistogramParams::LZ77Method::kRLE
- : cparams_.speed_tier >= SpeedTier::kKitten
- ? HistogramParams::LZ77Method::kLZ77
- : HistogramParams::LZ77Method::kOptimal;
- }
- if (cparams_.decoding_speed_tier >= 2 && cparams_.responsive) {
- params.uint_method = HistogramParams::HybridUintMethod::k000;
- params.force_huffman = true;
- }
+ HistogramParams params =
+ HistogramParams::ForModular(cparams_, extra_dc_precision, streaming_mode);
{
EntropyEncodingData tree_code;
std::vector<uint8_t> tree_context_map;
@@ -1082,6 +1235,7 @@ Status ModularFrameEncoder::EncodeStream(BitWriter* writer, AuxOut* aux_out,
const ModularStreamId& stream) {
size_t stream_id = stream.ID(frame_dim_);
if (stream_images_[stream_id].channel.empty()) {
+ JXL_DEBUG_V(10, "Modular stream %" PRIuS " is empty.", stream_id);
return true; // Image with no channels, header never gets decoded.
}
if (tokens_.empty()) {
@@ -1103,113 +1257,44 @@ void ModularFrameEncoder::ClearStreamData(const ModularStreamId& stream) {
std::swap(stream_images_[stream_id], empty_image);
}
-namespace {
-float EstimateWPCost(const Image& img, size_t i) {
- size_t extra_bits = 0;
- float histo_cost = 0;
- HybridUintConfig config;
- int32_t cutoffs[] = {-500, -392, -255, -191, -127, -95, -63, -47, -31,
- -23, -15, -11, -7, -4, -3, -1, 0, 1,
- 3, 5, 7, 11, 15, 23, 31, 47, 63,
- 95, 127, 191, 255, 392, 500};
- constexpr size_t nc = sizeof(cutoffs) / sizeof(*cutoffs) + 1;
- Histogram histo[nc] = {};
- weighted::Header wp_header;
- PredictorMode(i, &wp_header);
- for (const Channel& ch : img.channel) {
- const intptr_t onerow = ch.plane.PixelsPerRow();
- weighted::State wp_state(wp_header, ch.w, ch.h);
- Properties properties(1);
- for (size_t y = 0; y < ch.h; y++) {
- const pixel_type* JXL_RESTRICT r = ch.Row(y);
- for (size_t x = 0; x < ch.w; x++) {
- size_t offset = 0;
- pixel_type_w left = (x ? r[x - 1] : y ? *(r + x - onerow) : 0);
- pixel_type_w top = (y ? *(r + x - onerow) : left);
- pixel_type_w topleft = (x && y ? *(r + x - 1 - onerow) : left);
- pixel_type_w topright =
- (x + 1 < ch.w && y ? *(r + x + 1 - onerow) : top);
- pixel_type_w toptop = (y > 1 ? *(r + x - onerow - onerow) : top);
- pixel_type guess = wp_state.Predict</*compute_properties=*/true>(
- x, y, ch.w, top, left, topright, topleft, toptop, &properties,
- offset);
- size_t ctx = 0;
- for (int c : cutoffs) {
- ctx += c >= properties[0];
- }
- pixel_type res = r[x] - guess;
- uint32_t token, nbits, bits;
- config.Encode(PackSigned(res), &token, &nbits, &bits);
- histo[ctx].Add(token);
- extra_bits += nbits;
- wp_state.UpdateErrors(r[x], x, y, ch.w);
- }
- }
- for (size_t h = 0; h < nc; h++) {
- histo_cost += histo[h].ShannonEntropy();
- histo[h].Clear();
- }
+void ModularFrameEncoder::ClearModularStreamData() {
+ for (const auto& group : stream_params_) {
+ ClearStreamData(group.id);
}
- return histo_cost + extra_bits;
+ stream_params_.clear();
}
-float EstimateCost(const Image& img) {
- // TODO(veluca): consider SIMDfication of this code.
- size_t extra_bits = 0;
- float histo_cost = 0;
- HybridUintConfig config;
- uint32_t cutoffs[] = {0, 1, 3, 5, 7, 11, 15, 23, 31,
- 47, 63, 95, 127, 191, 255, 392, 500};
- constexpr size_t nc = sizeof(cutoffs) / sizeof(*cutoffs) + 1;
- Histogram histo[nc] = {};
- for (const Channel& ch : img.channel) {
- const intptr_t onerow = ch.plane.PixelsPerRow();
- for (size_t y = 0; y < ch.h; y++) {
- const pixel_type* JXL_RESTRICT r = ch.Row(y);
- for (size_t x = 0; x < ch.w; x++) {
- pixel_type_w left = (x ? r[x - 1] : y ? *(r + x - onerow) : 0);
- pixel_type_w top = (y ? *(r + x - onerow) : left);
- pixel_type_w topleft = (x && y ? *(r + x - 1 - onerow) : left);
- size_t maxdiff = std::max(std::max(left, top), topleft) -
- std::min(std::min(left, top), topleft);
- size_t ctx = 0;
- for (uint32_t c : cutoffs) {
- ctx += c > maxdiff;
- }
- pixel_type res = r[x] - ClampedGradient(top, left, topleft);
- uint32_t token, nbits, bits;
- config.Encode(PackSigned(res), &token, &nbits, &bits);
- histo[ctx].Add(token);
- extra_bits += nbits;
- }
- }
- for (size_t h = 0; h < nc; h++) {
- histo_cost += histo[h].ShannonEntropy();
- histo[h].Clear();
- }
- }
- return histo_cost + extra_bits;
+size_t ModularFrameEncoder::ComputeStreamingAbsoluteAcGroupId(
+ size_t dc_group_id, size_t ac_group_id,
+ const FrameDimensions& patch_dim) const {
+ size_t dc_group_x = dc_group_id % frame_dim_.xsize_dc_groups;
+ size_t dc_group_y = dc_group_id / frame_dim_.xsize_dc_groups;
+ size_t ac_group_x = ac_group_id % patch_dim.xsize_groups;
+ size_t ac_group_y = ac_group_id / patch_dim.xsize_groups;
+ return (dc_group_x * 8 + ac_group_x) +
+ (dc_group_y * 8 + ac_group_y) * frame_dim_.xsize_groups;
}
-} // namespace
-
Status ModularFrameEncoder::PrepareStreamParams(const Rect& rect,
const CompressParams& cparams_,
int minShift, int maxShift,
const ModularStreamId& stream,
- bool do_color) {
+ bool do_color, bool groupwise) {
size_t stream_id = stream.ID(frame_dim_);
Image& full_image = stream_images_[0];
const size_t xsize = rect.xsize();
const size_t ysize = rect.ysize();
Image& gi = stream_images_[stream_id];
if (stream_id > 0) {
- gi = Image(xsize, ysize, full_image.bitdepth, 0);
+ JXL_ASSIGN_OR_RETURN(gi,
+ Image::Create(xsize, ysize, full_image.bitdepth, 0));
// start at the first bigger-than-frame_dim.group_dim non-metachannel
size_t c = full_image.nb_meta_channels;
- for (; c < full_image.channel.size(); c++) {
- Channel& fc = full_image.channel[c];
- if (fc.w > frame_dim_.group_dim || fc.h > frame_dim_.group_dim) break;
+ if (!groupwise) {
+ for (; c < full_image.channel.size(); c++) {
+ Channel& fc = full_image.channel[c];
+ if (fc.w > frame_dim_.group_dim || fc.h > frame_dim_.group_dim) break;
+ }
}
for (; c < full_image.channel.size(); c++) {
Channel& fc = full_image.channel[c];
@@ -1220,7 +1305,7 @@ Status ModularFrameEncoder::PrepareStreamParams(const Rect& rect,
rect.xsize() >> fc.hshift, rect.ysize() >> fc.vshift, fc.w, fc.h);
if (r.xsize() == 0 || r.ysize() == 0) continue;
gi_channel_[stream_id].push_back(c);
- Channel gc(r.xsize(), r.ysize());
+ JXL_ASSIGN_OR_RETURN(Channel gc, Channel::Create(r.xsize(), r.ysize()));
gc.hshift = fc.hshift;
gc.vshift = fc.vshift;
for (size_t y = 0; y < r.ysize(); ++y) {
@@ -1245,7 +1330,7 @@ Status ModularFrameEncoder::PrepareStreamParams(const Rect& rect,
maybe_palette.num_c = gi.channel.size() - gi.nb_meta_channels;
maybe_palette.nb_colors = std::abs(cparams_.palette_colors);
maybe_palette.ordered_palette = cparams_.palette_colors >= 0;
- do_transform(gi, maybe_palette, weighted::Header());
+ maybe_do_transform(gi, maybe_palette, cparams_, weighted::Header());
}
// all-minus-one-channel palette (RGB with separate alpha, or CMY with
// separate K)
@@ -1259,7 +1344,7 @@ Status ModularFrameEncoder::PrepareStreamParams(const Rect& rect,
if (maybe_palette_3.lossy_palette) {
maybe_palette_3.predictor = Predictor::Weighted;
}
- do_transform(gi, maybe_palette_3, weighted::Header());
+ maybe_do_transform(gi, maybe_palette_3, cparams_, weighted::Header());
}
}
@@ -1271,9 +1356,10 @@ Status ModularFrameEncoder::PrepareStreamParams(const Rect& rect,
// single channel palette (like FLIF's ChannelCompact)
size_t nb_channels = gi.channel.size() - gi.nb_meta_channels;
for (size_t i = 0; i < nb_channels; i++) {
- int32_t min, max;
+ int32_t min;
+ int32_t max;
compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max);
- int64_t colors = (int64_t)max - min + 1;
+ int64_t colors = static_cast<int64_t>(max) - min + 1;
JXL_DEBUG_V(10, "Channel %" PRIuS ": range=%i..%i", i, min, max);
Transform maybe_palette_1(TransformId::kPalette);
maybe_palette_1.begin_c = i + gi.nb_meta_channels;
@@ -1282,10 +1368,10 @@ Status ModularFrameEncoder::PrepareStreamParams(const Rect& rect,
// actually occur, it is probably worth it to do a compaction
// (but only if the channel palette is less than 80% the size of the
// image itself)
- maybe_palette_1.nb_colors =
- std::min((int)(xsize * ysize * 0.8),
- (int)(cparams_.channel_colors_percent / 100. * colors));
- do_transform(gi, maybe_palette_1, weighted::Header());
+ maybe_palette_1.nb_colors = std::min(
+ static_cast<int>(xsize * ysize * 0.8),
+ static_cast<int>(cparams_.channel_colors_percent / 100. * colors));
+ maybe_do_transform(gi, maybe_palette_1, cparams_, weighted::Header());
}
}
}
@@ -1295,7 +1381,7 @@ Status ModularFrameEncoder::PrepareStreamParams(const Rect& rect,
if (cparams_.color_transform == ColorTransform::kNone &&
cparams_.IsLossless() && cparams_.colorspace < 0 &&
gi.channel.size() - gi.nb_meta_channels >= 3 &&
- cparams_.responsive == false && do_color &&
+ cparams_.responsive == JXL_FALSE && do_color &&
cparams_.speed_tier <= SpeedTier::kHare) {
Transform sg(TransformId::kRCT);
sg.begin_c = gi.nb_meta_channels;
@@ -1319,6 +1405,7 @@ Status ModularFrameEncoder::PrepareStreamParams(const Rect& rect,
case SpeedTier::kKitten:
nb_rcts_to_try = 9;
break;
+ case SpeedTier::kTectonicPlate:
case SpeedTier::kGlacier:
case SpeedTier::kTortoise:
nb_rcts_to_try = 19;
@@ -1403,11 +1490,11 @@ int QuantizeGradient(const int32_t* qrow, size_t onerow, size_t c, size_t x,
return residual + pred.guess;
}
-void ModularFrameEncoder::AddVarDCTDC(const FrameHeader& frame_header,
- const Image3F& dc, const Rect& r,
- size_t group_index, bool nl_dc,
- PassesEncoderState* enc_state,
- bool jpeg_transcode) {
+Status ModularFrameEncoder::AddVarDCTDC(const FrameHeader& frame_header,
+ const Image3F& dc, const Rect& r,
+ size_t group_index, bool nl_dc,
+ PassesEncoderState* enc_state,
+ bool jpeg_transcode) {
extra_dc_precision[group_index] = nl_dc ? 1 : 0;
float mul = 1 << extra_dc_precision[group_index];
@@ -1430,8 +1517,11 @@ void ModularFrameEncoder::AddVarDCTDC(const FrameHeader& frame_header,
stream_options_[stream_id].tree_kind =
ModularOptions::TreeKind::kGradientFixedDC;
}
+ stream_options_[stream_id].histogram_params =
+ stream_options_[0].histogram_params;
- stream_images_[stream_id] = Image(r.xsize(), r.ysize(), 8, 3);
+ JXL_ASSIGN_OR_RETURN(stream_images_[stream_id],
+ Image::Create(r.xsize(), r.ysize(), 8, 3));
if (nl_dc && stream_options_[stream_id].tree_kind ==
ModularOptions::TreeKind::kGradientFixedDC) {
JXL_ASSERT(frame_header.chroma_subsampling.Is444());
@@ -1531,7 +1621,7 @@ void ModularFrameEncoder::AddVarDCTDC(const FrameHeader& frame_header,
Channel& ch = stream_images_[stream_id].channel[c < 2 ? c ^ 1 : c];
ch.w = xs;
ch.h = ys;
- ch.shrink();
+ JXL_RETURN_IF_ERROR(ch.shrink());
for (size_t y = 0; y < ys; y++) {
int32_t* quant_row = ch.plane.Row(y);
const float* row = rect.ConstPlaneRow(dc, c, y);
@@ -1546,14 +1636,17 @@ void ModularFrameEncoder::AddVarDCTDC(const FrameHeader& frame_header,
stream_images_[stream_id], enc_state->shared.quantizer.MulDC(),
1.0 / mul, enc_state->shared.cmap.DCFactors(),
frame_header.chroma_subsampling, enc_state->shared.block_ctx_map);
+ return true;
}
-void ModularFrameEncoder::AddACMetadata(const Rect& r, size_t group_index,
- bool jpeg_transcode,
- PassesEncoderState* enc_state) {
+Status ModularFrameEncoder::AddACMetadata(const Rect& r, size_t group_index,
+ bool jpeg_transcode,
+ PassesEncoderState* enc_state) {
size_t stream_id = ModularStreamId::ACMetadata(group_index).ID(frame_dim_);
stream_options_[stream_id].max_chan_size = 0xFFFFFF;
- stream_options_[stream_id].wp_tree_mode = ModularOptions::TreeMode::kNoWP;
+ if (stream_options_[stream_id].predictor != Predictor::Weighted) {
+ stream_options_[stream_id].wp_tree_mode = ModularOptions::TreeMode::kNoWP;
+ }
if (jpeg_transcode) {
stream_options_[stream_id].tree_kind =
ModularOptions::TreeKind::kJpegTranscodeACMeta;
@@ -1569,14 +1662,19 @@ void ModularFrameEncoder::AddACMetadata(const Rect& r, size_t group_index,
cparams_.force_cfl_jpeg_recompression) {
stream_options_[stream_id].tree_kind = ModularOptions::TreeKind::kLearn;
}
+ stream_options_[stream_id].histogram_params =
+ stream_options_[0].histogram_params;
// YToX, YToB, ACS + QF, EPF
Image& image = stream_images_[stream_id];
- image = Image(r.xsize(), r.ysize(), 8, 4);
+ JXL_ASSIGN_OR_RETURN(image, Image::Create(r.xsize(), r.ysize(), 8, 4));
static_assert(kColorTileDimInBlocks == 8, "Color tile size changed");
Rect cr(r.x0() >> 3, r.y0() >> 3, (r.xsize() + 7) >> 3, (r.ysize() + 7) >> 3);
- image.channel[0] = Channel(cr.xsize(), cr.ysize(), 3, 3);
- image.channel[1] = Channel(cr.xsize(), cr.ysize(), 3, 3);
- image.channel[2] = Channel(r.xsize() * r.ysize(), 2, 0, 0);
+ JXL_ASSIGN_OR_RETURN(image.channel[0],
+ Channel::Create(cr.xsize(), cr.ysize(), 3, 3));
+ JXL_ASSIGN_OR_RETURN(image.channel[1],
+ Channel::Create(cr.xsize(), cr.ysize(), 3, 3));
+ JXL_ASSIGN_OR_RETURN(image.channel[2],
+ Channel::Create(r.xsize() * r.ysize(), 2, 0, 0));
ConvertPlaneAndClamp(cr, enc_state->shared.cmap.ytox_map,
Rect(image.channel[0].plane), &image.channel[0].plane);
ConvertPlaneAndClamp(cr, enc_state->shared.cmap.ytob_map,
@@ -1599,9 +1697,10 @@ void ModularFrameEncoder::AddACMetadata(const Rect& r, size_t group_index,
}
image.channel[2].w = num;
ac_metadata_size[group_index] = num;
+ return true;
}
-void ModularFrameEncoder::EncodeQuantTable(
+Status ModularFrameEncoder::EncodeQuantTable(
size_t size_x, size_t size_y, BitWriter* writer,
const QuantEncoding& encoding, size_t idx,
ModularFrameEncoder* modular_frame_encoder) {
@@ -1611,9 +1710,9 @@ void ModularFrameEncoder::EncodeQuantTable(
if (modular_frame_encoder) {
JXL_CHECK(modular_frame_encoder->EncodeStream(
writer, nullptr, 0, ModularStreamId::QuantTable(idx)));
- return;
+ return true;
}
- Image image(size_x, size_y, 8, 3);
+ JXL_ASSIGN_OR_RETURN(Image image, Image::Create(size_x, size_y, 8, 3));
for (size_t c = 0; c < 3; c++) {
for (size_t y = 0; y < size_y; y++) {
int32_t* JXL_RESTRICT row = image.channel[c].Row(y);
@@ -1624,16 +1723,17 @@ void ModularFrameEncoder::EncodeQuantTable(
}
ModularOptions cfopts;
JXL_CHECK(ModularGenericCompress(image, cfopts, writer));
+ return true;
}
-void ModularFrameEncoder::AddQuantTable(size_t size_x, size_t size_y,
- const QuantEncoding& encoding,
- size_t idx) {
+Status ModularFrameEncoder::AddQuantTable(size_t size_x, size_t size_y,
+ const QuantEncoding& encoding,
+ size_t idx) {
size_t stream_id = ModularStreamId::QuantTable(idx).ID(frame_dim_);
JXL_ASSERT(encoding.qraw.qtable != nullptr);
JXL_ASSERT(size_x * size_y * 3 == encoding.qraw.qtable->size());
Image& image = stream_images_[stream_id];
- image = Image(size_x, size_y, 8, 3);
+ JXL_ASSIGN_OR_RETURN(image, Image::Create(size_x, size_y, 8, 3));
for (size_t c = 0; c < 3; c++) {
for (size_t y = 0; y < size_y; y++) {
int32_t* JXL_RESTRICT row = image.channel[c].Row(y);
@@ -1642,5 +1742,6 @@ void ModularFrameEncoder::AddQuantTable(size_t size_x, size_t size_y,
}
}
}
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_modular.h b/third_party/jpeg-xl/lib/jxl/enc_modular.h
index 2158a781af..8e2015b226 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_modular.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_modular.h
@@ -6,18 +6,29 @@
#ifndef LIB_JXL_ENC_MODULAR_H_
#define LIB_JXL_ENC_MODULAR_H_
+#include <jxl/cms_interface.h>
+
+#include <cstddef>
#include <cstdint>
+#include <vector>
+#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_modular.h"
+#include "lib/jxl/enc_ans.h"
#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/enc_cache.h"
#include "lib/jxl/enc_params.h"
+#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/frame_header.h"
#include "lib/jxl/image.h"
-#include "lib/jxl/image_bundle.h"
+#include "lib/jxl/image_metadata.h"
+#include "lib/jxl/modular/encoding/dec_ma.h"
#include "lib/jxl/modular/encoding/encoding.h"
#include "lib/jxl/modular/modular_image.h"
+#include "lib/jxl/modular/options.h"
+#include "lib/jxl/quant_weights.h"
namespace jxl {
@@ -26,14 +37,14 @@ struct AuxOut;
class ModularFrameEncoder {
public:
ModularFrameEncoder(const FrameHeader& frame_header,
- const CompressParams& cparams_orig);
- Status ComputeEncodingData(const FrameHeader& frame_header,
- const ImageMetadata& metadata,
- Image3F* JXL_RESTRICT color,
- const std::vector<ImageF>& extra_channels,
- PassesEncoderState* JXL_RESTRICT enc_state,
- const JxlCmsInterface& cms, ThreadPool* pool,
- AuxOut* aux_out, bool do_color);
+ const CompressParams& cparams_orig, bool streaming_mode);
+ Status ComputeEncodingData(
+ const FrameHeader& frame_header, const ImageMetadata& metadata,
+ Image3F* JXL_RESTRICT color, const std::vector<ImageF>& extra_channels,
+ const Rect& group_rect, const FrameDimensions& patch_dim,
+ const Rect& frame_area_rect, PassesEncoderState* JXL_RESTRICT enc_state,
+ const JxlCmsInterface& cms, ThreadPool* pool, AuxOut* aux_out,
+ bool do_color);
Status ComputeTree(ThreadPool* pool);
Status ComputeTokens(ThreadPool* pool);
// Encodes global info (tree + histograms) in the `writer`.
@@ -43,28 +54,35 @@ class ModularFrameEncoder {
// assigning bits to the provided `layer`.
Status EncodeStream(BitWriter* writer, AuxOut* aux_out, size_t layer,
const ModularStreamId& stream);
+
void ClearStreamData(const ModularStreamId& stream);
+ void ClearModularStreamData();
+ size_t ComputeStreamingAbsoluteAcGroupId(
+ size_t dc_group_id, size_t ac_group_id,
+ const FrameDimensions& patch_dim) const;
+
// Creates a modular image for a given DC group of VarDCT mode. `dc` is the
// input DC image, not quantized; the group is specified by `group_index`, and
// `nl_dc` decides whether to apply a near-lossless processing to the DC or
// not.
- void AddVarDCTDC(const FrameHeader& frame_header, const Image3F& dc,
- const Rect& r, size_t group_index, bool nl_dc,
- PassesEncoderState* enc_state, bool jpeg_transcode);
+ Status AddVarDCTDC(const FrameHeader& frame_header, const Image3F& dc,
+ const Rect& r, size_t group_index, bool nl_dc,
+ PassesEncoderState* enc_state, bool jpeg_transcode);
// Creates a modular image for the AC metadata of the given group
// (`group_index`).
- void AddACMetadata(const Rect& r, size_t group_index, bool jpeg_transcode,
- PassesEncoderState* enc_state);
+ Status AddACMetadata(const Rect& r, size_t group_index, bool jpeg_transcode,
+ PassesEncoderState* enc_state);
// Encodes a RAW quantization table in `writer`. If `modular_frame_encoder` is
// null, the quantization table in `encoding` is used, with dimensions `size_x
// x size_y`. Otherwise, the table with ID `idx` is encoded from the given
// `modular_frame_encoder`.
- static void EncodeQuantTable(size_t size_x, size_t size_y, BitWriter* writer,
- const QuantEncoding& encoding, size_t idx,
- ModularFrameEncoder* modular_frame_encoder);
+ static Status EncodeQuantTable(size_t size_x, size_t size_y,
+ BitWriter* writer,
+ const QuantEncoding& encoding, size_t idx,
+ ModularFrameEncoder* modular_frame_encoder);
// Stores a quantization table for future usage with `EncodeQuantTable`.
- void AddQuantTable(size_t size_x, size_t size_y,
- const QuantEncoding& encoding, size_t idx);
+ Status AddQuantTable(size_t size_x, size_t size_y,
+ const QuantEncoding& encoding, size_t idx);
std::vector<size_t> ac_metadata_size;
std::vector<uint8_t> extra_dc_precision;
@@ -72,7 +90,8 @@ class ModularFrameEncoder {
private:
Status PrepareStreamParams(const Rect& rect, const CompressParams& cparams,
int minShift, int maxShift,
- const ModularStreamId& stream, bool do_color);
+ const ModularStreamId& stream, bool do_color,
+ bool groupwise);
std::vector<Image> stream_images_;
std::vector<ModularOptions> stream_options_;
std::vector<uint32_t> quants_;
@@ -89,6 +108,14 @@ class ModularFrameEncoder {
std::vector<std::vector<uint32_t>> gi_channel_;
std::vector<size_t> image_widths_;
Predictor delta_pred_ = Predictor::Average4;
+
+ struct GroupParams {
+ Rect rect;
+ int minShift;
+ int maxShift;
+ ModularStreamId id;
+ };
+ std::vector<GroupParams> stream_params_;
};
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_noise.cc b/third_party/jpeg-xl/lib/jxl/enc_noise.cc
index a12a9e6dc4..80b90eed2c 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_noise.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_noise.cc
@@ -114,7 +114,7 @@ class NoiseHistogram {
private:
template <typename T>
T ClampX(const T x) const {
- return std::min(std::max(T(0), x), T(kBins - 1));
+ return std::min(std::max(static_cast<T>(0), x), static_cast<T>(kBins - 1));
}
size_t Index(const float x) const { return ClampX(static_cast<int>(x)); }
@@ -321,7 +321,7 @@ std::vector<NoiseLevel> GetNoiseLevel(
void EncodeFloatParam(float val, float precision, BitWriter* writer) {
JXL_ASSERT(val >= 0);
- const int absval_quant = static_cast<int>(val * precision + 0.5f);
+ const int absval_quant = static_cast<int>(std::lround(val * precision));
JXL_ASSERT(absval_quant < (1 << 10));
writer->Write(10, absval_quant);
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_optimize_test.cc b/third_party/jpeg-xl/lib/jxl/enc_optimize_test.cc
index cc65bf1a0c..9184765be2 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_optimize_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_optimize_test.cc
@@ -12,7 +12,7 @@ namespace optimize {
namespace {
// The maximum number of iterations for the test.
-static const size_t kMaxTestIter = 100000;
+const size_t kMaxTestIter = 100000;
// F(w) = (w - w_min)^2.
struct SimpleQuadraticFunction {
diff --git a/third_party/jpeg-xl/lib/jxl/enc_params.h b/third_party/jpeg-xl/lib/jxl/enc_params.h
index 89fd2c924f..162c59d04c 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_params.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_params.h
@@ -15,6 +15,7 @@
#include <vector>
#include "lib/jxl/base/override.h"
+#include "lib/jxl/common.h"
#include "lib/jxl/enc_progressive_split.h"
#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/frame_header.h"
@@ -24,36 +25,6 @@
namespace jxl {
-enum class SpeedTier {
- // Try multiple combinations of Tortoise flags for modular mode. Otherwise
- // like kTortoise.
- kGlacier = 0,
- // Turns on FindBestQuantizationHQ loop. Equivalent to "guetzli" mode.
- kTortoise = 1,
- // Turns on FindBestQuantization butteraugli loop.
- kKitten = 2,
- // Turns on dots, patches, and spline detection by default, as well as full
- // context clustering. Default.
- kSquirrel = 3,
- // Turns on error diffusion and full AC strategy heuristics. Equivalent to
- // "fast" mode.
- kWombat = 4,
- // Turns on gaborish by default, non-default cmap, initial quant field.
- kHare = 5,
- // Turns on simple heuristics for AC strategy, quant field, and clustering;
- // also enables coefficient reordering.
- kCheetah = 6,
- // Turns off most encoder features. Does context clustering.
- // Modular: uses fixed tree with Weighted predictor.
- kFalcon = 7,
- // Currently fastest possible setting for VarDCT.
- // Modular: uses fixed tree with Gradient predictor.
- kThunder = 8,
- // VarDCT: same as kThunder.
- // Modular: no tree, Gradient predictor, fast histograms
- kLightning = 9
-};
-
// NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
struct CompressParams {
float butteraugli_distance = 1.0f;
@@ -106,7 +77,7 @@ struct CompressParams {
int progressive_dc = -1;
// If on: preserve color of invisible pixels (if off: don't care)
- // Default: on for lossless, off for lossy
+ // Default: on
Override keep_invisible = Override::kDefault;
JxlCmsInterface cms;
@@ -137,6 +108,7 @@ struct CompressParams {
ModularOptions options;
int responsive = -1;
int colorspace = -1;
+ int move_to_front_from_channel = -1;
// Use Global channel palette if #colors < this percentage of range
float channel_colors_pre_transform_percent = 95.f;
// Use Local channel palette if #colors < this percentage of range
@@ -159,9 +131,6 @@ struct CompressParams {
if (f > 0) return false;
if (f < 0 && butteraugli_distance != 0) return false;
}
- // if no explicit ec_distance given, and using vardct, then the modular part
- // is empty or not lossless
- if (!modular_mode && ec_distance.empty()) return false;
// all modular channels are encoded at distance 0
return true;
}
@@ -194,7 +163,7 @@ struct CompressParams {
int level = -1;
// See JXL_ENC_FRAME_SETTING_BUFFERING option value.
- int buffering = 0;
+ int buffering = -1;
// See JXL_ENC_FRAME_SETTING_USE_FULL_IMAGE_HEURISTICS option value.
bool use_full_image_heuristics = true;
diff --git a/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc b/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc
index 0abd177809..f19ba0dd9e 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc
@@ -5,24 +5,22 @@
#include "lib/jxl/enc_patch_dictionary.h"
+#include <jxl/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <algorithm>
#include <atomic>
-#include <string>
-#include <tuple>
#include <utility>
#include <vector>
-#include "lib/jxl/ans_params.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/override.h"
+#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/random.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/dec_cache.h"
#include "lib/jxl/dec_frame.h"
#include "lib/jxl/enc_ans.h"
@@ -31,7 +29,6 @@
#include "lib/jxl/enc_debug_image.h"
#include "lib/jxl/enc_dot_dictionary.h"
#include "lib/jxl/enc_frame.h"
-#include "lib/jxl/entropy_coder.h"
#include "lib/jxl/frame_header.h"
#include "lib/jxl/image.h"
#include "lib/jxl/image_bundle.h"
@@ -100,7 +97,7 @@ void PatchDictionaryEncoder::Encode(const PatchDictionary& pdic,
add_num(kPatchAlphaChannelContext, info.alpha_channel);
}
if (UsesClamp(info.mode)) {
- add_num(kPatchClampContext, info.clamp);
+ add_num(kPatchClampContext, TO_JXL_BOOL(info.clamp));
}
}
}
@@ -159,7 +156,7 @@ void PatchDictionaryEncoder::SubtractFrom(const PatchDictionary& pdic,
// Nothing to do.
} else {
JXL_UNREACHABLE("Blending mode %u not yet implemented",
- (uint32_t)mode);
+ static_cast<uint32_t>(mode));
}
}
}
@@ -208,11 +205,12 @@ struct PatchColorspaceInfo {
}
};
-std::vector<PatchInfo> FindTextLikePatches(
+StatusOr<std::vector<PatchInfo>> FindTextLikePatches(
const CompressParams& cparams, const Image3F& opsin,
const PassesEncoderState* JXL_RESTRICT state, ThreadPool* pool,
AuxOut* aux_out, bool is_xyb) {
- if (state->cparams.patches == Override::kOff) return {};
+ std::vector<PatchInfo> info;
+ if (state->cparams.patches == Override::kOff) return info;
const auto& frame_dim = state->shared.frame_dim;
PatchColorspaceInfo pci(is_xyb);
@@ -222,7 +220,8 @@ std::vector<PatchInfo> FindTextLikePatches(
std::pair<uint32_t, uint32_t> p2,
const float* JXL_RESTRICT rows[3],
size_t stride, float threshold) {
- float v1[3], v2[3];
+ float v1[3];
+ float v2[3];
for (size_t c = 0; c < 3; c++) {
v1[c] = rows[c][p1.second * stride + p1.first];
v2[c] = rows[c][p2.second * stride + p2.first];
@@ -258,8 +257,9 @@ std::vector<PatchInfo> FindTextLikePatches(
// Look for kPatchSide size squares, naturally aligned, that all have the same
// pixel values.
- ImageB is_screenshot_like(DivCeil(frame_dim.xsize, kPatchSide),
- DivCeil(frame_dim.ysize, kPatchSide));
+ JXL_ASSIGN_OR_RETURN(ImageB is_screenshot_like,
+ ImageB::Create(DivCeil(frame_dim.xsize, kPatchSide),
+ DivCeil(frame_dim.ysize, kPatchSide)));
ZeroFillImage(&is_screenshot_like);
uint8_t* JXL_RESTRICT screenshot_row = is_screenshot_like.Row(0);
const size_t screenshot_stride = is_screenshot_like.PixelsPerRow();
@@ -302,19 +302,22 @@ std::vector<PatchInfo> FindTextLikePatches(
// TODO(veluca): also parallelize the rest of this function.
if (WantDebugOutput(cparams)) {
- DumpPlaneNormalized(cparams, "screenshot_like", is_screenshot_like);
+ JXL_RETURN_IF_ERROR(
+ DumpPlaneNormalized(cparams, "screenshot_like", is_screenshot_like));
}
constexpr int kSearchRadius = 1;
if (!ApplyOverride(state->cparams.patches, has_screenshot_areas)) {
- return {};
+ return info;
}
// Search for "similar enough" pixels near the screenshot-like areas.
- ImageB is_background(frame_dim.xsize, frame_dim.ysize);
+ JXL_ASSIGN_OR_RETURN(ImageB is_background,
+ ImageB::Create(frame_dim.xsize, frame_dim.ysize));
ZeroFillImage(&is_background);
- Image3F background(frame_dim.xsize, frame_dim.ysize);
+ JXL_ASSIGN_OR_RETURN(Image3F background,
+ Image3F::Create(frame_dim.xsize, frame_dim.ysize));
ZeroFillImage(&background);
constexpr size_t kDistanceLimit = 50;
float* JXL_RESTRICT background_rows[3] = {
@@ -383,13 +386,14 @@ std::vector<PatchInfo> FindTextLikePatches(
Rng rng(0);
bool paint_ccs = false;
if (WantDebugOutput(cparams)) {
- DumpPlaneNormalized(cparams, "is_background", is_background);
+ JXL_RETURN_IF_ERROR(
+ DumpPlaneNormalized(cparams, "is_background", is_background));
if (is_xyb) {
- DumpXybImage(cparams, "background", background);
+ JXL_RETURN_IF_ERROR(DumpXybImage(cparams, "background", background));
} else {
- DumpImage(cparams, "background", background);
+ JXL_RETURN_IF_ERROR(DumpImage(cparams, "background", background));
}
- ccs = ImageF(frame_dim.xsize, frame_dim.ysize);
+ JXL_ASSIGN_OR_RETURN(ccs, ImageF::Create(frame_dim.xsize, frame_dim.ysize));
ZeroFillImage(&ccs);
paint_ccs = true;
}
@@ -407,11 +411,10 @@ std::vector<PatchInfo> FindTextLikePatches(
constexpr int kMinPeak = 2;
constexpr int kHasSimilarRadius = 2;
- std::vector<PatchInfo> info;
-
// Find small CC outside the "similar enough" areas, compute bounding boxes,
// and run heuristics to exclude some patches.
- ImageB visited(frame_dim.xsize, frame_dim.ysize);
+ JXL_ASSIGN_OR_RETURN(ImageB visited,
+ ImageB::Create(frame_dim.xsize, frame_dim.ysize));
ZeroFillImage(&visited);
uint8_t* JXL_RESTRICT visited_row = visited.Row(0);
const size_t visited_stride = visited.PixelsPerRow();
@@ -525,10 +528,10 @@ std::vector<PatchInfo> FindTextLikePatches(
if (paint_ccs) {
JXL_ASSERT(WantDebugOutput(cparams));
- DumpPlaneNormalized(cparams, "ccs", ccs);
+ JXL_RETURN_IF_ERROR(DumpPlaneNormalized(cparams, "ccs", ccs));
}
if (info.empty()) {
- return {};
+ return info;
}
// Remove duplicates.
@@ -560,19 +563,22 @@ std::vector<PatchInfo> FindTextLikePatches(
// don't use patches if all patches are smaller than this
constexpr size_t kMinMaxPatchSize = 20;
- if (max_patch_size < kMinMaxPatchSize) return {};
+ if (max_patch_size < kMinMaxPatchSize) {
+ info.clear();
+ }
return info;
}
} // namespace
-void FindBestPatchDictionary(const Image3F& opsin,
- PassesEncoderState* JXL_RESTRICT state,
- const JxlCmsInterface& cms, ThreadPool* pool,
- AuxOut* aux_out, bool is_xyb) {
- std::vector<PatchInfo> info =
- FindTextLikePatches(state->cparams, opsin, state, pool, aux_out, is_xyb);
+Status FindBestPatchDictionary(const Image3F& opsin,
+ PassesEncoderState* JXL_RESTRICT state,
+ const JxlCmsInterface& cms, ThreadPool* pool,
+ AuxOut* aux_out, bool is_xyb) {
+ JXL_ASSIGN_OR_RETURN(
+ std::vector<PatchInfo> info,
+ FindTextLikePatches(state->cparams, opsin, state, pool, aux_out, is_xyb));
// TODO(veluca): this doesn't work if both dots and patches are enabled.
// For now, since dots and patches are not likely to occur in the same kind of
@@ -582,10 +588,13 @@ void FindBestPatchDictionary(const Image3F& opsin,
state->cparams.dots,
state->cparams.speed_tier <= SpeedTier::kSquirrel &&
state->cparams.butteraugli_distance >= kMinButteraugliForDots)) {
- info = FindDotDictionary(state->cparams, opsin, state->shared.cmap, pool);
+ Rect rect(0, 0, state->shared.frame_dim.xsize,
+ state->shared.frame_dim.ysize);
+ JXL_ASSIGN_OR_RETURN(info, FindDotDictionary(state->cparams, opsin, rect,
+ state->shared.cmap, pool));
}
- if (info.empty()) return;
+ if (info.empty()) return true;
std::sort(
info.begin(), info.end(), [&](const PatchInfo& a, const PatchInfo& b) {
@@ -616,7 +625,7 @@ void FindBestPatchDictionary(const Image3F& opsin,
ref_xsize = ref_xsize * kBinPackingSlackness + 1;
ref_ysize = ref_ysize * kBinPackingSlackness + 1;
- ImageB occupied(ref_xsize, ref_ysize);
+ JXL_ASSIGN_OR_RETURN(ImageB occupied, ImageB::Create(ref_xsize, ref_ysize));
ZeroFillImage(&occupied);
uint8_t* JXL_RESTRICT occupied_rows = occupied.Row(0);
size_t occupied_stride = occupied.PixelsPerRow();
@@ -667,7 +676,7 @@ void FindBestPatchDictionary(const Image3F& opsin,
ref_positions[patch] = {x0, y0};
for (size_t y = y0; y < y0 + ysize; y++) {
for (size_t x = x0; x < x0 + xsize; x++) {
- occupied_rows[y * occupied_stride + x] = true;
+ occupied_rows[y * occupied_stride + x] = JXL_TRUE;
}
}
max_y = std::max(max_y, y0 + ysize);
@@ -680,7 +689,8 @@ void FindBestPatchDictionary(const Image3F& opsin,
ref_ysize = max_y;
- Image3F reference_frame(ref_xsize, ref_ysize);
+ JXL_ASSIGN_OR_RETURN(Image3F reference_frame,
+ Image3F::Create(ref_xsize, ref_ysize));
// TODO(veluca): figure out a better way to fill the image.
ZeroFillImage(&reference_frame);
std::vector<PatchPosition> positions;
@@ -710,6 +720,8 @@ void FindBestPatchDictionary(const Image3F& opsin,
}
}
for (const auto& pos : info[i].second) {
+ JXL_DEBUG_V(4, "Patch %" PRIuS "x%" PRIuS " at position %u,%u",
+ ref_pos.xsize, ref_pos.ysize, pos.first, pos.second);
positions.emplace_back(
PatchPosition{pos.first, pos.second, pref_positions.size()});
// Add blending for color channels, ignore other channels.
@@ -718,15 +730,16 @@ void FindBestPatchDictionary(const Image3F& opsin,
blendings.push_back({PatchBlendMode::kNone, 0, false});
}
}
- pref_positions.emplace_back(std::move(ref_pos));
+ pref_positions.emplace_back(ref_pos);
}
CompressParams cparams = state->cparams;
// Recursive application of patches could create very weird issues.
cparams.patches = Override::kOff;
- RoundtripPatchFrame(&reference_frame, state, kPatchFrameReferenceId, cparams,
- cms, pool, aux_out, /*subtract=*/true);
+ JXL_RETURN_IF_ERROR(RoundtripPatchFrame(&reference_frame, state,
+ kPatchFrameReferenceId, cparams, cms,
+ pool, aux_out, /*subtract=*/true));
// TODO(veluca): this assumes that applying patches is commutative, which is
// not true for all blending modes. This code only produces kAdd patches, so
@@ -734,12 +747,13 @@ void FindBestPatchDictionary(const Image3F& opsin,
PatchDictionaryEncoder::SetPositions(
&state->shared.image_features.patches, std::move(positions),
std::move(pref_positions), std::move(blendings));
+ return true;
}
-void RoundtripPatchFrame(Image3F* reference_frame,
- PassesEncoderState* JXL_RESTRICT state, int idx,
- CompressParams& cparams, const JxlCmsInterface& cms,
- ThreadPool* pool, AuxOut* aux_out, bool subtract) {
+Status RoundtripPatchFrame(Image3F* reference_frame,
+ PassesEncoderState* JXL_RESTRICT state, int idx,
+ CompressParams& cparams, const JxlCmsInterface& cms,
+ ThreadPool* pool, AuxOut* aux_out, bool subtract) {
FrameInfo patch_frame_info;
cparams.resampling = 1;
cparams.ec_resampling = 1;
@@ -768,7 +782,8 @@ void RoundtripPatchFrame(Image3F* reference_frame,
std::vector<ImageF> extra_channels;
extra_channels.reserve(ib.metadata()->extra_channel_info.size());
for (size_t i = 0; i < ib.metadata()->extra_channel_info.size(); i++) {
- extra_channels.emplace_back(ib.xsize(), ib.ysize());
+ JXL_ASSIGN_OR_RETURN(ImageF ch, ImageF::Create(ib.xsize(), ib.ysize()));
+ extra_channels.emplace_back(std::move(ch));
// Must initialize the image with data to not affect blending with
// uninitialized memory.
// TODO(lode): patches must copy and use the real extra channels instead.
@@ -814,6 +829,7 @@ void RoundtripPatchFrame(Image3F* reference_frame,
} else {
state->shared.reference_frames[idx].frame = std::move(ib);
}
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.h b/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.h
index e17bfe4f04..ac236d7f17 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.h
@@ -12,13 +12,10 @@
#include <string.h>
#include <sys/types.h>
-#include <tuple>
#include <vector>
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/chroma_from_luma.h"
-#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/dec_patch_dictionary.h"
#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/enc_cache.h"
@@ -92,15 +89,15 @@ class PatchDictionaryEncoder {
static void SubtractFrom(const PatchDictionary& pdic, Image3F* opsin);
};
-void FindBestPatchDictionary(const Image3F& opsin,
- PassesEncoderState* JXL_RESTRICT state,
- const JxlCmsInterface& cms, ThreadPool* pool,
- AuxOut* aux_out, bool is_xyb = true);
+Status FindBestPatchDictionary(const Image3F& opsin,
+ PassesEncoderState* JXL_RESTRICT state,
+ const JxlCmsInterface& cms, ThreadPool* pool,
+ AuxOut* aux_out, bool is_xyb = true);
-void RoundtripPatchFrame(Image3F* reference_frame,
- PassesEncoderState* JXL_RESTRICT state, int idx,
- CompressParams& cparams, const JxlCmsInterface& cms,
- ThreadPool* pool, AuxOut* aux_out, bool subtract);
+Status RoundtripPatchFrame(Image3F* reference_frame,
+ PassesEncoderState* JXL_RESTRICT state, int idx,
+ CompressParams& cparams, const JxlCmsInterface& cms,
+ ThreadPool* pool, AuxOut* aux_out, bool subtract);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_photon_noise_test.cc b/third_party/jpeg-xl/lib/jxl/enc_photon_noise_test.cc
index be11b465ad..2e10dd5457 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_photon_noise_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_photon_noise_test.cc
@@ -5,46 +5,37 @@
#include "lib/jxl/enc_photon_noise.h"
-#include "lib/jxl/test_utils.h"
+#include "lib/jxl/base/common.h"
+#include "lib/jxl/noise.h"
#include "lib/jxl/testing.h"
namespace jxl {
namespace {
-using ::testing::FloatNear;
-using ::testing::Pointwise;
-
-MATCHER(AreApproximatelyEqual, "") {
- constexpr float kTolerance = 1e-6;
- const float actual = std::get<0>(arg);
- const float expected = std::get<1>(arg);
- return testing::ExplainMatchResult(FloatNear(expected, kTolerance), actual,
- result_listener);
-}
-
TEST(EncPhotonNoiseTest, LUTs) {
- EXPECT_THAT(
+ const double kTolerance = 1e-6;
+ EXPECT_ARRAY_NEAR(
SimulatePhotonNoise(/*xsize=*/6000, /*ysize=*/4000, /*iso=*/100).lut,
- Pointwise(AreApproximatelyEqual(),
- {0.00259652, 0.0139648, 0.00681551, 0.00632582, 0.00694917,
- 0.00803922, 0.00934574, 0.0107607}));
- EXPECT_THAT(
+ (NoiseParams::Lut{0.00259652, 0.0139648, 0.00681551, 0.00632582,
+ 0.00694917, 0.00803922, 0.00934574, 0.0107607}),
+ kTolerance);
+ EXPECT_ARRAY_NEAR(
SimulatePhotonNoise(/*xsize=*/6000, /*ysize=*/4000, /*iso=*/800).lut,
- Pointwise(AreApproximatelyEqual(),
- {0.02077220, 0.0420923, 0.01820690, 0.01439020, 0.01293670,
- 0.01254030, 0.01277390, 0.0134161}));
- EXPECT_THAT(
+ (NoiseParams::Lut{0.02077220, 0.0420923, 0.01820690, 0.01439020,
+ 0.01293670, 0.01254030, 0.01277390, 0.0134161}),
+ kTolerance);
+ EXPECT_ARRAY_NEAR(
SimulatePhotonNoise(/*xsize=*/6000, /*ysize=*/4000, /*iso=*/6400).lut,
- Pointwise(AreApproximatelyEqual(),
- {0.1661770, 0.1691120, 0.05309080, 0.03963960, 0.03357410,
- 0.03001650, 0.02776740, 0.0263478}));
+ (NoiseParams::Lut{0.1661770, 0.1691120, 0.05309080, 0.03963960,
+ 0.03357410, 0.03001650, 0.02776740, 0.0263478}),
+ kTolerance);
// Lower when measured on a per-pixel basis as there are fewer of them.
- EXPECT_THAT(
+ EXPECT_ARRAY_NEAR(
SimulatePhotonNoise(/*xsize=*/4000, /*ysize=*/3000, /*iso=*/6400).lut,
- Pointwise(AreApproximatelyEqual(),
- {0.0830886, 0.1008720, 0.0367748, 0.0280305, 0.0240236,
- 0.0218040, 0.0205771, 0.0200058}));
+ (NoiseParams::Lut{0.0830886, 0.1008720, 0.0367748, 0.0280305, 0.0240236,
+ 0.0218040, 0.0205771, 0.0200058}),
+ kTolerance);
}
} // namespace
diff --git a/third_party/jpeg-xl/lib/jxl/enc_quant_weights.cc b/third_party/jpeg-xl/lib/jxl/enc_quant_weights.cc
index 236ddaacfd..35e49d5993 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_quant_weights.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_quant_weights.cc
@@ -5,24 +5,18 @@
#include "lib/jxl/enc_quant_weights.h"
+#include <jxl/types.h>
#include <stdlib.h>
-#include <algorithm>
#include <cmath>
-#include <limits>
-#include <utility>
-#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/dct_scales.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/enc_modular.h"
#include "lib/jxl/fields.h"
-#include "lib/jxl/image.h"
#include "lib/jxl/modular/encoding/encoding.h"
-#include "lib/jxl/modular/options.h"
namespace jxl {
@@ -95,8 +89,8 @@ Status EncodeQuant(const QuantEncoding& encoding, size_t idx, size_t size_x,
break;
}
case QuantEncoding::kQuantModeRAW: {
- ModularFrameEncoder::EncodeQuantTable(size_x, size_y, writer, encoding,
- idx, modular_frame_encoder);
+ JXL_RETURN_IF_ERROR(ModularFrameEncoder::EncodeQuantTable(
+ size_x, size_y, writer, encoding, idx, modular_frame_encoder));
break;
}
case QuantEncoding::kQuantModeAFV: {
@@ -130,7 +124,7 @@ Status DequantMatricesEncode(const DequantMatrices& matrices, BitWriter* writer,
}
// TODO(janwas): better bound
BitWriter::Allotment allotment(writer, 512 * 1024);
- writer->Write(1, all_default);
+ writer->Write(1, TO_JXL_BOOL(all_default));
if (!all_default) {
for (size_t i = 0; i < encodings.size(); i++) {
JXL_RETURN_IF_ERROR(EncodeQuant(
@@ -153,7 +147,7 @@ Status DequantMatricesEncodeDC(const DequantMatrices& matrices,
}
}
BitWriter::Allotment allotment(writer, 1 + sizeof(float) * kBitsPerByte * 3);
- writer->Write(1, all_default);
+ writer->Write(1, TO_JXL_BOOL(all_default));
if (!all_default) {
for (size_t c = 0; c < 3; c++) {
JXL_RETURN_IF_ERROR(F16Coder::Write(dc_quant[c] * 128.0f, writer));
@@ -195,19 +189,20 @@ void DequantMatricesRoundtrip(DequantMatrices* matrices) {
JXL_CHECK(br.Close());
}
-void DequantMatricesSetCustom(DequantMatrices* matrices,
- const std::vector<QuantEncoding>& encodings,
- ModularFrameEncoder* encoder) {
+Status DequantMatricesSetCustom(DequantMatrices* matrices,
+ const std::vector<QuantEncoding>& encodings,
+ ModularFrameEncoder* encoder) {
JXL_ASSERT(encodings.size() == DequantMatrices::kNum);
matrices->SetEncodings(encodings);
for (size_t i = 0; i < encodings.size(); i++) {
if (encodings[i].mode == QuantEncodingInternal::kQuantModeRAW) {
- encoder->AddQuantTable(DequantMatrices::required_size_x[i] * kBlockDim,
- DequantMatrices::required_size_y[i] * kBlockDim,
- encodings[i], i);
+ JXL_RETURN_IF_ERROR(encoder->AddQuantTable(
+ DequantMatrices::required_size_x[i] * kBlockDim,
+ DequantMatrices::required_size_y[i] * kBlockDim, encodings[i], i));
}
}
DequantMatricesRoundtrip(matrices);
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/enc_quant_weights.h b/third_party/jpeg-xl/lib/jxl/enc_quant_weights.h
index a47dfd4988..82d8278b72 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_quant_weights.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_quant_weights.h
@@ -27,9 +27,9 @@ void DequantMatricesSetCustomDC(DequantMatrices* matrices, const float* dc);
void DequantMatricesScaleDC(DequantMatrices* matrices, float scale);
-void DequantMatricesSetCustom(DequantMatrices* matrices,
- const std::vector<QuantEncoding>& encodings,
- ModularFrameEncoder* encoder);
+Status DequantMatricesSetCustom(DequantMatrices* matrices,
+ const std::vector<QuantEncoding>& encodings,
+ ModularFrameEncoder* encoder);
// Roundtrip encode/decode the matrices to ensure same values as decoder.
void DequantMatricesRoundtrip(DequantMatrices* matrices);
diff --git a/third_party/jpeg-xl/lib/jxl/enc_splines.cc b/third_party/jpeg-xl/lib/jxl/enc_splines.cc
index de6c9670ea..fa15648ca5 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_splines.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_splines.cc
@@ -73,13 +73,13 @@ void EncodeSplines(const Splines& splines, BitWriter* writer,
splines.QuantizedSplines();
std::vector<std::vector<Token>> tokens(1);
tokens[0].emplace_back(kNumSplinesContext, quantized_splines.size() - 1);
- EncodeAllStartingPoints(splines.StartingPoints(), &tokens[0]);
+ EncodeAllStartingPoints(splines.StartingPoints(), tokens.data());
tokens[0].emplace_back(kQuantizationAdjustmentContext,
PackSigned(splines.GetQuantizationAdjustment()));
for (const QuantizedSpline& spline : quantized_splines) {
- QuantizedSplineEncoder::Tokenize(spline, &tokens[0]);
+ QuantizedSplineEncoder::Tokenize(spline, tokens.data());
}
EntropyEncodingData codes;
diff --git a/third_party/jpeg-xl/lib/jxl/enc_transforms.cc b/third_party/jpeg-xl/lib/jxl/enc_transforms.cc
index 8978ba1dcb..d116183404 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_transforms.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_transforms.cc
@@ -21,20 +21,19 @@ void TransformFromPixels(const AcStrategy::Type strategy,
const float* JXL_RESTRICT pixels, size_t pixels_stride,
float* JXL_RESTRICT coefficients,
float* scratch_space) {
- return HWY_DYNAMIC_DISPATCH(TransformFromPixels)(
- strategy, pixels, pixels_stride, coefficients, scratch_space);
+ HWY_DYNAMIC_DISPATCH(TransformFromPixels)
+ (strategy, pixels, pixels_stride, coefficients, scratch_space);
}
HWY_EXPORT(DCFromLowestFrequencies);
void DCFromLowestFrequencies(AcStrategy::Type strategy, const float* block,
float* dc, size_t dc_stride) {
- return HWY_DYNAMIC_DISPATCH(DCFromLowestFrequencies)(strategy, block, dc,
- dc_stride);
+ HWY_DYNAMIC_DISPATCH(DCFromLowestFrequencies)(strategy, block, dc, dc_stride);
}
HWY_EXPORT(AFVDCT4x4);
void AFVDCT4x4(const float* JXL_RESTRICT pixels, float* JXL_RESTRICT coeffs) {
- return HWY_DYNAMIC_DISPATCH(AFVDCT4x4)(pixels, coeffs);
+ HWY_DYNAMIC_DISPATCH(AFVDCT4x4)(pixels, coeffs);
}
#endif // HWY_ONCE
diff --git a/third_party/jpeg-xl/lib/jxl/enc_transforms.h b/third_party/jpeg-xl/lib/jxl/enc_transforms.h
index 039ccc3893..f0ce95659d 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_transforms.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_transforms.h
@@ -9,14 +9,13 @@
// Facade for (non-inlined) integral transforms.
#include <stddef.h>
-#include <stdint.h>
#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/compiler_specific.h"
namespace jxl {
-void TransformFromPixels(const AcStrategy::Type strategy,
+void TransformFromPixels(AcStrategy::Type strategy,
const float* JXL_RESTRICT pixels, size_t pixels_stride,
float* JXL_RESTRICT coefficients,
float* JXL_RESTRICT scratch_space);
diff --git a/third_party/jpeg-xl/lib/jxl/enc_xyb.cc b/third_party/jpeg-xl/lib/jxl/enc_xyb.cc
index e538e8c91d..9fc68d8474 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_xyb.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_xyb.cc
@@ -21,9 +21,7 @@
#include "lib/jxl/cms/opsin_params.h"
#include "lib/jxl/cms/transfer_functions-inl.h"
#include "lib/jxl/color_encoding_internal.h"
-#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/enc_image_bundle.h"
-#include "lib/jxl/fields.h"
#include "lib/jxl/image_bundle.h"
#include "lib/jxl/image_ops.h"
@@ -44,7 +42,7 @@ JXL_INLINE void OpsinAbsorbance(const V r, const V g, const V b,
const float* JXL_RESTRICT premul_absorb,
V* JXL_RESTRICT mixed0, V* JXL_RESTRICT mixed1,
V* JXL_RESTRICT mixed2) {
- const float* bias = &jxl::cms::kOpsinAbsorbanceBias[0];
+ const float* bias = jxl::cms::kOpsinAbsorbanceBias.data();
const HWY_FULL(float) d;
const size_t N = Lanes(d);
const auto m0 = Load(d, premul_absorb + 0 * N);
@@ -77,7 +75,9 @@ void LinearRGBToXYB(const V r, const V g, const V b,
const float* JXL_RESTRICT premul_absorb,
float* JXL_RESTRICT valx, float* JXL_RESTRICT valy,
float* JXL_RESTRICT valz) {
- V mixed0, mixed1, mixed2;
+ V mixed0;
+ V mixed1;
+ V mixed2;
OpsinAbsorbance(r, g, b, premul_absorb, &mixed0, &mixed1, &mixed2);
// mixed* should be non-negative even for wide-gamut, so clamp to zero.
@@ -198,9 +198,11 @@ void ComputePremulAbsorb(float intensity_target, float* premul_absorb) {
const HWY_FULL(float) d;
const size_t N = Lanes(d);
const float mul = intensity_target / 255.0f;
- for (size_t i = 0; i < 9; ++i) {
- const auto absorb = Set(d, jxl::cms::kOpsinAbsorbanceMatrix[i] * mul);
- Store(absorb, d, premul_absorb + i * N);
+ for (size_t j = 0; j < 3; ++j) {
+ for (size_t i = 0; i < 3; ++i) {
+ const auto absorb = Set(d, jxl::cms::kOpsinAbsorbanceMatrix[j][i] * mul);
+ Store(absorb, d, premul_absorb + (j * 3 + i) * N);
+ }
}
for (size_t i = 0; i < 3; ++i) {
const auto neg_bias_cbrt =
@@ -209,15 +211,16 @@ void ComputePremulAbsorb(float intensity_target, float* premul_absorb) {
}
}
-Image3F TransformToLinearRGB(const Image3F& in,
- const ColorEncoding& color_encoding,
- float intensity_target, const JxlCmsInterface& cms,
- ThreadPool* pool) {
+StatusOr<Image3F> TransformToLinearRGB(const Image3F& in,
+ const ColorEncoding& color_encoding,
+ float intensity_target,
+ const JxlCmsInterface& cms,
+ ThreadPool* pool) {
ColorSpaceTransform c_transform(cms);
bool is_gray = color_encoding.IsGray();
const ColorEncoding& c_desired = ColorEncoding::LinearSRGB(is_gray);
- Image3F out(in.xsize(), in.ysize());
- std::atomic<bool> ok{true};
+ JXL_ASSIGN_OR_RETURN(Image3F out, Image3F::Create(in.xsize(), in.ysize()));
+ std::atomic<bool> has_error{false};
JXL_CHECK(RunOnPool(
pool, 0, in.ysize(),
[&](const size_t num_threads) {
@@ -225,6 +228,7 @@ Image3F TransformToLinearRGB(const Image3F& in,
in.xsize(), num_threads);
},
[&](const uint32_t y, const size_t thread) {
+ if (has_error) return;
float* mutable_src_buf = c_transform.BufSrc(thread);
const float* src_buf = mutable_src_buf;
// Interleave input.
@@ -241,8 +245,8 @@ Image3F TransformToLinearRGB(const Image3F& in,
}
}
float* JXL_RESTRICT dst_buf = c_transform.BufDst(thread);
- if (!c_transform.Run(thread, src_buf, dst_buf)) {
- ok.store(false);
+ if (!c_transform.Run(thread, src_buf, dst_buf, in.xsize())) {
+ has_error = true;
return;
}
float* JXL_RESTRICT row_out0 = out.PlaneRow(0, y);
@@ -264,7 +268,7 @@ Image3F TransformToLinearRGB(const Image3F& in,
}
},
"Colorspace transform"));
- JXL_CHECK(ok.load());
+ JXL_CHECK(!has_error);
return out;
}
@@ -394,12 +398,13 @@ void ToXYB(const ColorEncoding& c_current, float intensity_target,
(c_current, intensity_target, black, pool, image, cms, linear);
}
-void ToXYB(const ImageBundle& in, ThreadPool* pool, Image3F* JXL_RESTRICT xyb,
- const JxlCmsInterface& cms, Image3F* JXL_RESTRICT linear) {
- *xyb = Image3F(in.xsize(), in.ysize());
+Status ToXYB(const ImageBundle& in, ThreadPool* pool, Image3F* JXL_RESTRICT xyb,
+ const JxlCmsInterface& cms, Image3F* JXL_RESTRICT linear) {
+ JXL_ASSIGN_OR_RETURN(*xyb, Image3F::Create(in.xsize(), in.ysize()));
CopyImageTo(in.color(), xyb);
ToXYB(in.c_current(), in.metadata()->IntensityTarget(),
in.HasBlack() ? &in.black() : nullptr, pool, xyb, cms, linear);
+ return true;
}
HWY_EXPORT(LinearRGBRowToXYB);
diff --git a/third_party/jpeg-xl/lib/jxl/enc_xyb.h b/third_party/jpeg-xl/lib/jxl/enc_xyb.h
index 6a2e7c4123..741d447b92 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_xyb.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_xyb.h
@@ -27,8 +27,9 @@ void ToXYB(const ColorEncoding& c_current, float intensity_target,
const ImageF* black, ThreadPool* pool, Image3F* JXL_RESTRICT image,
const JxlCmsInterface& cms, Image3F* JXL_RESTRICT linear);
-void ToXYB(const ImageBundle& in, ThreadPool* pool, Image3F* JXL_RESTRICT xyb,
- const JxlCmsInterface& cms, Image3F* JXL_RESTRICT linear = nullptr);
+Status ToXYB(const ImageBundle& in, ThreadPool* pool, Image3F* JXL_RESTRICT xyb,
+ const JxlCmsInterface& cms,
+ Image3F* JXL_RESTRICT linear = nullptr);
void LinearRGBRowToXYB(float* JXL_RESTRICT row0, float* JXL_RESTRICT row1,
float* JXL_RESTRICT row2,
diff --git a/third_party/jpeg-xl/lib/jxl/encode.cc b/third_party/jpeg-xl/lib/jxl/encode.cc
index 76f2148d62..4dbbeba4e7 100644
--- a/third_party/jpeg-xl/lib/jxl/encode.cc
+++ b/third_party/jpeg-xl/lib/jxl/encode.cc
@@ -595,21 +595,21 @@ JxlEncoderStatus VerifyInputBitDepth(JxlBitDepth bit_depth,
return JxlErrorOrStatus::Success();
}
-static inline bool EncodeVarInt(uint64_t value, size_t output_size,
- size_t* output_pos, uint8_t* output) {
+inline bool EncodeVarInt(uint64_t value, size_t output_size, size_t* output_pos,
+ uint8_t* output) {
// While more than 7 bits of data are left,
// store 7 bits and set the next byte flag
while (value > 127) {
// TODO(eustas): should it be `>=` ?
if (*output_pos > output_size) return false;
// |128: Set the next byte flag
- output[(*output_pos)++] = ((uint8_t)(value & 127)) | 128;
+ output[(*output_pos)++] = (static_cast<uint8_t>(value & 127)) | 128;
// Remove the seven bits we just wrote
value >>= 7;
}
// TODO(eustas): should it be `>=` ?
if (*output_pos > output_size) return false;
- output[(*output_pos)++] = ((uint8_t)value) & 127;
+ output[(*output_pos)++] = static_cast<uint8_t>(value & 127);
return true;
}
@@ -854,7 +854,7 @@ jxl::Status JxlEncoderStruct::ProcessOneEnqueuedInput() {
timecode = 0;
}
- const bool last_frame = frames_closed && !num_queued_frames;
+ const bool last_frame = frames_closed && (num_queued_frames == 0);
uint32_t max_bits_per_sample = metadata.m.bit_depth.bits_per_sample;
for (const auto& info : metadata.m.extra_channel_info) {
@@ -901,7 +901,7 @@ jxl::Status JxlEncoderStruct::ProcessOneEnqueuedInput() {
return JXL_API_ERROR(
this, JXL_ENC_ERR_API_USAGE,
"Cannot use save_as_reference values >=3 (found: %d)",
- (int)save_as_reference);
+ static_cast<int>(save_as_reference));
}
jxl::FrameInfo frame_info;
@@ -909,8 +909,8 @@ jxl::Status JxlEncoderStruct::ProcessOneEnqueuedInput() {
frame_info.save_as_reference = save_as_reference;
frame_info.source =
input_frame->option_values.header.layer_info.blend_info.source;
- frame_info.clamp =
- input_frame->option_values.header.layer_info.blend_info.clamp;
+ frame_info.clamp = FROM_JXL_BOOL(
+ input_frame->option_values.header.layer_info.blend_info.clamp);
frame_info.alpha_channel =
input_frame->option_values.header.layer_info.blend_info.alpha;
frame_info.extra_channel_blending_info.resize(
@@ -989,7 +989,7 @@ jxl::Status JxlEncoderStruct::ProcessOneEnqueuedInput() {
#endif
jxl::WriteBoxHeader(jxl::MakeBoxType("jxlc"), frame_codestream_size,
/*unbounded=*/false, use_large_box,
- &box_header[0]);
+ box_header.data());
JXL_ASSERT(n == box_header_size);
} else {
#if JXL_ENABLE_ASSERT
@@ -997,7 +997,7 @@ jxl::Status JxlEncoderStruct::ProcessOneEnqueuedInput() {
#endif
jxl::WriteBoxHeader(
jxl::MakeBoxType("jxlp"), frame_codestream_size + 4,
- /*unbounded=*/false, use_large_box, &box_header[0]);
+ /*unbounded=*/false, use_large_box, box_header.data());
JXL_ASSERT(n == box_header_size - 4);
WriteJxlpBoxCounter(jxlp_counter++, last_frame,
&box_header[box_header_size - 4]);
@@ -1061,15 +1061,17 @@ JxlEncoderStatus JxlEncoderSetColorEncoding(JxlEncoder* enc,
}
if (enc->metadata.m.color_encoding.GetColorSpace() ==
jxl::ColorSpace::kGray) {
- if (enc->basic_info.num_color_channels != 1)
+ if (enc->basic_info.num_color_channels != 1) {
return JXL_API_ERROR(
enc, JXL_ENC_ERR_API_USAGE,
"Cannot use grayscale color encoding with num_color_channels != 1");
+ }
} else {
- if (enc->basic_info.num_color_channels != 3)
+ if (enc->basic_info.num_color_channels != 3) {
return JXL_API_ERROR(
enc, JXL_ENC_ERR_API_USAGE,
"Cannot use RGB color encoding with num_color_channels != 3");
+ }
}
enc->color_encoding_set = true;
if (!enc->intensity_target_set) {
@@ -1103,15 +1105,17 @@ JxlEncoderStatus JxlEncoderSetICCProfile(JxlEncoder* enc,
}
if (enc->metadata.m.color_encoding.GetColorSpace() ==
jxl::ColorSpace::kGray) {
- if (enc->basic_info.num_color_channels != 1)
+ if (enc->basic_info.num_color_channels != 1) {
return JXL_API_ERROR(
enc, JXL_ENC_ERR_BAD_INPUT,
"Cannot use grayscale ICC profile with num_color_channels != 1");
+ }
} else {
- if (enc->basic_info.num_color_channels != 3)
+ if (enc->basic_info.num_color_channels != 3) {
return JXL_API_ERROR(
enc, JXL_ENC_ERR_BAD_INPUT,
"Cannot use RGB ICC profile with num_color_channels != 3");
+ }
// TODO(jon): also check that a kBlack extra channel is provided in the CMYK
// case
}
@@ -1210,7 +1214,8 @@ JxlEncoderStatus JxlEncoderSetBasicInfo(JxlEncoder* enc,
enc->metadata.m.bit_depth.floating_point_sample =
(info->exponent_bits_per_sample != 0u);
enc->metadata.m.modular_16_bit_buffer_sufficient =
- (!info->uses_original_profile || info->bits_per_sample <= 12) &&
+ (!FROM_JXL_BOOL(info->uses_original_profile) ||
+ info->bits_per_sample <= 12) &&
info->alpha_bits <= 12;
if ((info->intrinsic_xsize > 0 || info->intrinsic_ysize > 0) &&
(info->intrinsic_xsize != info->xsize ||
@@ -1248,7 +1253,7 @@ JxlEncoderStatus JxlEncoderSetBasicInfo(JxlEncoder* enc,
}
}
- enc->metadata.m.xyb_encoded = !info->uses_original_profile;
+ enc->metadata.m.xyb_encoded = !FROM_JXL_BOOL(info->uses_original_profile);
if (info->orientation > 0 && info->orientation <= 8) {
enc->metadata.m.orientation = info->orientation;
} else {
@@ -1271,12 +1276,12 @@ JxlEncoderStatus JxlEncoderSetBasicInfo(JxlEncoder* enc,
}
enc->metadata.m.tone_mapping.min_nits = info->min_nits;
enc->metadata.m.tone_mapping.relative_to_max_display =
- info->relative_to_max_display;
+ FROM_JXL_BOOL(info->relative_to_max_display);
enc->metadata.m.tone_mapping.linear_below = info->linear_below;
enc->basic_info = *info;
enc->basic_info_set = true;
- enc->metadata.m.have_animation = info->have_animation;
+ enc->metadata.m.have_animation = FROM_JXL_BOOL(info->have_animation);
if (info->have_animation) {
if (info->animation.tps_denominator < 1) {
return JXL_API_ERROR(
@@ -1290,7 +1295,8 @@ JxlEncoderStatus JxlEncoderSetBasicInfo(JxlEncoder* enc,
enc->metadata.m.animation.tps_numerator = info->animation.tps_numerator;
enc->metadata.m.animation.tps_denominator = info->animation.tps_denominator;
enc->metadata.m.animation.num_loops = info->animation.num_loops;
- enc->metadata.m.animation.have_timecodes = info->animation.have_timecodes;
+ enc->metadata.m.animation.have_timecodes =
+ FROM_JXL_BOOL(info->animation.have_timecodes);
}
std::string level_message;
int required_level = VerifyLevelSettings(enc, &level_message);
@@ -1326,14 +1332,16 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetUpsamplingMode(JxlEncoder* enc,
const int64_t mode) {
// for convenience, allow calling this with factor 1 and just make it a no-op
if (factor == 1) return JxlErrorOrStatus::Success();
- if (factor != 2 && factor != 4 && factor != 8)
+ if (factor != 2 && factor != 4 && factor != 8) {
return JXL_API_ERROR(enc, JXL_ENC_ERR_API_USAGE,
"Invalid upsampling factor");
+ }
if (mode < -1)
return JXL_API_ERROR(enc, JXL_ENC_ERR_API_USAGE, "Invalid upsampling mode");
- if (mode > 1)
+ if (mode > 1) {
return JXL_API_ERROR(enc, JXL_ENC_ERR_NOT_SUPPORTED,
"Unsupported upsampling mode");
+ }
const size_t count = (factor == 2 ? 15 : (factor == 4 ? 55 : 210));
auto& td = enc->metadata.transform_data;
@@ -1436,7 +1444,7 @@ JxlEncoderFrameSettings* JxlEncoderFrameSettingsCreate(
}
opts->values.cparams.level = enc->codestream_level;
opts->values.cparams.ec_distance.resize(enc->metadata.m.num_extra_channels,
- -1);
+ 0);
JxlEncoderFrameSettings* ret = opts.get();
enc->encoder_options.emplace_back(std::move(opts));
@@ -1451,7 +1459,7 @@ JxlEncoderStatus JxlEncoderSetFrameLossless(
frame_settings->enc, JXL_ENC_ERR_API_USAGE,
"Set uses_original_profile=true for lossless encoding");
}
- frame_settings->values.lossless = lossless;
+ frame_settings->values.lossless = FROM_JXL_BOOL(lossless);
return JxlErrorOrStatus::Success();
}
@@ -1489,7 +1497,7 @@ JxlEncoderStatus JxlEncoderSetExtraChannelDistance(
// This can only happen if JxlEncoderFrameSettingsCreate() was called before
// JxlEncoderSetBasicInfo().
frame_settings->values.cparams.ec_distance.resize(
- frame_settings->enc->metadata.m.num_extra_channels, -1);
+ frame_settings->enc->metadata.m.num_extra_channels, 0);
}
frame_settings->values.cparams.ec_distance[index] = distance;
@@ -1537,14 +1545,14 @@ JxlEncoderStatus JxlEncoderFrameSettingsSetOption(
switch (option) {
case JXL_ENC_FRAME_SETTING_EFFORT:
if (frame_settings->enc->allow_expert_options) {
- if (value < 1 || value > 10) {
+ if (value < 1 || value > 11) {
return JXL_API_ERROR(frame_settings->enc, JXL_ENC_ERR_NOT_SUPPORTED,
- "Encode effort has to be in [1..10]");
+ "Encode effort has to be in [1..11]");
}
} else {
- if (value < 1 || value > 9) {
+ if (value < 1 || value > 10) {
return JXL_API_ERROR(frame_settings->enc, JXL_ENC_ERR_NOT_SUPPORTED,
- "Encode effort has to be in [1..9]");
+ "Encode effort has to be in [1..10]");
}
}
frame_settings->values.cparams.speed_tier =
@@ -1747,9 +1755,9 @@ JxlEncoderStatus JxlEncoderFrameSettingsSetOption(
frame_settings->values.cparams.jpeg_compress_boxes = value;
break;
case JXL_ENC_FRAME_SETTING_BUFFERING:
- if (value < 0 || value > 3) {
+ if (value < -1 || value > 3) {
return JXL_API_ERROR(frame_settings->enc, JXL_ENC_ERR_NOT_SUPPORTED,
- "Buffering has to be in [0..3]");
+ "Buffering has to be in [-1..3]");
}
frame_settings->values.cparams.buffering = value;
break;
@@ -1934,7 +1942,7 @@ JxlEncoderStatus JxlEncoderUseContainer(JxlEncoder* enc,
return JXL_API_ERROR(enc, JXL_ENC_ERR_API_USAGE,
"this setting can only be set at the beginning");
}
- enc->use_container = static_cast<bool>(use_container);
+ enc->use_container = FROM_JXL_BOOL(use_container);
return JxlErrorOrStatus::Success();
}
@@ -1944,7 +1952,7 @@ JxlEncoderStatus JxlEncoderStoreJPEGMetadata(JxlEncoder* enc,
return JXL_API_ERROR(enc, JXL_ENC_ERR_API_USAGE,
"this setting can only be set at the beginning");
}
- enc->store_jpeg_metadata = static_cast<bool>(store_jpeg_metadata);
+ enc->store_jpeg_metadata = FROM_JXL_BOOL(store_jpeg_metadata);
return JxlErrorOrStatus::Success();
}
@@ -2034,7 +2042,7 @@ JxlEncoderStatus JxlEncoderAddJPEGFrame(
JxlEncoderInitBasicInfo(&basic_info);
basic_info.xsize = io.Main().jpeg_data->width;
basic_info.ysize = io.Main().jpeg_data->height;
- basic_info.uses_original_profile = true;
+ basic_info.uses_original_profile = JXL_TRUE;
if (JxlEncoderSetBasicInfo(frame_settings->enc, &basic_info) !=
JXL_ENC_SUCCESS) {
return JXL_API_ERROR(frame_settings->enc, JXL_ENC_ERR_GENERIC,
@@ -2042,7 +2050,8 @@ JxlEncoderStatus JxlEncoderAddJPEGFrame(
}
}
- size_t xsize, ysize;
+ size_t xsize;
+ size_t ysize;
if (GetCurrentDimensions(frame_settings, xsize, ysize) != JXL_ENC_SUCCESS) {
return JXL_API_ERROR(frame_settings->enc, JXL_ENC_ERR_GENERIC,
"bad dimensions");
@@ -2074,21 +2083,23 @@ JxlEncoderStatus JxlEncoderAddJPEGFrame(
std::vector<uint8_t> exif(exif_size);
memcpy(exif.data() + 4, io.blobs.exif.data(), io.blobs.exif.size());
JxlEncoderUseBoxes(frame_settings->enc);
- JxlEncoderAddBox(frame_settings->enc, "Exif", exif.data(), exif_size,
- frame_settings->values.cparams.jpeg_compress_boxes);
+ JxlEncoderAddBox(
+ frame_settings->enc, "Exif", exif.data(), exif_size,
+ TO_JXL_BOOL(frame_settings->values.cparams.jpeg_compress_boxes));
}
if (!io.blobs.xmp.empty() && frame_settings->values.cparams.jpeg_keep_xmp) {
JxlEncoderUseBoxes(frame_settings->enc);
- JxlEncoderAddBox(frame_settings->enc, "xml ", io.blobs.xmp.data(),
- io.blobs.xmp.size(),
- frame_settings->values.cparams.jpeg_compress_boxes);
+ JxlEncoderAddBox(
+ frame_settings->enc, "xml ", io.blobs.xmp.data(), io.blobs.xmp.size(),
+ TO_JXL_BOOL(frame_settings->values.cparams.jpeg_compress_boxes));
}
if (!io.blobs.jumbf.empty() &&
frame_settings->values.cparams.jpeg_keep_jumbf) {
JxlEncoderUseBoxes(frame_settings->enc);
- JxlEncoderAddBox(frame_settings->enc, "jumb", io.blobs.jumbf.data(),
- io.blobs.jumbf.size(),
- frame_settings->values.cparams.jpeg_compress_boxes);
+ JxlEncoderAddBox(
+ frame_settings->enc, "jumb", io.blobs.jumbf.data(),
+ io.blobs.jumbf.size(),
+ TO_JXL_BOOL(frame_settings->values.cparams.jpeg_compress_boxes));
}
if (frame_settings->enc->store_jpeg_metadata) {
if (!frame_settings->values.cparams.jpeg_keep_exif ||
@@ -2259,10 +2270,12 @@ JxlEncoderStatus JxlEncoderAddImageFrameInternal(
pool, 0, count, jxl::ThreadPool::NoInit,
[&](size_t i, size_t) { fun(opaque, i); }, "Encode fast lossless"));
};
- auto frame_state = JxlFastLosslessPrepareFrame(
+ JXL_BOOL oneshot = TO_JXL_BOOL(!frame_data.StreamingInput());
+ auto* frame_state = JxlFastLosslessPrepareFrame(
frame_data.GetInputSource(), xsize, ysize, num_channels,
- frame_settings->enc->metadata.m.bit_depth.bits_per_sample, big_endian,
- /*effort=*/2, /*oneshot=*/!frame_data.StreamingInput());
+ frame_settings->enc->metadata.m.bit_depth.bits_per_sample,
+ TO_JXL_BOOL(big_endian),
+ /*effort=*/2, oneshot);
if (!streaming) {
JxlFastLosslessProcessFrame(frame_state, /*is_last=*/false,
frame_settings->enc->thread_pool.get(),
@@ -2325,7 +2338,8 @@ JxlEncoderStatus JxlEncoderAddImageFrameInternal(
JxlEncoderStatus JxlEncoderAddImageFrame(
const JxlEncoderFrameSettings* frame_settings,
const JxlPixelFormat* pixel_format, const void* buffer, size_t size) {
- size_t xsize, ysize;
+ size_t xsize;
+ size_t ysize;
if (GetCurrentDimensions(frame_settings, xsize, ysize) != JXL_ENC_SUCCESS) {
return JXL_API_ERROR(frame_settings->enc, JXL_ENC_ERR_GENERIC,
"bad dimensions");
@@ -2345,7 +2359,8 @@ JxlEncoderStatus JxlEncoderAddImageFrame(
JxlEncoderStatus JxlEncoderAddChunkedFrame(
const JxlEncoderFrameSettings* frame_settings, JXL_BOOL is_last_frame,
JxlChunkedFrameInputSource chunked_frame_input) {
- size_t xsize, ysize;
+ size_t xsize;
+ size_t ysize;
if (GetCurrentDimensions(frame_settings, xsize, ysize) != JXL_ENC_SUCCESS) {
return JXL_API_ERROR(frame_settings->enc, JXL_ENC_ERR_GENERIC,
"bad dimensions");
@@ -2417,7 +2432,7 @@ JxlEncoderStatus JxlEncoderAddBox(JxlEncoder* enc, const JxlBoxType type,
box->type = jxl::MakeBoxType(type);
box->contents.assign(contents, contents + size);
- box->compress_box = !!compress_box;
+ box->compress_box = FROM_JXL_BOOL(compress_box);
QueueBox(enc, box);
return JxlErrorOrStatus::Success();
}
@@ -2450,7 +2465,7 @@ JXL_EXPORT JxlEncoderStatus JxlEncoderSetExtraChannelBuffer(
return JXL_API_ERROR_NOSET("Invalid input bit depth");
}
const uint8_t* uint8_buffer = reinterpret_cast<const uint8_t*>(buffer);
- auto queued_frame = frame_settings->enc->input_queue.back().frame.get();
+ auto* queued_frame = frame_settings->enc->input_queue.back().frame.get();
if (!queued_frame->frame_data.SetFromBuffer(1 + index, uint8_buffer, size,
ec_format)) {
return JXL_API_ERROR(frame_settings->enc, JXL_ENC_ERR_API_USAGE,
@@ -2588,12 +2603,14 @@ JxlEncoderStatus JxlEncoderSetFrameBitDepth(
void JxlColorEncodingSetToSRGB(JxlColorEncoding* color_encoding,
JXL_BOOL is_gray) {
- *color_encoding = jxl::ColorEncoding::SRGB(is_gray).ToExternal();
+ *color_encoding =
+ jxl::ColorEncoding::SRGB(FROM_JXL_BOOL(is_gray)).ToExternal();
}
void JxlColorEncodingSetToLinearSRGB(JxlColorEncoding* color_encoding,
JXL_BOOL is_gray) {
- *color_encoding = jxl::ColorEncoding::LinearSRGB(is_gray).ToExternal();
+ *color_encoding =
+ jxl::ColorEncoding::LinearSRGB(FROM_JXL_BOOL(is_gray)).ToExternal();
}
void JxlEncoderAllowExpertOptions(JxlEncoder* enc) {
@@ -2611,9 +2628,7 @@ JXL_EXPORT JxlEncoderStats* JxlEncoderStatsCreate() {
return new JxlEncoderStats();
}
-JXL_EXPORT void JxlEncoderStatsDestroy(JxlEncoderStats* stats) {
- if (stats) delete stats;
-}
+JXL_EXPORT void JxlEncoderStatsDestroy(JxlEncoderStats* stats) { delete stats; }
JXL_EXPORT void JxlEncoderCollectStats(JxlEncoderFrameSettings* frame_settings,
JxlEncoderStats* stats) {
diff --git a/third_party/jpeg-xl/lib/jxl/encode_internal.h b/third_party/jpeg-xl/lib/jxl/encode_internal.h
index e89993f253..001df5fed5 100644
--- a/third_party/jpeg-xl/lib/jxl/encode_internal.h
+++ b/third_party/jpeg-xl/lib/jxl/encode_internal.h
@@ -580,12 +580,9 @@ jxl::Status AppendData(JxlEncoderOutputProcessorWrapper& output_processor,
// Internal use only struct, can only be initialized correctly by
// JxlEncoderCreate.
struct JxlEncoderStruct {
- JxlEncoderError error = JxlEncoderError::JXL_ENC_ERR_OK;
JxlMemoryManager memory_manager;
jxl::MemoryManagerUniquePtr<jxl::ThreadPool> thread_pool{
nullptr, jxl::MemoryManagerDeleteHelper(&memory_manager)};
- JxlCmsInterface cms;
- bool cms_set;
std::vector<jxl::MemoryManagerUniquePtr<JxlEncoderFrameSettings>>
encoder_options;
@@ -603,6 +600,9 @@ struct JxlEncoderStruct {
size_t codestream_bytes_written_end_of_frame;
jxl::JxlEncoderFrameIndexBox frame_index_box;
+ JxlCmsInterface cms;
+ bool cms_set;
+
// Force using the container even if not needed
bool use_container;
// User declared they will add metadata boxes
@@ -611,23 +611,26 @@ struct JxlEncoderStruct {
// TODO(lode): move level into jxl::CompressParams since some C++
// implementation decisions should be based on it: level 10 allows more
// features to be used.
- int32_t codestream_level;
bool store_jpeg_metadata;
+ int32_t codestream_level;
jxl::CodecMetadata metadata;
std::vector<uint8_t> jpeg_metadata;
- // Wrote any output at all, so wrote the data before the first user added
- // frame or box, such as signature, basic info, ICC profile or jpeg
- // reconstruction box.
- bool wrote_bytes;
jxl::CompressParams last_used_cparams;
JxlBasicInfo basic_info;
+ JxlEncoderError error = JxlEncoderError::JXL_ENC_ERR_OK;
+
// Encoder wrote a jxlp (partial codestream) box, so any next codestream
// parts must also be written in jxlp boxes, a single jxlc box cannot be
// used. The counter is used for the 4-byte jxlp box index header.
size_t jxlp_counter;
+ // Wrote any output at all, so wrote the data before the first user added
+ // frame or box, such as signature, basic info, ICC profile or jpeg
+ // reconstruction box.
+ bool wrote_bytes;
+
bool frames_closed;
bool boxes_closed;
bool basic_info_set;
diff --git a/third_party/jpeg-xl/lib/jxl/encode_test.cc b/third_party/jpeg-xl/lib/jxl/encode_test.cc
index 2c17fcab21..3e519cc45d 100644
--- a/third_party/jpeg-xl/lib/jxl/encode_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/encode_test.cc
@@ -33,6 +33,7 @@
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/c_callback_support.h"
+#include "lib/jxl/base/override.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/common.h" // JXL_HIGH_PRECISION
@@ -79,16 +80,16 @@ TEST(EncodeTest, AddFrameAfterCloseInputTest) {
jxl::test::JxlBasicInfoSetFromPixelFormat(&basic_info, &pixel_format);
basic_info.xsize = xsize;
basic_info.ysize = ysize;
- basic_info.uses_original_profile = false;
+ basic_info.uses_original_profile = 0;
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetCodestreamLevel(enc.get(), 10));
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc.get(), &basic_info));
JxlColorEncoding color_encoding;
- JxlColorEncodingSetToSRGB(&color_encoding,
- /*is_gray=*/pixel_format.num_channels < 3);
+ JXL_BOOL is_gray = TO_JXL_BOOL(pixel_format.num_channels < 3);
+ JxlColorEncodingSetToSRGB(&color_encoding, is_gray);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetColorEncoding(enc.get(), &color_encoding));
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_ERROR,
JxlEncoderAddImageFrame(frame_settings, &pixel_format,
pixels.data(), pixels.size()));
@@ -104,7 +105,7 @@ TEST(EncodeTest, AddJPEGAfterCloseTest) {
const std::vector<uint8_t> orig = jxl::test::ReadTestData(jpeg_path);
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_ERROR,
JxlEncoderAddJPEGFrame(frame_settings, orig.data(), orig.size()));
@@ -123,12 +124,12 @@ TEST(EncodeTest, AddFrameBeforeBasicInfoTest) {
jxl::test::SomeTestImageToCodecInOut(pixels, 4, xsize, ysize);
JxlColorEncoding color_encoding;
- JxlColorEncodingSetToSRGB(&color_encoding,
- /*is_gray=*/pixel_format.num_channels < 3);
+ JXL_BOOL is_gray = TO_JXL_BOOL(pixel_format.num_channels < 3);
+ JxlColorEncodingSetToSRGB(&color_encoding, is_gray);
EXPECT_EQ(JXL_ENC_ERROR,
JxlEncoderSetColorEncoding(enc.get(), &color_encoding));
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_ERROR,
JxlEncoderAddImageFrame(frame_settings, &pixel_format,
pixels.data(), pixels.size()));
@@ -188,17 +189,17 @@ void VerifyFrameEncoding(size_t xsize, size_t ysize, JxlEncoder* enc,
basic_info.xsize = xsize;
basic_info.ysize = ysize;
if (frame_settings->values.lossless || lossy_use_original_profile) {
- basic_info.uses_original_profile = true;
+ basic_info.uses_original_profile = JXL_TRUE;
} else {
- basic_info.uses_original_profile = false;
+ basic_info.uses_original_profile = JXL_FALSE;
}
// 16-bit alpha means this requires level 10
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetCodestreamLevel(enc, 10));
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc, &basic_info));
JxlColorEncoding color_encoding;
- JxlColorEncodingSetToSRGB(&color_encoding, true);
+ JxlColorEncodingSetToSRGB(&color_encoding, JXL_TRUE);
EXPECT_EQ(JXL_ENC_ERROR, JxlEncoderSetColorEncoding(enc, &color_encoding));
- JxlColorEncodingSetToSRGB(&color_encoding, false);
+ JxlColorEncodingSetToSRGB(&color_encoding, JXL_FALSE);
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetColorEncoding(enc, &color_encoding));
pixel_format.num_channels = 1;
EXPECT_EQ(JXL_ENC_ERROR,
@@ -230,18 +231,20 @@ void VerifyFrameEncoding(size_t xsize, size_t ysize, JxlEncoder* enc,
EXPECT_TRUE(jxl::test::DecodeFile(
{}, jxl::Bytes(compressed.data(), compressed.size()), &decoded_io));
- EXPECT_LE(
- ComputeDistance2(input_io.Main(), decoded_io.Main(), *JxlGetDefaultCms()),
+ static constexpr double kMaxButteraugli =
#if JXL_HIGH_PRECISION
- 1.84);
+ 1.84;
#else
- 8.7);
+ 8.7;
#endif
+ EXPECT_LE(
+ ComputeDistance2(input_io.Main(), decoded_io.Main(), *JxlGetDefaultCms()),
+ kMaxButteraugli);
}
void VerifyFrameEncoding(JxlEncoder* enc,
const JxlEncoderFrameSettings* frame_settings) {
- VerifyFrameEncoding(63, 129, enc, frame_settings, 2700,
+ VerifyFrameEncoding(63, 129, enc, frame_settings, 27000,
/*lossy_use_original_profile=*/false);
}
@@ -256,7 +259,7 @@ TEST(EncodeTest, EncoderResetTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
VerifyFrameEncoding(50, 200, enc.get(),
- JxlEncoderFrameSettingsCreate(enc.get(), nullptr), 4300,
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr), 4550,
false);
// Encoder should become reusable for a new image from scratch after using
// reset.
@@ -293,7 +296,7 @@ TEST(EncodeTest, CmsTest) {
JxlEncoderSetCms(enc.get(), cms);
JxlEncoderFrameSettings* frame_settings =
JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
- JxlEncoderSetFrameLossless(frame_settings, false);
+ JxlEncoderSetFrameLossless(frame_settings, JXL_FALSE);
ASSERT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(frame_settings,
JXL_ENC_FRAME_SETTING_EFFORT, 8));
@@ -306,7 +309,7 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(
frame_settings, JXL_ENC_FRAME_SETTING_EFFORT, 5));
@@ -318,7 +321,7 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
const size_t nb_options = 23;
const JxlEncoderFrameSettingId options[nb_options] = {
JXL_ENC_FRAME_SETTING_EFFORT,
@@ -346,7 +349,7 @@ TEST(EncodeTest, frame_settingsTest) {
JXL_ENC_FRAME_SETTING_JPEG_KEEP_JUMBF};
const int too_low[nb_options] = {0, -2, -2, 3, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2,
- -2, -1, -2, -1, -2, -2, -2};
+ -2, -1, -2, -2, -2, -2, -2};
const int too_high[nb_options] = {11, 12, 5, 16, 6, 2, 4, -3,
-3, 3, 70914, 3, 42, 4, 16, 12,
2, 2, 2, 4, 2, 2, 2};
@@ -367,14 +370,14 @@ TEST(EncodeTest, frame_settingsTest) {
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderFrameSettingsSetOption(
frame_settings, options[i], in_range[i]));
}
- // Effort 10 should only work when expert options are allowed
+ // Effort 11 should only work when expert options are allowed
EXPECT_EQ(JXL_ENC_ERROR,
JxlEncoderFrameSettingsSetOption(
- frame_settings, JXL_ENC_FRAME_SETTING_EFFORT, 10));
+ frame_settings, JXL_ENC_FRAME_SETTING_EFFORT, 11));
JxlEncoderAllowExpertOptions(enc.get());
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(
- frame_settings, JXL_ENC_FRAME_SETTING_EFFORT, 10));
+ frame_settings, JXL_ENC_FRAME_SETTING_EFFORT, 11));
// Non-existing option
EXPECT_EQ(JXL_ENC_ERROR,
@@ -438,14 +441,14 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderFrameSettingsSetOption(
frame_settings, JXL_ENC_FRAME_SETTING_PHOTON_NOISE, 50.0f));
- VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 2500, false);
+ VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3700, false);
}
{
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetFrameLossless(frame_settings, JXL_TRUE));
VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3000, false);
@@ -456,16 +459,16 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetFrameDistance(frame_settings, 0.5));
- VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3030, false);
+ VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3130, false);
EXPECT_EQ(0.5, enc->last_used_cparams.butteraugli_distance);
}
{
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
// Disallowed negative distance
EXPECT_EQ(JXL_ENC_ERROR, JxlEncoderSetFrameDistance(frame_settings, -1));
}
@@ -474,7 +477,7 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(
frame_settings, JXL_ENC_FRAME_SETTING_DECODING_SPEED, 2));
@@ -486,7 +489,7 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_ERROR,
JxlEncoderFrameSettingsSetOption(
frame_settings, JXL_ENC_FRAME_SETTING_GROUP_ORDER, 100));
@@ -506,7 +509,7 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(
frame_settings, JXL_ENC_FRAME_SETTING_RESPONSIVE, 0));
@@ -519,7 +522,7 @@ TEST(EncodeTest, frame_settingsTest) {
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(
frame_settings, JXL_ENC_FRAME_SETTING_PROGRESSIVE_DC, 2));
- VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 2830,
+ VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3430,
/*lossy_use_original_profile=*/false);
EXPECT_EQ(false, enc->last_used_cparams.responsive);
EXPECT_EQ(jxl::Override::kOn, enc->last_used_cparams.progressive_mode);
@@ -530,7 +533,7 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(
JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetFloatOption(
@@ -543,7 +546,7 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetFloatOption(
frame_settings,
@@ -571,7 +574,7 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(
JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(
@@ -603,7 +606,7 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(
frame_settings, JXL_ENC_FRAME_SETTING_JPEG_RECON_CFL, 0));
@@ -615,7 +618,7 @@ TEST(EncodeTest, frame_settingsTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(
frame_settings, JXL_ENC_FRAME_SETTING_JPEG_RECON_CFL, 1));
@@ -629,14 +632,14 @@ TEST(EncodeTest, LossyEncoderUseOriginalProfileTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
ASSERT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 7897, true);
}
{
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
ASSERT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(
frame_settings, JXL_ENC_FRAME_SETTING_PROGRESSIVE_DC, 2));
@@ -646,7 +649,7 @@ TEST(EncodeTest, LossyEncoderUseOriginalProfileTest) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
ASSERT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
ASSERT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(
frame_settings, JXL_ENC_FRAME_SETTING_EFFORT, 8));
@@ -787,7 +790,7 @@ TEST(EncodeTest, SingleFrameBoundedJXLCTest) {
EXPECT_NE(nullptr, enc.get());
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderUseContainer(enc.get(), true));
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
size_t xsize = 71;
size_t ysize = 23;
@@ -798,12 +801,12 @@ TEST(EncodeTest, SingleFrameBoundedJXLCTest) {
jxl::test::JxlBasicInfoSetFromPixelFormat(&basic_info, &pixel_format);
basic_info.xsize = xsize;
basic_info.ysize = ysize;
- basic_info.uses_original_profile = false;
+ basic_info.uses_original_profile = JXL_FALSE;
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetCodestreamLevel(enc.get(), 10));
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc.get(), &basic_info));
JxlColorEncoding color_encoding;
JxlColorEncodingSetToSRGB(&color_encoding,
- /*is_gray=*/false);
+ /*is_gray=*/JXL_FALSE);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetColorEncoding(enc.get(), &color_encoding));
EXPECT_EQ(JXL_ENC_SUCCESS,
@@ -866,17 +869,17 @@ TEST(EncodeTest, CodestreamLevelTest) {
jxl::test::JxlBasicInfoSetFromPixelFormat(&basic_info, &pixel_format);
basic_info.xsize = xsize;
basic_info.ysize = ysize;
- basic_info.uses_original_profile = false;
+ basic_info.uses_original_profile = 0;
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetCodestreamLevel(enc.get(), 10));
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc.get(), &basic_info));
JxlColorEncoding color_encoding;
- JxlColorEncodingSetToSRGB(&color_encoding,
- /*is_gray=*/pixel_format.num_channels < 3);
+ JXL_BOOL is_gray = TO_JXL_BOOL(pixel_format.num_channels < 3);
+ JxlColorEncodingSetToSRGB(&color_encoding, is_gray);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetColorEncoding(enc.get(), &color_encoding));
EXPECT_EQ(JXL_ENC_SUCCESS,
@@ -915,7 +918,7 @@ TEST(EncodeTest, CodestreamLevelVerificationTest) {
jxl::test::JxlBasicInfoSetFromPixelFormat(&basic_info, &pixel_format);
basic_info.xsize = 64;
basic_info.ysize = 64;
- basic_info.uses_original_profile = false;
+ basic_info.uses_original_profile = JXL_FALSE;
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc.get(), &basic_info));
@@ -943,7 +946,7 @@ TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionTest)) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderStoreJPEGMetadata(enc.get(), JXL_TRUE));
EXPECT_EQ(JXL_ENC_SUCCESS,
@@ -983,7 +986,7 @@ TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(ProgressiveJPEGReconstructionTest)) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
frame_settings->values.cparams.progressive_mode = jxl::Override::kOn;
@@ -1043,7 +1046,7 @@ TEST(EncodeTest, BasicInfoTest) {
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
size_t xsize = 1;
size_t ysize = 1;
JxlPixelFormat pixel_format = {4, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
@@ -1052,8 +1055,8 @@ TEST(EncodeTest, BasicInfoTest) {
jxl::test::JxlBasicInfoSetFromPixelFormat(&basic_info, &pixel_format);
basic_info.xsize = xsize;
basic_info.ysize = ysize;
- basic_info.uses_original_profile = false;
- basic_info.have_animation = true;
+ basic_info.uses_original_profile = 0;
+ basic_info.have_animation = 1;
basic_info.intensity_target = 123.4;
basic_info.min_nits = 5.0;
basic_info.linear_below = 12.7;
@@ -1067,7 +1070,7 @@ TEST(EncodeTest, BasicInfoTest) {
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetCodestreamLevel(enc.get(), 10));
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc.get(), &basic_info));
JxlColorEncoding color_encoding;
- JxlColorEncodingSetToSRGB(&color_encoding, /*is_gray=*/false);
+ JxlColorEncodingSetToSRGB(&color_encoding, /*is_gray=*/JXL_FALSE);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetColorEncoding(enc.get(), &color_encoding));
@@ -1155,7 +1158,7 @@ TEST(EncodeTest, AnimationHeaderTest) {
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
size_t xsize = 1;
size_t ysize = 1;
JxlPixelFormat pixel_format = {4, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
@@ -1164,14 +1167,14 @@ TEST(EncodeTest, AnimationHeaderTest) {
jxl::test::JxlBasicInfoSetFromPixelFormat(&basic_info, &pixel_format);
basic_info.xsize = xsize;
basic_info.ysize = ysize;
- basic_info.have_animation = true;
+ basic_info.have_animation = JXL_TRUE;
basic_info.animation.tps_numerator = 1000;
basic_info.animation.tps_denominator = 1;
basic_info.animation.have_timecodes = JXL_TRUE;
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetCodestreamLevel(enc.get(), 10));
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc.get(), &basic_info));
JxlColorEncoding color_encoding;
- JxlColorEncodingSetToSRGB(&color_encoding, /*is_gray=*/false);
+ JxlColorEncodingSetToSRGB(&color_encoding, /*is_gray=*/JXL_FALSE);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetColorEncoding(enc.get(), &color_encoding));
@@ -1258,7 +1261,7 @@ TEST(EncodeTest, CroppedFrameTest) {
EXPECT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
size_t xsize = 300;
size_t ysize = 300;
JxlPixelFormat pixel_format = {4, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
@@ -1273,7 +1276,7 @@ TEST(EncodeTest, CroppedFrameTest) {
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetCodestreamLevel(enc.get(), 10));
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc.get(), &basic_info));
JxlColorEncoding color_encoding;
- JxlColorEncodingSetToSRGB(&color_encoding, /*is_gray=*/false);
+ JxlColorEncodingSetToSRGB(&color_encoding, /*is_gray=*/JXL_FALSE);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetColorEncoding(enc.get(), &color_encoding));
@@ -1358,7 +1361,7 @@ TEST_P(EncodeBoxTest, JXL_BOXES_TEST(BoxTest)) {
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderUseBoxes(enc.get()));
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
size_t xsize = 50;
size_t ysize = 17;
JxlPixelFormat pixel_format = {4, JXL_TYPE_UINT16, JXL_BIG_ENDIAN, 0};
@@ -1367,12 +1370,12 @@ TEST_P(EncodeBoxTest, JXL_BOXES_TEST(BoxTest)) {
jxl::test::JxlBasicInfoSetFromPixelFormat(&basic_info, &pixel_format);
basic_info.xsize = xsize;
basic_info.ysize = ysize;
- basic_info.uses_original_profile = false;
+ basic_info.uses_original_profile = JXL_FALSE;
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetCodestreamLevel(enc.get(), 10));
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc.get(), &basic_info));
JxlColorEncoding color_encoding;
JxlColorEncodingSetToSRGB(&color_encoding,
- /*is_gray=*/false);
+ /*is_gray=*/JXL_FALSE);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetColorEncoding(enc.get(), &color_encoding));
@@ -1386,7 +1389,8 @@ TEST_P(EncodeBoxTest, JXL_BOXES_TEST(BoxTest)) {
const uint8_t* exif_data = reinterpret_cast<const uint8_t*>(exif_test_string);
// Skip the 4 zeroes for strlen
const size_t exif_size = 4 + strlen(exif_test_string + 4);
- JxlEncoderAddBox(enc.get(), "Exif", exif_data, exif_size, compress_box);
+ JxlEncoderAddBox(enc.get(), "Exif", exif_data, exif_size,
+ TO_JXL_BOOL(compress_box));
// Write to output
ProcessEncoder(enc.get(), compressed, next_out, avail_out);
@@ -1405,7 +1409,8 @@ TEST_P(EncodeBoxTest, JXL_BOXES_TEST(BoxTest)) {
constexpr const char* xml_test_string = "<some random xml data>";
const uint8_t* xml_data = reinterpret_cast<const uint8_t*>(xml_test_string);
size_t xml_size = strlen(xml_test_string);
- JxlEncoderAddBox(enc.get(), "XML ", xml_data, xml_size, compress_box);
+ JxlEncoderAddBox(enc.get(), "XML ", xml_data, xml_size,
+ TO_JXL_BOOL(compress_box));
// Indicate this is the last box
JxlEncoderCloseBoxes(enc.get());
@@ -1495,7 +1500,7 @@ TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGFrameTest)) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
JxlEncoderFrameSettingsSetOption(frame_settings,
JXL_ENC_FRAME_SETTING_EFFORT, 1);
if (!skip_basic_info) {
@@ -1503,13 +1508,13 @@ TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGFrameTest)) {
JxlEncoderInitBasicInfo(&basic_info);
basic_info.xsize = orig_io.xsize();
basic_info.ysize = orig_io.ysize();
- basic_info.uses_original_profile = true;
+ basic_info.uses_original_profile = JXL_TRUE;
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetBasicInfo(enc.get(), &basic_info));
}
if (!skip_color_encoding) {
JxlColorEncoding color_encoding;
- JxlColorEncodingSetToSRGB(&color_encoding, /*is_gray=*/false);
+ JxlColorEncodingSetToSRGB(&color_encoding, /*is_gray=*/JXL_FALSE);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetColorEncoding(enc.get(), &color_encoding));
}
@@ -1696,14 +1701,16 @@ class JxlChunkedFrameInputSourceAdapter {
struct StreamingTestParam {
size_t bitmask;
- bool use_container() const { return bitmask & 0x1; }
- bool return_large_buffers() const { return bitmask & 0x2; }
- bool multiple_frames() const { return bitmask & 0x4; }
- bool fast_lossless() const { return bitmask & 0x8; }
- bool can_seek() const { return bitmask & 0x10; }
- bool with_extra_channels() const { return bitmask & 0x20; }
- bool color_includes_alpha() const { return bitmask & 0x40; }
- bool onegroup() const { return bitmask & 0x80; }
+ bool use_container() const { return static_cast<bool>(bitmask & 0x1); }
+ bool return_large_buffers() const { return static_cast<bool>(bitmask & 0x2); }
+ bool multiple_frames() const { return static_cast<bool>(bitmask & 0x4); }
+ bool fast_lossless() const { return static_cast<bool>(bitmask & 0x8); }
+ bool can_seek() const { return static_cast<bool>(bitmask & 0x10); }
+ bool with_extra_channels() const { return static_cast<bool>(bitmask & 0x20); }
+ bool color_includes_alpha() const {
+ return static_cast<bool>(bitmask & 0x40);
+ }
+ bool onegroup() const { return static_cast<bool>(bitmask & 0x80); }
bool is_lossless() const { return fast_lossless(); }
@@ -1773,8 +1780,9 @@ class EncoderStreamingTest : public testing::TestWithParam<StreamingTestParam> {
bool include_alpha, bool is_lossless) {
basic_info.xsize = xsize;
basic_info.ysize = ysize;
- basic_info.num_extra_channels = number_extra_channels + include_alpha;
- basic_info.uses_original_profile = is_lossless;
+ basic_info.num_extra_channels =
+ number_extra_channels + (include_alpha ? 1 : 0);
+ basic_info.uses_original_profile = TO_JXL_BOOL(is_lossless);
}
static void SetupEncoder(JxlEncoderFrameSettings* frame_settings,
@@ -1791,7 +1799,7 @@ class EncoderStreamingTest : public testing::TestWithParam<StreamingTestParam> {
frame_settings, JXL_ENC_FRAME_SETTING_EFFORT, 1));
}
JxlColorEncoding color_encoding;
- JxlColorEncodingSetToSRGB(&color_encoding, /*is_gray=*/false);
+ JxlColorEncodingSetToSRGB(&color_encoding, /*is_gray=*/JXL_FALSE);
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetColorEncoding(enc, &color_encoding));
EXPECT_EQ(JXL_ENC_SUCCESS,
@@ -1825,7 +1833,7 @@ class EncoderStreamingTest : public testing::TestWithParam<StreamingTestParam> {
// Copy pixel data here because it is only guaranteed to be available
// during the call to JxlEncoderAddImageFrame().
std::vector<uint8_t> pixels(frame.pixels_size);
- memcpy(&pixels[0], frame.pixels(), pixels.size());
+ memcpy(pixels.data(), frame.pixels(), pixels.size());
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderAddImageFrame(frame_settings, &frame.format,
pixels.data(), pixels.size()));
@@ -1834,7 +1842,7 @@ class EncoderStreamingTest : public testing::TestWithParam<StreamingTestParam> {
// Copy pixel data here because it is only guaranteed to be available
// during the call to JxlEncoderSetExtraChannelBuffer().
std::vector<uint8_t> ec_pixels(ec_frame.pixels_size);
- memcpy(&ec_pixels[0], ec_frame.pixels(), ec_pixels.size());
+ memcpy(ec_pixels.data(), ec_frame.pixels(), ec_pixels.size());
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetExtraChannelBuffer(
frame_settings, &ec_frame.format,
ec_pixels.data(), ec_pixels.size(), i));
@@ -1885,7 +1893,7 @@ TEST_P(EncoderStreamingTest, OutputCallback) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
ASSERT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
SetupEncoder(frame_settings, p, basic_info, number_extra_channels, false);
SetupInputNonStreaming(frame_settings, p, number_extra_channels, frame,
ec_frame);
@@ -1900,7 +1908,7 @@ TEST_P(EncoderStreamingTest, OutputCallback) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
ASSERT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
SetupEncoder(frame_settings, p, basic_info, number_extra_channels, true);
SetupInputNonStreaming(frame_settings, p, number_extra_channels, frame,
ec_frame);
@@ -1938,7 +1946,7 @@ TEST_P(EncoderStreamingTest, ChunkedFrame) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
ASSERT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
SetupEncoder(frame_settings, p, basic_info, number_extra_channels, false);
SetupInputNonStreaming(frame_settings, p, number_extra_channels, frame,
ec_frame);
@@ -1952,7 +1960,7 @@ TEST_P(EncoderStreamingTest, ChunkedFrame) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
ASSERT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
SetupEncoder(frame_settings, p, basic_info, number_extra_channels, true);
SetupInputStreaming(frame_settings, p, number_extra_channels, frame,
ec_frame);
@@ -1988,7 +1996,7 @@ TEST_P(EncoderStreamingTest, ChunkedAndOutputCallback) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
ASSERT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
SetupEncoder(frame_settings, p, basic_info, number_extra_channels, false);
SetupInputNonStreaming(frame_settings, p, number_extra_channels, frame,
ec_frame);
@@ -2003,7 +2011,7 @@ TEST_P(EncoderStreamingTest, ChunkedAndOutputCallback) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
ASSERT_NE(nullptr, enc.get());
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
SetupEncoder(frame_settings, p, basic_info, number_extra_channels, true);
JxlStreamingAdapter streaming_adapter =
JxlStreamingAdapter(enc.get(), p.return_large_buffers(), p.can_seek());
@@ -2049,7 +2057,7 @@ TEST(EncoderTest, CMYK) {
JxlEncoderStruct* enc = enc_ptr.get();
ASSERT_NE(nullptr, enc);
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc, NULL);
+ JxlEncoderFrameSettingsCreate(enc, nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc, &basic_info));
JxlExtraChannelInfo channel_info;
diff --git a/third_party/jpeg-xl/lib/jxl/entropy_coder.cc b/third_party/jpeg-xl/lib/jxl/entropy_coder.cc
index a90ed0257a..5dc101b36f 100644
--- a/third_party/jpeg-xl/lib/jxl/entropy_coder.cc
+++ b/third_party/jpeg-xl/lib/jxl/entropy_coder.cc
@@ -33,7 +33,7 @@ Status DecodeBlockCtxMap(BitReader* br, BlockCtxMap* block_ctx_map) {
auto& dct = block_ctx_map->dc_thresholds;
auto& qft = block_ctx_map->qf_thresholds;
auto& ctx_map = block_ctx_map->ctx_map;
- bool is_default = br->ReadFixedBits<1>();
+ bool is_default = static_cast<bool>(br->ReadFixedBits<1>());
if (is_default) {
*block_ctx_map = BlockCtxMap();
return true;
diff --git a/third_party/jpeg-xl/lib/jxl/fast_dct-inl.h b/third_party/jpeg-xl/lib/jxl/fast_dct-inl.h
index de1f845901..e315200b0c 100644
--- a/third_party/jpeg-xl/lib/jxl/fast_dct-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/fast_dct-inl.h
@@ -191,7 +191,7 @@ HWY_NOINLINE void TestFastIDCT() {
}
}
printf("max error: %f mantissa bits: %d\n", max_error,
- 14 - (int)integer_bits);
+ 14 - static_cast<int>(integer_bits));
#endif
}
diff --git a/third_party/jpeg-xl/lib/jxl/fast_dct.cc b/third_party/jpeg-xl/lib/jxl/fast_dct.cc
deleted file mode 100644
index d796018fd0..0000000000
--- a/third_party/jpeg-xl/lib/jxl/fast_dct.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) the JPEG XL Project Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#undef HWY_TARGET_INCLUDE
-#define HWY_TARGET_INCLUDE "lib/jxl/fast_dct.cc"
-#include <hwy/foreach_target.h>
-#include <hwy/highway.h>
-
-#include "lib/jxl/base/random.h"
-#include "lib/jxl/dct-inl.h"
-#include "lib/jxl/fast_dct-inl.h"
-HWY_BEFORE_NAMESPACE();
-namespace jxl {
-namespace HWY_NAMESPACE {
-namespace {
-void BenchmarkFloatIDCT32x32() { TestFloatIDCT<32, 32>(); }
-void BenchmarkFastIDCT32x32() { TestFastIDCT<32, 32>(); }
-} // namespace
-// NOLINTNEXTLINE(google-readability-namespace-comments)
-} // namespace HWY_NAMESPACE
-} // namespace jxl
-HWY_AFTER_NAMESPACE();
-
-#if HWY_ONCE
-namespace jxl {
-HWY_EXPORT(BenchmarkFloatIDCT32x32);
-HWY_EXPORT(BenchmarkFastIDCT32x32);
-void BenchmarkFloatIDCT32x32() {
- HWY_DYNAMIC_DISPATCH(BenchmarkFloatIDCT32x32)();
-}
-void BenchmarkFastIDCT32x32() {
- HWY_DYNAMIC_DISPATCH(BenchmarkFastIDCT32x32)();
-}
-} // namespace jxl
-#endif
diff --git a/third_party/jpeg-xl/lib/jxl/fast_dct.h b/third_party/jpeg-xl/lib/jxl/fast_dct.h
deleted file mode 100644
index 641933d8a0..0000000000
--- a/third_party/jpeg-xl/lib/jxl/fast_dct.h
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) the JPEG XL Project Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-namespace jxl {
-void BenchmarkFloatIDCT32x32();
-void BenchmarkFastIDCT32x32();
-} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/fast_dct_test.cc b/third_party/jpeg-xl/lib/jxl/fast_dct_test.cc
index a55b67afb2..417e202988 100644
--- a/third_party/jpeg-xl/lib/jxl/fast_dct_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/fast_dct_test.cc
@@ -12,7 +12,6 @@
#include "lib/jxl/base/random.h"
#include "lib/jxl/dct-inl.h"
#include "lib/jxl/fast_dct-inl.h"
-#include "lib/jxl/fast_dct.h"
#include "lib/jxl/testing.h"
#include "lib/jxl/transpose-inl.h"
@@ -21,9 +20,13 @@
#include <hwy/tests/hwy_gtest.h>
HWY_BEFORE_NAMESPACE();
namespace jxl {
+
namespace HWY_NAMESPACE {
namespace {
+void BenchmarkFloatIDCT32x32() { TestFloatIDCT<32, 32>(); }
+void BenchmarkFastIDCT32x32() { TestFastIDCT<32, 32>(); }
+
template <size_t N, size_t M>
HWY_NOINLINE void TestFastTranspose() {
#if HWY_TARGET == HWY_NEON
@@ -370,8 +373,8 @@ HWY_EXPORT_AND_TEST_P(FastDCTTargetTest, TestFloatIDCT256x256);
HWY_EXPORT_AND_TEST_P(FastDCTTargetTest, TestFastIDCT256x256);
*/
-TEST(FastDCTTest, TestWrapperFloat) { BenchmarkFloatIDCT32x32(); }
-TEST(FastDCTTest, TestWrapperFast) { BenchmarkFastIDCT32x32(); }
+HWY_EXPORT_AND_TEST_P(FastDCTTargetTest, BenchmarkFloatIDCT32x32);
+HWY_EXPORT_AND_TEST_P(FastDCTTargetTest, BenchmarkFastIDCT32x32);
} // namespace jxl
#endif // HWY_ONCE
diff --git a/third_party/jpeg-xl/lib/jxl/fast_math_test.cc b/third_party/jpeg-xl/lib/jxl/fast_math_test.cc
index 868e1b72f4..b242dbe575 100644
--- a/third_party/jpeg-xl/lib/jxl/fast_math_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/fast_math_test.cc
@@ -167,7 +167,8 @@ HWY_NOINLINE void TestFastXYB() {
for (int cr = 0; cr < n; cr += kChunk) {
for (int cg = 0; cg < n; cg += kChunk) {
for (int cb = 0; cb < n; cb += kChunk) {
- Image3F chunk(kChunk * kChunk, kChunk);
+ JXL_ASSIGN_OR_DIE(Image3F chunk,
+ Image3F::Create(kChunk * kChunk, kChunk));
for (int ir = 0; ir < kChunk; ir++) {
for (int ig = 0; ig < kChunk; ig++) {
for (int ib = 0; ib < kChunk; ib++) {
@@ -181,9 +182,10 @@ HWY_NOINLINE void TestFastXYB() {
}
}
ib.SetFromImage(std::move(chunk), ColorEncoding::SRGB());
- Image3F xyb(kChunk * kChunk, kChunk);
+ JXL_ASSIGN_OR_DIE(Image3F xyb,
+ Image3F::Create(kChunk * kChunk, kChunk));
std::vector<uint8_t> roundtrip(kChunk * kChunk * kChunk * 3);
- ToXYB(ib, nullptr, &xyb, *JxlGetDefaultCms());
+ JXL_CHECK(ToXYB(ib, nullptr, &xyb, *JxlGetDefaultCms()));
for (int y = 0; y < kChunk; y++) {
const float* xyba[4] = {xyb.PlaneRow(0, y), xyb.PlaneRow(1, y),
xyb.PlaneRow(2, y), nullptr};
diff --git a/third_party/jpeg-xl/lib/jxl/fields.cc b/third_party/jpeg-xl/lib/jxl/fields.cc
index 746d7e4d30..6bb5eae25d 100644
--- a/third_party/jpeg-xl/lib/jxl/fields.cc
+++ b/third_party/jpeg-xl/lib/jxl/fields.cc
@@ -109,7 +109,7 @@ struct SetDefaultVisitor : public VisitorBase {
class AllDefaultVisitor : public VisitorBase {
public:
- explicit AllDefaultVisitor() : VisitorBase() {}
+ explicit AllDefaultVisitor() = default;
Status Bits(const size_t bits, const uint32_t default_value,
uint32_t* JXL_RESTRICT value) override {
@@ -148,7 +148,7 @@ class AllDefaultVisitor : public VisitorBase {
class ReadVisitor : public VisitorBase {
public:
- explicit ReadVisitor(BitReader* reader) : VisitorBase(), reader_(reader) {}
+ explicit ReadVisitor(BitReader* reader) : reader_(reader) {}
Status Bits(const size_t bits, const uint32_t /*default_value*/,
uint32_t* JXL_RESTRICT value) override {
@@ -267,7 +267,8 @@ class ReadVisitor : public VisitorBase {
uint64_t total_extension_bits_ = 0;
size_t pos_after_ext_size_ = 0; // 0 iff extensions == 0.
- friend Status jxl::CheckHasEnoughBits(Visitor*, size_t);
+ friend Status jxl::CheckHasEnoughBits(Visitor* /* visitor */,
+ size_t /* bits */);
};
class MaxBitsVisitor : public VisitorBase {
@@ -321,7 +322,7 @@ class MaxBitsVisitor : public VisitorBase {
class CanEncodeVisitor : public VisitorBase {
public:
- explicit CanEncodeVisitor() : VisitorBase() {}
+ explicit CanEncodeVisitor() = default;
Status Bits(const size_t bits, const uint32_t /*default_value*/,
uint32_t* JXL_RESTRICT value) override {
diff --git a/third_party/jpeg-xl/lib/jxl/fields.h b/third_party/jpeg-xl/lib/jxl/fields.h
index d05fe4517e..a8d8d8671a 100644
--- a/third_party/jpeg-xl/lib/jxl/fields.h
+++ b/third_party/jpeg-xl/lib/jxl/fields.h
@@ -298,7 +298,7 @@ class ExtensionStates {
class VisitorBase : public Visitor {
public:
- explicit VisitorBase() {}
+ explicit VisitorBase() = default;
~VisitorBase() override { JXL_ASSERT(depth_ == 0); }
// This is the only call site of Fields::VisitFields.
diff --git a/third_party/jpeg-xl/lib/jxl/fields_test.cc b/third_party/jpeg-xl/lib/jxl/fields_test.cc
index b178a6bd6a..0584458d07 100644
--- a/third_party/jpeg-xl/lib/jxl/fields_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/fields_test.cc
@@ -200,7 +200,8 @@ TEST(FieldsTest, TestRoundtripSize) {
SizeHeader size;
ASSERT_TRUE(size.Set(123 + 77 * i, 7 + i));
- size_t extension_bits = 999, total_bits = 999; // Initialize as garbage.
+ size_t extension_bits = 999;
+ size_t total_bits = 999; // Initialize as garbage.
ASSERT_TRUE(Bundle::CanEncode(size, &extension_bits, &total_bits));
EXPECT_EQ(0u, extension_bits);
@@ -230,7 +231,8 @@ TEST(FieldsTest, TestCropRect) {
f.frame_origin.y0 = i;
f.frame_size.xsize = 1000 + i;
f.frame_size.ysize = 1000 + i;
- size_t extension_bits = 0, total_bits = 0;
+ size_t extension_bits = 0;
+ size_t total_bits = 0;
ASSERT_TRUE(Bundle::CanEncode(f, &extension_bits, &total_bits));
EXPECT_EQ(0u, extension_bits);
EXPECT_GE(total_bits, 9u);
@@ -241,7 +243,8 @@ TEST(FieldsTest, TestPreview) {
for (uint32_t i = 1; i < 4360; ++i) {
PreviewHeader p;
ASSERT_TRUE(p.Set(i, i));
- size_t extension_bits = 0, total_bits = 0;
+ size_t extension_bits = 0;
+ size_t total_bits = 0;
ASSERT_TRUE(Bundle::CanEncode(p, &extension_bits, &total_bits));
EXPECT_EQ(0u, extension_bits);
EXPECT_GE(total_bits, 6u);
@@ -254,7 +257,8 @@ TEST(FieldsTest, TestRoundtripFrame) {
FrameHeader h(&metadata);
h.extensions = 0x800;
- size_t extension_bits = 999, total_bits = 999; // Initialize as garbage.
+ size_t extension_bits = 999;
+ size_t total_bits = 999; // Initialize as garbage.
ASSERT_TRUE(Bundle::CanEncode(h, &extension_bits, &total_bits));
EXPECT_EQ(0u, extension_bits);
BitWriter writer;
@@ -277,7 +281,8 @@ TEST(FieldsTest, TestRoundtripFrame) {
TEST(FieldsTest, TestOutOfRange) {
SizeHeader h;
ASSERT_TRUE(h.Set(0xFFFFFFFFull, 0xFFFFFFFFull));
- size_t extension_bits = 999, total_bits = 999; // Initialize as garbage.
+ size_t extension_bits = 999;
+ size_t total_bits = 999; // Initialize as garbage.
ASSERT_FALSE(Bundle::CanEncode(h, &extension_bits, &total_bits));
}
#endif
@@ -315,12 +320,12 @@ struct NewBundle : public Fields {
visitor->U32(Bits(7), Bits(12), Bits(16), Bits(32), 0, &old_large));
JXL_QUIET_RETURN_IF_ERROR(visitor->BeginExtensions(&extensions));
- if (visitor->Conditional(extensions & 1)) {
+ if (visitor->Conditional((extensions & 1) != 0)) {
JXL_QUIET_RETURN_IF_ERROR(
visitor->U32(Val(2), Bits(2), Bits(3), Bits(4), 2, &new_small));
JXL_QUIET_RETURN_IF_ERROR(visitor->F16(-2.0f, &new_f));
}
- if (visitor->Conditional(extensions & 2)) {
+ if (visitor->Conditional((extensions & 2) != 0)) {
JXL_QUIET_RETURN_IF_ERROR(
visitor->U32(Bits(9), Bits(12), Bits(16), Bits(32), 0, &new_large));
}
@@ -349,7 +354,8 @@ TEST(FieldsTest, TestNewDecoderOldData) {
const size_t kMaxOutBytes = 999;
BitWriter writer;
// Make sure values are initialized by code under test.
- size_t extension_bits = 12345, total_bits = 12345;
+ size_t extension_bits = 12345;
+ size_t total_bits = 12345;
ASSERT_TRUE(Bundle::CanEncode(old_bundle, &extension_bits, &total_bits));
ASSERT_LE(total_bits, kMaxOutBytes * kBitsPerByte);
EXPECT_EQ(0u, extension_bits);
@@ -393,7 +399,8 @@ TEST(FieldsTest, TestOldDecoderNewData) {
constexpr size_t kMaxOutBytes = 999;
BitWriter writer;
// Make sure values are initialized by code under test.
- size_t extension_bits = 12345, total_bits = 12345;
+ size_t extension_bits = 12345;
+ size_t total_bits = 12345;
ASSERT_TRUE(Bundle::CanEncode(new_bundle, &extension_bits, &total_bits));
EXPECT_NE(0u, extension_bits);
AuxOut aux_out;
diff --git a/third_party/jpeg-xl/lib/jxl/frame_header.cc b/third_party/jpeg-xl/lib/jxl/frame_header.cc
index a9e79ff1b8..6648e6d8cc 100644
--- a/third_party/jpeg-xl/lib/jxl/frame_header.cc
+++ b/third_party/jpeg-xl/lib/jxl/frame_header.cc
@@ -397,16 +397,18 @@ Status FrameHeader::VisitFields(Visitor* JXL_RESTRICT visitor) {
} else if (visitor->Conditional(frame_type == FrameType::kReferenceOnly)) {
JXL_QUIET_RETURN_IF_ERROR(
visitor->Bool(true, &save_before_color_transform));
+ size_t xsize = custom_size_or_origin ? frame_size.xsize
+ : nonserialized_metadata->xsize();
+ size_t ysize = custom_size_or_origin ? frame_size.ysize
+ : nonserialized_metadata->ysize();
if (!save_before_color_transform &&
- (frame_size.xsize < nonserialized_metadata->xsize() ||
- frame_size.ysize < nonserialized_metadata->ysize() ||
- frame_origin.x0 != 0 || frame_origin.y0 != 0)) {
+ (xsize < nonserialized_metadata->xsize() ||
+ ysize < nonserialized_metadata->ysize() || frame_origin.x0 != 0 ||
+ frame_origin.y0 != 0)) {
return JXL_FAILURE(
"non-patch reference frame with invalid crop: %" PRIuS "x%" PRIuS
"%+d%+d",
- static_cast<size_t>(frame_size.xsize),
- static_cast<size_t>(frame_size.ysize),
- static_cast<int>(frame_origin.x0),
+ xsize, ysize, static_cast<int>(frame_origin.x0),
static_cast<int>(frame_origin.y0));
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/frame_header.h b/third_party/jpeg-xl/lib/jxl/frame_header.h
index b246bf813e..30c62d5f27 100644
--- a/third_party/jpeg-xl/lib/jxl/frame_header.h
+++ b/third_party/jpeg-xl/lib/jxl/frame_header.h
@@ -82,8 +82,8 @@ struct YCbCrChromaSubsampling : public Fields {
Status VisitFields(Visitor* JXL_RESTRICT visitor) override {
// TODO(veluca): consider allowing 4x downsamples
- for (size_t i = 0; i < 3; i++) {
- JXL_QUIET_RETURN_IF_ERROR(visitor->Bits(2, 0, &channel_mode_[i]));
+ for (uint32_t& ch : channel_mode_) {
+ JXL_QUIET_RETURN_IF_ERROR(visitor->Bits(2, 0, &ch));
}
Recompute();
return true;
@@ -152,9 +152,9 @@ struct YCbCrChromaSubsampling : public Fields {
void Recompute() {
maxhs_ = 0;
maxvs_ = 0;
- for (size_t i = 0; i < 3; i++) {
- maxhs_ = std::max(maxhs_, kHShift[channel_mode_[i]]);
- maxvs_ = std::max(maxvs_, kVShift[channel_mode_[i]]);
+ for (uint32_t ch : channel_mode_) {
+ maxhs_ = std::max(maxhs_, kHShift[ch]);
+ maxvs_ = std::max(maxvs_, kVShift[ch]);
}
}
static const uint8_t kHShift[4];
diff --git a/third_party/jpeg-xl/lib/jxl/gradient_test.cc b/third_party/jpeg-xl/lib/jxl/gradient_test.cc
index 055a419f5b..d2c83619fc 100644
--- a/third_party/jpeg-xl/lib/jxl/gradient_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/gradient_test.cc
@@ -9,7 +9,6 @@
#include <stdint.h>
#include <algorithm>
-#include <array>
#include <cmath>
#include <utility>
#include <vector>
@@ -45,10 +44,10 @@ double PointLineDist(double x0, double y0, double x1, double y1, double x,
// angle in which the change direction happens.
Image3F GenerateTestGradient(uint32_t color0, uint32_t color1, double angle,
size_t xsize, size_t ysize) {
- Image3F image(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(Image3F image, Image3F::Create(xsize, ysize));
- double x0 = xsize / 2;
- double y0 = ysize / 2;
+ double x0 = xsize / 2.0;
+ double y0 = ysize / 2.0;
double x1 = x0 + std::sin(angle / 360.0 * 2.0 * kPi);
double y1 = y0 + std::cos(angle / 360.0 * 2.0 * kPi);
@@ -78,63 +77,60 @@ Image3F GenerateTestGradient(uint32_t color0, uint32_t color1, double angle,
// delta and right delta (top/bottom for vertical direction).
// The radius over which the derivative is computed is only 1 pixel and it only
// checks two angles (hor and ver), but this approximation works well enough.
-static ImageF Gradient2(const ImageF& image) {
+Image3F Gradient2(const Image3F& image) {
size_t xsize = image.xsize();
size_t ysize = image.ysize();
- ImageF image2(image.xsize(), image.ysize());
- for (size_t y = 1; y + 1 < ysize; y++) {
- const auto* JXL_RESTRICT row0 = image.Row(y - 1);
- const auto* JXL_RESTRICT row1 = image.Row(y);
- const auto* JXL_RESTRICT row2 = image.Row(y + 1);
- auto* row_out = image2.Row(y);
- for (size_t x = 1; x + 1 < xsize; x++) {
- float ddx = (row1[x] - row1[x - 1]) - (row1[x + 1] - row1[x]);
- float ddy = (row1[x] - row0[x]) - (row2[x] - row1[x]);
- row_out[x] = std::max(fabsf(ddx), fabsf(ddy));
- }
- }
- // Copy to the borders
- if (ysize > 2) {
- auto* JXL_RESTRICT row0 = image2.Row(0);
- const auto* JXL_RESTRICT row1 = image2.Row(1);
- const auto* JXL_RESTRICT row2 = image2.Row(ysize - 2);
- auto* JXL_RESTRICT row3 = image2.Row(ysize - 1);
- for (size_t x = 1; x + 1 < xsize; x++) {
- row0[x] = row1[x];
- row3[x] = row2[x];
- }
- } else {
- const auto* row0_in = image.Row(0);
- const auto* row1_in = image.Row(ysize - 1);
- auto* row0_out = image2.Row(0);
- auto* row1_out = image2.Row(ysize - 1);
- for (size_t x = 1; x + 1 < xsize; x++) {
- // Image too narrow, take first derivative instead
- row0_out[x] = row1_out[x] = fabsf(row0_in[x] - row1_in[x]);
+ JXL_ASSIGN_OR_DIE(Image3F image2, Image3F::Create(xsize, ysize));
+ for (size_t c = 0; c < 3; ++c) {
+ for (size_t y = 1; y + 1 < ysize; y++) {
+ const auto* JXL_RESTRICT row0 = image.ConstPlaneRow(c, y - 1);
+ const auto* JXL_RESTRICT row1 = image.ConstPlaneRow(c, y);
+ const auto* JXL_RESTRICT row2 = image.ConstPlaneRow(c, y + 1);
+ auto* row_out = image2.PlaneRow(c, y);
+ for (size_t x = 1; x + 1 < xsize; x++) {
+ float ddx = (row1[x] - row1[x - 1]) - (row1[x + 1] - row1[x]);
+ float ddy = (row1[x] - row0[x]) - (row2[x] - row1[x]);
+ row_out[x] = std::max(fabsf(ddx), fabsf(ddy));
+ }
}
- }
- if (xsize > 2) {
- for (size_t y = 0; y < ysize; y++) {
- auto* row = image2.Row(y);
- row[0] = row[1];
- row[xsize - 1] = row[xsize - 2];
+ // Copy to the borders
+ if (ysize > 2) {
+ auto* JXL_RESTRICT row0 = image2.PlaneRow(c, 0);
+ const auto* JXL_RESTRICT row1 = image2.PlaneRow(c, 1);
+ const auto* JXL_RESTRICT row2 = image2.PlaneRow(c, ysize - 2);
+ auto* JXL_RESTRICT row3 = image2.PlaneRow(c, ysize - 1);
+ for (size_t x = 1; x + 1 < xsize; x++) {
+ row0[x] = row1[x];
+ row3[x] = row2[x];
+ }
+ } else {
+ const auto* row0_in = image.ConstPlaneRow(c, 0);
+ const auto* row1_in = image.ConstPlaneRow(c, ysize - 1);
+ auto* row0_out = image2.PlaneRow(c, 0);
+ auto* row1_out = image2.PlaneRow(c, ysize - 1);
+ for (size_t x = 1; x + 1 < xsize; x++) {
+ // Image too narrow, take first derivative instead
+ row0_out[x] = row1_out[x] = fabsf(row0_in[x] - row1_in[x]);
+ }
}
- } else {
- for (size_t y = 0; y < ysize; y++) {
- const auto* JXL_RESTRICT row_in = image.Row(y);
- auto* row_out = image2.Row(y);
- // Image too narrow, take first derivative instead
- row_out[0] = row_out[xsize - 1] = fabsf(row_in[0] - row_in[xsize - 1]);
+ if (xsize > 2) {
+ for (size_t y = 0; y < ysize; y++) {
+ auto* row = image2.PlaneRow(c, y);
+ row[0] = row[1];
+ row[xsize - 1] = row[xsize - 2];
+ }
+ } else {
+ for (size_t y = 0; y < ysize; y++) {
+ const auto* JXL_RESTRICT row_in = image.ConstPlaneRow(c, y);
+ auto* row_out = image2.PlaneRow(c, y);
+ // Image too narrow, take first derivative instead
+ row_out[0] = row_out[xsize - 1] = fabsf(row_in[0] - row_in[xsize - 1]);
+ }
}
}
return image2;
}
-static Image3F Gradient2(const Image3F& image) {
- return Image3F(Gradient2(image.Plane(0)), Gradient2(image.Plane(1)),
- Gradient2(image.Plane(2)));
-}
-
/*
Tests if roundtrip with jxl on a gradient image doesn't cause banding.
Only tests if use_gradient is true. Set to false for debugging to see the
@@ -173,17 +169,19 @@ void TestGradient(ThreadPool* pool, uint32_t color0, uint32_t color1,
// butteraugli_distance).
Image3F gradient2 = Gradient2(*io2.Main().color());
- std::array<float, 3> image_max;
- Image3Max(gradient2, &image_max);
-
// TODO(jyrki): These values used to work with 0.2, 0.2, 0.2.
- EXPECT_LE(image_max[0], 3.15);
- EXPECT_LE(image_max[1], 1.72);
- EXPECT_LE(image_max[2], 5.05);
+ float image_min;
+ float image_max;
+ ImageMinMax(gradient2.Plane(0), &image_min, &image_max);
+ EXPECT_LE(image_max, 3.15);
+ ImageMinMax(gradient2.Plane(1), &image_min, &image_max);
+ EXPECT_LE(image_max, 1.72);
+ ImageMinMax(gradient2.Plane(2), &image_min, &image_max);
+ EXPECT_LE(image_max, 5.05);
}
}
-static constexpr bool fast_mode = true;
+constexpr bool fast_mode = true;
TEST(GradientTest, SteepGradient) {
test::ThreadPoolForTests pool(8);
diff --git a/third_party/jpeg-xl/lib/jxl/headers.cc b/third_party/jpeg-xl/lib/jxl/headers.cc
index db88147687..52e7cf5db3 100644
--- a/third_party/jpeg-xl/lib/jxl/headers.cc
+++ b/third_party/jpeg-xl/lib/jxl/headers.cc
@@ -17,7 +17,7 @@ struct Rational {
// Returns floor(multiplicand * rational).
constexpr uint32_t MulTruncate(uint32_t multiplicand) const {
- return uint64_t(multiplicand) * num / den;
+ return static_cast<uint64_t>(multiplicand) * num / den;
}
uint32_t num;
diff --git a/third_party/jpeg-xl/lib/jxl/icc_codec.cc b/third_party/jpeg-xl/lib/jxl/icc_codec.cc
index a1f118ebfb..8501c684ac 100644
--- a/third_party/jpeg-xl/lib/jxl/icc_codec.cc
+++ b/third_party/jpeg-xl/lib/jxl/icc_codec.cc
@@ -33,7 +33,8 @@ void Shuffle(uint8_t* data, size_t size, size_t width) {
size_t height = (size + width - 1) / width; // amount of rows of output
PaddedBytes result(size);
// i = output index, j input index
- size_t s = 0, j = 0;
+ size_t s = 0;
+ size_t j = 0;
for (size_t i = 0; i < size; i++) {
result[i] = data[j];
j += height;
@@ -55,7 +56,8 @@ uint64_t DecodeVarInt(const uint8_t* input, size_t inputSize, size_t* pos) {
size_t i;
uint64_t ret = 0;
for (i = 0; *pos + i < inputSize && i < 10; ++i) {
- ret |= uint64_t(input[*pos + i] & 127) << uint64_t(7 * i);
+ ret |= static_cast<uint64_t>(input[*pos + i] & 127)
+ << static_cast<uint64_t>(7 * i);
// If the next-byte flag is not set, stop
if ((input[*pos + i] & 128) == 0) break;
}
diff --git a/third_party/jpeg-xl/lib/jxl/icc_codec.h b/third_party/jpeg-xl/lib/jxl/icc_codec.h
index 87e523a575..8b880c7d3b 100644
--- a/third_party/jpeg-xl/lib/jxl/icc_codec.h
+++ b/third_party/jpeg-xl/lib/jxl/icc_codec.h
@@ -39,12 +39,6 @@ struct ICCReader {
PaddedBytes decompressed_;
};
-// Exposed only for testing
-Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result);
-
-// Exposed only for testing
-Status UnpredictICC(const uint8_t* enc, size_t size, PaddedBytes* result);
-
} // namespace jxl
#endif // LIB_JXL_ICC_CODEC_H_
diff --git a/third_party/jpeg-xl/lib/jxl/icc_codec_common.cc b/third_party/jpeg-xl/lib/jxl/icc_codec_common.cc
index d420567b6f..1cb4542687 100644
--- a/third_party/jpeg-xl/lib/jxl/icc_codec_common.cc
+++ b/third_party/jpeg-xl/lib/jxl/icc_codec_common.cc
@@ -17,7 +17,7 @@
namespace jxl {
namespace {
-static uint8_t ByteKind1(uint8_t b) {
+uint8_t ByteKind1(uint8_t b) {
if ('a' <= b && b <= 'z') return 0;
if ('A' <= b && b <= 'Z') return 0;
if ('0' <= b && b <= '9') return 1;
@@ -30,7 +30,7 @@ static uint8_t ByteKind1(uint8_t b) {
return 7;
}
-static uint8_t ByteKind2(uint8_t b) {
+uint8_t ByteKind2(uint8_t b) {
if ('a' <= b && b <= 'z') return 0;
if ('A' <= b && b <= 'Z') return 0;
if ('0' <= b && b <= '9') return 1;
@@ -105,7 +105,7 @@ const uint8_t kIccInitialHeaderPrediction[kICCHeaderSize] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
-const Span<const uint8_t> ICCInitialHeaderPrediction() {
+Span<const uint8_t> ICCInitialHeaderPrediction() {
return Bytes(kIccInitialHeaderPrediction);
}
diff --git a/third_party/jpeg-xl/lib/jxl/icc_codec_common.h b/third_party/jpeg-xl/lib/jxl/icc_codec_common.h
index 702a0e7b1f..0922d74145 100644
--- a/third_party/jpeg-xl/lib/jxl/icc_codec_common.h
+++ b/third_party/jpeg-xl/lib/jxl/icc_codec_common.h
@@ -95,7 +95,7 @@ void AppendKeyword(const Tag& keyword, PaddedBytes* data);
Status CheckOutOfBounds(uint64_t a, uint64_t b, uint64_t size);
Status CheckIs32Bit(uint64_t v);
-const Span<const uint8_t> ICCInitialHeaderPrediction();
+Span<const uint8_t> ICCInitialHeaderPrediction();
void ICCPredictHeader(const uint8_t* icc, size_t size, uint8_t* header,
size_t pos);
uint8_t LinearPredictICCValue(const uint8_t* data, size_t start, size_t i,
diff --git a/third_party/jpeg-xl/lib/jxl/icc_codec_test.cc b/third_party/jpeg-xl/lib/jxl/icc_codec_test.cc
index 743aa9a30e..175b4768a0 100644
--- a/third_party/jpeg-xl/lib/jxl/icc_codec_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/icc_codec_test.cc
@@ -37,12 +37,12 @@ void TestProfile(const IccBytes& icc) {
void TestProfile(const std::string& icc) {
IccBytes data;
- Bytes(icc).AppendTo(&data);
+ Bytes(icc).AppendTo(data);
TestProfile(data);
}
// Valid profile from one of the images output by the decoder.
-static const unsigned char kTestProfile[] = {
+const unsigned char kTestProfile[] = {
0x00, 0x00, 0x03, 0x80, 0x6c, 0x63, 0x6d, 0x73, 0x04, 0x30, 0x00, 0x00,
0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
0x07, 0xe3, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x0f, 0x00, 0x32, 0x00, 0x2e,
@@ -139,7 +139,7 @@ TEST(IccCodecTest, Icc) {
{
IccBytes profile;
- Bytes(kTestProfile, sizeof(kTestProfile)).AppendTo(&profile);
+ Bytes(kTestProfile, sizeof(kTestProfile)).AppendTo(profile);
TestProfile(profile);
}
diff --git a/third_party/jpeg-xl/lib/jxl/image.cc b/third_party/jpeg-xl/lib/jxl/image.cc
index 382c957799..7468dad130 100644
--- a/third_party/jpeg-xl/lib/jxl/image.cc
+++ b/third_party/jpeg-xl/lib/jxl/image.cc
@@ -5,123 +5,93 @@
#include "lib/jxl/image.h"
-#include <algorithm> // swap
+#include <algorithm> // fill, swap
+#include <cstddef>
+#include <cstdint>
-#undef HWY_TARGET_INCLUDE
-#define HWY_TARGET_INCLUDE "lib/jxl/image.cc"
-#include <hwy/foreach_target.h>
-#include <hwy/highway.h>
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/cache_aligned.h"
+#include "lib/jxl/simd_util.h"
+#if defined(MEMORY_SANITIZER)
#include "lib/jxl/base/common.h"
-#include "lib/jxl/frame_dimensions.h"
-#include "lib/jxl/image_ops.h"
#include "lib/jxl/sanitizers.h"
+#endif
-HWY_BEFORE_NAMESPACE();
namespace jxl {
+namespace detail {
-namespace HWY_NAMESPACE {
-size_t GetVectorSize() { return HWY_LANES(uint8_t); }
-// NOLINTNEXTLINE(google-readability-namespace-comments)
-} // namespace HWY_NAMESPACE
-
-} // namespace jxl
-HWY_AFTER_NAMESPACE();
-
-#if HWY_ONCE
-namespace jxl {
namespace {
-HWY_EXPORT(GetVectorSize); // Local function.
+// Initializes the minimum bytes required to suppress MSAN warnings from
+// legitimate vector loads/stores on the right border, where some lanes are
+// uninitialized and assumed to be unused.
+void InitializePadding(PlaneBase& plane, const size_t sizeof_t) {
+#if defined(MEMORY_SANITIZER)
+ size_t xsize = plane.xsize();
+ size_t ysize = plane.ysize();
+ if (xsize == 0 || ysize == 0) return;
-// Returns distance [bytes] between the start of two consecutive rows, a
-// multiple of vector/cache line size but NOT CacheAligned::kAlias - see below.
-size_t BytesPerRow(const size_t xsize, const size_t sizeof_t) {
- const size_t vec_size = VectorSize();
- size_t valid_bytes = xsize * sizeof_t;
+ const size_t vec_size = MaxVectorSize();
+ if (vec_size == 0) return; // Scalar mode: no padding needed
- // Allow unaligned accesses starting at the last valid value - this may raise
- // msan errors unless the user calls InitializePaddingForUnalignedAccesses.
- // Skip for the scalar case because no extra lanes will be loaded.
- if (vec_size != 0) {
- valid_bytes += vec_size - sizeof_t;
- }
+ const size_t valid_size = xsize * sizeof_t;
+ const size_t initialize_size = RoundUpTo(valid_size, vec_size);
+ if (valid_size == initialize_size) return;
- // Round up to vector and cache line size.
- const size_t align = std::max(vec_size, CacheAligned::kAlignment);
- size_t bytes_per_row = RoundUpTo(valid_bytes, align);
-
- // During the lengthy window before writes are committed to memory, CPUs
- // guard against read after write hazards by checking the address, but
- // only the lower 11 bits. We avoid a false dependency between writes to
- // consecutive rows by ensuring their sizes are not multiples of 2 KiB.
- // Avoid2K prevents the same problem for the planes of an Image3.
- if (bytes_per_row % CacheAligned::kAlias == 0) {
- bytes_per_row += align;
+ for (size_t y = 0; y < ysize; ++y) {
+ uint8_t* JXL_RESTRICT row = plane.bytes() + y * plane.bytes_per_row();
+#if defined(__clang__) && \
+ ((!defined(__apple_build_version__) && __clang_major__ <= 6) || \
+ (defined(__apple_build_version__) && \
+ __apple_build_version__ <= 10001145))
+ // There's a bug in MSAN in clang-6 when handling AVX2 operations. This
+ // workaround allows tests to pass on MSAN, although it is slower and
+ // prevents MSAN warnings from uninitialized images.
+ std::fill(row, msan::kSanitizerSentinelByte, initialize_size);
+#else
+ memset(row + valid_size, msan::kSanitizerSentinelByte,
+ initialize_size - valid_size);
+#endif // clang6
}
-
- JXL_ASSERT(bytes_per_row % align == 0);
- return bytes_per_row;
+#endif // MEMORY_SANITIZER
}
} // namespace
-size_t VectorSize() {
- static size_t bytes = HWY_DYNAMIC_DISPATCH(GetVectorSize)();
- return bytes;
-}
-
PlaneBase::PlaneBase(const size_t xsize, const size_t ysize,
const size_t sizeof_t)
: xsize_(static_cast<uint32_t>(xsize)),
ysize_(static_cast<uint32_t>(ysize)),
orig_xsize_(static_cast<uint32_t>(xsize)),
- orig_ysize_(static_cast<uint32_t>(ysize)) {
+ orig_ysize_(static_cast<uint32_t>(ysize)),
+ bytes_per_row_(BytesPerRow(xsize_, sizeof_t)),
+ bytes_(nullptr),
+ sizeof_t_(sizeof_t) {
+ // TODO(eustas): turn to error instead of abort.
JXL_CHECK(xsize == xsize_);
JXL_CHECK(ysize == ysize_);
JXL_ASSERT(sizeof_t == 1 || sizeof_t == 2 || sizeof_t == 4 || sizeof_t == 8);
+}
+
+Status PlaneBase::Allocate() {
+ JXL_CHECK(!bytes_.get());
- bytes_per_row_ = 0;
// Dimensions can be zero, e.g. for lazily-allocated images. Only allocate
// if nonzero, because "zero" bytes still have padding/bookkeeping overhead.
- if (xsize != 0 && ysize != 0) {
- bytes_per_row_ = BytesPerRow(xsize, sizeof_t);
- bytes_ = AllocateArray(bytes_per_row_ * ysize);
- JXL_CHECK(bytes_.get());
- InitializePadding(sizeof_t, Padding::kRoundUp);
+ if (xsize_ == 0 || ysize_ == 0) {
+ return true;
}
-}
-
-void PlaneBase::InitializePadding(const size_t sizeof_t, Padding padding) {
-#if defined(MEMORY_SANITIZER) || HWY_IDE
- if (xsize_ == 0 || ysize_ == 0) return;
-
- const size_t vec_size = VectorSize();
- if (vec_size == 0) return; // Scalar mode: no padding needed
-
- const size_t valid_size = xsize_ * sizeof_t;
- const size_t initialize_size = padding == Padding::kRoundUp
- ? RoundUpTo(valid_size, vec_size)
- : valid_size + vec_size - sizeof_t;
- if (valid_size == initialize_size) return;
- for (size_t y = 0; y < ysize_; ++y) {
- uint8_t* JXL_RESTRICT row = static_cast<uint8_t*>(VoidRow(y));
-#if defined(__clang__) && \
- ((!defined(__apple_build_version__) && __clang_major__ <= 6) || \
- (defined(__apple_build_version__) && \
- __apple_build_version__ <= 10001145))
- // There's a bug in msan in clang-6 when handling AVX2 operations. This
- // workaround allows tests to pass on msan, although it is slower and
- // prevents msan warnings from uninitialized images.
- std::fill(row, msan::kSanitizerSentinelByte, initialize_size);
-#else
- memset(row + valid_size, msan::kSanitizerSentinelByte,
- initialize_size - valid_size);
-#endif // clang6
+ bytes_ = AllocateArray(bytes_per_row_ * ysize_);
+ if (!bytes_.get()) {
+ // TODO(eustas): use specialized OOM error code
+ return JXL_FAILURE("Failed to allocate memory for image surface");
}
-#endif // MEMORY_SANITIZER
+ InitializePadding(*this, sizeof_t_);
+
+ return true;
}
void PlaneBase::Swap(PlaneBase& other) {
@@ -133,73 +103,5 @@ void PlaneBase::Swap(PlaneBase& other) {
std::swap(bytes_, other.bytes_);
}
-void PadImageToBlockMultipleInPlace(Image3F* JXL_RESTRICT in,
- size_t block_dim) {
- const size_t xsize_orig = in->xsize();
- const size_t ysize_orig = in->ysize();
- const size_t xsize = RoundUpTo(xsize_orig, block_dim);
- const size_t ysize = RoundUpTo(ysize_orig, block_dim);
- // Expands image size to the originally-allocated size.
- in->ShrinkTo(xsize, ysize);
- for (size_t c = 0; c < 3; c++) {
- for (size_t y = 0; y < ysize_orig; y++) {
- float* JXL_RESTRICT row = in->PlaneRow(c, y);
- for (size_t x = xsize_orig; x < xsize; x++) {
- row[x] = row[xsize_orig - 1];
- }
- }
- const float* JXL_RESTRICT row_src = in->ConstPlaneRow(c, ysize_orig - 1);
- for (size_t y = ysize_orig; y < ysize; y++) {
- memcpy(in->PlaneRow(c, y), row_src, xsize * sizeof(float));
- }
- }
-}
-
-static void DownsampleImage(const ImageF& input, size_t factor,
- ImageF* output) {
- JXL_ASSERT(factor != 1);
- output->ShrinkTo(DivCeil(input.xsize(), factor),
- DivCeil(input.ysize(), factor));
- size_t in_stride = input.PixelsPerRow();
- for (size_t y = 0; y < output->ysize(); y++) {
- float* row_out = output->Row(y);
- const float* row_in = input.Row(factor * y);
- for (size_t x = 0; x < output->xsize(); x++) {
- size_t cnt = 0;
- float sum = 0;
- for (size_t iy = 0; iy < factor && iy + factor * y < input.ysize();
- iy++) {
- for (size_t ix = 0; ix < factor && ix + factor * x < input.xsize();
- ix++) {
- sum += row_in[iy * in_stride + x * factor + ix];
- cnt++;
- }
- }
- row_out[x] = sum / cnt;
- }
- }
-}
-
-void DownsampleImage(ImageF* image, size_t factor) {
- // Allocate extra space to avoid a reallocation when padding.
- ImageF downsampled(DivCeil(image->xsize(), factor) + kBlockDim,
- DivCeil(image->ysize(), factor) + kBlockDim);
- DownsampleImage(*image, factor, &downsampled);
- *image = std::move(downsampled);
-}
-
-void DownsampleImage(Image3F* opsin, size_t factor) {
- JXL_ASSERT(factor != 1);
- // Allocate extra space to avoid a reallocation when padding.
- Image3F downsampled(DivCeil(opsin->xsize(), factor) + kBlockDim,
- DivCeil(opsin->ysize(), factor) + kBlockDim);
- downsampled.ShrinkTo(downsampled.xsize() - kBlockDim,
- downsampled.ysize() - kBlockDim);
- for (size_t c = 0; c < 3; c++) {
- DownsampleImage(opsin->Plane(c), factor, &downsampled.Plane(c));
- }
- *opsin = std::move(downsampled);
-}
-
+} // namespace detail
} // namespace jxl
-#endif // HWY_ONCE
diff --git a/third_party/jpeg-xl/lib/jxl/image.h b/third_party/jpeg-xl/lib/jxl/image.h
index 98c387bb77..be97b929e3 100644
--- a/third_party/jpeg-xl/lib/jxl/image.h
+++ b/third_party/jpeg-xl/lib/jxl/image.h
@@ -28,8 +28,8 @@
namespace jxl {
-// Helper function to create rows that are multiples of SIMD vector size.
-size_t VectorSize();
+// DO NOT use PlaneBase outside of image.{h|cc}
+namespace detail {
// Type-independent parts of Plane<> - reduces code duplication and facilitates
// moving member function implementations to cc file.
@@ -40,8 +40,8 @@ struct PlaneBase {
orig_xsize_(0),
orig_ysize_(0),
bytes_per_row_(0),
- bytes_(nullptr) {}
- PlaneBase(size_t xsize, size_t ysize, size_t sizeof_t);
+ bytes_(nullptr),
+ sizeof_t_(0) {}
// Copy construction/assignment is forbidden to avoid inadvertent copies,
// which can be very expensive. Use CopyImageTo() instead.
@@ -88,13 +88,16 @@ struct PlaneBase {
}
protected:
+ PlaneBase(size_t xsize, size_t ysize, size_t sizeof_t);
+ Status Allocate();
+
// Returns pointer to the start of a row.
JXL_INLINE void* VoidRow(const size_t y) const {
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
defined(THREAD_SANITIZER)
if (y >= ysize_) {
- JXL_ABORT("Row(%" PRIu64 ") in (%u x %u) image\n", (uint64_t)y, xsize_,
- ysize_);
+ JXL_ABORT("Row(%" PRIu64 ") in (%u x %u) image\n",
+ static_cast<uint64_t>(y), xsize_, ysize_);
}
#endif
@@ -102,21 +105,6 @@ struct PlaneBase {
return JXL_ASSUME_ALIGNED(row, 64);
}
- enum class Padding {
- // Allow Load(d, row + x) for x = 0; x < xsize(); x += Lanes(d). Default.
- kRoundUp,
- // Allow LoadU(d, row + x) for x = xsize() - 1. This requires an extra
- // vector to be initialized. If done by default, this would suppress
- // legitimate msan warnings. We therefore require users to explicitly call
- // InitializePadding before using unaligned loads (e.g. convolution).
- kUnaligned
- };
-
- // Initializes the minimum bytes required to suppress msan warnings from
- // legitimate (according to Padding mode) vector loads/stores on the right
- // border, where some lanes are uninitialized and assumed to be unused.
- void InitializePadding(size_t sizeof_t, Padding padding);
-
// (Members are non-const to enable assignment during move-assignment.)
uint32_t xsize_; // In valid pixels, not including any padding.
uint32_t ysize_;
@@ -124,8 +112,11 @@ struct PlaneBase {
uint32_t orig_ysize_;
size_t bytes_per_row_; // Includes padding.
CacheAlignedUniquePtr bytes_;
+ size_t sizeof_t_;
};
+} // namespace detail
+
// Single channel, aligned rows separated by padding. T must be POD.
//
// 'Single channel' (one 2D array per channel) simplifies vectorization
@@ -148,17 +139,17 @@ struct PlaneBase {
// provides convenient accessors for xsize/ysize, which shortens function
// argument lists. Supports move-construction so it can be stored in containers.
template <typename ComponentType>
-class Plane : public PlaneBase {
+class Plane : public detail::PlaneBase {
public:
using T = ComponentType;
static constexpr size_t kNumPlanes = 1;
Plane() = default;
- Plane(const size_t xsize, const size_t ysize)
- : PlaneBase(xsize, ysize, sizeof(T)) {}
- void InitializePaddingForUnalignedAccesses() {
- InitializePadding(sizeof(T), Padding::kUnaligned);
+ static StatusOr<Plane> Create(const size_t xsize, const size_t ysize) {
+ Plane plane(xsize, ysize, sizeof(T));
+ JXL_RETURN_IF_ERROR(plane.Allocate());
+ return plane;
}
JXL_INLINE T* Row(const size_t y) { return static_cast<T*>(VoidRow(y)); }
@@ -179,6 +170,10 @@ class Plane : public PlaneBase {
JXL_INLINE intptr_t PixelsPerRow() const {
return static_cast<intptr_t>(bytes_per_row_ / sizeof(T));
}
+
+ private:
+ Plane(size_t xsize, size_t ysize, size_t sizeof_t)
+ : detail::PlaneBase(xsize, ysize, sizeof_t) {}
};
using ImageSB = Plane<int8_t>;
@@ -189,12 +184,6 @@ using ImageI = Plane<int32_t>;
using ImageF = Plane<float>;
using ImageD = Plane<double>;
-// Also works for Image3 and mixed argument types.
-template <class Image1, class Image2>
-bool SameSize(const Image1& image1, const Image2& image2) {
- return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize();
-}
-
template <typename T>
class Image3;
@@ -339,7 +328,8 @@ class RectT {
template <typename U>
RectT<U> As() const {
- return RectT<U>(U(x0_), U(y0_), U(xsize_), U(ysize_));
+ return RectT<U>(static_cast<U>(x0_), static_cast<U>(y0_),
+ static_cast<U>(xsize_), static_cast<U>(ysize_));
}
private:
@@ -394,24 +384,12 @@ class Image3 {
Image3() : planes_{PlaneT(), PlaneT(), PlaneT()} {}
- Image3(const size_t xsize, const size_t ysize)
- : planes_{PlaneT(xsize, ysize), PlaneT(xsize, ysize),
- PlaneT(xsize, ysize)} {}
-
Image3(Image3&& other) noexcept {
for (size_t i = 0; i < kNumPlanes; i++) {
planes_[i] = std::move(other.planes_[i]);
}
}
- Image3(PlaneT&& plane0, PlaneT&& plane1, PlaneT&& plane2) {
- JXL_CHECK(SameSize(plane0, plane1));
- JXL_CHECK(SameSize(plane0, plane2));
- planes_[0] = std::move(plane0);
- planes_[1] = std::move(plane1);
- planes_[2] = std::move(plane2);
- }
-
// Copy construction/assignment is forbidden to avoid inadvertent copies,
// which can be very expensive. Use CopyImageTo instead.
Image3(const Image3& other) = delete;
@@ -424,6 +402,17 @@ class Image3 {
return *this;
}
+ static StatusOr<Image3> Create(const size_t xsize, const size_t ysize) {
+ StatusOr<PlaneT> plane0 = PlaneT::Create(xsize, ysize);
+ JXL_RETURN_IF_ERROR(plane0.status());
+ StatusOr<PlaneT> plane1 = PlaneT::Create(xsize, ysize);
+ JXL_RETURN_IF_ERROR(plane1.status());
+ StatusOr<PlaneT> plane2 = PlaneT::Create(xsize, ysize);
+ JXL_RETURN_IF_ERROR(plane2.status());
+ return Image3(std::move(plane0).value(), std::move(plane1).value(),
+ std::move(plane2).value());
+ }
+
// Returns row pointer; usage: PlaneRow(idx_plane, y)[x] = val.
JXL_INLINE T* PlaneRow(const size_t c, const size_t y) {
// Custom implementation instead of calling planes_[c].Row ensures only a
@@ -481,6 +470,12 @@ class Image3 {
JXL_INLINE intptr_t PixelsPerRow() const { return planes_[0].PixelsPerRow(); }
private:
+ Image3(PlaneT&& plane0, PlaneT&& plane1, PlaneT&& plane2) {
+ planes_[0] = std::move(plane0);
+ planes_[1] = std::move(plane1);
+ planes_[2] = std::move(plane2);
+ }
+
void PlaneRowBoundsCheck(const size_t c, const size_t y) const {
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
defined(THREAD_SANITIZER)
@@ -493,7 +488,6 @@ class Image3 {
#endif
}
- private:
PlaneT planes_[kNumPlanes];
};
diff --git a/third_party/jpeg-xl/lib/jxl/image_bundle.h b/third_party/jpeg-xl/lib/jxl/image_bundle.h
index 2eea496d5e..c8a76a9f59 100644
--- a/third_party/jpeg-xl/lib/jxl/image_bundle.h
+++ b/third_party/jpeg-xl/lib/jxl/image_bundle.h
@@ -42,14 +42,16 @@ class ImageBundle {
ImageBundle(ImageBundle&&) = default;
ImageBundle& operator=(ImageBundle&&) = default;
- ImageBundle Copy() const {
+ StatusOr<ImageBundle> Copy() const {
ImageBundle copy(metadata_);
- copy.color_ = Image3F(color_.xsize(), color_.ysize());
+ JXL_ASSIGN_OR_RETURN(copy.color_,
+ Image3F::Create(color_.xsize(), color_.ysize()));
CopyImageTo(color_, &copy.color_);
copy.c_current_ = c_current_;
copy.extra_channels_.reserve(extra_channels_.size());
for (const ImageF& plane : extra_channels_) {
- ImageF ec(plane.xsize(), plane.ysize());
+ JXL_ASSIGN_OR_RETURN(ImageF ec,
+ ImageF::Create(plane.xsize(), plane.ysize()));
CopyImageTo(plane, &ec);
copy.extra_channels_.emplace_back(std::move(ec));
}
diff --git a/third_party/jpeg-xl/lib/jxl/image_metadata.cc b/third_party/jpeg-xl/lib/jxl/image_metadata.cc
index 4cca910753..91d27ff44e 100644
--- a/third_party/jpeg-xl/lib/jxl/image_metadata.cc
+++ b/third_party/jpeg-xl/lib/jxl/image_metadata.cc
@@ -10,6 +10,7 @@
#include "lib/jxl/alpha.h"
#include "lib/jxl/base/byte_order.h"
+#include "lib/jxl/base/matrix_ops.h"
#include "lib/jxl/cms/opsin_params.h"
#include "lib/jxl/fields.h"
#include "lib/jxl/frame_header.h"
@@ -245,8 +246,8 @@ Status ExtraChannelInfo::VisitFields(Visitor* JXL_RESTRICT visitor) {
}
if (type == ExtraChannel::kUnknown ||
- (int(ExtraChannel::kReserved0) <= int(type) &&
- int(type) <= int(ExtraChannel::kReserved7))) {
+ (static_cast<int>(ExtraChannel::kReserved0) <= static_cast<int>(type) &&
+ static_cast<int>(type) <= static_cast<int>(ExtraChannel::kReserved7))) {
return JXL_FAILURE("Unknown extra channel (bits %u, shift %u, name '%s')\n",
bit_depth.bits_per_sample, dim_shift, name.c_str());
}
@@ -354,10 +355,13 @@ Status OpsinInverseMatrix::VisitFields(Visitor* JXL_RESTRICT visitor) {
visitor->SetDefault(this);
return true;
}
- for (int i = 0; i < 9; ++i) {
- JXL_QUIET_RETURN_IF_ERROR(
- visitor->F16(jxl::cms::DefaultInverseOpsinAbsorbanceMatrix()[i],
- &inverse_matrix[i]));
+ const Matrix3x3& default_inverse =
+ jxl::cms::DefaultInverseOpsinAbsorbanceMatrix();
+ for (int j = 0; j < 3; ++j) {
+ for (int i = 0; i < 3; ++i) {
+ JXL_QUIET_RETURN_IF_ERROR(
+ visitor->F16(default_inverse[j][i], &inverse_matrix[j][i]));
+ }
}
for (int i = 0; i < 3; ++i) {
JXL_QUIET_RETURN_IF_ERROR(visitor->F16(
diff --git a/third_party/jpeg-xl/lib/jxl/image_metadata.h b/third_party/jpeg-xl/lib/jxl/image_metadata.h
index be603a49f3..2b647cfa30 100644
--- a/third_party/jpeg-xl/lib/jxl/image_metadata.h
+++ b/third_party/jpeg-xl/lib/jxl/image_metadata.h
@@ -138,7 +138,7 @@ struct OpsinInverseMatrix : public Fields {
mutable bool all_default;
- float inverse_matrix[9];
+ Matrix3x3 inverse_matrix;
float opsin_biases[3];
float quant_biases[4];
};
diff --git a/third_party/jpeg-xl/lib/jxl/image_ops.cc b/third_party/jpeg-xl/lib/jxl/image_ops.cc
new file mode 100644
index 0000000000..36d19df938
--- /dev/null
+++ b/third_party/jpeg-xl/lib/jxl/image_ops.cc
@@ -0,0 +1,91 @@
+// Copyright (c) the JPEG XL Project Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "lib/jxl/image_ops.h"
+
+#include <cstddef>
+#include <cstring>
+
+#include "lib/jxl/base/common.h"
+#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/frame_dimensions.h"
+#include "lib/jxl/image.h"
+
+namespace jxl {
+
+void PadImageToBlockMultipleInPlace(Image3F* JXL_RESTRICT in,
+ size_t block_dim) {
+ const size_t xsize_orig = in->xsize();
+ const size_t ysize_orig = in->ysize();
+ const size_t xsize = RoundUpTo(xsize_orig, block_dim);
+ const size_t ysize = RoundUpTo(ysize_orig, block_dim);
+ // Expands image size to the originally-allocated size.
+ in->ShrinkTo(xsize, ysize);
+ for (size_t c = 0; c < 3; c++) {
+ for (size_t y = 0; y < ysize_orig; y++) {
+ float* JXL_RESTRICT row = in->PlaneRow(c, y);
+ for (size_t x = xsize_orig; x < xsize; x++) {
+ row[x] = row[xsize_orig - 1];
+ }
+ }
+ const float* JXL_RESTRICT row_src = in->ConstPlaneRow(c, ysize_orig - 1);
+ for (size_t y = ysize_orig; y < ysize; y++) {
+ memcpy(in->PlaneRow(c, y), row_src, xsize * sizeof(float));
+ }
+ }
+}
+
+static void DoDownsampleImage(const ImageF& input, size_t factor,
+ ImageF* output) {
+ JXL_ASSERT(factor != 1);
+ output->ShrinkTo(DivCeil(input.xsize(), factor),
+ DivCeil(input.ysize(), factor));
+ size_t in_stride = input.PixelsPerRow();
+ for (size_t y = 0; y < output->ysize(); y++) {
+ float* row_out = output->Row(y);
+ const float* row_in = input.Row(factor * y);
+ for (size_t x = 0; x < output->xsize(); x++) {
+ size_t cnt = 0;
+ float sum = 0;
+ for (size_t iy = 0; iy < factor && iy + factor * y < input.ysize();
+ iy++) {
+ for (size_t ix = 0; ix < factor && ix + factor * x < input.xsize();
+ ix++) {
+ sum += row_in[iy * in_stride + x * factor + ix];
+ cnt++;
+ }
+ }
+ row_out[x] = sum / cnt;
+ }
+ }
+}
+
+StatusOr<ImageF> DownsampleImage(const ImageF& image, size_t factor) {
+ ImageF downsampled;
+ // Allocate extra space to avoid a reallocation when padding.
+ JXL_ASSIGN_OR_RETURN(
+ downsampled, ImageF::Create(DivCeil(image.xsize(), factor) + kBlockDim,
+ DivCeil(image.ysize(), factor) + kBlockDim));
+ DoDownsampleImage(image, factor, &downsampled);
+ return downsampled;
+}
+
+StatusOr<Image3F> DownsampleImage(const Image3F& opsin, size_t factor) {
+ JXL_ASSERT(factor != 1);
+ // Allocate extra space to avoid a reallocation when padding.
+ Image3F downsampled;
+ JXL_ASSIGN_OR_RETURN(
+ downsampled, Image3F::Create(DivCeil(opsin.xsize(), factor) + kBlockDim,
+ DivCeil(opsin.ysize(), factor) + kBlockDim));
+ downsampled.ShrinkTo(downsampled.xsize() - kBlockDim,
+ downsampled.ysize() - kBlockDim);
+ for (size_t c = 0; c < 3; c++) {
+ DoDownsampleImage(opsin.Plane(c), factor, &downsampled.Plane(c));
+ }
+ return downsampled;
+}
+
+} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/image_ops.h b/third_party/jpeg-xl/lib/jxl/image_ops.h
index b2ce23f13d..84cf7dad76 100644
--- a/third_party/jpeg-xl/lib/jxl/image_ops.h
+++ b/third_party/jpeg-xl/lib/jxl/image_ops.h
@@ -9,16 +9,23 @@
// Operations on images.
#include <algorithm>
-#include <array>
+#include <cstddef>
+#include <cstdint>
#include <limits>
-#include <vector>
+#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/image.h"
namespace jxl {
+// Works for mixed image-like argument types.
+template <class Image1, class Image2>
+bool SameSize(const Image1& image1, const Image2& image2) {
+ return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize();
+}
+
template <typename T>
void CopyImageTo(const Plane<T>& from, Plane<T>* JXL_RESTRICT to) {
JXL_ASSERT(SameSize(from, *to));
@@ -102,76 +109,15 @@ void CopyImageToWithPadding(const Rect& from_rect, const T& from,
to);
}
-template <class ImageIn, class ImageOut>
-void Subtract(const ImageIn& image1, const ImageIn& image2, ImageOut* out) {
- using T = typename ImageIn::T;
- const size_t xsize = image1.xsize();
- const size_t ysize = image1.ysize();
- JXL_CHECK(xsize == image2.xsize());
- JXL_CHECK(ysize == image2.ysize());
-
- for (size_t y = 0; y < ysize; ++y) {
- const T* const JXL_RESTRICT row1 = image1.Row(y);
- const T* const JXL_RESTRICT row2 = image2.Row(y);
- T* const JXL_RESTRICT row_out = out->Row(y);
- for (size_t x = 0; x < xsize; ++x) {
- row_out[x] = row1[x] - row2[x];
- }
- }
-}
-
-// In-place.
-template <typename Tin, typename Tout>
-void SubtractFrom(const Plane<Tin>& what, Plane<Tout>* to) {
- const size_t xsize = what.xsize();
- const size_t ysize = what.ysize();
- for (size_t y = 0; y < ysize; ++y) {
- const Tin* JXL_RESTRICT row_what = what.ConstRow(y);
- Tout* JXL_RESTRICT row_to = to->Row(y);
- for (size_t x = 0; x < xsize; ++x) {
- row_to[x] -= row_what[x];
- }
- }
-}
-
-// In-place.
-template <typename Tin, typename Tout>
-void AddTo(const Plane<Tin>& what, Plane<Tout>* to) {
- const size_t xsize = what.xsize();
- const size_t ysize = what.ysize();
- for (size_t y = 0; y < ysize; ++y) {
- const Tin* JXL_RESTRICT row_what = what.ConstRow(y);
- Tout* JXL_RESTRICT row_to = to->Row(y);
- for (size_t x = 0; x < xsize; ++x) {
- row_to[x] += row_what[x];
- }
- }
-}
-
-template <typename Tin, typename Tout>
-void AddTo(Rect rectFrom, const Plane<Tin>& what, Rect rectTo,
- Plane<Tout>* to) {
- JXL_ASSERT(SameSize(rectFrom, rectTo));
- const size_t xsize = rectTo.xsize();
- const size_t ysize = rectTo.ysize();
- for (size_t y = 0; y < ysize; ++y) {
- const Tin* JXL_RESTRICT row_what = rectFrom.ConstRow(what, y);
- Tout* JXL_RESTRICT row_to = rectTo.Row(to, y);
- for (size_t x = 0; x < xsize; ++x) {
- row_to[x] += row_what[x];
- }
- }
-}
-
// Returns linear combination of two grayscale images.
template <typename T>
-Plane<T> LinComb(const T lambda1, const Plane<T>& image1, const T lambda2,
- const Plane<T>& image2) {
+StatusOr<Plane<T>> LinComb(const T lambda1, const Plane<T>& image1,
+ const T lambda2, const Plane<T>& image2) {
const size_t xsize = image1.xsize();
const size_t ysize = image1.ysize();
JXL_CHECK(xsize == image2.xsize());
JXL_CHECK(ysize == image2.ysize());
- Plane<T> out(xsize, ysize);
+ JXL_ASSIGN_OR_RETURN(Plane<T> out, Plane<T>::Create(xsize, ysize));
for (size_t y = 0; y < ysize; ++y) {
const T* const JXL_RESTRICT row1 = image1.Row(y);
const T* const JXL_RESTRICT row2 = image2.Row(y);
@@ -291,35 +237,6 @@ struct WrapRowUnchanged {
}
};
-// Sets "thickness" pixels on each border to "value". This is faster than
-// initializing the entire image and overwriting valid/interior pixels.
-template <typename T>
-void SetBorder(const size_t thickness, const T value, Plane<T>* image) {
- const size_t xsize = image->xsize();
- const size_t ysize = image->ysize();
- // Top: fill entire row
- for (size_t y = 0; y < std::min(thickness, ysize); ++y) {
- T* const JXL_RESTRICT row = image->Row(y);
- std::fill(row, row + xsize, value);
- }
-
- // Bottom: fill entire row
- for (size_t y = ysize - thickness; y < ysize; ++y) {
- T* const JXL_RESTRICT row = image->Row(y);
- std::fill(row, row + xsize, value);
- }
-
- // Left/right: fill the 'columns' on either side, but only if the image is
- // big enough that they don't already belong to the top/bottom rows.
- if (ysize >= 2 * thickness) {
- for (size_t y = thickness; y < ysize - thickness; ++y) {
- T* const JXL_RESTRICT row = image->Row(y);
- std::fill(row, row + thickness, value);
- std::fill(row + xsize - thickness, row + xsize, value);
- }
- }
-}
-
// Computes the minimum and maximum pixel value.
template <typename T>
void ImageMinMax(const Plane<T>& image, T* const JXL_RESTRICT min,
@@ -335,48 +252,6 @@ void ImageMinMax(const Plane<T>& image, T* const JXL_RESTRICT min,
}
}
-template <typename T>
-Plane<T> ImageFromPacked(const std::vector<T>& packed, const size_t xsize,
- const size_t ysize) {
- Plane<T> out(xsize, ysize);
- for (size_t y = 0; y < ysize; ++y) {
- T* const JXL_RESTRICT row = out.Row(y);
- const T* const JXL_RESTRICT packed_row = &packed[y * xsize];
- memcpy(row, packed_row, xsize * sizeof(T));
- }
- return out;
-}
-
-template <typename T>
-void Image3Max(const Image3<T>& image, std::array<T, 3>* out_max) {
- for (size_t c = 0; c < 3; ++c) {
- T max = std::numeric_limits<T>::min();
- for (size_t y = 0; y < image.ysize(); ++y) {
- const T* JXL_RESTRICT row = image.ConstPlaneRow(c, y);
- for (size_t x = 0; x < image.xsize(); ++x) {
- max = std::max(max, row[x]);
- }
- }
- (*out_max)[c] = max;
- }
-}
-
-template <typename T>
-std::vector<T> PackedFromImage(const Plane<T>& image, const Rect& rect) {
- const size_t xsize = rect.xsize();
- const size_t ysize = rect.ysize();
- std::vector<T> packed(xsize * ysize);
- for (size_t y = 0; y < rect.ysize(); ++y) {
- memcpy(&packed[y * xsize], rect.ConstRow(image, y), xsize * sizeof(T));
- }
- return packed;
-}
-
-template <typename T>
-std::vector<T> PackedFromImage(const Plane<T>& image) {
- return PackedFromImage(image, Rect(image));
-}
-
// Initializes all planes to the same "value".
template <typename T>
void FillImage(const T value, Image3<T>* image) {
@@ -391,28 +266,6 @@ void FillImage(const T value, Image3<T>* image) {
}
template <typename T>
-void FillPlane(const T value, Plane<T>* image) {
- for (size_t y = 0; y < image->ysize(); ++y) {
- T* JXL_RESTRICT row = image->Row(y);
- for (size_t x = 0; x < image->xsize(); ++x) {
- row[x] = value;
- }
- }
-}
-
-template <typename T>
-void FillImage(const T value, Image3<T>* image, Rect rect) {
- for (size_t c = 0; c < 3; ++c) {
- for (size_t y = 0; y < rect.ysize(); ++y) {
- T* JXL_RESTRICT row = rect.PlaneRow(image, c, y);
- for (size_t x = 0; x < rect.xsize(); ++x) {
- row[x] = value;
- }
- }
- }
-}
-
-template <typename T>
void FillPlane(const T value, Plane<T>* image, Rect rect) {
for (size_t y = 0; y < rect.ysize(); ++y) {
T* JXL_RESTRICT row = rect.Row(image, y);
@@ -432,22 +285,14 @@ void ZeroFillImage(Image3<T>* image) {
}
}
-template <typename T>
-void ZeroFillPlane(Plane<T>* image, Rect rect) {
- for (size_t y = 0; y < rect.ysize(); ++y) {
- T* JXL_RESTRICT row = rect.Row(image, y);
- memset(row, 0, rect.xsize() * sizeof(T));
- }
-}
-
// Same as above, but operates in-place. Assumes that the `in` image was
// allocated large enough.
void PadImageToBlockMultipleInPlace(Image3F* JXL_RESTRICT in,
size_t block_dim = kBlockDim);
// Downsamples an image by a given factor.
-void DownsampleImage(Image3F* opsin, size_t factor);
-void DownsampleImage(ImageF* image, size_t factor);
+StatusOr<Image3F> DownsampleImage(const Image3F& opsin, size_t factor);
+StatusOr<ImageF> DownsampleImage(const ImageF& image, size_t factor);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/image_ops_test.cc b/third_party/jpeg-xl/lib/jxl/image_ops_test.cc
index dfcb2292c5..6b308baab4 100644
--- a/third_party/jpeg-xl/lib/jxl/image_ops_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/image_ops_test.cc
@@ -8,43 +8,19 @@
#include <stdint.h>
#include <stdlib.h>
-#include <utility>
+#include <cstring>
+#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/random.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/cache_aligned.h"
#include "lib/jxl/image.h"
-#include "lib/jxl/image_test_utils.h"
#include "lib/jxl/testing.h"
namespace jxl {
namespace {
-template <typename T>
-void TestPacked(const size_t xsize, const size_t ysize) {
- Plane<T> image1(xsize, ysize);
- RandomFillImage(&image1);
- const std::vector<T>& packed = PackedFromImage(image1);
- const Plane<T>& image2 = ImageFromPacked(packed, xsize, ysize);
- JXL_EXPECT_OK(SamePixels(image1, image2, _));
-}
-
-TEST(ImageTest, TestPacked) {
- TestPacked<uint8_t>(1, 1);
- TestPacked<uint8_t>(7, 1);
- TestPacked<uint8_t>(1, 7);
-
- TestPacked<int16_t>(1, 1);
- TestPacked<int16_t>(7, 1);
- TestPacked<int16_t>(1, 7);
-
- TestPacked<uint16_t>(1, 1);
- TestPacked<uint16_t>(7, 1);
- TestPacked<uint16_t>(1, 7);
-
- TestPacked<float>(1, 1);
- TestPacked<float>(7, 1);
- TestPacked<float>(1, 7);
-}
-
// Ensure entire payload is readable/writable for various size/offset combos.
TEST(ImageTest, TestAllocator) {
Rng rng(0);
@@ -70,18 +46,18 @@ TEST(ImageTest, TestAllocator) {
template <typename T>
void TestFillImpl(Image3<T>* img, const char* layout) {
- FillImage(T(1), img);
+ FillImage(static_cast<T>(1), img);
for (size_t y = 0; y < img->ysize(); ++y) {
for (size_t c = 0; c < 3; ++c) {
T* JXL_RESTRICT row = img->PlaneRow(c, y);
for (size_t x = 0; x < img->xsize(); ++x) {
- if (row[x] != T(1)) {
+ if (row[x] != static_cast<T>(1)) {
printf("Not 1 at c=%" PRIuS " %" PRIuS ", %" PRIuS " (%" PRIuS
" x %" PRIuS ") (%s)\n",
c, x, y, img->xsize(), img->ysize(), layout);
abort();
}
- row[x] = T(2);
+ row[x] = static_cast<T>(2);
}
}
}
@@ -92,13 +68,13 @@ void TestFillImpl(Image3<T>* img, const char* layout) {
for (size_t y = 0; y < img->ysize(); ++y) {
T* JXL_RESTRICT row = img->PlaneRow(c, y);
for (size_t x = 0; x < img->xsize(); ++x) {
- if (row[x] != T(0)) {
+ if (row[x] != static_cast<T>(0)) {
printf("Not 0 at c=%" PRIuS " %" PRIuS ", %" PRIuS " (%" PRIuS
" x %" PRIuS ") (%s)\n",
c, x, y, img->xsize(), img->ysize(), layout);
abort();
}
- row[x] = T(3);
+ row[x] = static_cast<T>(3);
}
}
}
@@ -108,12 +84,8 @@ template <typename T>
void TestFillT() {
for (uint32_t xsize : {0, 1, 15, 16, 31, 32}) {
for (uint32_t ysize : {0, 1, 15, 16, 31, 32}) {
- Image3<T> image(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(Image3<T> image, Image3<T>::Create(xsize, ysize));
TestFillImpl(&image, "size ctor");
-
- Image3<T> planar(Plane<T>(xsize, ysize), Plane<T>(xsize, ysize),
- Plane<T>(xsize, ysize));
- TestFillImpl(&planar, "planar");
}
}
}
@@ -127,7 +99,7 @@ TEST(ImageTest, TestFill) {
}
TEST(ImageTest, CopyImageToWithPaddingTest) {
- Plane<uint32_t> src(100, 61);
+ JXL_ASSIGN_OR_DIE(Plane<uint32_t> src, Plane<uint32_t>::Create(100, 61));
for (size_t y = 0; y < src.ysize(); y++) {
for (size_t x = 0; x < src.xsize(); x++) {
src.Row(y)[x] = x * 1000 + y;
@@ -136,7 +108,7 @@ TEST(ImageTest, CopyImageToWithPaddingTest) {
Rect src_rect(10, 20, 30, 40);
EXPECT_TRUE(src_rect.IsInside(src));
- Plane<uint32_t> dst(60, 50);
+ JXL_ASSIGN_OR_DIE(Plane<uint32_t> dst, Plane<uint32_t>::Create(60, 50));
FillImage(0u, &dst);
Rect dst_rect(20, 5, 30, 40);
EXPECT_TRUE(dst_rect.IsInside(dst));
diff --git a/third_party/jpeg-xl/lib/jxl/image_test_utils.h b/third_party/jpeg-xl/lib/jxl/image_test_utils.h
index e7d72285e6..7bb146866e 100644
--- a/third_party/jpeg-xl/lib/jxl/image_test_utils.h
+++ b/third_party/jpeg-xl/lib/jxl/image_test_utils.h
@@ -6,10 +6,6 @@
#ifndef LIB_JXL_IMAGE_TEST_UTILS_H_
#define LIB_JXL_IMAGE_TEST_UTILS_H_
-#ifndef __STDC_FORMAT_MACROS
-#define __STDC_FORMAT_MACROS
-#endif
-
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
@@ -37,7 +33,8 @@ bool SamePixels(const Plane<T>& image1, const Plane<T>& image2,
for (size_t x = rect.x0(); x < rect.xsize(); ++x) {
if (row1[x] != row2[x]) {
failures << "pixel mismatch" << x << ", " << y << ": "
- << double(row1[x]) << " != " << double(row2[x]) << "\n";
+ << static_cast<double>(row1[x])
+ << " != " << static_cast<double>(row2[x]) << "\n";
if (++mismatches > 4) {
return false;
}
@@ -66,7 +63,7 @@ bool VerifyRelativeError(const Plane<T>& expected, const Plane<T>& actual,
const double threshold_l1,
const double threshold_relative,
std::stringstream& failures, const intptr_t border = 0,
- const size_t c = 0) {
+ const int c = 0) {
JXL_CHECK(SameSize(expected, actual));
const intptr_t xsize = expected.xsize();
const intptr_t ysize = expected.ysize();
@@ -89,7 +86,8 @@ bool VerifyRelativeError(const Plane<T>& expected, const Plane<T>& actual,
max_l1 = std::max(max_l1, l1);
}
} else {
- const double relative = l1 / std::abs(double(row_expected[x]));
+ const double relative =
+ l1 / std::abs(static_cast<double>(row_expected[x]));
if (l1 > threshold_l1 && relative > threshold_relative) {
// Fails both tolerances => will exit below, update max_*.
any_bad = true;
@@ -104,13 +102,11 @@ bool VerifyRelativeError(const Plane<T>& expected, const Plane<T>& actual,
}
// Never had a valid relative value, don't print it.
if (max_relative < 0) {
- fprintf(stderr, "c=%" PRIu64 ": max +/- %E exceeds +/- %.2E\n",
- static_cast<uint64_t>(c), max_l1, threshold_l1);
+ fprintf(stderr, "c=%d: max +/- %E exceeds +/- %.2E\n", c, max_l1,
+ threshold_l1);
} else {
- fprintf(stderr,
- "c=%" PRIu64 ": max +/- %E, x %E exceeds +/- %.2E, x %.2E\n",
- static_cast<uint64_t>(c), max_l1, max_relative, threshold_l1,
- threshold_relative);
+ fprintf(stderr, "c=%d: max +/- %E, x %E exceeds +/- %.2E, x %.2E\n", c,
+ max_l1, max_relative, threshold_l1, threshold_relative);
}
// Dump the expected image and actual image if the region is small enough.
const intptr_t kMaxTestDumpSize = 16;
@@ -134,7 +130,8 @@ bool VerifyRelativeError(const Plane<T>& expected, const Plane<T>& actual,
bool bad = l1 > threshold_l1;
if (row_expected[x] > 1E-10) {
- const double relative = l1 / std::abs(double(row_expected[x]));
+ const double relative =
+ l1 / std::abs(static_cast<double>(row_expected[x]));
bad &= relative > threshold_relative;
}
if (bad) {
@@ -157,7 +154,8 @@ bool VerifyRelativeError(const Plane<T>& expected, const Plane<T>& actual,
bool bad = l1 > threshold_l1;
if (row_expected[x] > 1E-10) {
- const double relative = l1 / std::abs(double(row_expected[x]));
+ const double relative =
+ l1 / std::abs(static_cast<double>(row_expected[x]));
bad &= relative > threshold_relative;
}
if (bad) {
@@ -179,9 +177,9 @@ bool VerifyRelativeError(const Image3<T>& expected, const Image3<T>& actual,
std::stringstream& failures,
const intptr_t border = 0) {
for (size_t c = 0; c < 3; ++c) {
- bool ok =
- VerifyRelativeError(expected.Plane(c), actual.Plane(c), threshold_l1,
- threshold_relative, failures, border, c);
+ bool ok = VerifyRelativeError(expected.Plane(c), actual.Plane(c),
+ threshold_l1, threshold_relative, failures,
+ border, static_cast<int>(c));
if (!ok) {
return false;
}
@@ -216,8 +214,8 @@ template <typename T>
typename std::enable_if<std::is_integral<T>::value>::type RandomFillImage(
Plane<T>* image) {
Rng rng(129);
- GenerateImage(rng, image, int64_t(0),
- int64_t(std::numeric_limits<T>::max()) + 1);
+ GenerateImage(rng, image, static_cast<int64_t>(0),
+ static_cast<int64_t>(std::numeric_limits<T>::max()) + 1);
}
JXL_INLINE void RandomFillImage(Plane<float>* image) {
@@ -236,8 +234,8 @@ template <typename T>
typename std::enable_if<std::is_integral<T>::value>::type RandomFillImage(
Image3<T>* image) {
Rng rng(129);
- GenerateImage(rng, image, int64_t(0),
- int64_t(std::numeric_limits<T>::max()) + 1);
+ GenerateImage(rng, image, static_cast<int64_t>(0),
+ static_cast<int64_t>(std::numeric_limits<T>::max()) + 1);
}
JXL_INLINE void RandomFillImage(Image3F* image) {
diff --git a/third_party/jpeg-xl/lib/jxl/inverse_mtf-inl.h b/third_party/jpeg-xl/lib/jxl/inverse_mtf-inl.h
index fcb01d7396..60ea69ddbd 100644
--- a/third_party/jpeg-xl/lib/jxl/inverse_mtf-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/inverse_mtf-inl.h
@@ -82,7 +82,7 @@ HWY_AFTER_NAMESPACE();
namespace jxl {
inline void InverseMoveToFrontTransform(uint8_t* v, int v_len) {
- return HWY_STATIC_DISPATCH(InverseMoveToFrontTransform)(v, v_len);
+ HWY_STATIC_DISPATCH(InverseMoveToFrontTransform)(v, v_len);
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/jpeg/dec_jpeg_data_writer.cc b/third_party/jpeg-xl/lib/jxl/jpeg/dec_jpeg_data_writer.cc
index 64560d9ab0..31bb2dda23 100644
--- a/third_party/jpeg-xl/lib/jxl/jpeg/dec_jpeg_data_writer.cc
+++ b/third_party/jpeg-xl/lib/jxl/jpeg/dec_jpeg_data_writer.cc
@@ -18,6 +18,7 @@
#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/common.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/image_bundle.h"
#include "lib/jxl/jpeg/dec_jpeg_serialization_state.h"
@@ -42,7 +43,7 @@ const size_t kJpegBitWriterChunkSize = 16384;
// Returns non-zero if and only if x has a zero byte, i.e. one of
// x & 0xff, x & 0xff00, ..., x & 0xff00000000000000 is zero.
-static JXL_INLINE uint64_t HasZeroByte(uint64_t x) {
+JXL_INLINE uint64_t HasZeroByte(uint64_t x) {
return (x - 0x0101010101010101ULL) & ~x & 0x8080808080808080ULL;
}
@@ -57,7 +58,7 @@ void JpegBitWriterInit(JpegBitWriter* bw,
bw->data = bw->chunk.buffer->data();
}
-static JXL_NOINLINE void SwapBuffer(JpegBitWriter* bw) {
+JXL_NOINLINE void SwapBuffer(JpegBitWriter* bw) {
bw->chunk.len = bw->pos;
bw->output->emplace_back(std::move(bw->chunk));
bw->chunk = OutputChunk(kJpegBitWriterChunkSize);
@@ -65,7 +66,7 @@ static JXL_NOINLINE void SwapBuffer(JpegBitWriter* bw) {
bw->pos = 0;
}
-static JXL_INLINE void Reserve(JpegBitWriter* bw, size_t n_bytes) {
+JXL_INLINE void Reserve(JpegBitWriter* bw, size_t n_bytes) {
if (JXL_UNLIKELY((bw->pos + n_bytes) > kJpegBitWriterChunkSize)) {
SwapBuffer(bw);
}
@@ -77,14 +78,14 @@ static JXL_INLINE void Reserve(JpegBitWriter* bw, size_t n_bytes) {
* This method is "careless" - caller must make sure that there is enough
* space in the output buffer. Emits up to 2 bytes to buffer.
*/
-static JXL_INLINE void EmitByte(JpegBitWriter* bw, int byte) {
+JXL_INLINE void EmitByte(JpegBitWriter* bw, int byte) {
bw->data[bw->pos] = byte;
bw->data[bw->pos + 1] = 0;
bw->pos += (byte != 0xFF ? 1 : 2);
}
-static JXL_INLINE void DischargeBitBuffer(JpegBitWriter* bw, int nbits,
- uint64_t bits) {
+JXL_INLINE void DischargeBitBuffer(JpegBitWriter* bw, int nbits,
+ uint64_t bits) {
// At this point we are ready to emit the put_buffer to the output.
// The JPEG format requires that after every 0xff byte in the entropy
// coded section, there is a zero byte, therefore we first check if any of
@@ -111,7 +112,7 @@ static JXL_INLINE void DischargeBitBuffer(JpegBitWriter* bw, int nbits,
bw->put_buffer = bits << bw->put_bits;
}
-static JXL_INLINE void WriteBits(JpegBitWriter* bw, int nbits, uint64_t bits) {
+JXL_INLINE void WriteBits(JpegBitWriter* bw, int nbits, uint64_t bits) {
JXL_DASSERT(nbits > 0);
bw->put_bits -= nbits;
if (JXL_UNLIKELY(bw->put_bits < 0)) {
@@ -142,12 +143,14 @@ bool JumpToByteBoundary(JpegBitWriter* bw, const uint8_t** pad_bits,
} else {
pad_pattern = 0;
const uint8_t* src = *pad_bits;
- // TODO(eustas): bitwise reading looks insanely ineffective...
+ // TODO(eustas): bitwise reading looks insanely ineffective!
while (n_bits--) {
pad_pattern <<= 1;
if (src >= pad_bits_end) return false;
- // TODO(eustas): DCHECK *src == {0, 1}
- pad_pattern |= !!*(src++);
+ uint8_t bit = *src;
+ src++;
+ JXL_ASSERT(bit <= 1);
+ pad_pattern |= bit;
}
*pad_bits = src;
}
@@ -187,21 +190,20 @@ void DCTCodingStateInit(DCTCodingState* s) {
s->refinement_bits_.reserve(64);
}
-static JXL_INLINE void WriteSymbol(int symbol, HuffmanCodeTable* table,
- JpegBitWriter* bw) {
+JXL_INLINE void WriteSymbol(int symbol, HuffmanCodeTable* table,
+ JpegBitWriter* bw) {
WriteBits(bw, table->depth[symbol], table->code[symbol]);
}
-static JXL_INLINE void WriteSymbolBits(int symbol, HuffmanCodeTable* table,
- JpegBitWriter* bw, int nbits,
- uint64_t bits) {
+JXL_INLINE void WriteSymbolBits(int symbol, HuffmanCodeTable* table,
+ JpegBitWriter* bw, int nbits, uint64_t bits) {
WriteBits(bw, nbits + table->depth[symbol],
bits | (table->code[symbol] << nbits));
}
// Emit all buffered data to the bit stream using the given Huffman code and
// bit writer.
-static JXL_INLINE void Flush(DCTCodingState* s, JpegBitWriter* bw) {
+JXL_INLINE void Flush(DCTCodingState* s, JpegBitWriter* bw) {
if (s->eob_run_ > 0) {
Reserve(bw, 16);
int nbits = FloorLog2Nonzero<uint32_t>(s->eob_run_);
@@ -233,11 +235,9 @@ static JXL_INLINE void Flush(DCTCodingState* s, JpegBitWriter* bw) {
// Buffer some more data at the end-of-band (the last non-zero or newly
// non-zero coefficient within the [Ss, Se] spectral band).
-static JXL_INLINE void BufferEndOfBand(DCTCodingState* s,
- HuffmanCodeTable* ac_huff,
- const int* new_bits_array,
- size_t new_bits_count,
- JpegBitWriter* bw) {
+JXL_INLINE void BufferEndOfBand(DCTCodingState* s, HuffmanCodeTable* ac_huff,
+ const int* new_bits_array,
+ size_t new_bits_count, JpegBitWriter* bw) {
if (s->eob_run_ == 0) {
s->cur_ac_huff_ = ac_huff;
}
@@ -530,7 +530,7 @@ bool EncodeDCTBlockSequential(const coeff_t* coeffs, HuffmanCodeTable* dc_huff,
int dc_nbits = (temp2 == 0) ? 0 : (FloorLog2Nonzero<uint32_t>(temp2) + 1);
WriteSymbol(dc_nbits, dc_huff, bw);
-#if false
+#if JXL_FALSE
// If the input is corrupt, this could be triggered. Checking is
// costly though, so it makes more sense to avoid this branch.
// (producing a corrupt JPEG when the input is corrupt, instead
@@ -543,7 +543,8 @@ bool EncodeDCTBlockSequential(const coeff_t* coeffs, HuffmanCodeTable* dc_huff,
int16_t r = 0;
for (size_t i = 1; i < 64; i++) {
- if ((temp = coeffs[kJPEGNaturalOrder[i]]) == 0) {
+ temp = coeffs[kJPEGNaturalOrder[i]];
+ if (temp == 0) {
r++;
} else {
temp2 = temp >> (8 * sizeof(coeff_t) - 1);
@@ -611,7 +612,8 @@ bool EncodeDCTBlockProgressive(const coeff_t* coeffs, HuffmanCodeTable* dc_huff,
}
int r = 0;
for (int k = Ss; k <= Se; ++k) {
- if ((temp = coeffs[kJPEGNaturalOrder[k]]) == 0) {
+ temp = coeffs[kJPEGNaturalOrder[k]];
+ if (temp == 0) {
r++;
continue;
}
@@ -884,8 +886,8 @@ SerializationStatus JXL_NOINLINE DoEncodeScan(const JPEGData& jpg,
return SerializationStatus::DONE;
}
-static SerializationStatus JXL_INLINE EncodeScan(const JPEGData& jpg,
- SerializationState* state) {
+SerializationStatus JXL_INLINE EncodeScan(const JPEGData& jpg,
+ SerializationState* state) {
const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
const bool is_progressive = state->is_progressive;
const int Al = is_progressive ? scan_info.Al : 0;
diff --git a/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data.cc b/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data.cc
index 97342553e5..d311908415 100644
--- a/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data.cc
+++ b/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data.cc
@@ -8,7 +8,7 @@
#include <brotli/encode.h>
#include "lib/jxl/codec_in_out.h"
-#include "lib/jxl/enc_fields.h"
+#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/image_bundle.h"
#include "lib/jxl/jpeg/enc_jpeg_data_reader.h"
#include "lib/jxl/luminance.h"
@@ -76,7 +76,8 @@ bool GetMarkerPayload(const uint8_t* data, size_t size, ByteSpan* payload) {
Status DetectBlobs(jpeg::JPEGData& jpeg_data) {
JXL_DASSERT(jpeg_data.app_data.size() == jpeg_data.app_marker_type.size());
- bool have_exif = false, have_xmp = false;
+ bool have_exif = false;
+ bool have_xmp = false;
for (size_t i = 0; i < jpeg_data.app_data.size(); i++) {
auto& marker = jpeg_data.app_data[i];
if (marker.empty() || marker[0] != kApp1) {
@@ -165,7 +166,7 @@ Status ParseChunkedMarker(const jpeg::JPEGData& src, uint8_t marker_type,
if (!presence[index]) {
return JXL_FAILURE("Missing chunk.");
}
- chunks[index].AppendTo(output);
+ chunks[index].AppendTo(*output);
}
return true;
@@ -173,7 +174,7 @@ Status ParseChunkedMarker(const jpeg::JPEGData& src, uint8_t marker_type,
Status SetBlobsFromJpegData(const jpeg::JPEGData& jpeg_data, Blobs* blobs) {
for (size_t i = 0; i < jpeg_data.app_data.size(); i++) {
- auto& marker = jpeg_data.app_data[i];
+ const auto& marker = jpeg_data.app_data[i];
if (marker.empty() || marker[0] != kApp1) {
continue;
}
@@ -210,7 +211,7 @@ Status SetBlobsFromJpegData(const jpeg::JPEGData& jpeg_data, Blobs* blobs) {
return true;
}
-static inline bool IsJPG(const Span<const uint8_t> bytes) {
+inline bool IsJPG(const Span<const uint8_t> bytes) {
return bytes.size() >= 2 && bytes[0] == 0xFF && bytes[1] == 0xD8;
}
@@ -239,14 +240,16 @@ Status SetChromaSubsamplingFromJpegData(const JPEGData& jpg,
return JXL_FAILURE("Cannot recompress JPEGs with neither 1 nor 3 channels");
}
if (nbcomp == 3) {
- uint8_t hsample[3], vsample[3];
+ uint8_t hsample[3];
+ uint8_t vsample[3];
for (size_t i = 0; i < nbcomp; i++) {
hsample[i] = jpg.components[i].h_samp_factor;
vsample[i] = jpg.components[i].v_samp_factor;
}
JXL_RETURN_IF_ERROR(cs->Set(hsample, vsample));
} else if (nbcomp == 1) {
- uint8_t hsample[3], vsample[3];
+ uint8_t hsample[3];
+ uint8_t vsample[3];
for (size_t i = 0; i < 3; i++) {
hsample[i] = jpg.components[0].h_samp_factor;
vsample[i] = jpg.components[0].v_samp_factor;
@@ -330,7 +333,7 @@ Status EncodeJPEGData(JPEGData& jpeg_data, std::vector<uint8_t>* bytes,
{
PaddedBytes serialized_jpeg_data = std::move(writer).TakeBytes();
bytes->reserve(serialized_jpeg_data.size() + brotli_capacity);
- Bytes(serialized_jpeg_data).AppendTo(bytes);
+ Bytes(serialized_jpeg_data).AppendTo(*bytes);
}
BrotliEncoderState* brotli_enc =
@@ -394,8 +397,9 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes, CodecInOut* io) {
io->metadata.m.SetIntensityTarget(kDefaultIntensityTarget);
io->metadata.m.SetUintSamples(BITS_IN_JSAMPLE);
- io->SetFromImage(Image3F(jpeg_data->width, jpeg_data->height),
- io->metadata.m.color_encoding);
+ JXL_ASSIGN_OR_RETURN(Image3F tmp,
+ Image3F::Create(jpeg_data->width, jpeg_data->height));
+ io->SetFromImage(std::move(tmp), io->metadata.m.color_encoding);
SetIntensityTarget(&io->metadata.m);
return true;
}
diff --git a/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data_reader.cc b/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data_reader.cc
index ce64dae47b..d1e8476db6 100644
--- a/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data_reader.cc
+++ b/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data_reader.cc
@@ -23,7 +23,7 @@ namespace jxl {
namespace jpeg {
namespace {
-static const int kBrunsliMaxSampling = 15;
+const int kBrunsliMaxSampling = 15;
// Macros for commonly used error conditions.
@@ -234,7 +234,7 @@ bool ProcessDHT(const uint8_t* data, const size_t len, JpegReadMode mode,
JPEGHuffmanCode huff;
huff.slot_id = ReadUint8(data, pos);
int huffman_index = huff.slot_id;
- int is_ac_table = (huff.slot_id & 0x10) != 0;
+ bool is_ac_table = ((huff.slot_id & 0x10) != 0);
HuffmanTableEntry* huff_lut;
if (is_ac_table) {
huffman_index -= 0x10;
@@ -292,7 +292,7 @@ bool ProcessDHT(const uint8_t* data, const size_t len, JpegReadMode mode,
}
huff.is_last = (*pos == start_pos + marker_len);
if (mode == JpegReadMode::kReadAll) {
- BuildJpegHuffmanTable(&huff.counts[0], &huff.values[0], huff_lut);
+ BuildJpegHuffmanTable(huff.counts.data(), huff.values.data(), huff_lut);
}
jpg->huffman_code.push_back(huff);
}
@@ -419,7 +419,7 @@ struct BitReaderState {
if (bits_left_ <= 16) {
while (bits_left_ <= 56) {
val_ <<= 8;
- val_ |= (uint64_t)GetNextByte();
+ val_ |= static_cast<uint64_t>(GetNextByte());
bits_left_ += 8;
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data_reader.h b/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data_reader.h
index 3fad820e9d..4389b2ffe3 100644
--- a/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data_reader.h
+++ b/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data_reader.h
@@ -27,7 +27,7 @@ enum class JpegReadMode {
// If mode is kReadHeader, it fills in only the image dimensions in *jpg.
// Returns false if the data is not valid JPEG, or if it contains an unsupported
// JPEG feature.
-bool ReadJpeg(const uint8_t* data, const size_t len, JpegReadMode mode,
+bool ReadJpeg(const uint8_t* data, size_t len, JpegReadMode mode,
JPEGData* jpg);
} // namespace jpeg
diff --git a/third_party/jpeg-xl/lib/jxl/jpeg/jpeg_data.cc b/third_party/jpeg-xl/lib/jxl/jpeg/jpeg_data.cc
index 6744e6935a..aeb9914cca 100644
--- a/third_party/jpeg-xl/lib/jxl/jpeg/jpeg_data.cc
+++ b/third_party/jpeg-xl/lib/jxl/jpeg/jpeg_data.cc
@@ -5,6 +5,8 @@
#include "lib/jxl/jpeg/jpeg_data.h"
+#include <jxl/types.h>
+
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/common.h" // kMaxNumPasses, JPEGXL_ENABLE_TRANSCODE_JPEG
@@ -214,7 +216,7 @@ Status JPEGData::VisitFields(Visitor* visitor) {
huffman_code.resize(num_huff);
}
for (JPEGHuffmanCode& hc : huffman_code) {
- bool is_ac = hc.slot_id >> 4;
+ bool is_ac = ((hc.slot_id >> 4) != 0);
uint32_t id = hc.slot_id & 0xF;
JXL_RETURN_IF_ERROR(visitor->Bool(false, &is_ac));
JXL_RETURN_IF_ERROR(visitor->Bits(2, 0, &id));
@@ -240,7 +242,8 @@ Status JPEGData::VisitFields(Visitor* visitor) {
JXL_RETURN_IF_ERROR(visitor->U32(Bits(2), BitsOffset(2, 4),
BitsOffset(4, 8), BitsOffset(8, 1), 0,
&hc.values[i]));
- value_slots[hc.values[i] >> 6] |= (uint64_t)1 << (hc.values[i] & 0x3F);
+ value_slots[hc.values[i] >> 6] |= static_cast<uint64_t>(1)
+ << (hc.values[i] & 0x3F);
}
if (hc.values[num_symbols - 1] != kJpegHuffmanAlphabetSize) {
return JXL_FAILURE("Missing EOI symbol");
@@ -361,13 +364,13 @@ Status JPEGData::VisitFields(Visitor* visitor) {
for (uint32_t i = 0; i < nbit; i++) {
bool bbit = false;
JXL_RETURN_IF_ERROR(visitor->Bool(false, &bbit));
- padding_bits.push_back(bbit);
+ padding_bits.push_back(TO_JXL_BOOL(bbit));
}
} else {
for (uint8_t& bit : padding_bits) {
- bool bbit = bit;
+ bool bbit = FROM_JXL_BOOL(bit);
JXL_RETURN_IF_ERROR(visitor->Bool(false, &bbit));
- bit = bbit;
+ bit = TO_JXL_BOOL(bbit);
}
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/jxl_test.cc b/third_party/jpeg-xl/lib/jxl/jxl_test.cc
index a91dbd0672..b0933d5d50 100644
--- a/third_party/jpeg-xl/lib/jxl/jxl_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/jxl_test.cc
@@ -33,7 +33,6 @@
#include "lib/jxl/codec_in_out.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/common.h" // JXL_HIGH_PRECISION
-#include "lib/jxl/enc_butteraugli_comparator.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/fake_parallel_runner_testonly.h"
#include "lib/jxl/image.h"
@@ -72,7 +71,7 @@ TEST(JxlTest, RoundtripSinglePixelWithAlpha) {
TestImage t;
t.SetDimensions(1, 1).SetChannels(4).AddFrame().ZeroFill();
PackedPixelFile ppf_out;
- EXPECT_EQ(Roundtrip(t.ppf(), {}, {}, nullptr, &ppf_out), 59);
+ EXPECT_EQ(Roundtrip(t.ppf(), {}, {}, nullptr, &ppf_out), 58);
}
// Changing serialized signature causes Decode to fail.
@@ -87,7 +86,7 @@ TEST(JxlTest, RoundtripMarker) {
compressed[i] ^= 0xFF;
PackedPixelFile ppf_out;
EXPECT_FALSE(extras::DecodeImageJXL(compressed.data(), compressed.size(),
- {}, /*decodec_bytes=*/nullptr,
+ {}, /* decoded_bytes */ nullptr,
&ppf_out));
}
}
@@ -121,7 +120,7 @@ TEST(JxlTest, RoundtripSmallD1) {
{
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), {}, {}, pool, &ppf_out), 916, 40);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.888));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.888);
}
// With a lower intensity target than the default, the bitrate should be
@@ -131,7 +130,7 @@ TEST(JxlTest, RoundtripSmallD1) {
{
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), {}, {}, pool, &ppf_out), 745, 20);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.3));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.3);
EXPECT_EQ(ppf_out.info.intensity_target, t.ppf().info.intensity_target);
}
}
@@ -147,8 +146,8 @@ TEST(JxlTest, RoundtripResample2) {
cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 3); // kFalcon
PackedPixelFile ppf_out;
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 18500, 200);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(90));
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 17300, 500);
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 90);
}
TEST(JxlTest, RoundtripResample2Slow) {
@@ -165,7 +164,7 @@ TEST(JxlTest, RoundtripResample2Slow) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 3888, 200);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(250));
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 250);
}
TEST(JxlTest, RoundtripResample2MT) {
@@ -180,8 +179,8 @@ TEST(JxlTest, RoundtripResample2MT) {
cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 3); // kFalcon
PackedPixelFile ppf_out;
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 223310, 2000);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(340));
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 203300, 2000);
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 340);
}
// Roundtrip the image using a parallel runner that executes single-threaded but
@@ -237,7 +236,7 @@ TEST(JxlTest, RoundtripResample4) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 5758, 100);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(22));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 22);
}
TEST(JxlTest, RoundtripResample8) {
@@ -252,7 +251,7 @@ TEST(JxlTest, RoundtripResample8) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 2036, 50);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(50));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 50);
}
TEST(JxlTest, RoundtripUnalignedD2) {
@@ -270,7 +269,7 @@ TEST(JxlTest, RoundtripUnalignedD2) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 506, 30);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.72));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.72);
}
TEST(JxlTest, RoundtripMultiGroup) {
@@ -289,8 +288,8 @@ TEST(JxlTest, RoundtripMultiGroup) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), expected_size,
700);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out),
- IsSlightlyBelow(expected_distance));
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out),
+ expected_distance);
};
auto run_kitten = std::async(std::launch::async, test, SpeedTier::kKitten,
@@ -339,10 +338,11 @@ TEST(JxlTest, RoundtripRGBToGrayscale) {
ASSERT_TRUE(io.frames[0].TransformTo(srgb_gamma, *JxlGetDefaultCms()));
io.metadata.m.color_encoding = io2.Main().c_current();
io.Main().OverrideProfile(io2.Main().c_current());
- EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr, &pool),
- IsSlightlyBelow(1.36));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr, &pool),
+ 1.4);
}
TEST(JxlTest, RoundtripLargeFast) {
@@ -355,8 +355,57 @@ TEST(JxlTest, RoundtripLargeFast) {
cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 7); // kSquirrel
PackedPixelFile ppf_out;
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 492867, 5000);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(78));
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 503000, 12000);
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 78);
+}
+
+TEST(JxlTest, JXL_X86_64_TEST(RoundtripLargeEmptyModular)) {
+ ThreadPoolForTests pool(8);
+ TestImage t;
+ t.SetDimensions(4096, 4096).SetDataType(JXL_TYPE_UINT8).SetChannels(4);
+ TestImage::Frame frame = t.AddFrame();
+ frame.ZeroFill();
+ for (size_t c = 0; c < 4; ++c) {
+ for (size_t y = 0; y < 1024; y += (c + 1)) {
+ for (size_t x = 0; x < 1024; x += ((y % 4) + 3)) {
+ frame.SetValue(y, x, c, 0.88);
+ }
+ }
+ }
+
+ JXLCompressParams cparams;
+ cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 1);
+ cparams.AddOption(JXL_ENC_FRAME_SETTING_MODULAR, 1);
+ cparams.AddOption(JXL_ENC_FRAME_SETTING_RESPONSIVE, 1);
+ cparams.AddOption(JXL_ENC_FRAME_SETTING_DECODING_SPEED, 2);
+
+ PackedPixelFile ppf_out;
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 3474795,
+ 100000);
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out),
+#if JXL_HIGH_PRECISION
+ 2050
+#else
+ 12100
+#endif
+ );
+}
+
+TEST(JxlTest, RoundtripOutputColorSpace) {
+ ThreadPoolForTests pool(8);
+ const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
+ TestImage t;
+ t.DecodeFromBytes(orig).ClearMetadata();
+
+ JXLCompressParams cparams;
+ cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 7); // kSquirrel
+
+ JXLDecompressParams dparams;
+ dparams.color_space = "RGB_D65_DCI_Rel_709";
+ PackedPixelFile ppf_out;
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), 503000,
+ 12000);
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 78);
}
TEST(JxlTest, RoundtripDotsForceEpf) {
@@ -373,7 +422,7 @@ TEST(JxlTest, RoundtripDotsForceEpf) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 41355, 300);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(18));
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 18);
}
// Checks for differing size/distance in two consecutive runs of distance 2,
@@ -453,7 +502,7 @@ TEST(JxlTest, RoundtripSmallNL) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), {}, {}, pool, &ppf_out), 916, 45);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.82));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.82);
}
TEST(JxlTest, RoundtripNoGaborishNoAR) {
@@ -469,7 +518,7 @@ TEST(JxlTest, RoundtripNoGaborishNoAR) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 41142, 400);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.8));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.8);
}
TEST(JxlTest, RoundtripSmallNoGaborish) {
@@ -487,7 +536,7 @@ TEST(JxlTest, RoundtripSmallNoGaborish) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 1006, 20);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.1));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.1);
}
TEST(JxlTest, RoundtripSmallPatchesAlpha) {
@@ -513,7 +562,7 @@ TEST(JxlTest, RoundtripSmallPatchesAlpha) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 597, 100);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.018f));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.018f);
}
TEST(JxlTest, RoundtripSmallPatches) {
@@ -538,17 +587,17 @@ TEST(JxlTest, RoundtripSmallPatches) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 486, 100);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.018f));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.018f);
}
// TODO(szabadka) Add encoder and decoder API functions that accept frame
// buffers in arbitrary unsigned and floating point formats, and then roundtrip
// test the lossless codepath to make sure the exact binary representations
// are preserved.
-#if 0
+#if JXL_FALSE
TEST(JxlTest, RoundtripImageBundleOriginalBits) {
// Image does not matter, only io.metadata.m and io2.metadata.m are tested.
- Image3F image(1, 1);
+ JXL_ASSIGN_OR_DIE(Image3F image, Image3F::Create(1, 1));
ZeroFillImage(&image);
CodecInOut io;
io.metadata.m.color_encoding = ColorEncoding::LinearSRGB();
@@ -639,10 +688,11 @@ TEST(JxlTest, RoundtripGrayscale) {
EXPECT_TRUE(io2.Main().IsGray());
EXPECT_LE(compressed.size(), 7000u);
- EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(1.6));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 1.6);
}
// Test with larger butteraugli distance and other settings enabled so
@@ -658,10 +708,11 @@ TEST(JxlTest, RoundtripGrayscale) {
EXPECT_TRUE(io2.Main().IsGray());
EXPECT_LE(compressed.size(), 1300u);
- EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(6.7));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 6.7);
}
{
@@ -678,10 +729,11 @@ TEST(JxlTest, RoundtripGrayscale) {
EXPECT_FALSE(io2.Main().IsGray());
EXPECT_LE(compressed.size(), 7000u);
- EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(1.6));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 1.6);
}
}
@@ -706,7 +758,7 @@ TEST(JxlTest, RoundtripAlpha) {
std::vector<uint8_t> compressed;
EXPECT_TRUE(test::EncodeFile(cparams, &io, &compressed));
- EXPECT_LE(compressed.size(), 10077u);
+ EXPECT_LE(compressed.size(), 20000u);
for (bool use_image_callback : {false, true}) {
for (bool unpremul_alpha : {false, true}) {
@@ -715,10 +767,11 @@ TEST(JxlTest, RoundtripAlpha) {
dparams.use_image_callback = use_image_callback;
dparams.unpremultiply_alpha = unpremul_alpha;
EXPECT_TRUE(test::DecodeFile(dparams, Bytes(compressed), &io2));
- EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames,
- ButteraugliParams(), *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(1.15));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 1.15);
}
}
}
@@ -781,7 +834,8 @@ bool UnpremultiplyAlpha(CodecInOut& io) {
TEST(JxlTest, RoundtripAlphaPremultiplied) {
const std::vector<uint8_t> orig =
ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_alpha.png");
- CodecInOut io, io_nopremul;
+ CodecInOut io;
+ CodecInOut io_nopremul;
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io));
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_nopremul));
@@ -803,7 +857,7 @@ TEST(JxlTest, RoundtripAlphaPremultiplied) {
std::vector<uint8_t> compressed;
EXPECT_TRUE(test::EncodeFile(cparams, &io, &compressed));
- EXPECT_LE(compressed.size(), 10000u);
+ EXPECT_LE(compressed.size(), 18000u);
for (bool use_image_callback : {false, true}) {
for (bool unpremul_alpha : {false, true}) {
@@ -826,19 +880,19 @@ TEST(JxlTest, RoundtripAlphaPremultiplied) {
EXPECT_EQ(unpremul_alpha, !io2.Main().AlphaIsPremultiplied());
if (!unpremul_alpha) {
- EXPECT_THAT(
+ EXPECT_SLIGHTLY_BELOW(
ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
*JxlGetDefaultCms(),
/*distmap=*/nullptr),
- IsSlightlyBelow(1.111));
+ 1.111);
EXPECT_TRUE(UnpremultiplyAlpha(io2));
EXPECT_FALSE(io2.Main().AlphaIsPremultiplied());
}
- EXPECT_THAT(
+ EXPECT_SLIGHTLY_BELOW(
ButteraugliDistance(io_nopremul.frames, io2.frames,
ButteraugliParams(), *JxlGetDefaultCms(),
/*distmap=*/nullptr),
- IsSlightlyBelow(1.55));
+ 1.0);
}
}
}
@@ -854,13 +908,14 @@ TEST(JxlTest, RoundtripAlphaResampling) {
ASSERT_TRUE(t.ppf().info.alpha_bits > 0);
JXLCompressParams cparams;
+ cparams.alpha_distance = 1.0;
cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 5); // kHare
cparams.AddOption(JXL_ENC_FRAME_SETTING_RESAMPLING, 2);
cparams.AddOption(JXL_ENC_FRAME_SETTING_EXTRA_CHANNEL_RESAMPLING, 2);
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 13507, 130);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(5.2));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 5.2);
}
TEST(JxlTest, RoundtripAlphaResamplingOnlyAlpha) {
@@ -873,12 +928,13 @@ TEST(JxlTest, RoundtripAlphaResamplingOnlyAlpha) {
ASSERT_TRUE(t.ppf().info.alpha_bits > 0);
JXLCompressParams cparams;
+ cparams.alpha_distance = 1.0;
cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 3); // kFalcon
cparams.AddOption(JXL_ENC_FRAME_SETTING_EXTRA_CHANNEL_RESAMPLING, 2);
PackedPixelFile ppf_out;
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 33571, 400);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.49));
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 32000, 1000);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.52);
}
TEST(JxlTest, RoundtripAlphaNonMultipleOf8) {
@@ -893,13 +949,14 @@ TEST(JxlTest, RoundtripAlphaNonMultipleOf8) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), {}, {}, pool, &ppf_out), 107, 10);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.95));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.006);
}
TEST(JxlTest, RoundtripAlpha16) {
ThreadPoolForTests pool(4);
// The image is wider than 512 pixels to ensure multiple groups are tested.
- size_t xsize = 1200, ysize = 160;
+ size_t xsize = 1200;
+ size_t ysize = 160;
TestImage t;
t.SetDimensions(xsize, ysize).SetChannels(4).SetAllBitDepths(16);
TestImage::Frame frame = t.AddFrame();
@@ -923,12 +980,13 @@ TEST(JxlTest, RoundtripAlpha16) {
JXLCompressParams cparams;
cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 6); // kWombat
cparams.distance = 0.5;
+ cparams.alpha_distance = 0.5;
PackedPixelFile ppf_out;
// TODO(szabadka) Investigate big size difference on i686
// This still keeps happening (2023-04-18).
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 3666, 120);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.65));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.65);
}
namespace {
@@ -990,8 +1048,8 @@ TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8LightningGradient)) {
PackedPixelFile ppf_out;
// Lax comparison because different SIMD will cause different compression.
- EXPECT_THAT(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out),
- IsSlightlyBelow(286848u));
+ EXPECT_SLIGHTLY_BELOW(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out),
+ 286848u);
EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0);
}
@@ -1035,7 +1093,8 @@ TEST(JxlTest, RoundtripLossless8Alpha) {
TEST(JxlTest, RoundtripLossless16Alpha) {
ThreadPool* pool = nullptr;
- size_t xsize = 1200, ysize = 160;
+ size_t xsize = 1200;
+ size_t ysize = 160;
TestImage t;
t.SetDimensions(xsize, ysize).SetChannels(4).SetAllBitDepths(16);
TestImage::Frame frame = t.AddFrame();
@@ -1062,7 +1121,7 @@ TEST(JxlTest, RoundtripLossless16Alpha) {
PackedPixelFile ppf_out;
// TODO(szabadka) Investigate big size difference on i686
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), 4884, 100);
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), 4665, 100);
EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0);
EXPECT_EQ(ppf_out.info.alpha_bits, 16);
EXPECT_TRUE(test::SameAlpha(t.ppf(), ppf_out));
@@ -1070,7 +1129,8 @@ TEST(JxlTest, RoundtripLossless16Alpha) {
TEST(JxlTest, RoundtripLossless16AlphaNotMisdetectedAs8Bit) {
ThreadPool* pool = nullptr;
- size_t xsize = 128, ysize = 128;
+ size_t xsize = 128;
+ size_t ysize = 128;
TestImage t;
t.SetDimensions(xsize, ysize).SetChannels(4).SetAllBitDepths(16);
TestImage::Frame frame = t.AddFrame();
@@ -1098,7 +1158,7 @@ TEST(JxlTest, RoundtripLossless16AlphaNotMisdetectedAs8Bit) {
dparams.accepted_formats.push_back(t.ppf().frames[0].color.format);
PackedPixelFile ppf_out;
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), 591, 50);
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), 280, 50);
EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0);
EXPECT_EQ(ppf_out.info.bits_per_sample, 16);
EXPECT_EQ(ppf_out.info.alpha_bits, 16);
@@ -1123,7 +1183,7 @@ TEST(JxlTest, RoundtripDots) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 280333, 4000);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.35));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.35);
}
TEST(JxlTest, RoundtripNoise) {
@@ -1143,7 +1203,7 @@ TEST(JxlTest, RoundtripNoise) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 41009, 750);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.42));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.42);
}
TEST(JxlTest, RoundtripLossless8Gray) {
@@ -1182,17 +1242,17 @@ TEST(JxlTest, RoundtripAnimation) {
dparams.accepted_formats.push_back(t.ppf().frames[0].color.format);
PackedPixelFile ppf_out;
- EXPECT_THAT(Roundtrip(t.ppf(), {}, dparams, pool, &ppf_out),
- IsSlightlyBelow(2888));
+ EXPECT_SLIGHTLY_BELOW(Roundtrip(t.ppf(), {}, dparams, pool, &ppf_out), 3350);
t.CoalesceGIFAnimationWithAlpha();
ASSERT_EQ(ppf_out.frames.size(), t.ppf().frames.size());
- EXPECT_LE(ButteraugliDistance(t.ppf(), ppf_out),
+ static constexpr double kMaxButteraugli =
#if JXL_HIGH_PRECISION
- 1.55);
+ 1.55;
#else
- 1.75);
+ 1.75;
#endif
+ EXPECT_LE(ButteraugliDistance(t.ppf(), ppf_out), kMaxButteraugli);
}
TEST(JxlTest, RoundtripLosslessAnimation) {
@@ -1212,8 +1272,8 @@ TEST(JxlTest, RoundtripLosslessAnimation) {
dparams.accepted_formats.push_back(t.ppf().frames[0].color.format);
PackedPixelFile ppf_out;
- EXPECT_THAT(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out),
- IsSlightlyBelow(958));
+ EXPECT_SLIGHTLY_BELOW(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out),
+ 958);
t.CoalesceGIFAnimationWithAlpha();
ASSERT_EQ(ppf_out.frames.size(), t.ppf().frames.size());
@@ -1240,11 +1300,11 @@ TEST(JxlTest, RoundtripAnimationPatches) {
PackedPixelFile ppf_out;
// 40k with no patches, 27k with patch frames encoded multiple times.
- EXPECT_THAT(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out),
- IsSlightlyBelow(19300));
+ EXPECT_SLIGHTLY_BELOW(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out),
+ 19300);
EXPECT_EQ(ppf_out.frames.size(), t.ppf().frames.size());
// >10 with broken patches; not all patches are detected on borders.
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.9));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.9);
}
size_t RoundtripJpeg(const std::vector<uint8_t>& jpeg_in, ThreadPool* pool) {
@@ -1293,7 +1353,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression444)) {
const std::vector<uint8_t> orig =
ReadTestData("jxl/flower/flower.png.im_q85_444.jpg");
// JPEG size is 696,659 bytes.
- EXPECT_NEAR(RoundtripJpeg(orig, &pool), 568940u, 20);
+ EXPECT_NEAR(RoundtripJpeg(orig, &pool), 568891u, 20);
}
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels)) {
@@ -1306,7 +1366,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels)) {
PackedPixelFile ppf_out;
RoundtripJpegToPixels(orig, {}, &pool, &ppf_out);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(12));
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 12);
}
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420)) {
@@ -1319,7 +1379,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420)) {
PackedPixelFile ppf_out;
RoundtripJpegToPixels(orig, {}, &pool, &ppf_out);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(11));
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 11);
}
TEST(JxlTest,
@@ -1336,7 +1396,7 @@ TEST(JxlTest,
PackedPixelFile ppf_out;
RoundtripJpegToPixels(orig, dparams, &pool, &ppf_out);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(4410));
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 4410);
}
TEST(JxlTest,
@@ -1350,7 +1410,7 @@ TEST(JxlTest,
PackedPixelFile ppf_out;
RoundtripJpegToPixels(orig, {}, &pool, &ppf_out);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(4));
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 4);
}
TEST(JxlTest,
@@ -1364,7 +1424,7 @@ TEST(JxlTest,
PackedPixelFile ppf_out;
RoundtripJpegToPixels(orig, {}, &pool, &ppf_out);
- EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(10));
+ EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 10);
}
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionGray)) {
@@ -1380,7 +1440,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression420)) {
const std::vector<uint8_t> orig =
ReadTestData("jxl/flower/flower.png.im_q85_420.jpg");
// JPEG size is 546,797 bytes.
- EXPECT_NEAR(RoundtripJpeg(orig, &pool), 455560u, 10);
+ EXPECT_NEAR(RoundtripJpeg(orig, &pool), 455510u, 20);
}
TEST(JxlTest,
@@ -1389,7 +1449,7 @@ TEST(JxlTest,
const std::vector<uint8_t> orig =
ReadTestData("jxl/flower/flower.png.im_q85_luma_subsample.jpg");
// JPEG size is 400,724 bytes.
- EXPECT_NEAR(RoundtripJpeg(orig, &pool), 325354u, 15);
+ EXPECT_NEAR(RoundtripJpeg(orig, &pool), 325310u, 20);
}
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression444_12)) {
@@ -1398,7 +1458,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression444_12)) {
const std::vector<uint8_t> orig =
ReadTestData("jxl/flower/flower.png.im_q85_444_1x2.jpg");
// JPEG size is 703,874 bytes.
- EXPECT_NEAR(RoundtripJpeg(orig, &pool), 569679u, 10);
+ EXPECT_NEAR(RoundtripJpeg(orig, &pool), 569630u, 20);
}
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression422)) {
@@ -1406,7 +1466,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression422)) {
const std::vector<uint8_t> orig =
ReadTestData("jxl/flower/flower.png.im_q85_422.jpg");
// JPEG size is 522,057 bytes.
- EXPECT_NEAR(RoundtripJpeg(orig, &pool), 499282u, 10);
+ EXPECT_NEAR(RoundtripJpeg(orig, &pool), 499236u, 20);
}
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression440)) {
@@ -1414,7 +1474,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression440)) {
const std::vector<uint8_t> orig =
ReadTestData("jxl/flower/flower.png.im_q85_440.jpg");
// JPEG size is 603,623 bytes.
- EXPECT_NEAR(RoundtripJpeg(orig, &pool), 501151u, 10);
+ EXPECT_NEAR(RoundtripJpeg(orig, &pool), 501101u, 20);
}
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression_asymmetric)) {
@@ -1424,7 +1484,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression_asymmetric)) {
const std::vector<uint8_t> orig =
ReadTestData("jxl/flower/flower.png.im_q85_asymmetric.jpg");
// JPEG size is 604,601 bytes.
- EXPECT_NEAR(RoundtripJpeg(orig, &pool), 500602u, 10);
+ EXPECT_NEAR(RoundtripJpeg(orig, &pool), 500548u, 20);
}
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression420Progr)) {
@@ -1432,7 +1492,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression420Progr)) {
const std::vector<uint8_t> orig =
ReadTestData("jxl/flower/flower.png.im_q85_420_progr.jpg");
// JPEG size is 522,057 bytes.
- EXPECT_NEAR(RoundtripJpeg(orig, &pool), 455499u, 10);
+ EXPECT_NEAR(RoundtripJpeg(orig, &pool), 455454u, 20);
}
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionMetadata)) {
@@ -1440,7 +1500,8 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionMetadata)) {
const std::vector<uint8_t> orig =
ReadTestData("jxl/jpeg_reconstruction/1x1_exif_xmp.jpg");
// JPEG size is 4290 bytes
- EXPECT_NEAR(RoundtripJpeg(orig, &pool), 1400u, 30);
+ // 1370 on 386, so higher margin.
+ EXPECT_NEAR(RoundtripJpeg(orig, &pool), 1334u, 100);
}
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionRestarts)) {
@@ -1448,7 +1509,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionRestarts)) {
const std::vector<uint8_t> orig =
ReadTestData("jxl/jpeg_reconstruction/bicycles_restarts.jpg");
// JPEG size is 87478 bytes
- EXPECT_NEAR(RoundtripJpeg(orig, &pool), 76125u, 30);
+ EXPECT_NEAR(RoundtripJpeg(orig, &pool), 76054u, 30);
}
TEST(JxlTest,
@@ -1475,7 +1536,7 @@ TEST(JxlTest, RoundtripProgressive) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 70544, 750);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.4));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.4);
}
TEST(JxlTest, RoundtripProgressiveLevel2Slow) {
@@ -1492,7 +1553,7 @@ TEST(JxlTest, RoundtripProgressiveLevel2Slow) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 76666, 1000);
- EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.17));
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.17);
}
TEST(JxlTest, RoundtripUnsignedCustomBitdepthLossless) {
@@ -1509,9 +1570,9 @@ TEST(JxlTest, RoundtripUnsignedCustomBitdepthLossless) {
t.SetAllBitDepths(bitdepth).SetEndianness(endianness);
TestImage::Frame frame = t.AddFrame();
frame.RandomFill();
+ t.ppf().input_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM;
JXLCompressParams cparams = CompressParamsForLossless();
- cparams.input_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM;
JXLDecompressParams dparams;
dparams.accepted_formats.push_back(t.ppf().frames[0].color.format);
@@ -1543,7 +1604,6 @@ TEST(JxlTest, LosslessPNMRoundtrip) {
JXLCompressParams cparams = CompressParamsForLossless();
cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 1); // kLightning
- cparams.input_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM;
JXLDecompressParams dparams;
dparams.accepted_formats.push_back(t.ppf().frames[0].color.format);
@@ -1592,10 +1652,13 @@ struct StreamingTestParam {
size_t xsize;
size_t ysize;
bool is_grey;
+ bool has_alpha;
int effort;
bool progressive;
- size_t num_channels() const { return is_grey ? 1 : 3; }
+ size_t num_channels() const {
+ return (is_grey ? 1 : 3) + (has_alpha ? 1 : 0);
+ }
float max_psnr() const { return is_grey ? 90 : 50; }
@@ -1603,11 +1666,13 @@ struct StreamingTestParam {
std::vector<StreamingTestParam> params;
for (int e : {1, 3, 4, 7}) {
for (bool g : {false, true}) {
- params.push_back(StreamingTestParam{357, 517, g, e, false});
- params.push_back(StreamingTestParam{2247, 2357, g, e, false});
+ params.push_back(StreamingTestParam{357, 517, g, false, e, false});
+ params.push_back(StreamingTestParam{2247, 2357, g, false, e, false});
}
}
- params.push_back(StreamingTestParam{2247, 2357, false, 1, true});
+ params.push_back(StreamingTestParam{2247, 2357, false, false, 1, true});
+ params.push_back(StreamingTestParam{2247, 2157, false, false, 5, false});
+ params.push_back(StreamingTestParam{2247, 2157, false, true, 5, false});
return params;
}
};
@@ -1651,15 +1716,66 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P(
JxlStreamingTest, JxlStreamingTest,
testing::ValuesIn(StreamingTestParam::All()));
+struct StreamingEncodingTestParam {
+ std::string file;
+ int effort;
+ float distance;
+ int group_size;
+ float palette_percent;
+
+ static std::vector<StreamingEncodingTestParam> All() {
+ std::vector<StreamingEncodingTestParam> params;
+ for (const auto* file :
+ {"jxl/flower/flower.png", "jxl/flower/flower_alpha.png"}) {
+ for (int effort : {1, 3, 5, 6}) {
+ if (effort != 1) {
+ params.push_back(
+ StreamingEncodingTestParam{file, effort, 1.0, 1, -1});
+ params.push_back(
+ StreamingEncodingTestParam{file, effort, 4.0, 1, -1});
+ }
+ for (auto group_size : {-1, 0}) {
+ for (float palette_percent : {-1, 50, 100}) {
+ params.push_back(StreamingEncodingTestParam{
+ file, effort, 0.0, group_size, palette_percent});
+ }
+ }
+ }
+ }
+ return params;
+ }
+};
+
+std::ostream& operator<<(std::ostream& out,
+ const StreamingEncodingTestParam& p) {
+ out << p.file << "-";
+ out << "e" << p.effort;
+ if (p.distance == 0) {
+ out << "Lossless";
+ out << "G" << p.group_size << "P" << p.palette_percent;
+ } else {
+ out << "D" << p.distance;
+ }
+ return out;
+}
+
+class JxlStreamingEncodingTest
+ : public ::testing::TestWithParam<StreamingEncodingTestParam> {};
+
// This is broken on mingw32, so we only enable it for x86_64 now.
-TEST(JxlTest, JXL_X86_64_TEST(StreamingSamePixels)) {
- const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
+TEST_P(JxlStreamingEncodingTest, JXL_X86_64_TEST(StreamingSamePixels)) {
+ const auto param = GetParam();
+ const std::vector<uint8_t> orig = ReadTestData(param.file);
jxl::test::TestImage image;
image.DecodeFromBytes(orig);
+
JXLCompressParams cparams;
- cparams.distance = 1.0;
- cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 6);
+ cparams.distance = param.distance;
+ cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, param.effort);
+ cparams.AddOption(JXL_ENC_FRAME_SETTING_MODULAR_GROUP_SIZE, param.group_size);
+ cparams.AddFloatOption(JXL_ENC_FRAME_SETTING_CHANNEL_COLORS_GROUP_PERCENT,
+ param.palette_percent);
cparams.AddOption(JXL_ENC_FRAME_SETTING_USE_FULL_IMAGE_HEURISTICS, 0);
ThreadPoolForTests pool(8);
@@ -1673,5 +1789,9 @@ TEST(JxlTest, JXL_X86_64_TEST(StreamingSamePixels)) {
EXPECT_TRUE(jxl::test::SamePixels(ppf_out, ppf_out_streaming));
}
+JXL_GTEST_INSTANTIATE_TEST_SUITE_P(
+ JxlStreamingTest, JxlStreamingEncodingTest,
+ testing::ValuesIn(StreamingEncodingTestParam::All()));
+
} // namespace
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/libjxl.pc.in b/third_party/jpeg-xl/lib/jxl/libjxl.pc.in
index 58b6941305..f5a9c43650 100644
--- a/third_party/jpeg-xl/lib/jxl/libjxl.pc.in
+++ b/third_party/jpeg-xl/lib/jxl/libjxl.pc.in
@@ -7,7 +7,7 @@ Name: libjxl
Description: Loads and saves JPEG XL files
Version: @JPEGXL_LIBRARY_VERSION@
@JPEGXL_REQUIRES_TYPE@: @JPEGXL_LIBRARY_REQUIRES@
-Libs: -L${libdir} -ljxl
-Libs.private: -lm
+Libs: -L${libdir} -ljxl @JPEGXL_PUBLIC_LIBS@
+Libs.private: @JPEGXL_PRIVATE_LIBS@
Cflags: -I${includedir}
Cflags.private: -DJXL_STATIC_DEFINE
diff --git a/third_party/jpeg-xl/lib/jxl/libjxl_cms.pc.in b/third_party/jpeg-xl/lib/jxl/libjxl_cms.pc.in
index 9aaa3f4dbe..deab7367ac 100644
--- a/third_party/jpeg-xl/lib/jxl/libjxl_cms.pc.in
+++ b/third_party/jpeg-xl/lib/jxl/libjxl_cms.pc.in
@@ -7,7 +7,7 @@ Name: libjxl_cms
Description: CMS support library for libjxl
Version: @JPEGXL_LIBRARY_VERSION@
@JPEGXL_REQUIRES_TYPE@: @JPEGXL_CMS_LIBRARY_REQUIRES@
-Libs: -L${libdir} -ljxl_cms
-Libs.private: -lm
+Libs: -L${libdir} -ljxl_cms @JPEGXL_CMS_PUBLIC_LIBS@
+Libs.private: @JPEGXL_CMS_PRIVATE_LIBS@
Cflags: -I${includedir}
Cflags.private: -DJXL_CMS_STATIC_DEFINE
diff --git a/third_party/jpeg-xl/lib/jxl/memory_manager_internal.h b/third_party/jpeg-xl/lib/jxl/memory_manager_internal.h
index c728d62e35..e578e91f8e 100644
--- a/third_party/jpeg-xl/lib/jxl/memory_manager_internal.h
+++ b/third_party/jpeg-xl/lib/jxl/memory_manager_internal.h
@@ -36,11 +36,13 @@ static JXL_INLINE Status MemoryManagerInit(
} else {
memset(self, 0, sizeof(*self));
}
- if (!self->alloc != !self->free) {
+ bool is_default_alloc = (self->alloc == nullptr);
+ bool is_default_free = (self->free == nullptr);
+ if (is_default_alloc != is_default_free) {
return false;
}
- if (!self->alloc) self->alloc = jxl::MemoryManagerDefaultAlloc;
- if (!self->free) self->free = jxl::MemoryManagerDefaultFree;
+ if (is_default_alloc) self->alloc = jxl::MemoryManagerDefaultAlloc;
+ if (is_default_free) self->free = jxl::MemoryManagerDefaultFree;
return true;
}
@@ -52,7 +54,7 @@ static JXL_INLINE void* MemoryManagerAlloc(
static JXL_INLINE void MemoryManagerFree(const JxlMemoryManager* memory_manager,
void* address) {
- return memory_manager->free(memory_manager->opaque, address);
+ memory_manager->free(memory_manager->opaque, address);
}
// Helper class to be used as a deleter in a unique_ptr<T> call.
diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h b/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h
index 4c3a33a52a..7bec5128fc 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h
@@ -10,6 +10,7 @@
#include <vector>
#include "lib/jxl/fields.h"
+#include "lib/jxl/image_ops.h"
#include "lib/jxl/modular/modular_image.h"
#include "lib/jxl/modular/options.h"
@@ -78,14 +79,14 @@ struct State {
294337, 289262, 284359, 279620, 275036, 270600, 266305, 262144};
constexpr static pixel_type_w AddBits(pixel_type_w x) {
- return uint64_t(x) << kPredExtraBits;
+ return static_cast<uint64_t>(x) << kPredExtraBits;
}
State(Header header, size_t xsize, size_t ysize) : header(header) {
// Extra margin to avoid out-of-bounds writes.
// All have space for two rows of data.
- for (size_t i = 0; i < 4; i++) {
- pred_errors[i].resize((xsize + 2) * 2);
+ for (auto &pred_error : pred_errors) {
+ pred_error.resize((xsize + 2) * 2);
}
error.resize((xsize + 2) * 2);
}
@@ -538,8 +539,9 @@ JXL_INLINE PredictionResult Predict(
}
if (mode & kAllPredictions) {
for (size_t i = 0; i < kNumModularPredictors; i++) {
- predictions[i] = PredictOne((Predictor)i, left, top, toptop, topleft,
- topright, leftleft, toprightright, wp_pred);
+ predictions[i] =
+ PredictOne(static_cast<Predictor>(i), left, top, toptop, topleft,
+ topright, leftleft, toprightright, wp_pred);
}
}
result.guess += PredictOne(predictor, left, top, toptop, topleft, topright,
diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/dec_ma.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/dec_ma.cc
index ee7177bcd6..b53b9a9103 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/encoding/dec_ma.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/dec_ma.cc
@@ -5,6 +5,8 @@
#include "lib/jxl/modular/encoding/dec_ma.h"
+#include <limits>
+
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/dec_ans.h"
#include "lib/jxl/modular/encoding/ma_common.h"
diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc
index bd27f28458..f863823629 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc
@@ -95,7 +95,7 @@ std::string PropertyName(size_t i) {
case 15:
return "WGH";
default:
- return "ch[" + ToString(15 - (int)i) + "]";
+ return "ch[" + ToString(15 - static_cast<int>(i)) + "]";
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_encoding.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_encoding.cc
index fc2e69e4a6..84d8137d21 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_encoding.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_encoding.cc
@@ -6,35 +6,24 @@
#include <stdint.h>
#include <stdlib.h>
-#include <cinttypes>
#include <limits>
-#include <numeric>
#include <queue>
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/dec_ans.h"
-#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/enc_ans.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/enc_fields.h"
-#include "lib/jxl/entropy_coder.h"
#include "lib/jxl/fields.h"
#include "lib/jxl/image_ops.h"
#include "lib/jxl/modular/encoding/context_predict.h"
-#include "lib/jxl/modular/encoding/enc_debug_tree.h"
#include "lib/jxl/modular/encoding/enc_ma.h"
#include "lib/jxl/modular/encoding/encoding.h"
#include "lib/jxl/modular/encoding/ma_common.h"
#include "lib/jxl/modular/options.h"
-#include "lib/jxl/modular/transform/transform.h"
#include "lib/jxl/pack_signed.h"
-#include "lib/jxl/toc.h"
namespace jxl {
@@ -61,7 +50,7 @@ inline std::array<uint8_t, 3> PredictorColor(Predictor p) {
return {{255, 0, 255}};
case Predictor::Weighted:
return {{0, 255, 255}};
- // TODO
+ // TODO(jon)
default:
return {{255, 255, 255}};
};
@@ -101,17 +90,17 @@ Tree MakeFixedTree(int property, const std::vector<int32_t> &cutoffs,
} // namespace
-void GatherTreeData(const Image &image, pixel_type chan, size_t group_id,
- const weighted::Header &wp_header,
- const ModularOptions &options, TreeSamples &tree_samples,
- size_t *total_pixels) {
+Status GatherTreeData(const Image &image, pixel_type chan, size_t group_id,
+ const weighted::Header &wp_header,
+ const ModularOptions &options, TreeSamples &tree_samples,
+ size_t *total_pixels) {
const Channel &channel = image.channel[chan];
JXL_DEBUG_V(7, "Learning %" PRIuS "x%" PRIuS " channel %d", channel.w,
channel.h, chan);
std::array<pixel_type, kNumStaticProperties> static_props = {
- {chan, (int)group_id}};
+ {chan, static_cast<int>(group_id)}};
Properties properties(kNumNonrefProperties +
kExtraPropsPerChannel * options.max_properties);
double pixel_fraction = std::min(1.0f, options.nb_repeats);
@@ -137,7 +126,9 @@ void GatherTreeData(const Image &image, pixel_type chan, size_t group_id,
};
const intptr_t onerow = channel.plane.PixelsPerRow();
- Channel references(properties.size() - kNumNonrefProperties, channel.w);
+ JXL_ASSIGN_OR_RETURN(
+ Channel references,
+ Channel::Create(properties.size() - kNumNonrefProperties, channel.w));
weighted::State wp_state(wp_header, channel.w, channel.h);
tree_samples.PrepareForSamples(pixel_fraction * channel.h * channel.w + 64);
const bool multiple_predictors = tree_samples.NumPredictors() != 1;
@@ -198,6 +189,7 @@ void GatherTreeData(const Image &image, pixel_type chan, size_t group_id,
}
}
}
+ return true;
}
Tree PredefinedTree(ModularOptions::TreeKind tree_kind, size_t total_pixels) {
@@ -316,7 +308,9 @@ Status EncodeModularChannelMAANS(const Image &image, pixel_type chan,
JXL_ASSERT(channel.w != 0 && channel.h != 0);
Image3F predictor_img;
- if (kWantDebug) predictor_img = Image3F(channel.w, channel.h);
+ if (kWantDebug) {
+ JXL_ASSIGN_OR_RETURN(predictor_img, Image3F::Create(channel.w, channel.h));
+ }
JXL_DEBUG_V(6,
"Encoding %" PRIuS "x%" PRIuS
@@ -325,8 +319,9 @@ Status EncodeModularChannelMAANS(const Image &image, pixel_type chan,
channel.w, channel.h, chan, channel.hshift, channel.vshift);
std::array<pixel_type, kNumStaticProperties> static_props = {
- {chan, (int)group_id}};
- bool use_wp, is_wp_only;
+ {chan, static_cast<int>(group_id)}};
+ bool use_wp;
+ bool is_wp_only;
bool is_gradient_only;
size_t num_props;
FlatTree tree = FilterTree(global_tree, static_props, &num_props, &use_wp,
@@ -439,7 +434,8 @@ Status EncodeModularChannelMAANS(const Image &image, pixel_type chan,
FillImage(static_cast<float>(PredictorColor(tree[0].predictor)[c]),
&predictor_img.Plane(c));
}
- uint32_t mul_shift = FloorLog2Nonzero((uint32_t)tree[0].multiplier);
+ uint32_t mul_shift =
+ FloorLog2Nonzero(static_cast<uint32_t>(tree[0].multiplier));
const intptr_t onerow = channel.plane.PixelsPerRow();
for (size_t y = 0; y < channel.h; y++) {
const pixel_type *JXL_RESTRICT r = channel.Row(y);
@@ -454,7 +450,9 @@ Status EncodeModularChannelMAANS(const Image &image, pixel_type chan,
} else if (!use_wp && !skip_encoder_fast_path) {
const intptr_t onerow = channel.plane.PixelsPerRow();
- Channel references(properties.size() - kNumNonrefProperties, channel.w);
+ JXL_ASSIGN_OR_RETURN(
+ Channel references,
+ Channel::Create(properties.size() - kNumNonrefProperties, channel.w));
for (size_t y = 0; y < channel.h; y++) {
const pixel_type *JXL_RESTRICT p = channel.Row(y);
PrecomputeReferences(channel, y, image, chan, &references);
@@ -481,7 +479,9 @@ Status EncodeModularChannelMAANS(const Image &image, pixel_type chan,
}
} else {
const intptr_t onerow = channel.plane.PixelsPerRow();
- Channel references(properties.size() - kNumNonrefProperties, channel.w);
+ JXL_ASSIGN_OR_RETURN(
+ Channel references,
+ Channel::Create(properties.size() - kNumNonrefProperties, channel.w));
weighted::State wp_state(wp_header, channel.w, channel.h);
for (size_t y = 0; y < channel.h; y++) {
const pixel_type *JXL_RESTRICT p = channel.Row(y);
@@ -556,8 +556,20 @@ Status ModularEncode(const Image &image, const ModularOptions &options,
TreeSamples tree_samples_storage;
size_t total_pixels_storage = 0;
if (!total_pixels) total_pixels = &total_pixels_storage;
+ if (*total_pixels == 0) {
+ for (size_t i = 0; i < nb_channels; i++) {
+ if (i >= image.nb_meta_channels &&
+ (image.channel[i].w > options.max_chan_size ||
+ image.channel[i].h > options.max_chan_size)) {
+ break;
+ }
+ *total_pixels += image.channel[i].w * image.channel[i].h;
+ }
+ *total_pixels = std::max<size_t>(*total_pixels, 1);
+ }
// If there's no tree, compute one (or gather data to).
- if (tree == nullptr) {
+ if (tree == nullptr &&
+ options.tree_kind == ModularOptions::TreeKind::kLearn) {
bool gather_data = tree_samples != nullptr;
if (tree_samples == nullptr) {
JXL_RETURN_IF_ERROR(tree_samples_storage.SetPredictor(
@@ -586,9 +598,9 @@ Status ModularEncode(const Image &image, const ModularOptions &options,
image.channel[i].h > options.max_chan_size)) {
break;
}
- GatherTreeData(image, i, group_id, header->wp_header, options,
- gather_data ? *tree_samples : tree_samples_storage,
- total_pixels);
+ JXL_RETURN_IF_ERROR(GatherTreeData(
+ image, i, group_id, header->wp_header, options,
+ gather_data ? *tree_samples : tree_samples_storage, total_pixels));
}
if (gather_data) return true;
}
@@ -609,10 +621,10 @@ Status ModularEncode(const Image &image, const ModularOptions &options,
? LearnTree(std::move(tree_samples_storage), *total_pixels, options)
: PredefinedTree(options.tree_kind, *total_pixels);
tree = &tree_storage;
- tokens = &tokens_storage[0];
+ tokens = tokens_storage.data();
Tree decoded_tree;
- TokenizeTree(*tree, &tree_tokens[0], &decoded_tree);
+ TokenizeTree(*tree, tree_tokens.data(), &decoded_tree);
JXL_ASSERT(tree->size() == decoded_tree.size());
tree_storage = std::move(decoded_tree);
@@ -622,9 +634,9 @@ Status ModularEncode(const Image &image, const ModularOptions &options,
} */
// Write tree
- BuildAndEncodeHistograms(HistogramParams(), kNumTreeContexts, tree_tokens,
- &code, &context_map, writer, kLayerModularTree,
- aux_out);
+ BuildAndEncodeHistograms(options.histogram_params, kNumTreeContexts,
+ tree_tokens, &code, &context_map, writer,
+ kLayerModularTree, aux_out);
WriteTokens(tree_tokens[0], code, context_map, 0, writer, kLayerModularTree,
aux_out);
}
@@ -669,7 +681,7 @@ Status ModularEncode(const Image &image, const ModularOptions &options,
if (!header->use_global_tree) {
EntropyEncodingData code;
std::vector<uint8_t> context_map;
- HistogramParams histo_params;
+ HistogramParams histo_params = options.histogram_params;
histo_params.image_widths.push_back(image_width);
BuildAndEncodeHistograms(histo_params, (tree->size() + 1) / 2,
tokens_storage, &code, &context_map, writer, layer,
@@ -691,7 +703,7 @@ Status ModularGenericCompress(Image &image, const ModularOptions &opts,
if (image.w == 0 || image.h == 0) return true;
ModularOptions options = opts; // Make a copy to modify it.
- if (options.predictor == static_cast<Predictor>(-1)) {
+ if (options.predictor == kUndefinedPredictor) {
options.predictor = Predictor::Gradient;
}
diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_ma.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_ma.cc
index ef72b2477b..de629ad038 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_ma.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_ma.cc
@@ -109,8 +109,8 @@ IntersectionType BoxIntersects(StaticPropRange needle, StaticPropRange haystack,
void SplitTreeSamples(TreeSamples &tree_samples, size_t begin, size_t pos,
size_t end, size_t prop) {
auto cmp = [&](size_t a, size_t b) {
- return int32_t(tree_samples.Property(prop, a)) -
- int32_t(tree_samples.Property(prop, b));
+ return static_cast<int32_t>(tree_samples.Property(prop, a)) -
+ static_cast<int32_t>(tree_samples.Property(prop, b));
};
Rng rng(0);
while (end > begin + 1) {
@@ -243,7 +243,8 @@ void FindBestSplit(TreeSamples &tree_samples, float threshold,
// properties. We do this even if the current node is not a leaf, to
// minimize the number of nodes in the resulting tree.
for (size_t i = 0; i < mul_info.size(); i++) {
- uint32_t axis, val;
+ uint32_t axis;
+ uint32_t val;
IntersectionType t =
BoxIntersects(static_prop_range, mul_info[i].range, axis, val);
if (t == IntersectionType::kNone) continue;
@@ -696,7 +697,11 @@ void TreeSamples::Swap(size_t a, size_t b) {
}
void TreeSamples::ThreeShuffle(size_t a, size_t b, size_t c) {
- if (b == c) return Swap(a, b);
+ if (b == c) {
+ Swap(a, b);
+ return;
+ }
+
for (auto &r : residuals) {
auto tmp = r[a];
r[a] = r[c];
@@ -966,7 +971,7 @@ void CollectPixelSamples(const Image &image, const ModularOptions &options,
const pixel_type *row = image.channel[channel_ids[i]].Row(y);
pixel_samples.push_back(row[x]);
size_t xp = x == 0 ? 1 : x - 1;
- diff_samples.push_back((int64_t)row[x] - row[xp]);
+ diff_samples.push_back(static_cast<int64_t>(row[x]) - row[xp]);
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc
index a6abdcfc91..bb690b74ba 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc
@@ -14,6 +14,8 @@
#include "lib/jxl/base/scope_guard.h"
#include "lib/jxl/dec_ans.h"
#include "lib/jxl/dec_bit_reader.h"
+#include "lib/jxl/frame_dimensions.h"
+#include "lib/jxl/image_ops.h"
#include "lib/jxl/modular/encoding/context_predict.h"
#include "lib/jxl/modular/options.h"
#include "lib/jxl/pack_signed.h"
@@ -141,7 +143,7 @@ Status DecodeModularChannelMAANS(BitReader *br, ANSSymbolReader *reader,
Channel &channel = image->channel[chan];
std::array<pixel_type, kNumStaticProperties> static_props = {
- {chan, (int)group_id}};
+ {chan, static_cast<int>(group_id)}};
// TODO(veluca): filter the tree according to static_props.
// zero pixel channel? could happen
@@ -376,7 +378,9 @@ Status DecodeModularChannelMAANS(BitReader *br, ANSSymbolReader *reader,
MATreeLookup tree_lookup(tree);
Properties properties = Properties(num_props);
const intptr_t onerow = channel.plane.PixelsPerRow();
- Channel references(properties.size() - kNumNonrefProperties, channel.w);
+ JXL_ASSIGN_OR_RETURN(
+ Channel references,
+ Channel::Create(properties.size() - kNumNonrefProperties, channel.w));
for (size_t y = 0; y < channel.h; y++) {
pixel_type *JXL_RESTRICT p = channel.Row(y);
PrecomputeReferences(channel, y, *image, chan, &references);
@@ -422,7 +426,9 @@ Status DecodeModularChannelMAANS(BitReader *br, ANSSymbolReader *reader,
MATreeLookup tree_lookup(tree);
Properties properties = Properties(num_props);
const intptr_t onerow = channel.plane.PixelsPerRow();
- Channel references(properties.size() - kNumNonrefProperties, channel.w);
+ JXL_ASSIGN_OR_RETURN(
+ Channel references,
+ Channel::Create(properties.size() - kNumNonrefProperties, channel.w));
weighted::State wp_state(wp_header, channel.w, channel.h);
for (size_t y = 0; y < channel.h; y++) {
pixel_type *JXL_RESTRICT p = channel.Row(y);
diff --git a/third_party/jpeg-xl/lib/jxl/modular/modular_image.cc b/third_party/jpeg-xl/lib/jxl/modular/modular_image.cc
index 746d7c87fd..32a5531080 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/modular_image.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/modular_image.cc
@@ -8,6 +8,7 @@
#include <sstream>
#include "lib/jxl/base/status.h"
+#include "lib/jxl/image_ops.h"
#include "lib/jxl/modular/transform/transform.h"
namespace jxl {
@@ -28,9 +29,18 @@ void Image::undo_transforms(const weighted::Header &wp_header,
}
}
-Image::Image(size_t iw, size_t ih, int bitdepth, int nb_chans)
- : w(iw), h(ih), bitdepth(bitdepth), nb_meta_channels(0), error(false) {
- for (int i = 0; i < nb_chans; i++) channel.emplace_back(Channel(iw, ih));
+Image::Image(size_t iw, size_t ih, int bitdepth)
+ : w(iw), h(ih), bitdepth(bitdepth), nb_meta_channels(0), error(false) {}
+
+StatusOr<Image> Image::Create(size_t iw, size_t ih, int bitdepth,
+ int nb_chans) {
+ Image result(iw, ih, bitdepth);
+ for (int i = 0; i < nb_chans; i++) {
+ StatusOr<Channel> channel_or = Channel::Create(iw, ih);
+ JXL_RETURN_IF_ERROR(channel_or.status());
+ result.channel.emplace_back(std::move(channel_or).value());
+ }
+ return result;
}
Image::Image() : w(0), h(0), bitdepth(8), nb_meta_channels(0), error(true) {}
@@ -46,17 +56,18 @@ Image &Image::operator=(Image &&other) noexcept {
return *this;
}
-Image Image::clone() {
- Image c(w, h, bitdepth, 0);
- c.nb_meta_channels = nb_meta_channels;
- c.error = error;
- c.transform = transform;
- for (Channel &ch : channel) {
- Channel a(ch.w, ch.h, ch.hshift, ch.vshift);
+StatusOr<Image> Image::Clone(const Image &that) {
+ Image clone(that.w, that.h, that.bitdepth);
+ clone.nb_meta_channels = that.nb_meta_channels;
+ clone.error = that.error;
+ clone.transform = that.transform;
+ for (const Channel &ch : that.channel) {
+ JXL_ASSIGN_OR_RETURN(Channel a,
+ Channel::Create(ch.w, ch.h, ch.hshift, ch.vshift));
CopyImageTo(ch.plane, &a.plane);
- c.channel.push_back(std::move(a));
+ clone.channel.push_back(std::move(a));
}
- return c;
+ return clone;
}
#if JXL_DEBUG_V_LEVEL >= 1
diff --git a/third_party/jpeg-xl/lib/jxl/modular/modular_image.h b/third_party/jpeg-xl/lib/jxl/modular/modular_image.h
index 56e80d823a..eb95b1cb6c 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/modular_image.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/modular_image.h
@@ -18,7 +18,6 @@
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/image.h"
-#include "lib/jxl/image_ops.h"
namespace jxl {
@@ -36,12 +35,16 @@ class Channel {
jxl::Plane<pixel_type> plane;
size_t w, h;
int hshift, vshift; // w ~= image.w >> hshift; h ~= image.h >> vshift
- Channel(size_t iw, size_t ih, int hsh = 0, int vsh = 0)
- : plane(iw, ih), w(iw), h(ih), hshift(hsh), vshift(vsh) {}
-
Channel(const Channel& other) = delete;
Channel& operator=(const Channel& other) = delete;
+ static StatusOr<Channel> Create(size_t iw, size_t ih, int hsh = 0,
+ int vsh = 0) {
+ JXL_ASSIGN_OR_RETURN(Plane<pixel_type> plane,
+ Plane<pixel_type>::Create(iw, ih));
+ return Channel(std::move(plane), iw, ih, hsh, vsh);
+ }
+
// Move assignment
Channel& operator=(Channel&& other) noexcept {
w = other.w;
@@ -55,21 +58,25 @@ class Channel {
// Move constructor
Channel(Channel&& other) noexcept = default;
- void shrink() {
- if (plane.xsize() == w && plane.ysize() == h) return;
- jxl::Plane<pixel_type> resizedplane(w, h);
- plane = std::move(resizedplane);
+ Status shrink() {
+ if (plane.xsize() == w && plane.ysize() == h) return true;
+ JXL_ASSIGN_OR_RETURN(plane, Plane<pixel_type>::Create(w, h));
+ return true;
}
- void shrink(int nw, int nh) {
+ Status shrink(int nw, int nh) {
w = nw;
h = nh;
- shrink();
+ return shrink();
}
JXL_INLINE pixel_type* Row(const size_t y) { return plane.Row(y); }
JXL_INLINE const pixel_type* Row(const size_t y) const {
return plane.Row(y);
}
+
+ private:
+ Channel(jxl::Plane<pixel_type>&& p, size_t iw, size_t ih, int hsh, int vsh)
+ : plane(std::move(p)), w(iw), h(ih), hshift(hsh), vshift(vsh) {}
};
class Transform;
@@ -88,7 +95,6 @@ class Image {
size_t nb_meta_channels; // first few channels might contain palette(s)
bool error; // true if a fatal error occurred, false otherwise
- Image(size_t iw, size_t ih, int bitdepth, int nb_chans);
Image();
Image(const Image& other) = delete;
@@ -97,6 +103,9 @@ class Image {
Image& operator=(Image&& other) noexcept;
Image(Image&& other) noexcept = default;
+ static StatusOr<Image> Create(size_t iw, size_t ih, int bitdepth,
+ int nb_chans);
+
bool empty() const {
for (const auto& ch : channel) {
if (ch.w && ch.h) return false;
@@ -104,12 +113,15 @@ class Image {
return true;
}
- Image clone();
+ static StatusOr<Image> Clone(const Image& that);
void undo_transforms(const weighted::Header& wp_header,
jxl::ThreadPool* pool = nullptr);
std::string DebugString() const;
+
+ private:
+ Image(size_t iw, size_t ih, int bitdepth);
};
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/modular/options.h b/third_party/jpeg-xl/lib/jxl/modular/options.h
index ce6596b912..6613b513de 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/options.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/options.h
@@ -11,6 +11,8 @@
#include <array>
#include <vector>
+#include "lib/jxl/enc_ans_params.h"
+
namespace jxl {
using PropertyVal = int32_t;
@@ -37,6 +39,8 @@ enum class Predictor : uint32_t {
15, // Find the best decision tree for predictors/predictor per row
};
+constexpr Predictor kUndefinedPredictor = static_cast<Predictor>(~0u);
+
constexpr size_t kNumModularPredictors =
static_cast<size_t>(Predictor::Average4) + 1;
constexpr size_t kNumModularEncoderPredictors =
@@ -80,7 +84,7 @@ struct ModularOptions {
size_t max_property_values = 32;
// Predictor to use for each channel.
- Predictor predictor = static_cast<Predictor>(-1);
+ Predictor predictor = kUndefinedPredictor;
int wp_mode = 0;
@@ -108,6 +112,8 @@ struct ModularOptions {
};
TreeKind tree_kind = TreeKind::kLearn;
+ HistogramParams histogram_params;
+
// Ignore the image and just pretend all tokens are zeroes
bool zero_tokens = false;
};
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc
index f5172aa126..24c64f5aad 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc
@@ -10,8 +10,8 @@
#include <set>
#include "lib/jxl/base/common.h"
-#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
+#include "lib/jxl/image_ops.h"
#include "lib/jxl/modular/encoding/context_predict.h"
#include "lib/jxl/modular/modular_image.h"
#include "lib/jxl/modular/transform/enc_transform.h"
@@ -34,7 +34,8 @@ float ColorDistance(const std::vector<float> &JXL_RESTRICT a,
if (a.size() >= 3) {
ave3 = (a[0] + b[0] + a[1] + b[1] + a[2] + b[2]) * (1.21f / 3.0f);
}
- float sum_a = 0, sum_b = 0;
+ float sum_a = 0;
+ float sum_b = 0;
for (size_t c = 0; c < a.size(); ++c) {
const float difference =
static_cast<float>(a[c]) - static_cast<float>(b[c]);
@@ -132,7 +133,8 @@ struct PaletteIterationData {
delta_frequency.first[1],
delta_frequency.first[2]};
float delta_distance =
- sqrt(palette_internal::ColorDistance({0, 0, 0}, current_delta)) + 1;
+ std::sqrt(palette_internal::ColorDistance({0, 0, 0}, current_delta)) +
+ 1;
delta_frequency.second *= delta_distance * delta_distance_multiplier;
}
@@ -174,7 +176,8 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
// Channel palette special case
if (nb_colors == 0) return false;
std::vector<pixel_type> lookup;
- pixel_type minval, maxval;
+ pixel_type minval;
+ pixel_type maxval;
compute_minmax(input.channel[begin_c], &minval, &maxval);
size_t lookup_table_size =
static_cast<int64_t>(maxval) - static_cast<int64_t>(minval) + 1;
@@ -189,12 +192,12 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
const bool new_color = chpalette.insert(p[x]).second;
if (new_color) {
idx++;
- if (idx > (int)nb_colors) return false;
+ if (idx > static_cast<int>(nb_colors)) return false;
}
}
}
JXL_DEBUG_V(6, "Channel %i uses only %i colors.", begin_c, idx);
- Channel pch(idx, 1);
+ JXL_ASSIGN_OR_RETURN(Channel pch, Channel::Create(idx, 1));
pch.hshift = -1;
pch.vshift = -1;
nb_colors = idx;
@@ -206,9 +209,12 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
for (size_t y = 0; y < h; y++) {
pixel_type *p = input.channel[begin_c].Row(y);
for (size_t x = 0; x < w; x++) {
- for (idx = 0; p[x] != p_palette[idx] && idx < (int)nb_colors; idx++) {
+ for (idx = 0;
+ p[x] != p_palette[idx] && idx < static_cast<int>(nb_colors);
+ idx++) {
+ // no-op
}
- JXL_DASSERT(idx < (int)nb_colors);
+ JXL_DASSERT(idx < static_cast<int>(nb_colors));
p[x] = idx;
}
}
@@ -226,12 +232,12 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
if (lookup[p[x] - minval] == 0) {
lookup[p[x] - minval] = 1;
idx++;
- if (idx > (int)nb_colors) return false;
+ if (idx > static_cast<int>(nb_colors)) return false;
}
}
}
JXL_DEBUG_V(6, "Channel %i uses only %i colors.", begin_c, idx);
- Channel pch(idx, 1);
+ JXL_ASSIGN_OR_RETURN(Channel pch, Channel::Create(idx, 1));
pch.hshift = -1;
pch.vshift = -1;
nb_colors = idx;
@@ -256,7 +262,8 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
Image quantized_input;
if (lossy) {
- quantized_input = Image(w, h, input.bitdepth, nb);
+ JXL_ASSIGN_OR_RETURN(quantized_input,
+ Image::Create(w, h, input.bitdepth, nb));
for (size_t c = 0; c < nb; c++) {
CopyImageTo(input.channel[begin_c + c].plane,
&quantized_input.channel[c].plane);
@@ -337,7 +344,7 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
JXL_DEBUG_V(6, "Channels %i-%i can be represented using a %i-color palette.",
begin_c, end_c, nb_colors);
- Channel pch(nb_colors, nb);
+ JXL_ASSIGN_OR_RETURN(Channel pch, Channel::Create(nb_colors, nb));
pch.hshift = -1;
pch.vshift = -1;
pixel_type *JXL_RESTRICT p_palette = pch.Row(0);
@@ -361,7 +368,8 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
std::sort(candidate_palette_imageorder.begin(),
candidate_palette_imageorder.end(),
[](std::vector<pixel_type> ap, std::vector<pixel_type> bp) {
- float ay, by;
+ float ay;
+ float by;
ay = (0.299f * ap[0] + 0.587f * ap[1] + 0.114f * ap[2] + 0.1f);
if (ap.size() > 3) ay *= 1.f + ap[3];
by = (0.299f * bp[0] + 0.587f * bp[1] + 0.114f * bp[2] + 0.1f);
@@ -420,7 +428,7 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
for (int diffusion_index = 0; diffusion_index < 2; ++diffusion_index) {
for (size_t c = 0; c < nb; c++) {
color_with_error[c] =
- p_in[c][x] + palette_iteration_data.final_run *
+ p_in[c][x] + (palette_iteration_data.final_run ? 1 : 0) *
kDiffusionMultiplier[diffusion_index] *
error_row[0][c][x + 2];
color[c] = Clamp1(lroundf(color_with_error[c]), 0l,
@@ -503,7 +511,7 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
float local_error = color_with_error[c] - best_val[c];
len_error += local_error * local_error;
}
- len_error = sqrt(len_error);
+ len_error = std::sqrt(len_error);
float modulate = 1.0;
int len_limit = 38 << std::max(0, bit_depth - 8);
if (len_error > len_limit) {
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/enc_squeeze.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/enc_squeeze.cc
index 489f72a90d..0d924c0ace 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/enc_squeeze.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/enc_squeeze.cc
@@ -14,15 +14,20 @@
namespace jxl {
-void FwdHSqueeze(Image &input, int c, int rc) {
+#define AVERAGE(X, Y) (((X) + (Y) + (((X) > (Y)) ? 1 : 0)) >> 1)
+
+Status FwdHSqueeze(Image &input, int c, int rc) {
const Channel &chin = input.channel[c];
JXL_DEBUG_V(4, "Doing horizontal squeeze of channel %i to new channel %i", c,
rc);
- Channel chout((chin.w + 1) / 2, chin.h, chin.hshift + 1, chin.vshift);
- Channel chout_residual(chin.w - chout.w, chout.h, chin.hshift + 1,
- chin.vshift);
+ JXL_ASSIGN_OR_RETURN(
+ Channel chout,
+ Channel::Create((chin.w + 1) / 2, chin.h, chin.hshift + 1, chin.vshift));
+ JXL_ASSIGN_OR_RETURN(
+ Channel chout_residual,
+ Channel::Create(chin.w - chout.w, chout.h, chin.hshift + 1, chin.vshift));
for (size_t y = 0; y < chout.h; y++) {
const pixel_type *JXL_RESTRICT p_in = chin.Row(y);
@@ -31,18 +36,19 @@ void FwdHSqueeze(Image &input, int c, int rc) {
for (size_t x = 0; x < chout_residual.w; x++) {
pixel_type A = p_in[x * 2];
pixel_type B = p_in[x * 2 + 1];
- pixel_type avg = (A + B + (A > B)) >> 1;
+ pixel_type avg = AVERAGE(A, B);
p_out[x] = avg;
pixel_type diff = A - B;
pixel_type next_avg = avg;
if (x + 1 < chout_residual.w) {
- next_avg = (p_in[x * 2 + 2] + p_in[x * 2 + 3] +
- (p_in[x * 2 + 2] > p_in[x * 2 + 3])) >>
- 1; // which will be chout.value(y,x+1)
- } else if (chin.w & 1)
+ pixel_type C = p_in[x * 2 + 2];
+ pixel_type D = p_in[x * 2 + 3];
+ next_avg = AVERAGE(C, D); // which will be chout.value(y,x+1)
+ } else if (chin.w & 1) {
next_avg = p_in[x * 2 + 2];
+ }
pixel_type left = (x > 0 ? p_in[x * 2 - 1] : avg);
pixel_type tendency = SmoothTendency(left, avg, next_avg);
@@ -55,17 +61,21 @@ void FwdHSqueeze(Image &input, int c, int rc) {
}
input.channel[c] = std::move(chout);
input.channel.insert(input.channel.begin() + rc, std::move(chout_residual));
+ return true;
}
-void FwdVSqueeze(Image &input, int c, int rc) {
+Status FwdVSqueeze(Image &input, int c, int rc) {
const Channel &chin = input.channel[c];
JXL_DEBUG_V(4, "Doing vertical squeeze of channel %i to new channel %i", c,
rc);
- Channel chout(chin.w, (chin.h + 1) / 2, chin.hshift, chin.vshift + 1);
- Channel chout_residual(chin.w, chin.h - chout.h, chin.hshift,
- chin.vshift + 1);
+ JXL_ASSIGN_OR_RETURN(
+ Channel chout,
+ Channel::Create(chin.w, (chin.h + 1) / 2, chin.hshift, chin.vshift + 1));
+ JXL_ASSIGN_OR_RETURN(
+ Channel chout_residual,
+ Channel::Create(chin.w, chin.h - chout.h, chin.hshift, chin.vshift + 1));
intptr_t onerow_in = chin.plane.PixelsPerRow();
for (size_t y = 0; y < chout_residual.h; y++) {
const pixel_type *JXL_RESTRICT p_in = chin.Row(y * 2);
@@ -74,16 +84,16 @@ void FwdVSqueeze(Image &input, int c, int rc) {
for (size_t x = 0; x < chout.w; x++) {
pixel_type A = p_in[x];
pixel_type B = p_in[x + onerow_in];
- pixel_type avg = (A + B + (A > B)) >> 1;
+ pixel_type avg = AVERAGE(A, B);
p_out[x] = avg;
pixel_type diff = A - B;
pixel_type next_avg = avg;
if (y + 1 < chout_residual.h) {
- next_avg = (p_in[x + 2 * onerow_in] + p_in[x + 3 * onerow_in] +
- (p_in[x + 2 * onerow_in] > p_in[x + 3 * onerow_in])) >>
- 1; // which will be chout.value(y+1,x)
+ pixel_type C = p_in[x + 2 * onerow_in];
+ pixel_type D = p_in[x + 3 * onerow_in];
+ next_avg = AVERAGE(C, D); // which will be chout.value(y+1,x)
} else if (chin.h & 1) {
next_avg = p_in[x + 2 * onerow_in];
}
@@ -104,6 +114,7 @@ void FwdVSqueeze(Image &input, int c, int rc) {
}
input.channel[c] = std::move(chout);
input.channel.insert(input.channel.begin() + rc, std::move(chout_residual));
+ return true;
}
Status FwdSqueeze(Image &input, std::vector<SqueezeParams> parameters,
@@ -128,9 +139,9 @@ Status FwdSqueeze(Image &input, std::vector<SqueezeParams> parameters,
}
for (uint32_t c = beginc; c <= endc; c++) {
if (horizontal) {
- FwdHSqueeze(input, c, offset + c - beginc);
+ JXL_RETURN_IF_ERROR(FwdHSqueeze(input, c, offset + c - beginc));
} else {
- FwdVSqueeze(input, c, offset + c - beginc);
+ JXL_RETURN_IF_ERROR(FwdVSqueeze(input, c, offset + c - beginc));
}
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc
index bffbacf160..1ab499ccf6 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc
@@ -23,9 +23,11 @@ Status InvPalette(Image &input, uint32_t begin_c, uint32_t nb_colors,
size_t h = input.channel[c0].h;
if (nb < 1) return JXL_FAILURE("Corrupted transforms");
for (int i = 1; i < nb; i++) {
- input.channel.insert(
- input.channel.begin() + c0 + 1,
- Channel(w, h, input.channel[c0].hshift, input.channel[c0].vshift));
+ StatusOr<Channel> channel_or = Channel::Create(
+ w, h, input.channel[c0].hshift, input.channel[c0].vshift);
+ JXL_RETURN_IF_ERROR(channel_or.status());
+ input.channel.insert(input.channel.begin() + c0 + 1,
+ std::move(channel_or).value());
}
const Channel &palette = input.channel[0];
const pixel_type *JXL_RESTRICT p_palette = input.channel[0].Row(0);
@@ -44,7 +46,8 @@ Status InvPalette(Image &input, uint32_t begin_c, uint32_t nb_colors,
const size_t y = task;
pixel_type *p = input.channel[c0].Row(y);
for (size_t x = 0; x < w; x++) {
- const int index = Clamp1<int>(p[x], 0, (pixel_type)palette.w - 1);
+ const int index =
+ Clamp1<int>(p[x], 0, static_cast<pixel_type>(palette.w) - 1);
p[x] = palette_internal::GetPaletteValue(
p_palette, index, /*c=*/0,
/*palette_size=*/palette.w,
@@ -75,8 +78,10 @@ Status InvPalette(Image &input, uint32_t begin_c, uint32_t nb_colors,
}
} else {
// Parallelized per channel.
- ImageI indices = std::move(input.channel[c0].plane);
- input.channel[c0].plane = ImageI(indices.xsize(), indices.ysize());
+ ImageI indices;
+ ImageI &plane = input.channel[c0].plane;
+ JXL_ASSIGN_OR_RETURN(indices, ImageI::Create(plane.xsize(), plane.ysize()));
+ plane.Swap(indices);
if (predictor == Predictor::Weighted) {
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, nb, ThreadPool::NoInit,
@@ -167,7 +172,7 @@ Status MetaPalette(Image &input, uint32_t begin_c, uint32_t end_c,
}
input.channel.erase(input.channel.begin() + begin_c + 1,
input.channel.begin() + end_c + 1);
- Channel pch(nb_colors + nb_deltas, nb);
+ JXL_ASSIGN_OR_RETURN(Channel pch, Channel::Create(nb_colors + nb_deltas, nb));
pch.hshift = -1;
pch.vshift = -1;
input.channel.insert(input.channel.begin(), std::move(pch));
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h
index 279ef04568..e0405a2162 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h
@@ -101,6 +101,7 @@ GetPaletteValue(const pixel_type *const palette, int index, const size_t c,
// index >= kLargeCube ** 3 ?
switch (c) {
case 0:
+ default:
break;
case 1:
index /= kLargeCube;
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc
index e9892ea48f..580829741a 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc
@@ -113,7 +113,9 @@ Status InvHSqueeze(Image &input, uint32_t c, uint32_t rc, ThreadPool *pool) {
}
// Note: chin.w >= chin_residual.w and at most 1 different.
- Channel chout(chin.w + chin_residual.w, chin.h, chin.hshift - 1, chin.vshift);
+ JXL_ASSIGN_OR_RETURN(Channel chout,
+ Channel::Create(chin.w + chin_residual.w, chin.h,
+ chin.hshift - 1, chin.vshift));
JXL_DEBUG_V(4,
"Undoing horizontal squeeze of channel %i using residuals in "
"channel %i (going from width %" PRIuS " to %" PRIuS ")",
@@ -222,7 +224,9 @@ Status InvVSqueeze(Image &input, uint32_t c, uint32_t rc, ThreadPool *pool) {
}
// Note: chin.h >= chin_residual.h and at most 1 different.
- Channel chout(chin.w, chin.h + chin_residual.h, chin.hshift, chin.vshift - 1);
+ JXL_ASSIGN_OR_RETURN(Channel chout,
+ Channel::Create(chin.w, chin.h + chin_residual.h,
+ chin.hshift, chin.vshift - 1));
JXL_DEBUG_V(
4,
"Undoing vertical squeeze of channel %i using residuals in channel "
@@ -238,7 +242,8 @@ Status InvVSqueeze(Image &input, uint32_t c, uint32_t rc, ThreadPool *pool) {
static constexpr const int kColsPerThread = 64;
const auto unsqueeze_slice = [&](const uint32_t task, size_t /* thread */) {
const size_t x0 = task * kColsPerThread;
- const size_t x1 = std::min((size_t)(task + 1) * kColsPerThread, chin.w);
+ const size_t x1 =
+ std::min(static_cast<size_t>(task + 1) * kColsPerThread, chin.w);
const size_t w = x1 - x0;
// We only iterate up to std::min(chin_residual.h, chin.h) which is
// always chin_residual.h.
@@ -289,7 +294,7 @@ Status InvVSqueeze(Image &input, uint32_t c, uint32_t rc, ThreadPool *pool) {
return true;
}
-Status InvSqueeze(Image &input, std::vector<SqueezeParams> parameters,
+Status InvSqueeze(Image &input, const std::vector<SqueezeParams> &parameters,
ThreadPool *pool) {
for (int i = parameters.size() - 1; i >= 0; i--) {
JXL_RETURN_IF_ERROR(
@@ -340,7 +345,7 @@ HWY_AFTER_NAMESPACE();
namespace jxl {
HWY_EXPORT(InvSqueeze);
-Status InvSqueeze(Image &input, std::vector<SqueezeParams> parameters,
+Status InvSqueeze(Image &input, const std::vector<SqueezeParams> &parameters,
ThreadPool *pool) {
return HWY_DYNAMIC_DISPATCH(InvSqueeze)(input, parameters, pool);
}
@@ -459,8 +464,8 @@ Status MetaSqueeze(Image &image, std::vector<SqueezeParams> *parameters) {
if (image.channel[c].vshift >= 0) image.channel[c].vshift++;
h = h - (h + 1) / 2;
}
- image.channel[c].shrink();
- Channel placeholder(w, h);
+ JXL_RETURN_IF_ERROR(image.channel[c].shrink());
+ JXL_ASSIGN_OR_RETURN(Channel placeholder, Channel::Create(w, h));
placeholder.hshift = image.channel[c].hshift;
placeholder.vshift = image.channel[c].vshift;
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h
index 305a0ca3ec..bbd16c59c0 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h
@@ -81,7 +81,7 @@ Status CheckMetaSqueezeParams(const SqueezeParams &parameter, int num_channels);
Status MetaSqueeze(Image &image, std::vector<SqueezeParams> *parameters);
-Status InvSqueeze(Image &input, std::vector<SqueezeParams> parameters,
+Status InvSqueeze(Image &input, const std::vector<SqueezeParams> &parameters,
ThreadPool *pool);
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h
index d5d3259f7a..b68861706f 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h
@@ -77,11 +77,13 @@ class Transform : public Fields {
Transform() : Transform(TransformId::kInvalid) {}
Status VisitFields(Visitor *JXL_RESTRICT visitor) override {
- JXL_QUIET_RETURN_IF_ERROR(visitor->U32(
- Val((uint32_t)TransformId::kRCT), Val((uint32_t)TransformId::kPalette),
- Val((uint32_t)TransformId::kSqueeze),
- Val((uint32_t)TransformId::kInvalid), (uint32_t)TransformId::kRCT,
- reinterpret_cast<uint32_t *>(&id)));
+ JXL_QUIET_RETURN_IF_ERROR(
+ visitor->U32(Val(static_cast<uint32_t>(TransformId::kRCT)),
+ Val(static_cast<uint32_t>(TransformId::kPalette)),
+ Val(static_cast<uint32_t>(TransformId::kSqueeze)),
+ Val(static_cast<uint32_t>(TransformId::kInvalid)),
+ static_cast<uint32_t>(TransformId::kRCT),
+ reinterpret_cast<uint32_t *>(&id)));
if (id == TransformId::kInvalid) {
return JXL_FAILURE("Invalid transform ID");
}
@@ -109,7 +111,7 @@ class Transform : public Fields {
visitor->U32(Val(0), BitsOffset(8, 1), BitsOffset(10, 257),
BitsOffset(16, 1281), 0, &nb_deltas));
JXL_QUIET_RETURN_IF_ERROR(
- visitor->Bits(4, (uint32_t)Predictor::Zero,
+ visitor->Bits(4, static_cast<uint32_t>(Predictor::Zero),
reinterpret_cast<uint32_t *>(&predictor)));
if (predictor >= Predictor::Best) {
return JXL_FAILURE("Invalid predictor");
diff --git a/third_party/jpeg-xl/lib/jxl/modular_test.cc b/third_party/jpeg-xl/lib/jxl/modular_test.cc
index 689063ce95..bd1a947493 100644
--- a/third_party/jpeg-xl/lib/jxl/modular_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular_test.cc
@@ -7,6 +7,7 @@
#include <jxl/encode.h>
#include <jxl/types.h>
+#include <cmath>
#include <cstddef>
#include <cstdint>
#include <sstream>
@@ -29,7 +30,6 @@
#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_bit_writer.h"
-#include "lib/jxl/enc_butteraugli_comparator.h"
#include "lib/jxl/enc_fields.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/enc_toc.h"
@@ -54,6 +54,7 @@
namespace jxl {
namespace {
+using test::ButteraugliDistance;
using test::ReadTestData;
using test::Roundtrip;
using test::TestImage;
@@ -130,10 +131,11 @@ TEST(ModularTest, RoundtripLossyDeltaPalette) {
size_t compressed_size;
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io_out, _, &compressed_size));
EXPECT_LE(compressed_size, 6800u);
- EXPECT_THAT(ButteraugliDistance(io.frames, io_out.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(1.5));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io_out.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 1.5);
}
TEST(ModularTest, RoundtripLossyDeltaPaletteWP) {
const std::vector<uint8_t> orig =
@@ -153,10 +155,11 @@ TEST(ModularTest, RoundtripLossyDeltaPaletteWP) {
size_t compressed_size;
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io_out, _, &compressed_size));
EXPECT_LE(compressed_size, 7000u);
- EXPECT_THAT(ButteraugliDistance(io.frames, io_out.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(10.1));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io_out.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 10.1);
}
TEST(ModularTest, RoundtripLossy) {
@@ -175,10 +178,11 @@ TEST(ModularTest, RoundtripLossy) {
size_t compressed_size;
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io_out, _, &compressed_size));
EXPECT_LE(compressed_size, 30000u);
- EXPECT_THAT(ButteraugliDistance(io.frames, io_out.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(2.3));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io_out.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 2.3);
}
TEST(ModularTest, RoundtripLossy16) {
@@ -201,15 +205,17 @@ TEST(ModularTest, RoundtripLossy16) {
size_t compressed_size;
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io_out, _, &compressed_size));
EXPECT_LE(compressed_size, 300u);
- EXPECT_THAT(ButteraugliDistance(io.frames, io_out.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(1.6));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io_out.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 1.6);
}
TEST(ModularTest, RoundtripExtraProperties) {
constexpr size_t kSize = 250;
- Image image(kSize, kSize, /*bitdepth=*/8, 3);
+ JXL_ASSIGN_OR_DIE(Image image,
+ Image::Create(kSize, kSize, /*bitdepth=*/8, 3));
ModularOptions options;
options.max_properties = 4;
options.predictor = Predictor::Zero;
@@ -224,10 +230,12 @@ TEST(ModularTest, RoundtripExtraProperties) {
BitWriter writer;
ASSERT_TRUE(ModularGenericCompress(image, options, &writer));
writer.ZeroPadToByte();
- Image decoded(kSize, kSize, /*bitdepth=*/8, image.channel.size());
+ JXL_ASSIGN_OR_DIE(Image decoded, Image::Create(kSize, kSize, /*bitdepth=*/8,
+ image.channel.size()));
for (size_t i = 0; i < image.channel.size(); i++) {
const Channel& ch = image.channel[i];
- decoded.channel[i] = Channel(ch.w, ch.h, ch.hshift, ch.vshift);
+ JXL_ASSIGN_OR_DIE(decoded.channel[i],
+ Channel::Create(ch.w, ch.h, ch.hshift, ch.vshift));
}
Status status = true;
{
@@ -302,7 +310,7 @@ TEST_P(ModularTestParam, RoundtripLossless) {
double factor = ((1lu << bitdepth) - 1lu);
double ifactor = 1.0 / factor;
- Image3F noise_added(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(Image3F noise_added, Image3F::Create(xsize, ysize));
for (size_t c = 0; c < 3; c++) {
for (size_t y = 0; y < ysize; y++) {
@@ -313,7 +321,7 @@ TEST_P(ModularTestParam, RoundtripLossless) {
float f = in[x] + generator.UniformF(0.0f, 1.f / 255.f);
if (f > 1.f) f = 1.f;
// quantize to the bitdepth we're testing
- unsigned int u = f * factor + 0.5;
+ unsigned int u = static_cast<unsigned int>(std::lround(f * factor));
out[x] = u * ifactor;
}
}
@@ -330,7 +338,7 @@ TEST_P(ModularTestParam, RoundtripLossless) {
CodecInOut io2;
size_t compressed_size;
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _, &compressed_size));
- EXPECT_LE(compressed_size, bitdepth * xsize * ysize / 3);
+ EXPECT_LE(compressed_size, bitdepth * xsize * ysize / 3.0 * 1.1);
EXPECT_LE(0, ComputeDistance2(io.Main(), io2.Main(), *JxlGetDefaultCms()));
size_t different = 0;
for (size_t c = 0; c < 3; c++) {
@@ -350,7 +358,8 @@ TEST_P(ModularTestParam, RoundtripLossless) {
TEST(ModularTest, RoundtripLosslessCustomFloat) {
CodecInOut io;
- size_t xsize = 100, ysize = 300;
+ size_t xsize = 100;
+ size_t ysize = 300;
io.SetSize(xsize, ysize);
io.metadata.m.bit_depth.bits_per_sample = 18;
io.metadata.m.bit_depth.exponent_bits_per_sample = 6;
@@ -359,7 +368,7 @@ TEST(ModularTest, RoundtripLosslessCustomFloat) {
ColorEncoding color_encoding;
color_encoding.Tf().SetTransferFunction(TransferFunction::kLinear);
color_encoding.SetColorSpace(ColorSpace::kRGB);
- Image3F testimage(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(Image3F testimage, Image3F::Create(xsize, ysize));
float factor = 1.f / (1 << 14);
for (size_t c = 0; c < 3; c++) {
for (size_t y = 0; y < ysize; y++) {
@@ -442,7 +451,7 @@ TEST(ModularTest, PredictorIntegerOverflow) {
WriteHeaders(&writer, xsize, ysize);
std::vector<BitWriter> group_codes(1);
{
- BitWriter* bw = &group_codes[0];
+ BitWriter* bw = group_codes.data();
BitWriter::Allotment allotment(bw, 1 << 20);
WriteHistograms(bw);
GroupHeader header;
@@ -466,7 +475,7 @@ TEST(ModularTest, PredictorIntegerOverflow) {
nullptr, &ppf));
ASSERT_EQ(1, ppf.frames.size());
const auto& img = ppf.frames[0].color;
- const auto pixels = reinterpret_cast<const float*>(img.pixels());
+ const auto* pixels = reinterpret_cast<const float*>(img.pixels());
EXPECT_EQ(-1.0f, pixels[0]);
}
@@ -478,7 +487,7 @@ TEST(ModularTest, UnsqueezeIntegerOverflow) {
WriteHeaders(&writer, xsize, ysize);
std::vector<BitWriter> group_codes(1);
{
- BitWriter* bw = &group_codes[0];
+ BitWriter* bw = group_codes.data();
BitWriter::Allotment allotment(bw, 1 << 20);
WriteHistograms(bw);
GroupHeader header;
@@ -514,7 +523,7 @@ TEST(ModularTest, UnsqueezeIntegerOverflow) {
nullptr, &ppf));
ASSERT_EQ(1, ppf.frames.size());
const auto& img = ppf.frames[0].color;
- const auto pixels = reinterpret_cast<const float*>(img.pixels());
+ const float* pixels = reinterpret_cast<const float*>(img.pixels());
for (size_t x = 0; x < xsize; ++x) {
EXPECT_NEAR(-0.5f, pixels[x], 1e-10);
EXPECT_NEAR(0.5f, pixels[xsize + x], 1e-10);
diff --git a/third_party/jpeg-xl/lib/jxl/noise.h b/third_party/jpeg-xl/lib/jxl/noise.h
index 585fab0d42..c588c59d33 100644
--- a/third_party/jpeg-xl/lib/jxl/noise.h
+++ b/third_party/jpeg-xl/lib/jxl/noise.h
@@ -11,6 +11,7 @@
#include <stddef.h>
#include <algorithm>
+#include <array>
#include <cmath>
#include <utility>
@@ -23,7 +24,9 @@ const float kNoisePrecision = 1 << 10;
struct NoiseParams {
// LUT index is an intensity of pixel / mean intensity of patch
static constexpr size_t kNumNoisePoints = 8;
- float lut[kNumNoisePoints];
+ using Lut = std::array<float, kNumNoisePoints>;
+
+ Lut lut;
void Clear() {
for (float& i : lut) i = 0.f;
@@ -39,7 +42,7 @@ struct NoiseParams {
static inline std::pair<int, float> IndexAndFrac(float x) {
constexpr size_t kScaleNumerator = NoiseParams::kNumNoisePoints - 2;
// TODO(user): instead of 1, this should be a proper Y range.
- constexpr float kScale = kScaleNumerator / 1;
+ constexpr float kScale = kScaleNumerator / 1.0f;
float scaled_x = std::max(0.f, x * kScale);
float floor_x;
float frac_x = std::modf(scaled_x, &floor_x);
diff --git a/third_party/jpeg-xl/lib/jxl/opsin_image_test.cc b/third_party/jpeg-xl/lib/jxl/opsin_image_test.cc
index f7842c32e4..b8ea839b9e 100644
--- a/third_party/jpeg-xl/lib/jxl/opsin_image_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/opsin_image_test.cc
@@ -27,7 +27,7 @@ namespace {
void LinearSrgbToOpsin(float rgb_r, float rgb_g, float rgb_b,
float* JXL_RESTRICT xyb_x, float* JXL_RESTRICT xyb_y,
float* JXL_RESTRICT xyb_b) {
- Image3F linear(1, 1);
+ JXL_ASSIGN_OR_DIE(Image3F linear, Image3F::Create(1, 1));
linear.PlaneRow(0, 0)[0] = rgb_r;
linear.PlaneRow(1, 0)[0] = rgb_g;
linear.PlaneRow(2, 0)[0] = rgb_b;
@@ -37,7 +37,7 @@ void LinearSrgbToOpsin(float rgb_r, float rgb_g, float rgb_b,
metadata.color_encoding = ColorEncoding::LinearSRGB();
ImageBundle ib(&metadata);
ib.SetFromImage(std::move(linear), metadata.color_encoding);
- Image3F opsin(1, 1);
+ JXL_ASSIGN_OR_DIE(Image3F opsin, Image3F::Create(1, 1));
(void)ToXYB(ib, /*pool=*/nullptr, &opsin, *JxlGetDefaultCms());
*xyb_x = opsin.PlaneRow(0, 0)[0];
@@ -50,11 +50,11 @@ void LinearSrgbToOpsin(float rgb_r, float rgb_g, float rgb_b,
void OpsinToLinearSrgb(float xyb_x, float xyb_y, float xyb_b,
float* JXL_RESTRICT rgb_r, float* JXL_RESTRICT rgb_g,
float* JXL_RESTRICT rgb_b) {
- Image3F opsin(1, 1);
+ JXL_ASSIGN_OR_DIE(Image3F opsin, Image3F::Create(1, 1));
opsin.PlaneRow(0, 0)[0] = xyb_x;
opsin.PlaneRow(1, 0)[0] = xyb_y;
opsin.PlaneRow(2, 0)[0] = xyb_b;
- Image3F linear(1, 1);
+ JXL_ASSIGN_OR_DIE(Image3F linear, Image3F::Create(1, 1));
OpsinParams opsin_params;
opsin_params.Init(/*intensity_target=*/255.0f);
OpsinToLinear(opsin, Rect(opsin), nullptr, &linear, opsin_params);
@@ -64,9 +64,13 @@ void OpsinToLinearSrgb(float xyb_x, float xyb_y, float xyb_b,
}
void OpsinRoundtripTestRGB(float r, float g, float b) {
- float xyb_x, xyb_y, xyb_b;
+ float xyb_x;
+ float xyb_y;
+ float xyb_b;
LinearSrgbToOpsin(r, g, b, &xyb_x, &xyb_y, &xyb_b);
- float r2, g2, b2;
+ float r2;
+ float g2;
+ float b2;
OpsinToLinearSrgb(xyb_x, xyb_y, xyb_b, &r2, &g2, &b2);
EXPECT_NEAR(r, r2, 1e-3);
EXPECT_NEAR(g, g2, 1e-3);
@@ -74,13 +78,13 @@ void OpsinRoundtripTestRGB(float r, float g, float b) {
}
TEST(OpsinImageTest, VerifyOpsinAbsorbanceInverseMatrix) {
- float matrix[9]; // writable copy
- for (int i = 0; i < 9; i++) {
- matrix[i] = GetOpsinAbsorbanceInverseMatrix()[i];
- }
+ Matrix3x3 matrix; // writable copy
+ matrix = GetOpsinAbsorbanceInverseMatrix();
EXPECT_TRUE(Inv3x3Matrix(matrix));
- for (int i = 0; i < 9; i++) {
- EXPECT_NEAR(matrix[i], jxl::cms::kOpsinAbsorbanceMatrix[i], 1e-6);
+ for (int j = 0; j < 3; j++) {
+ for (int i = 0; i < 3; i++) {
+ EXPECT_NEAR(matrix[j][i], jxl::cms::kOpsinAbsorbanceMatrix[j][i], 1e-6);
+ }
}
}
@@ -105,7 +109,9 @@ TEST(OpsinImageTest, OpsinRoundtrip) {
TEST(OpsinImageTest, VerifyZero) {
// Test that black color (zero energy) is 0,0,0 in xyb.
- float x, y, b;
+ float x;
+ float y;
+ float b;
LinearSrgbToOpsin(0, 0, 0, &x, &y, &b);
EXPECT_NEAR(0, x, 1e-9);
EXPECT_NEAR(0, y, 1e-7);
@@ -115,7 +121,9 @@ TEST(OpsinImageTest, VerifyZero) {
TEST(OpsinImageTest, VerifyGray) {
// Test that grayscale colors have a fixed y/b ratio and x==0.
for (size_t i = 1; i < 255; i++) {
- float x, y, b;
+ float x;
+ float y;
+ float b;
LinearSrgbToOpsin(i / 255., i / 255., i / 255., &x, &y, &b);
EXPECT_NEAR(0, x, 1e-6);
EXPECT_NEAR(jxl::cms::kYToBRatio, b / y, 3e-5);
diff --git a/third_party/jpeg-xl/lib/jxl/opsin_inverse_test.cc b/third_party/jpeg-xl/lib/jxl/opsin_inverse_test.cc
index b8c151fbea..b8f9aa13df 100644
--- a/third_party/jpeg-xl/lib/jxl/opsin_inverse_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/opsin_inverse_test.cc
@@ -21,17 +21,17 @@ namespace jxl {
namespace {
TEST(OpsinInverseTest, LinearInverseInverts) {
- Image3F linear(128, 128);
+ JXL_ASSIGN_OR_DIE(Image3F linear, Image3F::Create(128, 128));
RandomFillImage(&linear, 0.0f, 1.0f);
CodecInOut io;
io.metadata.m.SetFloat32Samples();
io.metadata.m.color_encoding = ColorEncoding::LinearSRGB();
- Image3F linear2(128, 128);
+ JXL_ASSIGN_OR_DIE(Image3F linear2, Image3F::Create(128, 128));
CopyImageTo(linear, &linear2);
io.SetFromImage(std::move(linear2), io.metadata.m.color_encoding);
ThreadPool* null_pool = nullptr;
- Image3F opsin(io.xsize(), io.ysize());
+ JXL_ASSIGN_OR_DIE(Image3F opsin, Image3F::Create(io.xsize(), io.ysize()));
(void)ToXYB(io.Main(), null_pool, &opsin, *JxlGetDefaultCms());
OpsinParams opsin_params;
@@ -42,16 +42,16 @@ TEST(OpsinInverseTest, LinearInverseInverts) {
}
TEST(OpsinInverseTest, YcbCrInverts) {
- Image3F rgb(128, 128);
+ JXL_ASSIGN_OR_DIE(Image3F rgb, Image3F::Create(128, 128));
RandomFillImage(&rgb, 0.0f, 1.0f);
ThreadPool* null_pool = nullptr;
- Image3F ycbcr(rgb.xsize(), rgb.ysize());
+ JXL_ASSIGN_OR_DIE(Image3F ycbcr, Image3F::Create(rgb.xsize(), rgb.ysize()));
EXPECT_TRUE(RgbToYcbcr(rgb.Plane(0), rgb.Plane(1), rgb.Plane(2),
&ycbcr.Plane(1), &ycbcr.Plane(0), &ycbcr.Plane(2),
null_pool));
- Image3F rgb2(rgb.xsize(), rgb.ysize());
+ JXL_ASSIGN_OR_DIE(Image3F rgb2, Image3F::Create(rgb.xsize(), rgb.ysize()));
YcbcrToRgb(ycbcr, &rgb2, Rect(rgb));
JXL_ASSERT_OK(VerifyRelativeError(rgb, rgb2, 4E-5, 4E-7, _));
diff --git a/third_party/jpeg-xl/lib/jxl/opsin_params.cc b/third_party/jpeg-xl/lib/jxl/opsin_params.cc
index e1fdda5322..8aae4e3597 100644
--- a/third_party/jpeg-xl/lib/jxl/opsin_params.cc
+++ b/third_party/jpeg-xl/lib/jxl/opsin_params.cc
@@ -9,24 +9,19 @@
#define INVERSE_OPSIN_FROM_SPEC 1
-#if not(INVERSE_OPSIN_FROM_SPEC)
#include "lib/jxl/base/matrix_ops.h"
-#endif
namespace jxl {
-const float* GetOpsinAbsorbanceInverseMatrix() {
+const Matrix3x3& GetOpsinAbsorbanceInverseMatrix() {
#if INVERSE_OPSIN_FROM_SPEC
return jxl::cms::DefaultInverseOpsinAbsorbanceMatrix();
#else // INVERSE_OPSIN_FROM_SPEC
// Compute the inverse opsin matrix from the forward matrix. Less precise
// than taking the values from the specification, but must be used if the
// forward transform is changed and the spec will require updating.
- static const float* const kInverse = [] {
- static float inverse[9];
- for (int i = 0; i < 9; i++) {
- inverse[i] = kOpsinAbsorbanceMatrix[i];
- }
+ static const Matrix3x3 const kInverse = [] {
+ static Matrix3x3 inverse = kOpsinAbsorbanceMatrix;
Inv3x3Matrix(inverse);
return inverse;
}();
@@ -34,12 +29,15 @@ const float* GetOpsinAbsorbanceInverseMatrix() {
#endif // INVERSE_OPSIN_FROM_SPEC
}
-void InitSIMDInverseMatrix(const float* JXL_RESTRICT inverse,
+void InitSIMDInverseMatrix(const Matrix3x3& inverse,
float* JXL_RESTRICT simd_inverse,
float intensity_target) {
- for (size_t i = 0; i < 9; ++i) {
- simd_inverse[4 * i] = simd_inverse[4 * i + 1] = simd_inverse[4 * i + 2] =
- simd_inverse[4 * i + 3] = inverse[i] * (255.0f / intensity_target);
+ for (size_t j = 0; j < 3; ++j) {
+ for (size_t i = 0; i < 3; ++i) {
+ size_t idx = (j * 3 + i) * 4;
+ simd_inverse[idx] = simd_inverse[idx + 1] = simd_inverse[idx + 2] =
+ simd_inverse[idx + 3] = inverse[j][i] * (255.0f / intensity_target);
+ }
}
}
diff --git a/third_party/jpeg-xl/lib/jxl/opsin_params.h b/third_party/jpeg-xl/lib/jxl/opsin_params.h
index fc285ac208..4ed2124fd7 100644
--- a/third_party/jpeg-xl/lib/jxl/opsin_params.h
+++ b/third_party/jpeg-xl/lib/jxl/opsin_params.h
@@ -9,14 +9,15 @@
// Constants that define the XYB color space.
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/matrix_ops.h"
namespace jxl {
// Returns 3x3 row-major matrix inverse of kOpsinAbsorbanceMatrix.
// opsin_image_test verifies this is actually the inverse.
-const float* GetOpsinAbsorbanceInverseMatrix();
+const Matrix3x3& GetOpsinAbsorbanceInverseMatrix();
-void InitSIMDInverseMatrix(const float* JXL_RESTRICT inverse,
+void InitSIMDInverseMatrix(const Matrix3x3& inverse,
float* JXL_RESTRICT simd_inverse,
float intensity_target);
diff --git a/third_party/jpeg-xl/lib/jxl/padded_bytes.h b/third_party/jpeg-xl/lib/jxl/padded_bytes.h
index 0d696475fa..38167ed408 100644
--- a/third_party/jpeg-xl/lib/jxl/padded_bytes.h
+++ b/third_party/jpeg-xl/lib/jxl/padded_bytes.h
@@ -71,7 +71,7 @@ class PaddedBytes {
return *this;
}
- void swap(PaddedBytes& other) {
+ void swap(PaddedBytes& other) noexcept {
std::swap(size_, other.size_);
std::swap(capacity_, other.capacity_);
std::swap(data_, other.data_);
diff --git a/third_party/jpeg-xl/lib/jxl/passes_state.cc b/third_party/jpeg-xl/lib/jxl/passes_state.cc
index 12cc6a0c93..5da731b48e 100644
--- a/third_party/jpeg-xl/lib/jxl/passes_state.cc
+++ b/third_party/jpeg-xl/lib/jxl/passes_state.cc
@@ -5,6 +5,7 @@
#include "lib/jxl/passes_state.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/coeff_order.h"
#include "lib/jxl/frame_dimensions.h"
@@ -21,13 +22,17 @@ Status InitializePassesSharedState(const FrameHeader& frame_header,
const FrameDimensions& frame_dim = shared->frame_dim;
- shared->ac_strategy =
- AcStrategyImage(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
- shared->raw_quant_field =
- ImageI(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
- shared->epf_sharpness =
- ImageB(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
- shared->cmap = ColorCorrelationMap(frame_dim.xsize, frame_dim.ysize);
+ JXL_ASSIGN_OR_RETURN(
+ shared->ac_strategy,
+ AcStrategyImage::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
+ JXL_ASSIGN_OR_RETURN(
+ shared->raw_quant_field,
+ ImageI::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
+ JXL_ASSIGN_OR_RETURN(
+ shared->epf_sharpness,
+ ImageB::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
+ JXL_ASSIGN_OR_RETURN(shared->cmap, ColorCorrelationMap::Create(
+ frame_dim.xsize, frame_dim.ysize));
// In the decoder, we allocate coeff orders afterwards, when we know how many
// we will actually need.
@@ -40,9 +45,11 @@ Status InitializePassesSharedState(const FrameHeader& frame_header,
kCoeffOrderMaxSize);
}
- shared->quant_dc = ImageB(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
+ JXL_ASSIGN_OR_RETURN(
+ shared->quant_dc,
+ ImageB::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
- bool use_dc_frame = !!(frame_header.flags & FrameHeader::kUseDcFrame);
+ bool use_dc_frame = ((frame_header.flags & FrameHeader::kUseDcFrame) != 0u);
if (!encoder && use_dc_frame) {
if (frame_header.dc_level == 4) {
return JXL_FAILURE("Invalid DC level for kUseDcFrame: %u",
@@ -58,8 +65,9 @@ Status InitializePassesSharedState(const FrameHeader& frame_header,
}
ZeroFillImage(&shared->quant_dc);
} else {
- shared->dc_storage =
- Image3F(frame_dim.xsize_blocks, frame_dim.ysize_blocks);
+ JXL_ASSIGN_OR_RETURN(
+ shared->dc_storage,
+ Image3F::Create(frame_dim.xsize_blocks, frame_dim.ysize_blocks));
shared->dc = &shared->dc_storage;
}
diff --git a/third_party/jpeg-xl/lib/jxl/passes_test.cc b/third_party/jpeg-xl/lib/jxl/passes_test.cc
index a47134cd00..cb9164706f 100644
--- a/third_party/jpeg-xl/lib/jxl/passes_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/passes_test.cc
@@ -17,7 +17,6 @@
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/override.h"
#include "lib/jxl/base/span.h"
-#include "lib/jxl/enc_butteraugli_comparator.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/image.h"
#include "lib/jxl/image_bundle.h"
@@ -27,6 +26,7 @@
namespace jxl {
+using test::ButteraugliDistance;
using test::ReadTestData;
using test::Roundtrip;
using test::ThreadPoolForTests;
@@ -47,10 +47,11 @@ TEST(PassesTest, RoundtripSmallPasses) {
CodecInOut io2;
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _));
- EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(0.8222));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 0.8222);
}
TEST(PassesTest, RoundtripUnalignedPasses) {
@@ -67,10 +68,11 @@ TEST(PassesTest, RoundtripUnalignedPasses) {
CodecInOut io2;
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _));
- EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(1.72));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 1.72);
}
TEST(PassesTest, RoundtripMultiGroupPasses) {
@@ -91,10 +93,11 @@ TEST(PassesTest, RoundtripMultiGroupPasses) {
CodecInOut io2;
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _,
/* compressed_size */ nullptr, &pool));
- EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr, &pool),
- IsSlightlyBelow(target_distance + threshold));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr, &pool),
+ target_distance + threshold);
};
auto run1 = std::async(std::launch::async, test, 1.0f, 0.15f);
@@ -256,7 +259,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectlyGrayscale) {
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, &pool));
Rect rect(0, 0, io_orig.xsize(), 128);
// need 2 DC groups for the DC frame to actually be progressive.
- Image3F large(4242, rect.ysize());
+ JXL_ASSIGN_OR_DIE(Image3F large, Image3F::Create(4242, rect.ysize()));
ZeroFillImage(&large);
CopyImageTo(rect, *io_orig.Main().color(), rect, &large);
CodecInOut io;
@@ -268,7 +271,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectlyGrayscale) {
CompressParams cparams;
cparams.speed_tier = SpeedTier::kSquirrel;
cparams.progressive_dc = 1;
- cparams.responsive = true;
+ cparams.responsive = JXL_TRUE;
cparams.qprogressive_mode = Override::kOn;
cparams.butteraugli_distance = 1.0;
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool));
@@ -300,7 +303,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectly) {
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, &pool));
Rect rect(0, 0, io_orig.xsize(), 128);
// need 2 DC groups for the DC frame to actually be progressive.
- Image3F large(4242, rect.ysize());
+ JXL_ASSIGN_OR_DIE(Image3F large, Image3F::Create(4242, rect.ysize()));
ZeroFillImage(&large);
CopyImageTo(rect, *io_orig.Main().color(), rect, &large);
CodecInOut io;
@@ -311,7 +314,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectly) {
CompressParams cparams;
cparams.speed_tier = SpeedTier::kSquirrel;
cparams.progressive_dc = 1;
- cparams.responsive = true;
+ cparams.responsive = JXL_TRUE;
cparams.qprogressive_mode = Override::kOn;
cparams.butteraugli_distance = 1.0;
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool));
@@ -375,10 +378,11 @@ TEST(PassesTest, RoundtripSmallNoGaborishPasses) {
CodecInOut io2;
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _));
- EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
- *JxlGetDefaultCms(),
- /*distmap=*/nullptr),
- IsSlightlyBelow(1.2));
+ EXPECT_SLIGHTLY_BELOW(
+ ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
+ *JxlGetDefaultCms(),
+ /*distmap=*/nullptr),
+ 1.2);
}
} // namespace
diff --git a/third_party/jpeg-xl/lib/jxl/patch_dictionary_test.cc b/third_party/jpeg-xl/lib/jxl/patch_dictionary_test.cc
index 60f7c32229..fd04b7fc2e 100644
--- a/third_party/jpeg-xl/lib/jxl/patch_dictionary_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/patch_dictionary_test.cc
@@ -12,7 +12,6 @@
#include "lib/extras/codec.h"
#include "lib/jxl/base/override.h"
#include "lib/jxl/base/span.h"
-#include "lib/jxl/enc_butteraugli_comparator.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/image_test_utils.h"
#include "lib/jxl/test_utils.h"
@@ -21,6 +20,7 @@
namespace jxl {
namespace {
+using test::ButteraugliDistance;
using test::ReadTestData;
using test::Roundtrip;
diff --git a/third_party/jpeg-xl/lib/jxl/preview_test.cc b/third_party/jpeg-xl/lib/jxl/preview_test.cc
index b7fe855d4d..c482db9fd8 100644
--- a/third_party/jpeg-xl/lib/jxl/preview_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/preview_test.cc
@@ -13,7 +13,6 @@
#include "lib/extras/codec.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/codec_in_out.h"
-#include "lib/jxl/enc_butteraugli_comparator.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/headers.h"
#include "lib/jxl/image_bundle.h"
@@ -22,6 +21,7 @@
namespace jxl {
namespace {
+using test::ButteraugliDistance;
using test::ReadTestData;
using test::Roundtrip;
@@ -32,7 +32,7 @@ TEST(PreviewTest, RoundtripGivenPreview) {
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io));
io.ShrinkTo(io.xsize() / 8, io.ysize() / 8);
// Same as main image
- io.preview_frame = io.Main().Copy();
+ JXL_ASSIGN_OR_DIE(io.preview_frame, io.Main().Copy());
const size_t preview_xsize = 15;
const size_t preview_ysize = 27;
io.preview_frame.ShrinkTo(preview_xsize, preview_ysize);
diff --git a/third_party/jpeg-xl/lib/jxl/quant_weights.cc b/third_party/jpeg-xl/lib/jxl/quant_weights.cc
index 70b3b9e451..00563c5cbd 100644
--- a/third_party/jpeg-xl/lib/jxl/quant_weights.cc
+++ b/third_party/jpeg-xl/lib/jxl/quant_weights.cc
@@ -160,8 +160,8 @@ Status ComputeQuantTable(const QuantEncoding& encoding,
float* JXL_RESTRICT inv_table, size_t table_num,
DequantMatrices::QuantTable kind, size_t* pos) {
constexpr size_t N = kBlockDim;
- size_t wrows = 8 * DequantMatrices::required_size_x[kind],
- wcols = 8 * DequantMatrices::required_size_y[kind];
+ size_t wrows = 8 * DequantMatrices::required_size_x[kind];
+ size_t wcols = 8 * DequantMatrices::required_size_y[kind];
size_t num = wrows * wcols;
std::vector<float> weights(3 * num);
@@ -361,7 +361,7 @@ namespace {
HWY_EXPORT(ComputeQuantTable);
-static constexpr const float kAlmostZero = 1e-8f;
+constexpr const float kAlmostZero = 1e-8f;
Status DecodeDctParams(BitReader* br, DctQuantWeightParams* params) {
params->num_distance_bands =
@@ -474,16 +474,16 @@ Status Decode(BitReader* br, QuantEncoding* encoding, size_t required_size_x,
default:
return JXL_FAILURE("Invalid quantization table encoding");
}
- encoding->mode = QuantEncoding::Mode(mode);
+ encoding->mode = static_cast<QuantEncoding::Mode>(mode);
return true;
}
} // namespace
// These definitions are needed before C++17.
-constexpr size_t DequantMatrices::required_size_[];
-constexpr size_t DequantMatrices::required_size_x[];
-constexpr size_t DequantMatrices::required_size_y[];
+constexpr const std::array<int, 17> DequantMatrices::required_size_x;
+constexpr const std::array<int, 17> DequantMatrices::required_size_y;
+constexpr const size_t DequantMatrices::kSumRequiredXy;
constexpr DequantMatrices::QuantTable DequantMatrices::kQuantTable[];
Status DequantMatrices::Decode(BitReader* br,
@@ -502,7 +502,7 @@ Status DequantMatrices::Decode(BitReader* br,
}
Status DequantMatrices::DecodeDC(BitReader* br) {
- bool all_default = br->ReadBits(1);
+ bool all_default = static_cast<bool>(br->ReadBits(1));
if (!br->AllReadsWithinBounds()) return JXL_FAILURE("EOS during DecodeDC");
if (!all_default) {
for (size_t c = 0; c < 3; c++) {
@@ -1162,11 +1162,12 @@ const QuantEncoding* DequantMatrices::Library() {
}
DequantMatrices::DequantMatrices() {
- encodings_.resize(size_t(QuantTable::kNum), QuantEncoding::Library(0));
+ encodings_.resize(static_cast<size_t>(QuantTable::kNum),
+ QuantEncoding::Library(0));
size_t pos = 0;
size_t offsets[kNum * 3];
- for (size_t i = 0; i < size_t(QuantTable::kNum); i++) {
- size_t num = required_size_[i] * kDCTBlockSize;
+ for (size_t i = 0; i < static_cast<size_t>(QuantTable::kNum); i++) {
+ size_t num = required_size_x[i] * required_size_y[i] * kDCTBlockSize;
for (size_t c = 0; c < 3; c++) {
offsets[3 * i + c] = pos + c * num;
}
@@ -1191,7 +1192,7 @@ Status DequantMatrices::EnsureComputed(uint32_t acs_mask) {
size_t offsets[kNum * 3 + 1];
size_t pos = 0;
for (size_t i = 0; i < kNum; i++) {
- size_t num = required_size_[i] * kDCTBlockSize;
+ size_t num = required_size_x[i] * required_size_y[i] * kDCTBlockSize;
for (size_t c = 0; c < 3; c++) {
offsets[3 * i + c] = pos + c * num;
}
diff --git a/third_party/jpeg-xl/lib/jxl/quant_weights.h b/third_party/jpeg-xl/lib/jxl/quant_weights.h
index 3004176aba..0fa23ffddb 100644
--- a/third_party/jpeg-xl/lib/jxl/quant_weights.h
+++ b/third_party/jpeg-xl/lib/jxl/quant_weights.h
@@ -15,6 +15,7 @@
#include <vector>
#include "lib/jxl/ac_strategy.h"
+#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
@@ -23,12 +24,6 @@
namespace jxl {
-template <typename T, size_t N>
-constexpr T ArraySum(T (&a)[N], size_t i = N - 1) {
- static_assert(N > 0, "Trying to compute the sum of an empty array");
- return i == 0 ? a[0] : a[i] + ArraySum(a, i - 1);
-}
-
static constexpr size_t kMaxQuantTableSize = AcStrategy::kMaxCoeffArea;
static constexpr size_t kNumPredefinedTables = 1;
static constexpr size_t kCeilLog2NumPredefinedTables = 0;
@@ -410,25 +405,23 @@ class DequantMatrices {
const std::vector<QuantEncoding>& encodings() const { return encodings_; }
- static constexpr size_t required_size_x[] = {1, 1, 1, 1, 2, 4, 1, 1, 2,
- 1, 1, 8, 4, 16, 8, 32, 16};
- static_assert(kNum == sizeof(required_size_x) / sizeof(*required_size_x),
+ static constexpr auto required_size_x =
+ to_array<int>({1, 1, 1, 1, 2, 4, 1, 1, 2, 1, 1, 8, 4, 16, 8, 32, 16});
+ static_assert(kNum == required_size_x.size(),
"Update this array when adding or removing quant tables.");
- static constexpr size_t required_size_y[] = {1, 1, 1, 1, 2, 4, 2, 4, 4,
- 1, 1, 8, 8, 16, 16, 32, 32};
- static_assert(kNum == sizeof(required_size_y) / sizeof(*required_size_y),
+ static constexpr auto required_size_y =
+ to_array<int>({1, 1, 1, 1, 2, 4, 2, 4, 4, 1, 1, 8, 8, 16, 16, 32, 32});
+ static_assert(kNum == required_size_y.size(),
"Update this array when adding or removing quant tables.");
+ // MUST be equal `sum(dot(required_size_x, required_size_y))`.
+ static constexpr size_t kSumRequiredXy = 2056;
+
Status EnsureComputed(uint32_t acs_mask);
private:
- static constexpr size_t required_size_[] = {
- 1, 1, 1, 1, 4, 16, 2, 4, 8, 1, 1, 64, 32, 256, 128, 1024, 512};
- static_assert(kNum == sizeof(required_size_) / sizeof(*required_size_),
- "Update this array when adding or removing quant tables.");
- static constexpr size_t kTotalTableSize =
- ArraySum(required_size_) * kDCTBlockSize * 3;
+ static constexpr size_t kTotalTableSize = kSumRequiredXy * kDCTBlockSize * 3;
uint32_t computed_mask_ = 0;
// kTotalTableSize entries followed by kTotalTableSize for inv_table
diff --git a/third_party/jpeg-xl/lib/jxl/quant_weights_test.cc b/third_party/jpeg-xl/lib/jxl/quant_weights_test.cc
index 2dd513804c..e92cbf2151 100644
--- a/third_party/jpeg-xl/lib/jxl/quant_weights_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/quant_weights_test.cc
@@ -23,6 +23,18 @@
namespace jxl {
namespace {
+// This should have been static assert; not compiling though with C++<17.
+TEST(QuantWeightsTest, Invariant) {
+ size_t sum = 0;
+ ASSERT_EQ(DequantMatrices::required_size_x.size(),
+ DequantMatrices::required_size_y.size());
+ for (size_t i = 0; i < DequantMatrices::required_size_x.size(); ++i) {
+ sum += DequantMatrices::required_size_x[i] *
+ DequantMatrices::required_size_y[i];
+ }
+ ASSERT_EQ(DequantMatrices::kSumRequiredXy, sum);
+}
+
template <typename T>
void CheckSimilar(T a, T b) {
EXPECT_EQ(a, b);
@@ -50,8 +62,8 @@ void RoundtripMatrices(const std::vector<QuantEncoding>& encodings) {
DequantMatrices mat;
CodecMetadata metadata;
FrameHeader frame_header(&metadata);
- ModularFrameEncoder encoder(frame_header, CompressParams{});
- DequantMatricesSetCustom(&mat, encodings, &encoder);
+ ModularFrameEncoder encoder(frame_header, CompressParams{}, false);
+ JXL_CHECK(DequantMatricesSetCustom(&mat, encodings, &encoder));
const std::vector<QuantEncoding>& encodings_dec = mat.encodings();
for (size_t i = 0; i < encodings.size(); i++) {
const QuantEncoding& e = encodings[i];
@@ -172,8 +184,8 @@ TEST_P(QuantWeightsTargetTest, DCTUniform) {
DequantMatrices dequant_matrices;
CodecMetadata metadata;
FrameHeader frame_header(&metadata);
- ModularFrameEncoder encoder(frame_header, CompressParams{});
- DequantMatricesSetCustom(&dequant_matrices, encodings, &encoder);
+ ModularFrameEncoder encoder(frame_header, CompressParams{}, false);
+ JXL_CHECK(DequantMatricesSetCustom(&dequant_matrices, encodings, &encoder));
JXL_CHECK(dequant_matrices.EnsureComputed(~0u));
const float dc_quant[3] = {1.0f / kUniformQuant, 1.0f / kUniformQuant,
diff --git a/third_party/jpeg-xl/lib/jxl/quantizer.h b/third_party/jpeg-xl/lib/jxl/quantizer.h
index 4e34ac78e8..602d12bdfa 100644
--- a/third_party/jpeg-xl/lib/jxl/quantizer.h
+++ b/third_party/jpeg-xl/lib/jxl/quantizer.h
@@ -73,7 +73,7 @@ class Quantizer {
}
float ScaleGlobalScale(const float scale) {
- int new_global_scale = static_cast<int>(global_scale_ * scale + 0.5f);
+ int new_global_scale = static_cast<int>(std::lround(global_scale_ * scale));
float scale_out = new_global_scale * 1.0f / global_scale_;
global_scale_ = new_global_scale;
RecomputeFromGlobalScale();
diff --git a/third_party/jpeg-xl/lib/jxl/quantizer_test.cc b/third_party/jpeg-xl/lib/jxl/quantizer_test.cc
index aff19f42c1..eeaac9ba53 100644
--- a/third_party/jpeg-xl/lib/jxl/quantizer_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/quantizer_test.cc
@@ -5,10 +5,8 @@
#include "lib/jxl/quantizer.h"
-#include "lib/jxl/base/span.h"
#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/enc_fields.h"
-#include "lib/jxl/image_ops.h"
#include "lib/jxl/image_test_utils.h"
#include "lib/jxl/testing.h"
@@ -24,7 +22,8 @@ TEST(QuantizerTest, QuantizerParams) {
for (uint32_t i = 1; i < 10000; ++i) {
QuantizerParams p;
p.global_scale = i;
- size_t extension_bits = 0, total_bits = 0;
+ size_t extension_bits = 0;
+ size_t total_bits = 0;
EXPECT_TRUE(Bundle::CanEncode(p, &extension_bits, &total_bits));
EXPECT_EQ(0u, extension_bits);
EXPECT_GE(total_bits, 4u);
@@ -36,7 +35,7 @@ TEST(QuantizerTest, BitStreamRoundtripSameQuant) {
const int qysize = 8;
DequantMatrices dequant;
Quantizer quantizer1(&dequant);
- ImageI raw_quant_field(qxsize, qysize);
+ JXL_ASSIGN_OR_DIE(ImageI raw_quant_field, ImageI::Create(qxsize, qysize));
quantizer1.SetQuant(0.17f, 0.17f, &raw_quant_field);
BitWriter writer;
QuantizerParams params = quantizer1.GetParams();
@@ -57,10 +56,10 @@ TEST(QuantizerTest, BitStreamRoundtripRandomQuant) {
const int qysize = 8;
DequantMatrices dequant;
Quantizer quantizer1(&dequant);
- ImageI raw_quant_field(qxsize, qysize);
+ JXL_ASSIGN_OR_DIE(ImageI raw_quant_field, ImageI::Create(qxsize, qysize));
quantizer1.SetQuant(0.17f, 0.17f, &raw_quant_field);
float quant_dc = 0.17f;
- ImageF qf(qxsize, qysize);
+ JXL_ASSIGN_OR_DIE(ImageF qf, ImageF::Create(qxsize, qysize));
RandomFillImage(&qf, 0.0f, 1.0f);
quantizer1.SetQuantField(quant_dc, qf, &raw_quant_field);
BitWriter writer;
diff --git a/third_party/jpeg-xl/lib/jxl/rational_polynomial_test.cc b/third_party/jpeg-xl/lib/jxl/rational_polynomial_test.cc
index bc31cdd092..e5211cda7a 100644
--- a/third_party/jpeg-xl/lib/jxl/rational_polynomial_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/rational_polynomial_test.cc
@@ -158,8 +158,8 @@ void TestExp() {
const T q[4 * (2 + 1)] = {HWY_REP4(9.6259895571622622E-01),
HWY_REP4(-4.7272457588933831E-01),
HWY_REP4(7.4802088567547664E-02)};
- const T err =
- RunApproximation(-1, 1, p, q, EvalPoly(), [](T x) { return T(exp(x)); });
+ const T err = RunApproximation(-1, 1, p, q, EvalPoly(),
+ [](T x) { return static_cast<T>(exp(x)); });
EXPECT_LT(err, 1E-4);
}
@@ -174,8 +174,8 @@ void TestNegExp() {
HWY_REP4(5.9579108238812878E-02), HWY_REP4(3.4542074345478582E-02),
HWY_REP4(8.7263562483501714E-03), HWY_REP4(1.4095109143061216E-03)};
- const T err =
- RunApproximation(0, 10, p, q, EvalPoly(), [](T x) { return T(exp(-x)); });
+ const T err = RunApproximation(0, 10, p, q, EvalPoly(),
+ [](T x) { return static_cast<T>(exp(-x)); });
EXPECT_LT(err, sizeof(T) == 8 ? 2E-5 : 3E-5);
}
@@ -191,7 +191,7 @@ void TestSin() {
HWY_REP4(3.1546157932479282E-03), HWY_REP4(-1.6692542019380155E-04)};
const T err = RunApproximation(0, Pi<T>(1) * 2, p, q, EvalPoly(),
- [](T x) { return T(sin(x)); });
+ [](T x) { return static_cast<T>(sin(x)); });
EXPECT_LT(err, sizeof(T) == 8 ? 5E-4 : 7E-4);
}
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.cc
index 9aefdd007d..27718e6413 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.cc
@@ -6,10 +6,9 @@
#include "lib/jxl/render_pipeline/low_memory_render_pipeline.h"
#include <algorithm>
-#include <queue>
-#include <tuple>
#include "lib/jxl/base/arch_macros.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/image_ops.h"
namespace jxl {
@@ -174,7 +173,7 @@ size_t LowMemoryRenderPipeline::GroupInputYSize(size_t c) const {
channel_shifts_[0][c].second;
}
-void LowMemoryRenderPipeline::EnsureBordersStorage() {
+Status LowMemoryRenderPipeline::EnsureBordersStorage() {
const auto& shifts = channel_shifts_[0];
if (borders_horizontal_.size() < shifts.size()) {
borders_horizontal_.resize(shifts.size());
@@ -194,16 +193,20 @@ void LowMemoryRenderPipeline::EnsureBordersStorage() {
1 << shifts[c].second);
Rect horizontal = Rect(0, 0, downsampled_xsize, bordery * num_yborders);
if (!SameSize(horizontal, borders_horizontal_[c])) {
- borders_horizontal_[c] = ImageF(horizontal.xsize(), horizontal.ysize());
+ JXL_ASSIGN_OR_RETURN(
+ borders_horizontal_[c],
+ ImageF::Create(horizontal.xsize(), horizontal.ysize()));
}
Rect vertical = Rect(0, 0, borderx * num_xborders, downsampled_ysize);
if (!SameSize(vertical, borders_vertical_[c])) {
- borders_vertical_[c] = ImageF(vertical.xsize(), vertical.ysize());
+ JXL_ASSIGN_OR_RETURN(borders_vertical_[c],
+ ImageF::Create(vertical.xsize(), vertical.ysize()));
}
}
+ return true;
}
-void LowMemoryRenderPipeline::Init() {
+Status LowMemoryRenderPipeline::Init() {
group_border_ = {0, 0};
base_color_shift_ = CeilLog2Nonzero(frame_dimensions_.xsize_upsampled_padded /
frame_dimensions_.xsize_padded);
@@ -255,7 +258,7 @@ void LowMemoryRenderPipeline::Init() {
group_data_x_border_ = RoundUpTo(max_border.first, kGroupXAlign);
group_data_y_border_ = max_border.second;
- EnsureBordersStorage();
+ JXL_RETURN_IF_ERROR(EnsureBordersStorage());
group_border_assigner_.Init(frame_dimensions_);
for (first_trailing_stage_ = stages_.size(); first_trailing_stage_ > 0;
@@ -282,7 +285,7 @@ void LowMemoryRenderPipeline::Init() {
DivCeil(frame_dimensions_.ysize_upsampled,
1 << channel_shifts_[i][c].second));
}
- stages_[i]->SetInputSizes(input_sizes);
+ JXL_RETURN_IF_ERROR(stages_[i]->SetInputSizes(input_sizes));
if (stages_[i]->SwitchToImageDimensions()) {
// We don't allow kInOut after switching to image dimensions.
JXL_ASSERT(i >= first_trailing_stage_);
@@ -300,7 +303,7 @@ void LowMemoryRenderPipeline::Init() {
for (size_t c = 0; c < shifts.size(); c++) {
input_sizes[c] = {full_image_xsize_, full_image_ysize_};
}
- stages_[i]->SetInputSizes(input_sizes);
+ JXL_RETURN_IF_ERROR(stages_[i]->SetInputSizes(input_sizes));
}
anyc_.resize(stages_.size());
@@ -355,10 +358,11 @@ void LowMemoryRenderPipeline::Init() {
}
}
}
+ return true;
}
-void LowMemoryRenderPipeline::PrepareForThreadsInternal(size_t num,
- bool use_group_ids) {
+Status LowMemoryRenderPipeline::PrepareForThreadsInternal(size_t num,
+ bool use_group_ids) {
const auto& shifts = channel_shifts_[0];
use_group_ids_ = use_group_ids;
size_t num_buffers = use_group_ids_ ? frame_dimensions_.num_groups : num;
@@ -366,8 +370,10 @@ void LowMemoryRenderPipeline::PrepareForThreadsInternal(size_t num,
group_data_.emplace_back();
group_data_[t].resize(shifts.size());
for (size_t c = 0; c < shifts.size(); c++) {
- group_data_[t][c] = ImageF(GroupInputXSize(c) + group_data_x_border_ * 2,
- GroupInputYSize(c) + group_data_y_border_ * 2);
+ JXL_ASSIGN_OR_RETURN(
+ group_data_[t][c],
+ ImageF::Create(GroupInputXSize(c) + group_data_x_border_ * 2,
+ GroupInputYSize(c) + group_data_y_border_ * 2));
}
}
// TODO(veluca): avoid reallocating buffers if not needed.
@@ -390,7 +396,9 @@ void LowMemoryRenderPipeline::PrepareForThreadsInternal(size_t num,
2 * next_y_border + (1 << stages_[i]->settings_.shift_y);
stage_buffer_ysize = 1 << CeilLog2Nonzero(stage_buffer_ysize);
next_y_border = stages_[i]->settings_.border_y;
- stage_data_[t][c][i] = ImageF(stage_buffer_xsize, stage_buffer_ysize);
+ JXL_ASSIGN_OR_RETURN(
+ stage_data_[t][c][i],
+ ImageF::Create(stage_buffer_xsize, stage_buffer_ysize));
}
}
}
@@ -412,9 +420,11 @@ void LowMemoryRenderPipeline::PrepareForThreadsInternal(size_t num,
std::max(left_padding, std::max(middle_padding, right_padding));
out_of_frame_data_.resize(num);
for (size_t t = 0; t < num; t++) {
- out_of_frame_data_[t] = ImageF(out_of_frame_xsize, shifts.size());
+ JXL_ASSIGN_OR_RETURN(out_of_frame_data_[t],
+ ImageF::Create(out_of_frame_xsize, shifts.size()));
}
}
+ return true;
}
std::vector<std::pair<ImageF*, Rect>> LowMemoryRenderPipeline::PrepareBuffers(
@@ -520,7 +530,8 @@ class Rows {
.Translate(-group_data_x_border, -group_data_y_border)
.ShiftLeft(base_color_shift)
.CeilShiftRight(group_data_shift[c])
- .Translate(group_data_x_border - ssize_t(kRenderPipelineXOffset),
+ .Translate(group_data_x_border -
+ static_cast<ssize_t>(kRenderPipelineXOffset),
group_data_y_border);
rows_[0][c].base_ptr = channel_group_data_rect.Row(&input_data[c], 0);
rows_[0][c].stride = input_data[c].PixelsPerRow();
@@ -533,7 +544,8 @@ class Rows {
JXL_INLINE float* GetBuffer(int stage, int y, size_t c) const {
JXL_DASSERT(stage >= -1);
const RowInfo& info = rows_[stage + 1][c];
- return info.base_ptr + ssize_t(info.stride) * (y & info.ymod_minus_1);
+ return info.base_ptr +
+ static_cast<ssize_t>(info.stride) * (y & info.ymod_minus_1);
}
private:
@@ -551,10 +563,10 @@ class Rows {
} // namespace
-void LowMemoryRenderPipeline::RenderRect(size_t thread_id,
- std::vector<ImageF>& input_data,
- Rect data_max_color_channel_rect,
- Rect image_max_color_channel_rect) {
+Status LowMemoryRenderPipeline::RenderRect(size_t thread_id,
+ std::vector<ImageF>& input_data,
+ Rect data_max_color_channel_rect,
+ Rect image_max_color_channel_rect) {
// For each stage, the rect corresponding to the image area currently being
// processed, in the coordinates of that stage (i.e. with the scaling factor
// that that stage has).
@@ -599,7 +611,7 @@ void LowMemoryRenderPipeline::RenderRect(size_t thread_id,
// is no point in proceeding. Note: this uses the assumption that if there is
// a stage with observable effects (i.e. a kInput stage), it only appears
// after the stage that switches to image dimensions.
- if (full_image_x1 <= full_image_x0) return;
+ if (full_image_x1 <= full_image_x0) return true;
// Data structures to hold information about input/output rows and their
// buffers.
@@ -643,7 +655,7 @@ void LowMemoryRenderPipeline::RenderRect(size_t thread_id,
}
// If we already have rows from a previous iteration, we can just shift
// the rows by 1 and insert the new one.
- if (input_rows[i][c].size() == 2 * size_t(bordery) + 1) {
+ if (input_rows[i][c].size() == 2 * static_cast<size_t>(bordery) + 1) {
for (ssize_t iy = 0; iy < 2 * bordery; iy++) {
input_rows[i][c][iy] = input_rows[i][c][iy + 1];
}
@@ -674,7 +686,7 @@ void LowMemoryRenderPipeline::RenderRect(size_t thread_id,
virtual_ypadding_for_output_.end());
for (int vy = -num_extra_rows;
- vy < int(image_area_rect.ysize()) + num_extra_rows; vy++) {
+ vy < static_cast<int>(image_area_rect.ysize()) + num_extra_rows; vy++) {
for (size_t i = 0; i < first_trailing_stage_; i++) {
int stage_vy = vy - num_extra_rows + virtual_ypadding_for_output_[i];
@@ -688,9 +700,10 @@ void LowMemoryRenderPipeline::RenderRect(size_t thread_id,
int y = stage_vy >> channel_shifts_[i][anyc_[i]].second;
- ssize_t image_y = ssize_t(group_rect[i].y0()) + y;
+ ssize_t image_y = static_cast<ssize_t>(group_rect[i].y0()) + y;
// Do not produce rows in out-of-bounds areas.
- if (image_y < 0 || image_y >= ssize_t(image_rect_[i].ysize())) {
+ if (image_y < 0 ||
+ image_y >= static_cast<ssize_t>(image_rect_[i].ysize())) {
continue;
}
@@ -698,9 +711,9 @@ void LowMemoryRenderPipeline::RenderRect(size_t thread_id,
prepare_io_rows(y, i);
// Produce output rows.
- stages_[i]->ProcessRow(input_rows[i], output_rows,
- xpadding_for_output_[i], group_rect[i].xsize(),
- group_rect[i].x0(), image_y, thread_id);
+ JXL_RETURN_IF_ERROR(stages_[i]->ProcessRow(
+ input_rows[i], output_rows, xpadding_for_output_[i],
+ group_rect[i].xsize(), group_rect[i].x0(), image_y, thread_id));
}
// Process trailing stages, i.e. the final set of non-kInOut stages; they
@@ -719,7 +732,7 @@ void LowMemoryRenderPipeline::RenderRect(size_t thread_id,
// Check that we are not outside of the bounds for the current rendering
// rect. Not doing so might result in overwriting some rows that have been
// written (or will be written) by other threads.
- if (y < 0 || y >= ssize_t(image_area_rect.ysize())) {
+ if (y < 0 || y >= static_cast<ssize_t>(image_area_rect.ysize())) {
continue;
}
@@ -728,7 +741,8 @@ void LowMemoryRenderPipeline::RenderRect(size_t thread_id,
// (and may be necessary for correctness, as some stages assume coordinates
// are within bounds).
ssize_t full_image_y = frame_y0 + image_area_rect.y0() + y;
- if (full_image_y < 0 || full_image_y >= ssize_t(full_image_ysize)) {
+ if (full_image_y < 0 ||
+ full_image_y >= static_cast<ssize_t>(full_image_ysize)) {
continue;
}
@@ -739,15 +753,16 @@ void LowMemoryRenderPipeline::RenderRect(size_t thread_id,
i < first_image_dim_stage_ ? full_image_x0 - frame_x0 : full_image_x0;
size_t y =
i < first_image_dim_stage_ ? full_image_y - frame_y0 : full_image_y;
- stages_[i]->ProcessRow(input_rows[first_trailing_stage_], output_rows,
- /*xextra=*/0, full_image_x1 - full_image_x0, x0, y,
- thread_id);
+ JXL_RETURN_IF_ERROR(stages_[i]->ProcessRow(
+ input_rows[first_trailing_stage_], output_rows,
+ /*xextra=*/0, full_image_x1 - full_image_x0, x0, y, thread_id));
}
}
+ return true;
}
-void LowMemoryRenderPipeline::RenderPadding(size_t thread_id, Rect rect) {
- if (rect.xsize() == 0) return;
+Status LowMemoryRenderPipeline::RenderPadding(size_t thread_id, Rect rect) {
+ if (rect.xsize() == 0) return true;
size_t numc = channel_shifts_[0].size();
RenderPipelineStage::RowInfo input_rows(numc, std::vector<float*>(1));
RenderPipelineStage::RowInfo output_rows;
@@ -760,15 +775,16 @@ void LowMemoryRenderPipeline::RenderPadding(size_t thread_id, Rect rect) {
stages_[first_image_dim_stage_ - 1]->ProcessPaddingRow(
input_rows, rect.xsize(), rect.x0(), rect.y0() + y);
for (size_t i = first_image_dim_stage_; i < stages_.size(); i++) {
- stages_[i]->ProcessRow(input_rows, output_rows,
- /*xextra=*/0, rect.xsize(), rect.x0(),
- rect.y0() + y, thread_id);
+ JXL_RETURN_IF_ERROR(stages_[i]->ProcessRow(
+ input_rows, output_rows,
+ /*xextra=*/0, rect.xsize(), rect.x0(), rect.y0() + y, thread_id));
}
}
+ return true;
}
-void LowMemoryRenderPipeline::ProcessBuffers(size_t group_id,
- size_t thread_id) {
+Status LowMemoryRenderPipeline::ProcessBuffers(size_t group_id,
+ size_t thread_id) {
std::vector<ImageF>& input_data =
group_data_[use_group_ids_ ? group_id : thread_id];
@@ -804,38 +820,43 @@ void LowMemoryRenderPipeline::ProcessBuffers(size_t group_id,
if (group_id == 0 && (image_rect.xsize() == 0 || image_rect.ysize() == 0)) {
// If this frame does not intersect with the full image, we have to
// initialize the whole image area with RenderPadding.
- RenderPadding(thread_id,
- Rect(0, 0, full_image_xsize_, full_image_ysize_));
+ JXL_RETURN_IF_ERROR(RenderPadding(
+ thread_id, Rect(0, 0, full_image_xsize_, full_image_ysize_)));
}
// Render padding for groups that intersect with the full image. The case
// where no groups intersect was handled above.
if (group_rect.xsize() > 0 && group_rect.ysize() > 0) {
if (gx == 0 && gy == 0) {
- RenderPadding(thread_id, Rect(0, 0, x0, y0));
+ JXL_RETURN_IF_ERROR(RenderPadding(thread_id, Rect(0, 0, x0, y0)));
}
if (gy == 0) {
- RenderPadding(thread_id, Rect(x0, 0, x1 - x0, y0));
+ JXL_RETURN_IF_ERROR(RenderPadding(thread_id, Rect(x0, 0, x1 - x0, y0)));
}
if (gx == 0) {
- RenderPadding(thread_id, Rect(0, y0, x0, y1 - y0));
+ JXL_RETURN_IF_ERROR(RenderPadding(thread_id, Rect(0, y0, x0, y1 - y0)));
}
if (gx == 0 && gy + 1 == frame_dimensions_.ysize_groups) {
- RenderPadding(thread_id, Rect(0, y1, x0, full_image_ysize_ - y1));
+ JXL_RETURN_IF_ERROR(
+ RenderPadding(thread_id, Rect(0, y1, x0, full_image_ysize_ - y1)));
}
if (gy + 1 == frame_dimensions_.ysize_groups) {
- RenderPadding(thread_id, Rect(x0, y1, x1 - x0, full_image_ysize_ - y1));
+ JXL_RETURN_IF_ERROR(RenderPadding(
+ thread_id, Rect(x0, y1, x1 - x0, full_image_ysize_ - y1)));
}
if (gy == 0 && gx + 1 == frame_dimensions_.xsize_groups) {
- RenderPadding(thread_id, Rect(x1, 0, full_image_xsize_ - x1, y0));
+ JXL_RETURN_IF_ERROR(
+ RenderPadding(thread_id, Rect(x1, 0, full_image_xsize_ - x1, y0)));
}
if (gx + 1 == frame_dimensions_.xsize_groups) {
- RenderPadding(thread_id, Rect(x1, y0, full_image_xsize_ - x1, y1 - y0));
+ JXL_RETURN_IF_ERROR(RenderPadding(
+ thread_id, Rect(x1, y0, full_image_xsize_ - x1, y1 - y0)));
}
if (gy + 1 == frame_dimensions_.ysize_groups &&
gx + 1 == frame_dimensions_.xsize_groups) {
- RenderPadding(thread_id, Rect(x1, y1, full_image_xsize_ - x1,
- full_image_ysize_ - y1));
+ JXL_RETURN_IF_ERROR(RenderPadding(
+ thread_id,
+ Rect(x1, y1, full_image_xsize_ - x1, full_image_ysize_ - y1)));
}
}
}
@@ -857,8 +878,10 @@ void LowMemoryRenderPipeline::ProcessBuffers(size_t group_id,
gy * frame_dimensions_.group_dim,
image_max_color_channel_rect.xsize(),
image_max_color_channel_rect.ysize());
- RenderRect(thread_id, input_data, data_max_color_channel_rect,
- image_max_color_channel_rect);
+ JXL_RETURN_IF_ERROR(RenderRect(thread_id, input_data,
+ data_max_color_channel_rect,
+ image_max_color_channel_rect));
}
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.h
index b386f7c078..f0b21d3dca 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.h
@@ -20,21 +20,21 @@ class LowMemoryRenderPipeline final : public RenderPipeline {
std::vector<std::pair<ImageF*, Rect>> PrepareBuffers(
size_t group_id, size_t thread_id) override;
- void PrepareForThreadsInternal(size_t num, bool use_group_ids) override;
+ Status PrepareForThreadsInternal(size_t num, bool use_group_ids) override;
- void ProcessBuffers(size_t group_id, size_t thread_id) override;
+ Status ProcessBuffers(size_t group_id, size_t thread_id) override;
void ClearDone(size_t i) override { group_border_assigner_.ClearDone(i); }
- void Init() override;
+ Status Init() override;
- void EnsureBordersStorage();
+ Status EnsureBordersStorage();
size_t GroupInputXSize(size_t c) const;
size_t GroupInputYSize(size_t c) const;
- void RenderRect(size_t thread_id, std::vector<ImageF>& input_data,
- Rect data_max_color_channel_rect,
- Rect image_max_color_channel_rect);
- void RenderPadding(size_t thread_id, Rect rect);
+ Status RenderRect(size_t thread_id, std::vector<ImageF>& input_data,
+ Rect data_max_color_channel_rect,
+ Rect image_max_color_channel_rect);
+ Status RenderPadding(size_t thread_id, Rect rect);
void SaveBorders(size_t group_id, size_t c, const ImageF& in);
void LoadBorders(size_t group_id, size_t c, const Rect& r, ImageF* out);
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.cc
index 68b6ef613f..14bd363110 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.cc
@@ -5,8 +5,7 @@
#include "lib/jxl/render_pipeline/render_pipeline.h"
-#include <algorithm>
-
+#include "lib/jxl/base/status.h"
#include "lib/jxl/render_pipeline/low_memory_render_pipeline.h"
#include "lib/jxl/render_pipeline/simple_render_pipeline.h"
#include "lib/jxl/sanitizers.h"
@@ -18,7 +17,7 @@ void RenderPipeline::Builder::AddStage(
stages_.push_back(std::move(stage));
}
-std::unique_ptr<RenderPipeline> RenderPipeline::Builder::Finalize(
+StatusOr<std::unique_ptr<RenderPipeline>> RenderPipeline::Builder::Finalize(
FrameDimensions frame_dimensions) && {
#if JXL_ENABLE_ASSERT
// Check that the last stage is not an kInOut stage for any channel, and that
@@ -88,7 +87,7 @@ std::unique_ptr<RenderPipeline> RenderPipeline::Builder::Finalize(
}
}
res->stages_ = std::move(stages_);
- res->Init();
+ JXL_RETURN_IF_ERROR(res->Init());
return res;
}
@@ -103,7 +102,7 @@ RenderPipelineInput RenderPipeline::GetInputBuffers(size_t group_id,
return ret;
}
-void RenderPipeline::InputReady(
+Status RenderPipeline::InputReady(
size_t group_id, size_t thread_id,
const std::vector<std::pair<ImageF*, Rect>>& buffers) {
JXL_DASSERT(group_id < group_completed_passes_.size());
@@ -113,20 +112,22 @@ void RenderPipeline::InputReady(
JXL_CHECK_PLANE_INITIALIZED(*buffers[i].first, buffers[i].second, i);
}
- ProcessBuffers(group_id, thread_id);
+ JXL_RETURN_IF_ERROR(ProcessBuffers(group_id, thread_id));
+ return true;
}
Status RenderPipeline::PrepareForThreads(size_t num, bool use_group_ids) {
for (const auto& stage : stages_) {
JXL_RETURN_IF_ERROR(stage->PrepareForThreads(num));
}
- PrepareForThreadsInternal(num, use_group_ids);
+ JXL_RETURN_IF_ERROR(PrepareForThreadsInternal(num, use_group_ids));
return true;
}
-void RenderPipelineInput::Done() {
+Status RenderPipelineInput::Done() {
JXL_ASSERT(pipeline_);
- pipeline_->InputReady(group_id_, thread_id_, buffers_);
+ JXL_RETURN_IF_ERROR(pipeline_->InputReady(group_id_, thread_id_, buffers_));
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.h
index bf3ad4975e..c61420be4b 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.h
@@ -32,7 +32,7 @@ class RenderPipelineInput {
}
RenderPipelineInput() = default;
- void Done();
+ Status Done();
const std::pair<ImageF*, Rect>& GetBuffer(size_t c) const {
JXL_ASSERT(c < buffers_.size());
@@ -63,7 +63,7 @@ class RenderPipeline {
// Finalizes setup of the pipeline. Shifts for all channels should be 0 at
// this point.
- std::unique_ptr<RenderPipeline> Finalize(
+ StatusOr<std::unique_ptr<RenderPipeline>> Finalize(
FrameDimensions frame_dimensions) &&;
private:
@@ -118,20 +118,20 @@ class RenderPipeline {
friend class RenderPipelineInput;
private:
- void InputReady(size_t group_id, size_t thread_id,
- const std::vector<std::pair<ImageF*, Rect>>& buffers);
+ Status InputReady(size_t group_id, size_t thread_id,
+ const std::vector<std::pair<ImageF*, Rect>>& buffers);
virtual std::vector<std::pair<ImageF*, Rect>> PrepareBuffers(
size_t group_id, size_t thread_id) = 0;
- virtual void ProcessBuffers(size_t group_id, size_t thread_id) = 0;
+ virtual Status ProcessBuffers(size_t group_id, size_t thread_id) = 0;
// Note that this method may be called multiple times with different (or
// equal) `num`.
- virtual void PrepareForThreadsInternal(size_t num, bool use_group_ids) = 0;
+ virtual Status PrepareForThreadsInternal(size_t num, bool use_group_ids) = 0;
// Called once frame dimensions and stages are known.
- virtual void Init() {}
+ virtual Status Init() { return true; }
};
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_stage.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_stage.h
index d1a0074161..d054027ba7 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_stage.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_stage.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "lib/jxl/base/arch_macros.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/frame_header.h"
namespace jxl {
@@ -99,9 +100,10 @@ class RenderPipelineStage {
// `GroupBorderAssigner::kPaddingXRound`. If `settings_.temp_buffer_size` is
// nonzero, `temp` will point to an HWY-aligned buffer of at least that number
// of floats; concurrent calls will have different buffers.
- virtual void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const = 0;
+ virtual Status ProcessRow(const RowInfo& input_rows,
+ const RowInfo& output_rows, size_t xextra,
+ size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const = 0;
// How each channel will be processed. Channels are numbered starting from
// color channels (always 3) and followed by all other channels.
@@ -114,8 +116,10 @@ class RenderPipelineStage {
// Informs the stage about the total size of each channel. Few stages will
// actually need to use this information.
- virtual void SetInputSizes(
- const std::vector<std::pair<size_t, size_t>>& input_sizes) {}
+ virtual Status SetInputSizes(
+ const std::vector<std::pair<size_t, size_t>>& input_sizes) {
+ return true;
+ }
virtual Status PrepareForThreads(size_t num_threads) { return true; }
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_test.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_test.cc
index 51b9f273f8..e9cb913983 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_test.cc
@@ -111,7 +111,7 @@ TEST(RenderPipelineTest, Build) {
frame_dimensions.Set(/*xsize=*/1024, /*ysize=*/1024, /*group_size_shift=*/0,
/*max_hshift=*/0, /*max_vshift=*/0,
/*modular_mode=*/false, /*upsampling=*/1);
- std::move(builder).Finalize(frame_dimensions);
+ std::move(builder).Finalize(frame_dimensions).value();
}
TEST(RenderPipelineTest, CallAllGroups) {
@@ -124,14 +124,14 @@ TEST(RenderPipelineTest, CallAllGroups) {
frame_dimensions.Set(/*xsize=*/1024, /*ysize=*/1024, /*group_size_shift=*/0,
/*max_hshift=*/0, /*max_vshift=*/0,
/*modular_mode=*/false, /*upsampling=*/1);
- auto pipeline = std::move(builder).Finalize(frame_dimensions);
+ auto pipeline = std::move(builder).Finalize(frame_dimensions).value();
ASSERT_TRUE(pipeline->PrepareForThreads(1, /*use_group_ids=*/false));
for (size_t i = 0; i < frame_dimensions.num_groups; i++) {
auto input_buffers = pipeline->GetInputBuffers(i, 0);
FillPlane(0.0f, input_buffers.GetBuffer(0).first,
input_buffers.GetBuffer(0).second);
- input_buffers.Done();
+ JXL_CHECK(input_buffers.Done());
}
EXPECT_EQ(pipeline->PassesWithAllInput(), 1);
@@ -146,7 +146,7 @@ TEST(RenderPipelineTest, BuildFast) {
frame_dimensions.Set(/*xsize=*/1024, /*ysize=*/1024, /*group_size_shift=*/0,
/*max_hshift=*/0, /*max_vshift=*/0,
/*modular_mode=*/false, /*upsampling=*/1);
- std::move(builder).Finalize(frame_dimensions);
+ std::move(builder).Finalize(frame_dimensions).value();
}
TEST(RenderPipelineTest, CallAllGroupsFast) {
@@ -159,14 +159,14 @@ TEST(RenderPipelineTest, CallAllGroupsFast) {
frame_dimensions.Set(/*xsize=*/1024, /*ysize=*/1024, /*group_size_shift=*/0,
/*max_hshift=*/0, /*max_vshift=*/0,
/*modular_mode=*/false, /*upsampling=*/1);
- auto pipeline = std::move(builder).Finalize(frame_dimensions);
+ auto pipeline = std::move(builder).Finalize(frame_dimensions).value();
ASSERT_TRUE(pipeline->PrepareForThreads(1, /*use_group_ids=*/false));
for (size_t i = 0; i < frame_dimensions.num_groups; i++) {
auto input_buffers = pipeline->GetInputBuffers(i, 0);
FillPlane(0.0f, input_buffers.GetBuffer(0).first,
input_buffers.GetBuffer(0).second);
- input_buffers.Done();
+ JXL_CHECK(input_buffers.Done());
}
EXPECT_EQ(pipeline->PassesWithAllInput(), 1);
@@ -208,7 +208,7 @@ TEST_P(RenderPipelineTestParam, PipelineTest) {
io.ShrinkTo(config.xsize, config.ysize);
if (config.add_spot_color) {
- jxl::ImageF spot(config.xsize, config.ysize);
+ JXL_ASSIGN_OR_DIE(ImageF spot, ImageF::Create(config.xsize, config.ysize));
jxl::ZeroFillImage(&spot);
for (size_t y = 0; y < config.ysize; y++) {
@@ -227,7 +227,7 @@ TEST_P(RenderPipelineTestParam, PipelineTest) {
info.spot_color[3] = 0.5f;
io.metadata.m.extra_channel_info.push_back(info);
- std::vector<jxl::ImageF> ec;
+ std::vector<ImageF> ec;
ec.push_back(std::move(spot));
io.frames[0].SetExtraChannels(std::move(ec));
}
@@ -267,11 +267,11 @@ Splines CreateTestSplines() {
const ColorCorrelationMap cmap;
std::vector<Spline::Point> control_points{{9, 54}, {118, 159}, {97, 3},
{10, 40}, {150, 25}, {120, 300}};
- const Spline spline{
- control_points,
- /*color_dct=*/
- {{0.03125f, 0.00625f, 0.003125f}, {1.f, 0.321875f}, {1.f, 0.24375f}},
- /*sigma_dct=*/{0.3125f, 0.f, 0.f, 0.0625f}};
+ const Spline spline{control_points,
+ /*color_dct=*/
+ {Dct32{0.03125f, 0.00625f, 0.003125f},
+ Dct32{1.f, 0.321875f}, Dct32{1.f, 0.24375f}},
+ /*sigma_dct=*/{0.3125f, 0.f, 0.f, 0.0625f}};
std::vector<Spline> spline_data = {spline};
std::vector<QuantizedSpline> quantized_splines;
std::vector<Spline::Point> starting_points;
@@ -522,7 +522,7 @@ std::ostream& operator<<(std::ostream& os,
filename = c.input_path.substr(pos + 1);
}
std::replace_if(
- filename.begin(), filename.end(), [](char c) { return !isalnum(c); },
+ filename.begin(), filename.end(), [](char c) { return isalnum(c) == 0; },
'_');
os << filename << "_" << (c.jpeg_transcode ? "JPEG_" : "") << c.xsize << "x"
<< c.ysize << "_" << c.cparams_descr;
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.cc
index 4495288860..7f5a8ef00f 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.cc
@@ -7,27 +7,31 @@
#include <hwy/base.h>
+#include "lib/jxl/base/status.h"
#include "lib/jxl/image_ops.h"
#include "lib/jxl/render_pipeline/render_pipeline_stage.h"
#include "lib/jxl/sanitizers.h"
namespace jxl {
-void SimpleRenderPipeline::PrepareForThreadsInternal(size_t num,
- bool use_group_ids) {
+Status SimpleRenderPipeline::PrepareForThreadsInternal(size_t num,
+ bool use_group_ids) {
if (!channel_data_.empty()) {
- return;
+ return true;
}
auto ch_size = [](size_t frame_size, size_t shift) {
return DivCeil(frame_size, 1 << shift) + kRenderPipelineXOffset * 2;
};
for (size_t c = 0; c < channel_shifts_[0].size(); c++) {
- channel_data_.push_back(ImageF(
- ch_size(frame_dimensions_.xsize_upsampled, channel_shifts_[0][c].first),
- ch_size(frame_dimensions_.ysize_upsampled,
- channel_shifts_[0][c].second)));
+ JXL_ASSIGN_OR_RETURN(
+ ImageF ch, ImageF::Create(ch_size(frame_dimensions_.xsize_upsampled,
+ channel_shifts_[0][c].first),
+ ch_size(frame_dimensions_.ysize_upsampled,
+ channel_shifts_[0][c].second)));
+ channel_data_.push_back(std::move(ch));
msan::PoisonImage(channel_data_.back());
}
+ return true;
}
Rect SimpleRenderPipeline::MakeChannelRect(size_t group_id, size_t channel) {
@@ -60,14 +64,14 @@ std::vector<std::pair<ImageF*, Rect>> SimpleRenderPipeline::PrepareBuffers(
return ret;
}
-void SimpleRenderPipeline::ProcessBuffers(size_t group_id, size_t thread_id) {
+Status SimpleRenderPipeline::ProcessBuffers(size_t group_id, size_t thread_id) {
for (size_t c = 0; c < channel_data_.size(); c++) {
Rect r = MakeChannelRect(group_id, c);
(void)r;
JXL_CHECK_PLANE_INITIALIZED(channel_data_[c], r, c);
}
- if (PassesWithAllInput() <= processed_passes_) return;
+ if (PassesWithAllInput() <= processed_passes_) return true;
processed_passes_++;
for (size_t stage_id = 0; stage_id < stages_.size(); stage_id++) {
@@ -89,11 +93,13 @@ void SimpleRenderPipeline::ProcessBuffers(size_t group_id, size_t thread_id) {
}
// Ensure that the newly allocated channels are large enough to avoid
// problems with padding.
- new_channels[c] =
- ImageF(frame_dimensions_.xsize_upsampled_padded +
- kRenderPipelineXOffset * 2 + hwy::kMaxVectorSize * 8,
- frame_dimensions_.ysize_upsampled_padded +
- kRenderPipelineXOffset * 2);
+ JXL_ASSIGN_OR_RETURN(
+ new_channels[c],
+ ImageF::Create(frame_dimensions_.xsize_upsampled_padded +
+ kRenderPipelineXOffset * 2 +
+ hwy::kMaxVectorSize * 8,
+ frame_dimensions_.ysize_upsampled_padded +
+ kRenderPipelineXOffset * 2));
new_channels[c].ShrinkTo(
(input_sizes[c].first << stage->settings_.shift_x) +
kRenderPipelineXOffset * 2,
@@ -116,7 +122,8 @@ void SimpleRenderPipeline::ProcessBuffers(size_t group_id, size_t thread_id) {
for (size_t y = 0; y < input_sizes[c].second; y++) {
float* row = get_row(c, y);
for (size_t ix = 0; ix < stage->settings_.border_x; ix++) {
- *(row - ix - 1) = row[Mirror(-ssize_t(ix) - 1, input_sizes[c].first)];
+ *(row - ix - 1) =
+ row[Mirror(-static_cast<ssize_t>(ix) - 1, input_sizes[c].first)];
}
for (size_t ix = 0; ix < stage->settings_.border_x; ix++) {
*(row + ix + input_sizes[c].first) =
@@ -126,7 +133,8 @@ void SimpleRenderPipeline::ProcessBuffers(size_t group_id, size_t thread_id) {
// Vertical mirroring.
for (int y = 0; y < static_cast<int>(stage->settings_.border_y); y++) {
memcpy(get_row(c, -y - 1) - stage->settings_.border_x,
- get_row(c, Mirror(-ssize_t(y) - 1, input_sizes[c].second)) -
+ get_row(c, Mirror(-static_cast<ssize_t>(y) - 1,
+ input_sizes[c].second)) -
stage->settings_.border_x,
sizeof(float) *
(input_sizes[c].first + 2 * stage->settings_.border_x));
@@ -160,7 +168,7 @@ void SimpleRenderPipeline::ProcessBuffers(size_t group_id, size_t thread_id) {
// Run the pipeline.
{
- stage->SetInputSizes(input_sizes);
+ JXL_RETURN_IF_ERROR(stage->SetInputSizes(input_sizes));
int border_y = stage->settings_.border_y;
for (size_t y = 0; y < ysize; y++) {
// Prepare input rows.
@@ -183,8 +191,9 @@ void SimpleRenderPipeline::ProcessBuffers(size_t group_id, size_t thread_id) {
(y << stage->settings_.shift_y) + iy + kRenderPipelineXOffset);
}
}
- stage->ProcessRow(input_rows, output_rows, /*xextra=*/0, xsize,
- /*xpos=*/0, y, thread_id);
+ JXL_RETURN_IF_ERROR(stage->ProcessRow(input_rows, output_rows,
+ /*xextra=*/0, xsize,
+ /*xpos=*/0, y, thread_id));
}
}
@@ -210,7 +219,8 @@ void SimpleRenderPipeline::ProcessBuffers(size_t group_id, size_t thread_id) {
}
if (stage->SwitchToImageDimensions()) {
- size_t image_xsize, image_ysize;
+ size_t image_xsize;
+ size_t image_ysize;
FrameOrigin frame_origin;
stage->GetImageDimensions(&image_xsize, &image_ysize, &frame_origin);
frame_dimensions_.Set(image_xsize, image_ysize, 0, 0, 0, false, 1);
@@ -218,8 +228,11 @@ void SimpleRenderPipeline::ProcessBuffers(size_t group_id, size_t thread_id) {
channel_data_.clear();
channel_data_.reserve(old_channels.size());
for (size_t c = 0; c < old_channels.size(); c++) {
- channel_data_.emplace_back(2 * kRenderPipelineXOffset + image_xsize,
- 2 * kRenderPipelineXOffset + image_ysize);
+ JXL_ASSIGN_OR_RETURN(
+ ImageF ch,
+ ImageF::Create(2 * kRenderPipelineXOffset + image_xsize,
+ 2 * kRenderPipelineXOffset + image_ysize));
+ channel_data_.emplace_back(std::move(ch));
}
for (size_t y = 0; y < image_ysize; ++y) {
for (size_t c = 0; c < channel_data_.size(); c++) {
@@ -262,5 +275,6 @@ void SimpleRenderPipeline::ProcessBuffers(size_t group_id, size_t thread_id) {
}
}
}
+ return true;
}
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.h
index 10f4505912..1240b9fa46 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.h
@@ -19,9 +19,9 @@ class SimpleRenderPipeline : public RenderPipeline {
std::vector<std::pair<ImageF*, Rect>> PrepareBuffers(
size_t group_id, size_t thread_id) override;
- void ProcessBuffers(size_t group_id, size_t thread_id) override;
+ Status ProcessBuffers(size_t group_id, size_t thread_id) override;
- void PrepareForThreadsInternal(size_t num, bool use_group_ids) override;
+ Status PrepareForThreadsInternal(size_t num, bool use_group_ids) override;
// Full frame buffers. Both X and Y dimensions are padded by
// kRenderPipelineXOffset.
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_blending.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_blending.cc
index b68105f4c9..ef3899d1b3 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_blending.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_blending.cc
@@ -109,7 +109,7 @@ class BlendingStage : public RenderPipelineStage {
}
}
};
- make_blending(info_, &blending_info_[0]);
+ make_blending(info_, blending_info_.data());
for (size_t i = 0; i < ec_info.size(); i++) {
make_blending(ec_info[i], &blending_info_[1 + i]);
}
@@ -117,9 +117,9 @@ class BlendingStage : public RenderPipelineStage {
Status IsInitialized() const override { return initialized_; }
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
JXL_ASSERT(initialized_);
const FrameOrigin& frame_origin = frame_header_.frame_origin;
ssize_t bg_xpos = frame_origin.x0 + static_cast<ssize_t>(xpos);
@@ -128,7 +128,8 @@ class BlendingStage : public RenderPipelineStage {
if (bg_xpos + static_cast<ssize_t>(xsize) <= 0 ||
frame_origin.x0 >= static_cast<ssize_t>(image_xsize_) || bg_ypos < 0 ||
bg_ypos >= static_cast<ssize_t>(image_ysize_)) {
- return;
+ // TODO(eustas): or fail?
+ return true;
}
if (bg_xpos < 0) {
offset -= bg_xpos;
@@ -160,9 +161,9 @@ class BlendingStage : public RenderPipelineStage {
: zeroes_.data();
}
}
- PerformBlending(bg_row_ptrs_.data(), fg_row_ptrs_.data(),
- fg_row_ptrs_.data(), 0, xsize, blending_info_[0],
- blending_info_.data() + 1, *extra_channel_info_);
+ return PerformBlending(bg_row_ptrs_.data(), fg_row_ptrs_.data(),
+ fg_row_ptrs_.data(), 0, xsize, blending_info_[0],
+ blending_info_.data() + 1, *extra_channel_info_);
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_chroma_upsampling.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_chroma_upsampling.cc
index 936fbd3a44..2bc88ada67 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_chroma_upsampling.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_chroma_upsampling.cc
@@ -27,9 +27,9 @@ class HorizontalChromaUpsamplingStage : public RenderPipelineStage {
/*shift=*/1, /*border=*/1)),
c_(channel) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
HWY_FULL(float) df;
xextra = RoundUpTo(xextra, Lanes(df));
auto threefour = Set(df, 0.75f);
@@ -45,6 +45,7 @@ class HorizontalChromaUpsamplingStage : public RenderPipelineStage {
auto right = MulAdd(onefour, next, current);
StoreInterleaved(df, left, right, row_out + x * 2);
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
@@ -65,9 +66,9 @@ class VerticalChromaUpsamplingStage : public RenderPipelineStage {
/*shift=*/1, /*border=*/1)),
c_(channel) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
HWY_FULL(float) df;
xextra = RoundUpTo(xextra, Lanes(df));
auto threefour = Set(df, 0.75f);
@@ -86,6 +87,7 @@ class VerticalChromaUpsamplingStage : public RenderPipelineStage {
Store(MulAdd(it, onefour, im_scaled), df, row_out0 + x);
Store(MulAdd(ib, onefour, im_scaled), df, row_out1 + x);
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_cms.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_cms.cc
index 2465146b47..3202a03e44 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_cms.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_cms.cc
@@ -7,10 +7,8 @@
#include <memory>
-#include "jxl/cms_interface.h"
-#include "jxl/color_encoding.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
-#include "lib/jxl/common.h"
#include "lib/jxl/dec_xyb.h"
#undef HWY_TARGET_INCLUDE
@@ -19,7 +17,6 @@
#include <hwy/highway.h>
#include "lib/jxl/dec_xyb-inl.h"
-#include "lib/jxl/sanitizers.h"
HWY_BEFORE_NAMESPACE();
namespace jxl {
@@ -44,10 +41,10 @@ class CmsStage : public RenderPipelineStage {
not_mixing_color_and_grey;
}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
- JXL_ASSERT(xsize == xsize_);
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
+ JXL_ASSERT(xsize <= xsize_);
// TODO(firsching): handle grey case seperately
// interleave
float* JXL_RESTRICT row0 = GetInputRow(input_rows, 0, 0);
@@ -62,16 +59,15 @@ class CmsStage : public RenderPipelineStage {
}
const float* buf_src = mutable_buf_src;
float* JXL_RESTRICT buf_dst = color_space_transform->BufDst(thread_id);
- if (!color_space_transform->Run(thread_id, buf_src, buf_dst)) {
- // TODO(firsching): somehow mark failing here?
- return;
- }
+ JXL_RETURN_IF_ERROR(
+ color_space_transform->Run(thread_id, buf_src, buf_dst, xsize));
// de-interleave
for (size_t x = 0; x < xsize; x++) {
row0[x] = buf_dst[3 * x + 0];
row1[x] = buf_dst[3 * x + 1];
row2[x] = buf_dst[3 * x + 2];
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
return c < 3 ? RenderPipelineChannelMode::kInPlace
@@ -86,7 +82,7 @@ class CmsStage : public RenderPipelineStage {
std::unique_ptr<jxl::ColorSpaceTransform> color_space_transform;
ColorEncoding c_src_;
- void SetInputSizes(
+ Status SetInputSizes(
const std::vector<std::pair<size_t, size_t>>& input_sizes) override {
#if JXL_ENABLE_ASSERT
JXL_ASSERT(input_sizes.size() >= 3);
@@ -96,6 +92,7 @@ class CmsStage : public RenderPipelineStage {
}
#endif
xsize_ = input_sizes[0].first;
+ return true;
}
Status PrepareForThreads(size_t num_threads) override {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_epf.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_epf.cc
index 5d1a379ede..d3030b02cb 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_epf.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_epf.cc
@@ -8,7 +8,6 @@
#include "lib/jxl/base/common.h"
#include "lib/jxl/common.h" // JXL_HIGH_PRECISION
#include "lib/jxl/epf.h"
-#include "lib/jxl/sanitizers.h"
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/render_pipeline/stage_epf.cc"
@@ -67,9 +66,9 @@ class EPF0Stage : public RenderPipelineStage {
*B = MulAdd(weight, cb, *B);
}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
DF df;
using V = decltype(Zero(df));
@@ -163,6 +162,7 @@ class EPF0Stage : public RenderPipelineStage {
StoreU(Mul(Y, inv_w), df, GetOutputRow(output_rows, 1, 0) + x);
StoreU(Mul(B, inv_w), df, GetOutputRow(output_rows, 2, 0) + x);
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
@@ -207,9 +207,9 @@ class EPF1Stage : public RenderPipelineStage {
*B = MulAdd(weight, cb, *B);
}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
DF df;
xextra = RoundUpTo(xextra, Lanes(df));
const float* JXL_RESTRICT row_sigma =
@@ -343,6 +343,7 @@ class EPF1Stage : public RenderPipelineStage {
Store(Mul(Y, inv_w), df, GetOutputRow(output_rows, 1, 0) + x);
Store(Mul(B, inv_w), df, GetOutputRow(output_rows, 2, 0) + x);
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
@@ -392,9 +393,9 @@ class EPF2Stage : public RenderPipelineStage {
*B = MulAdd(weight, cb, *B);
}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
DF df;
xextra = RoundUpTo(xextra, Lanes(df));
const float* JXL_RESTRICT row_sigma =
@@ -465,6 +466,7 @@ class EPF2Stage : public RenderPipelineStage {
Store(Mul(Y, inv_w), df, GetOutputRow(output_rows, 1, 0) + x);
Store(Mul(B, inv_w), df, GetOutputRow(output_rows, 2, 0) + x);
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_from_linear.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_from_linear.cc
index 6b1f646cd5..922c7da366 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_from_linear.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_from_linear.cc
@@ -68,7 +68,7 @@ struct OpPq {
};
struct OpHlg {
- explicit OpHlg(const float luminances[3], const float intensity_target)
+ explicit OpHlg(const Vector3& luminances, const float intensity_target)
: hlg_ootf_(HlgOOTF::ToSceneLight(/*display_luminance=*/intensity_target,
luminances)) {}
@@ -105,9 +105,9 @@ class FromLinearStage : public RenderPipelineStage {
: RenderPipelineStage(RenderPipelineStage::Settings()),
op_(std::move(op)) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
const HWY_FULL(float) d;
const size_t xsize_v = RoundUpTo(xsize, Lanes(d));
float* JXL_RESTRICT row0 = GetInputRow(input_rows, 0, 0);
@@ -119,7 +119,8 @@ class FromLinearStage : public RenderPipelineStage {
msan::UnpoisonMemory(row0 + xsize, sizeof(float) * (xsize_v - xsize));
msan::UnpoisonMemory(row1 + xsize, sizeof(float) * (xsize_v - xsize));
msan::UnpoisonMemory(row2 + xsize, sizeof(float) * (xsize_v - xsize));
- for (ssize_t x = -xextra; x < (ssize_t)(xsize + xextra); x += Lanes(d)) {
+ for (ssize_t x = -xextra; x < static_cast<ssize_t>(xsize + xextra);
+ x += Lanes(d)) {
auto r = LoadU(d, row0 + x);
auto g = LoadU(d, row1 + x);
auto b = LoadU(d, row2 + x);
@@ -131,6 +132,7 @@ class FromLinearStage : public RenderPipelineStage {
msan::PoisonMemory(row0 + xsize, sizeof(float) * (xsize_v - xsize));
msan::PoisonMemory(row1 + xsize, sizeof(float) * (xsize_v - xsize));
msan::PoisonMemory(row2 + xsize, sizeof(float) * (xsize_v - xsize));
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_gaborish.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_gaborish.cc
index 0917db3f9a..6fcd5e14df 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_gaborish.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_gaborish.cc
@@ -44,9 +44,9 @@ class GaborishStage : public RenderPipelineStage {
}
}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
const HWY_FULL(float) d;
for (size_t c = 0; c < 3; c++) {
float* JXL_RESTRICT row_t = GetInputRow(input_rows, c, -1);
@@ -66,7 +66,7 @@ class GaborishStage : public RenderPipelineStage {
// Since GetInputRow(input_rows, c, {-1, 0, 1}) is aligned, rounding
// xextra up to Lanes(d) doesn't access anything problematic.
for (ssize_t x = -RoundUpTo(xextra, Lanes(d));
- x < (ssize_t)(xsize + xextra); x += Lanes(d)) {
+ x < static_cast<ssize_t>(xsize + xextra); x += Lanes(d)) {
const auto t = LoadMaybeU(d, row_t + x);
const auto tl = LoadU(d, row_t + x - 1);
const auto tr = LoadU(d, row_t + x + 1);
@@ -83,6 +83,7 @@ class GaborishStage : public RenderPipelineStage {
Store(pixels, d, row_out + x);
}
}
+ return true;
}
#undef LoadMaybeU
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_noise.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_noise.cc
index 5cf8a6ed51..eca679b948 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_noise.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_noise.cc
@@ -5,6 +5,8 @@
#include "lib/jxl/render_pipeline/stage_noise.h"
+#include "lib/jxl/noise.h"
+
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/render_pipeline/stage_noise.cc"
#include <hwy/foreach_target.h>
@@ -61,9 +63,10 @@ class StrengthEvalLut {
#endif
{
#if HWY_TARGET != HWY_SCALAR
- uint32_t lut[8];
- memcpy(lut, noise_params.lut, sizeof(lut));
- for (size_t i = 0; i < 8; i++) {
+ uint32_t lut[NoiseParams::kNumNoisePoints];
+ memcpy(lut, noise_params.lut.data(),
+ NoiseParams::kNumNoisePoints * sizeof(uint32_t));
+ for (size_t i = 0; i < NoiseParams::kNumNoisePoints; i++) {
low16_lut[2 * i] = (lut[i] >> 0) & 0xFF;
low16_lut[2 * i + 1] = (lut[i] >> 8) & 0xFF;
high16_lut[2 * i] = (lut[i] >> 16) & 0xFF;
@@ -161,10 +164,10 @@ class AddNoiseStage : public RenderPipelineStage {
cmap_(cmap),
first_c_(first_c) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
- if (!noise_params_.HasAny()) return;
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
+ if (!noise_params_.HasAny()) return true;
const StrengthEvalLut noise_model(noise_params_);
D d;
const auto half = Set(d, 0.5f);
@@ -212,6 +215,7 @@ class AddNoiseStage : public RenderPipelineStage {
msan::PoisonMemory(row_x + xsize, (xsize_v - xsize) * sizeof(float));
msan::PoisonMemory(row_y + xsize, (xsize_v - xsize) * sizeof(float));
msan::PoisonMemory(row_b + xsize, (xsize_v - xsize) * sizeof(float));
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
@@ -241,9 +245,9 @@ class ConvolveNoiseStage : public RenderPipelineStage {
/*shift=*/0, /*border=*/2)),
first_c_(first_c) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
const HWY_FULL(float) d;
for (size_t c = first_c_; c < first_c_ + 3; c++) {
float* JXL_RESTRICT rows[5];
@@ -252,7 +256,7 @@ class ConvolveNoiseStage : public RenderPipelineStage {
}
float* JXL_RESTRICT row_out = GetOutputRow(output_rows, c, 0);
for (ssize_t x = -RoundUpTo(xextra, Lanes(d));
- x < (ssize_t)(xsize + xextra); x += Lanes(d)) {
+ x < static_cast<ssize_t>(xsize + xextra); x += Lanes(d)) {
const auto p00 = LoadU(d, rows[2] + x);
auto others = Zero(d);
// TODO(eustas): sum loaded values to reduce the calculation chain
@@ -271,6 +275,7 @@ class ConvolveNoiseStage : public RenderPipelineStage {
StoreU(pixels, d, row_out + x);
}
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_patches.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_patches.cc
index c5a75b09f7..e0a66167d4 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_patches.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_patches.cc
@@ -14,16 +14,17 @@ class PatchDictionaryStage : public RenderPipelineStage {
patches_(*patches),
num_channels_(num_channels) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
JXL_ASSERT(xpos == 0 || xpos >= xextra);
size_t x0 = xpos ? xpos - xextra : 0;
std::vector<float*> row_ptrs(num_channels_);
for (size_t i = 0; i < num_channels_; i++) {
row_ptrs[i] = GetInputRow(input_rows, i, 0) + x0 - xpos;
}
- patches_.AddOneRow(row_ptrs.data(), ypos, x0, xsize + xextra + xpos - x0);
+ return patches_.AddOneRow(row_ptrs.data(), ypos, x0,
+ xsize + xextra + xpos - x0);
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_splines.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_splines.cc
index 4a0529ce2c..92a13090a7 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_splines.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_splines.cc
@@ -20,13 +20,14 @@ class SplineStage : public RenderPipelineStage {
: RenderPipelineStage(RenderPipelineStage::Settings()),
splines_(*splines) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
float* row_x = GetInputRow(input_rows, 0, 0);
float* row_y = GetInputRow(input_rows, 1, 0);
float* row_b = GetInputRow(input_rows, 2, 0);
splines_.AddToRow(row_x, row_y, row_b, Rect(xpos, ypos, xsize, 1));
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_spot.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_spot.cc
index a43cb4e1ab..18588e2012 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_spot.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_spot.cc
@@ -15,19 +15,20 @@ class SpotColorStage : public RenderPipelineStage {
JXL_ASSERT(spot_c_ >= 3);
}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
// TODO(veluca): add SIMD.
float scale = spot_color_[3];
for (size_t c = 0; c < 3; c++) {
float* JXL_RESTRICT p = GetInputRow(input_rows, c, 0);
const float* JXL_RESTRICT s = GetInputRow(input_rows, spot_c_, 0);
- for (ssize_t x = -xextra; x < ssize_t(xsize + xextra); x++) {
+ for (ssize_t x = -xextra; x < static_cast<ssize_t>(xsize + xextra); x++) {
float mix = scale * s[x];
p[x] = mix * spot_color_[c] + (1.0f - mix) * p[x];
}
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_to_linear.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_to_linear.cc
index 85eca2f039..c2c5ac484b 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_to_linear.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_to_linear.cc
@@ -63,7 +63,7 @@ struct OpPq {
};
struct OpHlg {
- explicit OpHlg(const float luminances[3], const float intensity_target)
+ explicit OpHlg(const Vector3& luminances, const float intensity_target)
: hlg_ootf_(HlgOOTF::FromSceneLight(
/*display_luminance=*/intensity_target, luminances)) {}
@@ -113,9 +113,9 @@ class ToLinearStage : public RenderPipelineStage {
explicit ToLinearStage()
: RenderPipelineStage(RenderPipelineStage::Settings()), valid_(false) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
const HWY_FULL(float) d;
const size_t xsize_v = RoundUpTo(xsize, Lanes(d));
float* JXL_RESTRICT row0 = GetInputRow(input_rows, 0, 0);
@@ -127,7 +127,8 @@ class ToLinearStage : public RenderPipelineStage {
msan::UnpoisonMemory(row0 + xsize, sizeof(float) * (xsize_v - xsize));
msan::UnpoisonMemory(row1 + xsize, sizeof(float) * (xsize_v - xsize));
msan::UnpoisonMemory(row2 + xsize, sizeof(float) * (xsize_v - xsize));
- for (ssize_t x = -xextra; x < (ssize_t)(xsize + xextra); x += Lanes(d)) {
+ for (ssize_t x = -xextra; x < static_cast<ssize_t>(xsize + xextra);
+ x += Lanes(d)) {
auto r = LoadU(d, row0 + x);
auto g = LoadU(d, row1 + x);
auto b = LoadU(d, row2 + x);
@@ -139,6 +140,7 @@ class ToLinearStage : public RenderPipelineStage {
msan::PoisonMemory(row0 + xsize, sizeof(float) * (xsize_v - xsize));
msan::PoisonMemory(row1 + xsize, sizeof(float) * (xsize_v - xsize));
msan::PoisonMemory(row2 + xsize, sizeof(float) * (xsize_v - xsize));
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_tone_mapping.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_tone_mapping.cc
index 2a272e15dc..e8cd90b244 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_tone_mapping.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_tone_mapping.cc
@@ -56,10 +56,10 @@ class ToneMappingStage : public RenderPipelineStage {
bool IsNeeded() const { return tone_mapper_ || hlg_ootf_; }
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
- if (!(tone_mapper_ || hlg_ootf_)) return;
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
+ if (!(tone_mapper_ || hlg_ootf_)) return true;
const HWY_FULL(float) d;
const size_t xsize_v = RoundUpTo(xsize, Lanes(d));
@@ -72,7 +72,8 @@ class ToneMappingStage : public RenderPipelineStage {
msan::UnpoisonMemory(row0 + xsize, sizeof(float) * (xsize_v - xsize));
msan::UnpoisonMemory(row1 + xsize, sizeof(float) * (xsize_v - xsize));
msan::UnpoisonMemory(row2 + xsize, sizeof(float) * (xsize_v - xsize));
- for (ssize_t x = -xextra; x < (ssize_t)(xsize + xextra); x += Lanes(d)) {
+ for (ssize_t x = -xextra; x < static_cast<ssize_t>(xsize + xextra);
+ x += Lanes(d)) {
auto r = LoadU(d, row0 + x);
auto g = LoadU(d, row1 + x);
auto b = LoadU(d, row2 + x);
@@ -100,6 +101,7 @@ class ToneMappingStage : public RenderPipelineStage {
msan::PoisonMemory(row0 + xsize, sizeof(float) * (xsize_v - xsize));
msan::PoisonMemory(row1 + xsize, sizeof(float) * (xsize_v - xsize));
msan::PoisonMemory(row2 + xsize, sizeof(float) * (xsize_v - xsize));
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_upsampling.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_upsampling.cc
index ade37d59a6..897b20c4c6 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_upsampling.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_upsampling.cc
@@ -46,9 +46,9 @@ class UpsamplingStage : public RenderPipelineStage {
}
}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
static HWY_FULL(float) df;
size_t shift = settings_.shift_x;
size_t N = 1 << shift;
@@ -74,6 +74,7 @@ class UpsamplingStage : public RenderPipelineStage {
msan::PoisonMemory(dst_row + xsize * N,
sizeof(float) * (xsize_v - xsize) * N);
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.cc
index 847972acc8..c5a91e8efd 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.cc
@@ -9,7 +9,9 @@
#include "lib/jxl/alpha.h"
#include "lib/jxl/base/common.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_cache.h"
+#include "lib/jxl/image.h"
#include "lib/jxl/image_bundle.h"
#include "lib/jxl/sanitizers.h"
@@ -150,13 +152,13 @@ class WriteToOutputStage : public RenderPipelineStage {
}
}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
JXL_DASSERT(xextra == 0);
JXL_DASSERT(main_.run_opaque_ || main_.buffer_);
- if (ypos >= height_) return;
- if (xpos >= width_) return;
+ if (ypos >= height_) return true;
+ if (xpos >= width_) return true;
if (flip_y_) {
ypos = height_ - 1u - ypos;
}
@@ -184,6 +186,7 @@ class WriteToOutputStage : public RenderPipelineStage {
OutputBuffers(extra, thread_id, ypos, xstart, len, line_buffers);
}
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
@@ -202,7 +205,7 @@ class WriteToOutputStage : public RenderPipelineStage {
private:
struct Output {
- Output(const ImageOutput& image_out)
+ explicit Output(const ImageOutput& image_out)
: pixel_callback_(image_out.callback),
buffer_(image_out.buffer),
buffer_size_(image_out.buffer_size),
@@ -406,8 +409,8 @@ class WriteToOutputStage : public RenderPipelineStage {
sizeof(output[0]) * out.num_channels_ * padding);
}
- void StoreFloat16Row(const Output& out, const float* input[4], size_t len,
- uint16_t* output) const {
+ static void StoreFloat16Row(const Output& out, const float* input[4],
+ size_t len, uint16_t* output) {
const HWY_FULL(float) d;
const Rebind<uint16_t, decltype(d)> du;
const Rebind<hwy::float16_t, decltype(d)> df16;
@@ -452,8 +455,8 @@ class WriteToOutputStage : public RenderPipelineStage {
sizeof(output[0]) * out.num_channels_ * padding);
}
- void StoreFloatRow(const Output& out, const float* input[4], size_t len,
- float* output) const {
+ static void StoreFloatRow(const Output& out, const float* input[4],
+ size_t len, float* output) {
const HWY_FULL(float) d;
if (out.num_channels_ == 1) {
memcpy(output, input[0], len * sizeof(output[0]));
@@ -559,7 +562,7 @@ class WriteToImageBundleStage : public RenderPipelineStage {
image_bundle_(image_bundle),
color_encoding_(std::move(color_encoding)) {}
- void SetInputSizes(
+ Status SetInputSizes(
const std::vector<std::pair<size_t, size_t>>& input_sizes) override {
#if JXL_ENABLE_ASSERT
JXL_ASSERT(input_sizes.size() >= 3);
@@ -569,19 +572,22 @@ class WriteToImageBundleStage : public RenderPipelineStage {
}
#endif
// TODO(eustas): what should we do in the case of "want only ECs"?
- image_bundle_->SetFromImage(
- Image3F(input_sizes[0].first, input_sizes[0].second), color_encoding_);
+ JXL_ASSIGN_OR_RETURN(Image3F tmp, Image3F::Create(input_sizes[0].first,
+ input_sizes[0].second));
+ image_bundle_->SetFromImage(std::move(tmp), color_encoding_);
// TODO(veluca): consider not reallocating ECs if not needed.
image_bundle_->extra_channels().clear();
for (size_t c = 3; c < input_sizes.size(); c++) {
- image_bundle_->extra_channels().emplace_back(input_sizes[c].first,
- input_sizes[c].second);
+ JXL_ASSIGN_OR_RETURN(ImageF ch, ImageF::Create(input_sizes[c].first,
+ input_sizes[c].second));
+ image_bundle_->extra_channels().emplace_back(std::move(ch));
}
+ return true;
}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
for (size_t c = 0; c < 3; c++) {
memcpy(image_bundle_->color()->PlaneRow(c, ypos) + xpos - xextra,
GetInputRow(input_rows, c, 0) - xextra,
@@ -594,6 +600,7 @@ class WriteToImageBundleStage : public RenderPipelineStage {
GetInputRow(input_rows, 3 + ec, 0) - xextra,
sizeof(float) * (xsize + 2 * xextra));
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
@@ -612,7 +619,7 @@ class WriteToImage3FStage : public RenderPipelineStage {
explicit WriteToImage3FStage(Image3F* image)
: RenderPipelineStage(RenderPipelineStage::Settings()), image_(image) {}
- void SetInputSizes(
+ Status SetInputSizes(
const std::vector<std::pair<size_t, size_t>>& input_sizes) override {
#if JXL_ENABLE_ASSERT
JXL_ASSERT(input_sizes.size() >= 3);
@@ -621,17 +628,20 @@ class WriteToImage3FStage : public RenderPipelineStage {
JXL_ASSERT(input_sizes[c].second == input_sizes[0].second);
}
#endif
- *image_ = Image3F(input_sizes[0].first, input_sizes[0].second);
+ JXL_ASSIGN_OR_RETURN(
+ *image_, Image3F::Create(input_sizes[0].first, input_sizes[0].second));
+ return true;
}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
for (size_t c = 0; c < 3; c++) {
memcpy(image_->PlaneRow(c, ypos) + xpos - xextra,
GetInputRow(input_rows, c, 0) - xextra,
sizeof(float) * (xsize + 2 * xextra));
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_xyb.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_xyb.cc
index 56e86e6095..a20e686de6 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_xyb.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_xyb.cc
@@ -28,9 +28,9 @@ class XYBStage : public RenderPipelineStage {
output_is_xyb_(output_encoding_info.color_encoding.GetColorSpace() ==
ColorSpace::kXYB) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
const HWY_FULL(float) d;
JXL_ASSERT(xextra == 0);
const size_t xsize_v = RoundUpTo(xsize, Lanes(d));
@@ -52,7 +52,8 @@ class XYBStage : public RenderPipelineStage {
const auto offset_x = Set(d, jxl::cms::kScaledXYBOffset[0]);
const auto offset_y = Set(d, jxl::cms::kScaledXYBOffset[1]);
const auto offset_bmy = Set(d, jxl::cms::kScaledXYBOffset[2]);
- for (ssize_t x = -xextra; x < (ssize_t)(xsize + xextra); x += Lanes(d)) {
+ for (ssize_t x = -xextra; x < static_cast<ssize_t>(xsize + xextra);
+ x += Lanes(d)) {
const auto in_x = LoadU(d, row0 + x);
const auto in_y = LoadU(d, row1 + x);
const auto in_b = LoadU(d, row2 + x);
@@ -64,7 +65,8 @@ class XYBStage : public RenderPipelineStage {
StoreU(out_b, d, row2 + x);
}
} else {
- for (ssize_t x = -xextra; x < (ssize_t)(xsize + xextra); x += Lanes(d)) {
+ for (ssize_t x = -xextra; x < static_cast<ssize_t>(xsize + xextra);
+ x += Lanes(d)) {
const auto in_opsin_x = LoadU(d, row0 + x);
const auto in_opsin_y = LoadU(d, row1 + x);
const auto in_opsin_b = LoadU(d, row2 + x);
@@ -81,6 +83,7 @@ class XYBStage : public RenderPipelineStage {
msan::PoisonMemory(row0 + xsize, sizeof(float) * (xsize_v - xsize));
msan::PoisonMemory(row1 + xsize, sizeof(float) * (xsize_v - xsize));
msan::PoisonMemory(row2 + xsize, sizeof(float) * (xsize_v - xsize));
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
@@ -130,10 +133,10 @@ class FastXYBStage : public RenderPipelineStage {
has_alpha_(has_alpha),
alpha_c_(alpha_c) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
- if (ypos >= height_) return;
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
+ if (ypos >= height_) return true;
JXL_ASSERT(xextra == 0);
const float* xyba[4] = {
GetInputRow(input_rows, 0, 0), GetInputRow(input_rows, 1, 0),
@@ -142,6 +145,7 @@ class FastXYBStage : public RenderPipelineStage {
uint8_t* out_buf = rgb_ + stride_ * ypos + (rgba_ ? 4 : 3) * xpos;
FastXYBTosRGB8(xyba, out_buf, rgba_,
xsize + xpos <= width_ ? xsize : width_ - xpos);
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_ycbcr.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_ycbcr.cc
index 30ad327221..f21a00c728 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_ycbcr.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_ycbcr.cc
@@ -22,9 +22,9 @@ class kYCbCrStage : public RenderPipelineStage {
public:
kYCbCrStage() : RenderPipelineStage(RenderPipelineStage::Settings()) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
const HWY_FULL(float) df;
// Full-range BT.601 as defined by JFIF Clause 7:
@@ -51,6 +51,7 @@ class kYCbCrStage : public RenderPipelineStage {
StoreU(g_vec, df, row1 + x);
StoreU(b_vec, df, row2 + x);
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/test_render_pipeline_stages.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/test_render_pipeline_stages.h
index 789a52f8b2..c2c25c46c3 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/test_render_pipeline_stages.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/test_render_pipeline_stages.h
@@ -7,10 +7,7 @@
#include <stdint.h>
#include <stdio.h>
-#include <algorithm>
-#include <utility>
-#include <vector>
-
+#include "lib/jxl/base/status.h"
#include "lib/jxl/render_pipeline/render_pipeline_stage.h"
namespace jxl {
@@ -20,13 +17,13 @@ class UpsampleXSlowStage : public RenderPipelineStage {
UpsampleXSlowStage()
: RenderPipelineStage(RenderPipelineStage::Settings::ShiftX(1, 1)) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
for (size_t c = 0; c < input_rows.size(); c++) {
const float* row = GetInputRow(input_rows, c, 0);
float* row_out = GetOutputRow(output_rows, c, 0);
- for (int64_t x = -xextra; x < (int64_t)(xsize + xextra); x++) {
+ for (int64_t x = -xextra; x < static_cast<int64_t>(xsize + xextra); x++) {
float xp = *(row + x - 1);
float xc = *(row + x);
float xn = *(row + x + 1);
@@ -36,6 +33,7 @@ class UpsampleXSlowStage : public RenderPipelineStage {
*(row_out + 2 * x + 1) = xout1;
}
}
+ return true;
}
const char* GetName() const override { return "TEST::UpsampleXSlowStage"; }
@@ -50,16 +48,16 @@ class UpsampleYSlowStage : public RenderPipelineStage {
UpsampleYSlowStage()
: RenderPipelineStage(RenderPipelineStage::Settings::ShiftY(1, 1)) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
for (size_t c = 0; c < input_rows.size(); c++) {
const float* rowp = GetInputRow(input_rows, c, -1);
const float* rowc = GetInputRow(input_rows, c, 0);
const float* rown = GetInputRow(input_rows, c, 1);
float* row_out0 = GetOutputRow(output_rows, c, 0);
float* row_out1 = GetOutputRow(output_rows, c, 1);
- for (int64_t x = -xextra; x < (int64_t)(xsize + xextra); x++) {
+ for (int64_t x = -xextra; x < static_cast<int64_t>(xsize + xextra); x++) {
float xp = *(rowp + x);
float xc = *(rowc + x);
float xn = *(rown + x);
@@ -69,6 +67,7 @@ class UpsampleYSlowStage : public RenderPipelineStage {
*(row_out1 + x) = yout1;
}
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
@@ -82,14 +81,15 @@ class Check0FinalStage : public RenderPipelineStage {
public:
Check0FinalStage() : RenderPipelineStage(RenderPipelineStage::Settings()) {}
- void ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
- size_t xextra, size_t xsize, size_t xpos, size_t ypos,
- size_t thread_id) const final {
+ Status ProcessRow(const RowInfo& input_rows, const RowInfo& output_rows,
+ size_t xextra, size_t xsize, size_t xpos, size_t ypos,
+ size_t thread_id) const final {
for (size_t c = 0; c < input_rows.size(); c++) {
for (size_t x = 0; x < xsize; x++) {
JXL_CHECK(fabsf(GetInputRow(input_rows, c, 0)[x]) < 1e-8);
}
}
+ return true;
}
RenderPipelineChannelMode GetChannelMode(size_t c) const final {
diff --git a/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc b/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc
index c00fda0de1..a4a87bebb7 100644
--- a/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc
@@ -26,7 +26,6 @@
#include "lib/jxl/butteraugli/butteraugli.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/dec_bit_reader.h"
-#include "lib/jxl/enc_butteraugli_comparator.h"
#include "lib/jxl/enc_external_image.h"
#include "lib/jxl/encode_internal.h"
#include "lib/jxl/image.h"
@@ -37,6 +36,9 @@
namespace {
+using jxl::ImageF;
+using jxl::test::ButteraugliDistance;
+
// Converts a test image to a CodecInOut.
// icc_profile can be empty to automatically deduce profile from the pixel
// format, or filled in to force this ICC profile
@@ -94,7 +96,7 @@ jxl::CodecInOut ConvertTestImage(const std::vector<uint8_t>& buf,
jxl::ColorEncoding color_encoding;
if (!icc_profile.empty()) {
jxl::IccBytes icc_profile_copy;
- icc_profile.AppendTo(&icc_profile_copy);
+ icc_profile.AppendTo(icc_profile_copy);
EXPECT_TRUE(
color_encoding.SetICC(std::move(icc_profile_copy), JxlGetDefaultCms()));
} else if (pixel_format.data_type == JXL_TYPE_FLOAT) {
@@ -118,12 +120,12 @@ float ConvertTestPixel<float>(const float val) {
template <>
uint16_t ConvertTestPixel<uint16_t>(const float val) {
- return (uint16_t)(val * UINT16_MAX);
+ return static_cast<uint16_t>(val * UINT16_MAX);
}
template <>
uint8_t ConvertTestPixel<uint8_t>(const float val) {
- return (uint8_t)(val * UINT8_MAX);
+ return static_cast<uint8_t>(val * UINT8_MAX);
}
// Returns a test image.
@@ -146,6 +148,7 @@ std::vector<uint8_t> GetTestImage(const size_t xsize, const size_t ysize,
val = static_cast<float>(x + y) / static_cast<float>(xsize + ysize);
break;
case 3:
+ default:
val = static_cast<float>(x * y) / static_cast<float>(xsize * ysize);
break;
}
@@ -233,7 +236,7 @@ void VerifyRoundtripCompression(
}
}
if (alpha_in_extra_channels_vector && !has_interleaved_alpha) {
- jxl::ImageF alpha_channel(xsize, ysize);
+ JXL_ASSIGN_OR_DIE(ImageF alpha_channel, ImageF::Create(xsize, ysize));
EXPECT_TRUE(jxl::ConvertFromExternal(
extra_channel_bytes.data(), extra_channel_bytes.size(), xsize, ysize,
basic_info.bits_per_sample, extra_channel_pixel_format, 0,
@@ -298,17 +301,18 @@ void VerifyRoundtripCompression(
frame_settings, JXL_ENC_FRAME_SETTING_ALREADY_DOWNSAMPLED,
already_downsampled));
}
- EXPECT_EQ(JXL_ENC_SUCCESS,
- JxlEncoderAddImageFrame(frame_settings, &input_pixel_format,
- (void*)original_bytes.data(),
- original_bytes.size()));
+ EXPECT_EQ(
+ JXL_ENC_SUCCESS,
+ JxlEncoderAddImageFrame(frame_settings, &input_pixel_format,
+ static_cast<const void*>(original_bytes.data()),
+ original_bytes.size()));
EXPECT_EQ(frame_settings->enc->input_queue.empty(), false);
for (size_t index = 0; index < channel_infos.size(); index++) {
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetExtraChannelBuffer(
frame_settings, &extra_channel_pixel_format,
- (void*)extra_channel_bytes.data(), extra_channel_bytes.size(),
- index + has_interleaved_alpha));
+ static_cast<const void*>(extra_channel_bytes.data()),
+ extra_channel_bytes.size(), index + has_interleaved_alpha));
}
JxlEncoderCloseInput(enc);
std::vector<uint8_t> compressed;
@@ -412,10 +416,10 @@ void VerifyRoundtripCompression(
if (already_downsampled) {
jxl::Image3F* color = decoded_io.Main().color();
- jxl::DownsampleImage(color, resampling);
+ JXL_ASSIGN_OR_DIE(*color, jxl::DownsampleImage(*color, resampling));
if (decoded_io.Main().HasAlpha()) {
- jxl::ImageF* alpha = decoded_io.Main().alpha();
- jxl::DownsampleImage(alpha, resampling);
+ ImageF* alpha = decoded_io.Main().alpha();
+ JXL_ASSIGN_OR_DIE(*alpha, jxl::DownsampleImage(*alpha, resampling));
}
decoded_io.SetSize(color->xsize(), color->ysize());
}
@@ -463,8 +467,8 @@ TEST(RoundtripTest, FloatFrameRoundtripTest) {
{JXL_CHANNEL_CFA, "my cfa channel"},
{JXL_CHANNEL_OPTIONAL, "optional channel"}},
{{JXL_CHANNEL_DEPTH, "very deep"}}};
- for (int use_container = 0; use_container < 2; use_container++) {
- for (int lossless = 0; lossless < 2; lossless++) {
+ for (bool use_container : {false, true}) {
+ for (bool lossless : {false, true}) {
for (uint32_t num_channels = 1; num_channels < 5; num_channels++) {
for (auto& extra_channels : extra_channels_cases) {
uint32_t has_alpha = static_cast<uint32_t>(num_channels % 2 == 0);
@@ -475,8 +479,8 @@ TEST(RoundtripTest, FloatFrameRoundtripTest) {
JxlPixelFormat pixel_format = JxlPixelFormat{
num_channels, JXL_TYPE_FLOAT, JXL_NATIVE_ENDIAN, 0};
VerifyRoundtripCompression<float>(
- 63, 129, pixel_format, pixel_format, (bool)lossless,
- (bool)use_container, 1, false, extra_channels);
+ 63, 129, pixel_format, pixel_format, lossless, use_container, 1,
+ false, extra_channels);
}
}
}
@@ -499,8 +503,8 @@ TEST(RoundtripTest, Uint16FrameRoundtripTest) {
JxlPixelFormat pixel_format = JxlPixelFormat{
num_channels, JXL_TYPE_UINT16, JXL_NATIVE_ENDIAN, 0};
VerifyRoundtripCompression<uint16_t>(
- 63, 129, pixel_format, pixel_format, (bool)lossless,
- (bool)use_container, 1, false, extra_channels);
+ 63, 129, pixel_format, pixel_format, static_cast<bool>(lossless),
+ static_cast<bool>(use_container), 1, false, extra_channels);
}
}
}
@@ -523,8 +527,8 @@ TEST(RoundtripTest, Uint8FrameRoundtripTest) {
JxlPixelFormat pixel_format = JxlPixelFormat{
num_channels, JXL_TYPE_UINT8, JXL_NATIVE_ENDIAN, 0};
VerifyRoundtripCompression<uint8_t>(
- 63, 129, pixel_format, pixel_format, (bool)lossless,
- (bool)use_container, 1, false, extra_channels);
+ 63, 129, pixel_format, pixel_format, static_cast<bool>(lossless),
+ static_cast<bool>(use_container), 1, false, extra_channels);
}
}
}
@@ -540,7 +544,7 @@ TEST(RoundtripTest, TestNonlinearSrgbAsXybEncoded) {
JxlPixelFormat{num_channels, JXL_TYPE_FLOAT, JXL_NATIVE_ENDIAN, 0};
VerifyRoundtripCompression<uint8_t>(
63, 129, pixel_format_in, pixel_format_out,
- /*lossless=*/false, (bool)use_container, 1, false, {});
+ /*lossless=*/false, static_cast<bool>(use_container), 1, false, {});
}
}
}
@@ -586,25 +590,25 @@ TEST(RoundtripTest, ExtraBoxesTest) {
jxl::test::JxlBasicInfoSetFromPixelFormat(&basic_info, &pixel_format);
basic_info.xsize = xsize;
basic_info.ysize = ysize;
- basic_info.uses_original_profile = false;
+ basic_info.uses_original_profile = JXL_FALSE;
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetCodestreamLevel(enc, 10));
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc, &basic_info));
JxlColorEncoding color_encoding;
+ JXL_BOOL is_gray = TO_JXL_BOOL(pixel_format.num_channels < 3);
if (pixel_format.data_type == JXL_TYPE_FLOAT) {
- JxlColorEncodingSetToLinearSRGB(&color_encoding,
- /*is_gray=*/pixel_format.num_channels < 3);
+ JxlColorEncodingSetToLinearSRGB(&color_encoding, is_gray);
} else {
- JxlColorEncodingSetToSRGB(&color_encoding,
- /*is_gray=*/pixel_format.num_channels < 3);
+ JxlColorEncodingSetToSRGB(&color_encoding, is_gray);
}
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetColorEncoding(enc, &color_encoding));
JxlEncoderFrameSettings* frame_settings =
JxlEncoderFrameSettingsCreate(enc, nullptr);
- JxlEncoderSetFrameLossless(frame_settings, false);
- EXPECT_EQ(JXL_ENC_SUCCESS,
- JxlEncoderAddImageFrame(frame_settings, &pixel_format,
- (void*)original_bytes.data(),
- original_bytes.size()));
+ JxlEncoderSetFrameLossless(frame_settings, JXL_FALSE);
+ EXPECT_EQ(
+ JXL_ENC_SUCCESS,
+ JxlEncoderAddImageFrame(frame_settings, &pixel_format,
+ static_cast<const void*>(original_bytes.data()),
+ original_bytes.size()));
JxlEncoderCloseInput(enc);
std::vector<uint8_t> compressed;
@@ -703,19 +707,17 @@ TEST(RoundtripTest, MultiFrameTest) {
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetBasicInfo(enc, &basic_info));
JxlColorEncoding color_encoding;
+ JXL_BOOL is_gray = TO_JXL_BOOL(pixel_format.num_channels < 3);
if (pixel_format.data_type == JXL_TYPE_FLOAT) {
- JxlColorEncodingSetToLinearSRGB(
- &color_encoding,
- /*is_gray=*/pixel_format.num_channels < 3);
+ JxlColorEncodingSetToLinearSRGB(&color_encoding, is_gray);
} else {
- JxlColorEncodingSetToSRGB(&color_encoding,
- /*is_gray=*/pixel_format.num_channels < 3);
+ JxlColorEncodingSetToSRGB(&color_encoding, is_gray);
}
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderSetColorEncoding(enc, &color_encoding));
JxlEncoderFrameSettings* frame_settings =
JxlEncoderFrameSettingsCreate(enc, nullptr);
- JxlEncoderSetFrameLossless(frame_settings, false);
+ JxlEncoderSetFrameLossless(frame_settings, JXL_FALSE);
if (index_frames == 1) {
EXPECT_EQ(JXL_ENC_SUCCESS,
JxlEncoderFrameSettingsSetOption(frame_settings,
@@ -733,9 +735,10 @@ TEST(RoundtripTest, MultiFrameTest) {
JxlEncoderSetFrameHeader(frame_settings, &frame_header);
EXPECT_EQ(
JXL_ENC_SUCCESS,
- JxlEncoderAddImageFrame(
- frame_settings, &pixel_format,
- (void*)(original_bytes.data() + oneframesize * i), oneframesize));
+ JxlEncoderAddImageFrame(frame_settings, &pixel_format,
+ static_cast<const void*>(
+ original_bytes.data() + oneframesize * i),
+ oneframesize));
}
JxlEncoderCloseInput(enc);
@@ -877,10 +880,11 @@ TEST(RoundtripTest, TestICCProfile) {
JxlEncoderSetICCProfile(enc, icc.data(), icc.size()));
JxlEncoderFrameSettings* frame_settings =
JxlEncoderFrameSettingsCreate(enc, nullptr);
- EXPECT_EQ(JXL_ENC_SUCCESS,
- JxlEncoderAddImageFrame(frame_settings, &format,
- (void*)original_bytes.data(),
- original_bytes.size()));
+ EXPECT_EQ(
+ JXL_ENC_SUCCESS,
+ JxlEncoderAddImageFrame(frame_settings, &format,
+ static_cast<const void*>(original_bytes.data()),
+ original_bytes.size()));
JxlEncoderCloseInput(enc);
std::vector<uint8_t> compressed;
@@ -946,7 +950,7 @@ TEST(RoundtripTest, JXL_TRANSCODE_JPEG_TEST(TestJPEGReconstruction)) {
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
JxlEncoderFrameSettings* frame_settings =
- JxlEncoderFrameSettingsCreate(enc.get(), NULL);
+ JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderUseContainer(enc.get(), JXL_TRUE));
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderStoreJPEGMetadata(enc.get(), JXL_TRUE));
diff --git a/third_party/jpeg-xl/lib/jxl/sanitizers.h b/third_party/jpeg-xl/lib/jxl/sanitizers.h
index adeaea67ed..bb133e9203 100644
--- a/third_party/jpeg-xl/lib/jxl/sanitizers.h
+++ b/third_party/jpeg-xl/lib/jxl/sanitizers.h
@@ -43,28 +43,18 @@ static JXL_INLINE JXL_MAYBE_UNUSED void UnpoisonMemory(const volatile void* m,
__msan_unpoison(m, size);
}
-static JXL_INLINE JXL_MAYBE_UNUSED void UnpoisonCStr(const char* c) {
- do {
- UnpoisonMemory(c, 1);
- } while (*c++);
-}
-
static JXL_INLINE JXL_MAYBE_UNUSED void MemoryIsInitialized(
const volatile void* m, size_t size) {
__msan_check_mem_is_initialized(m, size);
}
// Mark all the bytes of an image (including padding) as poisoned bytes.
-static JXL_INLINE JXL_MAYBE_UNUSED void PoisonImage(const PlaneBase& im) {
+template <typename T>
+static JXL_INLINE JXL_MAYBE_UNUSED void PoisonImage(const Plane<T>& im) {
PoisonMemory(im.bytes(), im.bytes_per_row() * im.ysize());
}
-template <typename T>
-static JXL_INLINE JXL_MAYBE_UNUSED void PoisonImage(const Image3<T>& im) {
- PoisonImage(im.Plane(0));
- PoisonImage(im.Plane(1));
- PoisonImage(im.Plane(2));
-}
+namespace {
// Print the uninitialized regions of an image.
template <typename T>
@@ -210,6 +200,8 @@ static JXL_INLINE JXL_MAYBE_UNUSED void CheckImageInitialized(
}
}
+} // namespace
+
#define JXL_CHECK_IMAGE_INITIALIZED(im, r) \
::jxl::msan::CheckImageInitialized(im, r, "im=" #im ", r=" #r);
@@ -221,13 +213,13 @@ static JXL_INLINE JXL_MAYBE_UNUSED void CheckImageInitialized(
// In non-msan mode these functions don't use volatile since it is not needed
// for the empty functions.
-static JXL_INLINE JXL_MAYBE_UNUSED void PoisonMemory(const void*, size_t) {}
-static JXL_INLINE JXL_MAYBE_UNUSED void UnpoisonMemory(const void*, size_t) {}
-static JXL_INLINE JXL_MAYBE_UNUSED void UnpoisonCStr(const char*) {}
-static JXL_INLINE JXL_MAYBE_UNUSED void MemoryIsInitialized(const void*,
- size_t) {}
+static JXL_INLINE JXL_MAYBE_UNUSED void PoisonMemory(const void* m,
+ size_t size) {}
+static JXL_INLINE JXL_MAYBE_UNUSED void UnpoisonMemory(const void* m,
+ size_t size) {}
+static JXL_INLINE JXL_MAYBE_UNUSED void MemoryIsInitialized(const void* m,
+ size_t size) {}
-static JXL_INLINE JXL_MAYBE_UNUSED void PoisonImage(const PlaneBase& im) {}
template <typename T>
static JXL_INLINE JXL_MAYBE_UNUSED void PoisonImage(const Plane<T>& im) {}
diff --git a/third_party/jpeg-xl/lib/jxl/simd_util.cc b/third_party/jpeg-xl/lib/jxl/simd_util.cc
index a3971ff900..6515daaa2b 100644
--- a/third_party/jpeg-xl/lib/jxl/simd_util.cc
+++ b/third_party/jpeg-xl/lib/jxl/simd_util.cc
@@ -5,11 +5,18 @@
#include "lib/jxl/simd_util.h"
+#include <algorithm>
+#include <cstddef>
+
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/simd_util.cc"
#include <hwy/foreach_target.h>
#include <hwy/highway.h>
+#include "lib/jxl/base/common.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/cache_aligned.h"
+
HWY_BEFORE_NAMESPACE();
namespace jxl {
namespace HWY_NAMESPACE {
@@ -36,5 +43,37 @@ size_t MaxVectorSize() {
return HWY_DYNAMIC_DISPATCH(MaxVectorSize)();
}
+size_t BytesPerRow(const size_t xsize, const size_t sizeof_t) {
+ // Special case: we don't allow any ops -> don't need extra padding/
+ if (xsize == 0) {
+ return 0;
+ }
+
+ const size_t vec_size = MaxVectorSize();
+ size_t valid_bytes = xsize * sizeof_t;
+
+ // Allow unaligned accesses starting at the last valid value.
+ // Skip for the scalar case because no extra lanes will be loaded.
+ if (vec_size != 0) {
+ valid_bytes += vec_size - sizeof_t;
+ }
+
+ // Round up to vector and cache line size.
+ const size_t align = std::max(vec_size, CacheAligned::kAlignment);
+ size_t bytes_per_row = RoundUpTo(valid_bytes, align);
+
+ // During the lengthy window before writes are committed to memory, CPUs
+ // guard against read after write hazards by checking the address, but
+ // only the lower 11 bits. We avoid a false dependency between writes to
+ // consecutive rows by ensuring their sizes are not multiples of 2 KiB.
+ // Avoid2K prevents the same problem for the planes of an Image3.
+ if (bytes_per_row % CacheAligned::kAlias == 0) {
+ bytes_per_row += align;
+ }
+
+ JXL_ASSERT(bytes_per_row % align == 0);
+ return bytes_per_row;
+}
+
} // namespace jxl
#endif
diff --git a/third_party/jpeg-xl/lib/jxl/simd_util.h b/third_party/jpeg-xl/lib/jxl/simd_util.h
index 84938a931a..62b68c989c 100644
--- a/third_party/jpeg-xl/lib/jxl/simd_util.h
+++ b/third_party/jpeg-xl/lib/jxl/simd_util.h
@@ -12,6 +12,10 @@ namespace jxl {
// Maximal vector size in bytes.
size_t MaxVectorSize();
+// Returns distance [bytes] between the start of two consecutive rows, a
+// multiple of vector/cache line size but NOT CacheAligned::kAlias - see below.
+size_t BytesPerRow(size_t xsize, size_t sizeof_t);
+
} // namespace jxl
#endif // LIB_JXL_SIMD_UTIL_H_
diff --git a/third_party/jpeg-xl/lib/jxl/speed_tier_test.cc b/third_party/jpeg-xl/lib/jxl/speed_tier_test.cc
index 7874bdc158..381367b54d 100644
--- a/third_party/jpeg-xl/lib/jxl/speed_tier_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/speed_tier_test.cc
@@ -105,7 +105,7 @@ TEST_P(SpeedTierTest, Roundtrip) {
{
extras::PackedPixelFile ppf_out;
test::Roundtrip(t.ppf(), cparams, dparams, nullptr, &ppf_out);
- EXPECT_LE(test::ButteraugliDistance(t.ppf(), ppf_out), 1.6);
+ EXPECT_LE(test::ButteraugliDistance(t.ppf(), ppf_out), 2.0);
}
if (params.shrink8) {
cparams.distance = 0.0f;
diff --git a/third_party/jpeg-xl/lib/jxl/splines.cc b/third_party/jpeg-xl/lib/jxl/splines.cc
index acbaf38428..1d4fc69e3e 100644
--- a/third_party/jpeg-xl/lib/jxl/splines.cc
+++ b/third_party/jpeg-xl/lib/jxl/splines.cc
@@ -40,7 +40,7 @@ using hwy::HWY_NAMESPACE::Sub;
// Given a set of DCT coefficients, this returns the result of performing cosine
// interpolation on the original samples.
-float ContinuousIDCT(const float dct[32], const float t) {
+float ContinuousIDCT(const Dct32& dct, const float t) {
// We compute here the DCT-3 of the `dct` vector, rescaled by a factor of
// sqrt(32). This is such that an input vector vector {x, 0, ..., 0} produces
// a constant result of x. dct[0] was scaled in Dequantize() to allow uniform
@@ -60,7 +60,7 @@ float ContinuousIDCT(const float dct[32], const float t) {
for (int i = 0; i < 32; i += Lanes(df)) {
auto cos_arg = Mul(LoadU(df, kMultipliers + i), tandhalf);
auto cos = FastCosf(df, cos_arg);
- auto local_res = Mul(LoadU(df, dct + i), cos);
+ auto local_res = Mul(LoadU(df, dct.data() + i), cos);
result = MulAdd(Set(df, kSqrt2), local_res, result);
}
return GetLane(SumOfLanes(df, result));
@@ -140,8 +140,9 @@ void ComputeSegments(const Spline::Point& center, const float intensity,
segment.inv_sigma = 1.0f / sigma;
segment.sigma_over_4_times_intensity = .25f * sigma * intensity;
segment.maximum_distance = maximum_distance;
- ssize_t y0 = center.y - maximum_distance + .5f;
- ssize_t y1 = center.y + maximum_distance + 1.5f; // one-past-the-end
+ ssize_t y0 = std::llround(center.y - maximum_distance);
+ ssize_t y1 =
+ std::llround(center.y + maximum_distance) + 1; // one-past-the-end
for (ssize_t y = std::max<ssize_t>(y0, 0); y < y1; y++) {
segments_by_y.emplace_back(y, segments.size());
}
@@ -227,7 +228,7 @@ float InvAdjustedQuant(const int32_t adjustment) {
}
// X, Y, B, sigma.
-static constexpr float kChannelWeight[] = {0.0042f, 0.075f, 0.07f, .3333f};
+constexpr float kChannelWeight[] = {0.0042f, 0.075f, 0.07f, .3333f};
Status DecodeAllStartingPoints(std::vector<Spline::Point>* const points,
BitReader* const br, ANSSymbolReader* reader,
@@ -366,7 +367,8 @@ QuantizedSpline::QuantizedSpline(const Spline& original,
const Spline::Point& starting_point = original.control_points.front();
int previous_x = static_cast<int>(std::roundf(starting_point.x));
int previous_y = static_cast<int>(std::roundf(starting_point.y));
- int previous_delta_x = 0, previous_delta_y = 0;
+ int previous_delta_x = 0;
+ int previous_delta_y = 0;
for (auto it = original.control_points.begin() + 1;
it != original.control_points.end(); ++it) {
const int new_x = static_cast<int>(std::roundf(it->x));
@@ -426,9 +428,10 @@ Status QuantizedSpline::Dequantize(const Spline::Point& starting_point,
JXL_RETURN_IF_ERROR(ValidateSplinePointPos(px, py));
int current_x = static_cast<int>(px);
int current_y = static_cast<int>(py);
- result.control_points.push_back(Spline::Point{static_cast<float>(current_x),
- static_cast<float>(current_y)});
- int current_delta_x = 0, current_delta_y = 0;
+ result.control_points.emplace_back(static_cast<float>(current_x),
+ static_cast<float>(current_y));
+ int current_delta_x = 0;
+ int current_delta_y = 0;
uint64_t manhattan_distance = 0;
for (const auto& point : control_points_) {
current_delta_x += point.first;
@@ -443,8 +446,8 @@ Status QuantizedSpline::Dequantize(const Spline::Point& starting_point,
current_x += current_delta_x;
current_y += current_delta_y;
JXL_RETURN_IF_ERROR(ValidateSplinePointPos(current_x, current_y));
- result.control_points.push_back(Spline::Point{
- static_cast<float>(current_x), static_cast<float>(current_y)});
+ result.control_points.emplace_back(static_cast<float>(current_x),
+ static_cast<float>(current_y));
}
const auto inv_quant = InvAdjustedQuant(quantization_adjustment);
@@ -605,15 +608,15 @@ Status Splines::Decode(jxl::BitReader* br, const size_t num_pixels) {
void Splines::AddTo(Image3F* const opsin, const Rect& opsin_rect,
const Rect& image_rect) const {
- return Apply</*add=*/true>(opsin, opsin_rect, image_rect);
+ Apply</*add=*/true>(opsin, opsin_rect, image_rect);
}
void Splines::AddToRow(float* JXL_RESTRICT row_x, float* JXL_RESTRICT row_y,
float* JXL_RESTRICT row_b, const Rect& image_row) const {
- return ApplyToRow</*add=*/true>(row_x, row_y, row_b, image_row);
+ ApplyToRow</*add=*/true>(row_x, row_y, row_b, image_row);
}
void Splines::SubtractFrom(Image3F* const opsin) const {
- return Apply</*add=*/false>(opsin, Rect(*opsin), Rect(*opsin));
+ Apply</*add=*/false>(opsin, Rect(*opsin), Rect(*opsin));
}
Status Splines::InitializeDrawCache(const size_t image_xsize,
@@ -646,8 +649,9 @@ Status Splines::InitializeDrawCache(const size_t image_xsize,
}
// TODO(firsching) Change this into a JXL_FAILURE for level 5 codestreams.
if (total_estimated_area_reached >
- std::min((8 * image_xsize * image_ysize + (uint64_t(1) << 25)),
- (uint64_t(1) << 30))) {
+ std::min(
+ (8 * image_xsize * image_ysize + (static_cast<uint64_t>(1) << 25)),
+ (static_cast<uint64_t>(1) << 30))) {
JXL_WARNING(
"Large total_estimated_area_reached, expect slower decoding: %" PRIu64,
total_estimated_area_reached);
diff --git a/third_party/jpeg-xl/lib/jxl/splines.h b/third_party/jpeg-xl/lib/jxl/splines.h
index acdd0857d0..af51ec937e 100644
--- a/third_party/jpeg-xl/lib/jxl/splines.h
+++ b/third_party/jpeg-xl/lib/jxl/splines.h
@@ -6,6 +6,7 @@
#ifndef LIB_JXL_SPLINES_H_
#define LIB_JXL_SPLINES_H_
+#include <array>
#include <cmath>
#include <cstddef>
#include <cstdint>
@@ -24,6 +25,8 @@ class BitReader;
static constexpr float kDesiredRenderingDistance = 1.f;
+typedef std::array<float, 32> Dct32;
+
enum SplineEntropyContexts : size_t {
kQuantizationAdjustmentContext = 0,
kStartingPositionContext,
@@ -45,10 +48,10 @@ struct Spline {
};
std::vector<Point> control_points;
// X, Y, B.
- float color_dct[3][32];
+ std::array<Dct32, 3> color_dct;
// Splines are draws by normalized Gaussian splatting. This controls the
// Gaussian's parameter along the spline.
- float sigma_dct[32];
+ Dct32 sigma_dct;
};
class QuantizedSplineEncoder;
diff --git a/third_party/jpeg-xl/lib/jxl/splines_gbench.cc b/third_party/jpeg-xl/lib/jxl/splines_gbench.cc
index 78ff6d41c0..903c5b6328 100644
--- a/third_party/jpeg-xl/lib/jxl/splines_gbench.cc
+++ b/third_party/jpeg-xl/lib/jxl/splines_gbench.cc
@@ -3,7 +3,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <array>
+
#include "benchmark/benchmark.h"
+#include "lib/jxl/image_ops.h"
#include "lib/jxl/splines.h"
namespace jxl {
@@ -17,12 +20,14 @@ const float kYToB = cmap->YtoBRatio(0);
void BM_Splines(benchmark::State& state) {
const size_t n = state.range();
- std::vector<Spline> spline_data = {
- {/*control_points=*/{
- {9, 54}, {118, 159}, {97, 3}, {10, 40}, {150, 25}, {120, 300}},
- /*color_dct=*/
- {{0.03125f, 0.00625f, 0.003125f}, {1.f, 0.321875f}, {1.f, 0.24375f}},
- /*sigma_dct=*/{0.3125f, 0.f, 0.f, 0.0625f}}};
+ Spline spline1{
+ /*control_points=*/{
+ {9, 54}, {118, 159}, {97, 3}, {10, 40}, {150, 25}, {120, 300}},
+ /*color_dct=*/
+ {Dct32{0.03125f, 0.00625f, 0.003125f}, Dct32{1.f, 0.321875f},
+ Dct32{1.f, 0.24375f}},
+ /*sigma_dct=*/{0.3125f, 0.f, 0.f, 0.0625f}};
+ std::vector<Spline> spline_data = {spline1};
std::vector<QuantizedSpline> quantized_splines;
std::vector<Spline::Point> starting_points;
for (const Spline& spline : spline_data) {
@@ -33,7 +38,7 @@ void BM_Splines(benchmark::State& state) {
Splines splines(kQuantizationAdjustment, std::move(quantized_splines),
std::move(starting_points));
- Image3F drawing_area(320, 320);
+ JXL_ASSIGN_OR_DIE(Image3F drawing_area, Image3F::Create(320, 320));
ZeroFillImage(&drawing_area);
for (auto _ : state) {
for (size_t i = 0; i < n; ++i) {
diff --git a/third_party/jpeg-xl/lib/jxl/splines_test.cc b/third_party/jpeg-xl/lib/jxl/splines_test.cc
index d812545a37..83cc524234 100644
--- a/third_party/jpeg-xl/lib/jxl/splines_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/splines_test.cc
@@ -23,7 +23,6 @@
#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_bit_writer.h"
-#include "lib/jxl/enc_params.h"
#include "lib/jxl/enc_splines.h"
#include "lib/jxl/image.h"
#include "lib/jxl/image_ops.h"
@@ -45,10 +44,6 @@ std::ostream& operator<<(std::ostream& os, const Spline& spline) {
namespace {
using test::ReadTestData;
-using ::testing::AllOf;
-using ::testing::Field;
-using ::testing::FloatNear;
-using ::testing::Pointwise;
constexpr int kQuantizationAdjustment = 0;
const ColorCorrelationMap* const cmap = new ColorCorrelationMap;
@@ -73,127 +68,75 @@ std::vector<Spline> DequantizeSplines(const Splines& splines) {
return dequantized;
}
-MATCHER(ControlPointIs, "") {
- const Spline::Point& actual = std::get<0>(arg);
- const Spline::Point& expected = std::get<1>(arg);
- return testing::ExplainMatchResult(
- AllOf(Field(&Spline::Point::x, FloatNear(expected.x, kTolerance)),
- Field(&Spline::Point::y, FloatNear(expected.y, kTolerance))),
- actual, result_listener);
-}
-
-MATCHER(ControlPointsMatch, "") {
- const Spline& actual = std::get<0>(arg);
- const Spline& expected = std::get<1>(arg);
- return testing::ExplainMatchResult(
- Field(&Spline::control_points,
- Pointwise(ControlPointIs(), expected.control_points)),
- actual, result_listener);
-}
-
-MATCHER(SplinesMatch, "") {
- const Spline& actual = std::get<0>(arg);
- const Spline& expected = std::get<1>(arg);
- if (!testing::ExplainMatchResult(ControlPointsMatch(), arg,
- result_listener)) {
- return false;
- }
- for (int i = 0; i < 3; ++i) {
- size_t color_dct_size =
- sizeof(expected.color_dct[i]) / sizeof(expected.color_dct[i][0]);
- for (size_t j = 0; j < color_dct_size; j++) {
- testing::StringMatchResultListener color_dct_listener;
- if (!testing::ExplainMatchResult(
- FloatNear(expected.color_dct[i][j], kTolerance),
- actual.color_dct[i][j], &color_dct_listener)) {
- *result_listener << ", where color_dct[" << i << "][" << j
- << "] don't match, " << color_dct_listener.str();
- return false;
- }
- }
- }
- size_t sigma_dct_size =
- sizeof(expected.sigma_dct) / sizeof(expected.sigma_dct[0]);
- for (size_t i = 0; i < sigma_dct_size; i++) {
- testing::StringMatchResultListener sigma_listener;
- if (!testing::ExplainMatchResult(
- FloatNear(expected.sigma_dct[i], kTolerance), actual.sigma_dct[i],
- &sigma_listener)) {
- *result_listener << ", where sigma_dct[" << i << "] don't match, "
- << sigma_listener.str();
- return false;
- }
- }
- return true;
-}
-
} // namespace
TEST(SplinesTest, Serialization) {
- std::vector<Spline> spline_data = {
- {/*control_points=*/{
- {109, 54}, {218, 159}, {80, 3}, {110, 274}, {94, 185}, {17, 277}},
- /*color_dct=*/
- {{36.3, 39.7, 23.2, 67.5, 4.4, 71.5, 62.3, 32.3, 92.2, 10.1, 10.8,
- 9.2, 6.1, 10.5, 79.1, 7, 24.6, 90.8, 5.5, 84, 43.8, 49,
- 33.5, 78.9, 54.5, 77.9, 62.1, 51.4, 36.4, 14.3, 83.7, 35.4},
- {9.4, 53.4, 9.5, 74.9, 72.7, 26.7, 7.9, 0.9, 84.9, 23.2, 26.5,
- 31.1, 91, 11.7, 74.1, 39.3, 23.7, 82.5, 4.8, 2.7, 61.2, 96.4,
- 13.7, 66.7, 62.9, 82.4, 5.9, 98.7, 21.5, 7.9, 51.7, 63.1},
- {48, 39.3, 6.9, 26.3, 33.3, 6.2, 1.7, 98.9, 59.9, 59.6, 95,
- 61.3, 82.7, 53, 6.1, 30.4, 34.7, 96.9, 93.4, 17, 38.8, 80.8,
- 63, 18.6, 43.6, 32.3, 61, 20.2, 24.3, 28.3, 69.1, 62.4}},
- /*sigma_dct=*/{32.7, 21.5, 44.4, 1.8, 45.8, 90.6, 29.3, 59.2,
- 23.7, 85.2, 84.8, 27.2, 42.1, 84.1, 50.6, 17.6,
- 93.7, 4.9, 2.6, 69.8, 94.9, 52, 24.3, 18.8,
- 12.1, 95.7, 28.5, 81.4, 89.9, 31.4, 74.8, 52}},
- {/*control_points=*/{{172, 309},
- {196, 277},
- {42, 238},
- {114, 350},
- {307, 290},
- {316, 269},
- {124, 66},
- {233, 267}},
- /*color_dct=*/
- {{15, 28.9, 22, 6.6, 41.8, 83, 8.6, 56.8, 68.9, 9.7, 5.4,
- 19.8, 70.8, 90, 52.5, 65.2, 7.8, 23.5, 26.4, 72.2, 64.7, 87.1,
- 1.3, 67.5, 46, 68.4, 65.4, 35.5, 29.1, 13, 41.6, 23.9},
- {47.7, 79.4, 62.7, 29.1, 96.8, 18.5, 17.6, 15.2, 80.5, 56, 96.2,
- 59.9, 26.7, 96.1, 92.3, 42.1, 35.8, 54, 23.2, 55, 76, 35.8,
- 58.4, 88.7, 2.4, 78.1, 95.6, 27.5, 6.6, 78.5, 24.1, 69.8},
- {43.8, 96.5, 0.9, 95.1, 49.1, 71.2, 25.1, 33.6, 75.2, 95, 82.1,
- 19.7, 10.5, 44.9, 50, 93.3, 83.5, 99.5, 64.6, 54, 3.5, 99.7,
- 45.3, 82.1, 22.4, 37.9, 60, 32.2, 12.6, 4.6, 65.5, 96.4}},
- /*sigma_dct=*/{72.5, 2.6, 41.7, 2.2, 39.7, 79.1, 69.6, 19.9,
- 92.3, 71.5, 41.9, 62.1, 30, 49.4, 70.3, 45.3,
- 62.5, 47.2, 46.7, 41.2, 90.8, 46.8, 91.2, 55,
- 8.1, 69.6, 25.4, 84.7, 61.7, 27.6, 3.7, 46.9}},
- {/*control_points=*/{{100, 186},
- {257, 97},
- {170, 49},
- {25, 169},
- {309, 104},
- {232, 237},
- {385, 101},
- {122, 168},
- {26, 300},
- {390, 88}},
- /*color_dct=*/
- {{16.9, 64.8, 4.2, 10.6, 23.5, 17, 79.3, 5.7, 60.4, 16.6, 94.9,
- 63.7, 87.6, 10.5, 3.8, 61.1, 22.9, 81.9, 80.4, 40.5, 45.9, 25.4,
- 39.8, 30, 50.2, 90.4, 27.9, 93.7, 65.1, 48.2, 22.3, 43.9},
- {24.9, 66, 3.5, 90.2, 97.1, 15.8, 35.6, 0.6, 68, 39.6, 24.4,
- 85.9, 57.7, 77.6, 47.5, 67.9, 4.3, 5.4, 91.2, 58.5, 0.1, 52.2,
- 3.5, 47.8, 63.2, 43.5, 85.8, 35.8, 50.2, 35.9, 19.2, 48.2},
- {82.8, 44.9, 76.4, 39.5, 94.1, 14.3, 89.8, 10, 10.5, 74.5, 56.3,
- 65.8, 7.8, 23.3, 52.8, 99.3, 56.8, 46, 76.7, 13.5, 67, 22.4,
- 29.9, 43.3, 70.3, 26, 74.3, 53.9, 62, 19.1, 49.3, 46.7}},
- /*sigma_dct=*/{83.5, 1.7, 25.1, 18.7, 46.5, 75.3, 28, 62.3,
- 50.3, 23.3, 85.6, 96, 45.8, 33.1, 33.4, 52.9,
- 26.3, 58.5, 19.6, 70, 92.6, 22.5, 57, 21.6,
- 76.8, 87.5, 22.9, 66.3, 35.7, 35.6, 56.8, 67.2}},
- };
+ Spline spline1{
+ /*control_points=*/{
+ {109, 54}, {218, 159}, {80, 3}, {110, 274}, {94, 185}, {17, 277}},
+ /*color_dct=*/
+ {Dct32{36.3, 39.7, 23.2, 67.5, 4.4, 71.5, 62.3, 32.3, 92.2, 10.1, 10.8,
+ 9.2, 6.1, 10.5, 79.1, 7, 24.6, 90.8, 5.5, 84, 43.8, 49,
+ 33.5, 78.9, 54.5, 77.9, 62.1, 51.4, 36.4, 14.3, 83.7, 35.4},
+ Dct32{9.4, 53.4, 9.5, 74.9, 72.7, 26.7, 7.9, 0.9, 84.9, 23.2, 26.5,
+ 31.1, 91, 11.7, 74.1, 39.3, 23.7, 82.5, 4.8, 2.7, 61.2, 96.4,
+ 13.7, 66.7, 62.9, 82.4, 5.9, 98.7, 21.5, 7.9, 51.7, 63.1},
+ Dct32{48, 39.3, 6.9, 26.3, 33.3, 6.2, 1.7, 98.9, 59.9, 59.6, 95,
+ 61.3, 82.7, 53, 6.1, 30.4, 34.7, 96.9, 93.4, 17, 38.8, 80.8,
+ 63, 18.6, 43.6, 32.3, 61, 20.2, 24.3, 28.3, 69.1, 62.4}},
+ /*sigma_dct=*/{32.7, 21.5, 44.4, 1.8, 45.8, 90.6, 29.3, 59.2,
+ 23.7, 85.2, 84.8, 27.2, 42.1, 84.1, 50.6, 17.6,
+ 93.7, 4.9, 2.6, 69.8, 94.9, 52, 24.3, 18.8,
+ 12.1, 95.7, 28.5, 81.4, 89.9, 31.4, 74.8, 52}};
+ Spline spline2{
+ /*control_points=*/{{172, 309},
+ {196, 277},
+ {42, 238},
+ {114, 350},
+ {307, 290},
+ {316, 269},
+ {124, 66},
+ {233, 267}},
+ /*color_dct=*/
+ {Dct32{15, 28.9, 22, 6.6, 41.8, 83, 8.6, 56.8, 68.9, 9.7, 5.4,
+ 19.8, 70.8, 90, 52.5, 65.2, 7.8, 23.5, 26.4, 72.2, 64.7, 87.1,
+ 1.3, 67.5, 46, 68.4, 65.4, 35.5, 29.1, 13, 41.6, 23.9},
+ Dct32{47.7, 79.4, 62.7, 29.1, 96.8, 18.5, 17.6, 15.2, 80.5, 56, 96.2,
+ 59.9, 26.7, 96.1, 92.3, 42.1, 35.8, 54, 23.2, 55, 76, 35.8,
+ 58.4, 88.7, 2.4, 78.1, 95.6, 27.5, 6.6, 78.5, 24.1, 69.8},
+ Dct32{43.8, 96.5, 0.9, 95.1, 49.1, 71.2, 25.1, 33.6, 75.2, 95, 82.1,
+ 19.7, 10.5, 44.9, 50, 93.3, 83.5, 99.5, 64.6, 54, 3.5, 99.7,
+ 45.3, 82.1, 22.4, 37.9, 60, 32.2, 12.6, 4.6, 65.5, 96.4}},
+ /*sigma_dct=*/{72.5, 2.6, 41.7, 2.2, 39.7, 79.1, 69.6, 19.9,
+ 92.3, 71.5, 41.9, 62.1, 30, 49.4, 70.3, 45.3,
+ 62.5, 47.2, 46.7, 41.2, 90.8, 46.8, 91.2, 55,
+ 8.1, 69.6, 25.4, 84.7, 61.7, 27.6, 3.7, 46.9}};
+ Spline spline3{
+ /*control_points=*/{{100, 186},
+ {257, 97},
+ {170, 49},
+ {25, 169},
+ {309, 104},
+ {232, 237},
+ {385, 101},
+ {122, 168},
+ {26, 300},
+ {390, 88}},
+ /*color_dct=*/
+ {Dct32{16.9, 64.8, 4.2, 10.6, 23.5, 17, 79.3, 5.7, 60.4, 16.6, 94.9,
+ 63.7, 87.6, 10.5, 3.8, 61.1, 22.9, 81.9, 80.4, 40.5, 45.9, 25.4,
+ 39.8, 30, 50.2, 90.4, 27.9, 93.7, 65.1, 48.2, 22.3, 43.9},
+ Dct32{24.9, 66, 3.5, 90.2, 97.1, 15.8, 35.6, 0.6, 68, 39.6, 24.4,
+ 85.9, 57.7, 77.6, 47.5, 67.9, 4.3, 5.4, 91.2, 58.5, 0.1, 52.2,
+ 3.5, 47.8, 63.2, 43.5, 85.8, 35.8, 50.2, 35.9, 19.2, 48.2},
+ Dct32{82.8, 44.9, 76.4, 39.5, 94.1, 14.3, 89.8, 10, 10.5, 74.5, 56.3,
+ 65.8, 7.8, 23.3, 52.8, 99.3, 56.8, 46, 76.7, 13.5, 67, 22.4,
+ 29.9, 43.3, 70.3, 26, 74.3, 53.9, 62, 19.1, 49.3, 46.7}},
+ /*sigma_dct=*/{83.5, 1.7, 25.1, 18.7, 46.5, 75.3, 28, 62.3,
+ 50.3, 23.3, 85.6, 96, 45.8, 33.1, 33.4, 52.9,
+ 26.3, 58.5, 19.6, 70, 92.6, 22.5, 57, 21.6,
+ 76.8, 87.5, 22.9, 66.3, 35.7, 35.6, 56.8, 67.2}};
+ std::vector<Spline> spline_data{spline1, spline2, spline3};
std::vector<QuantizedSpline> quantized_splines;
std::vector<Spline::Point> starting_points;
@@ -206,8 +149,20 @@ TEST(SplinesTest, Serialization) {
Splines splines(kQuantizationAdjustment, std::move(quantized_splines),
std::move(starting_points));
const std::vector<Spline> quantized_spline_data = DequantizeSplines(splines);
- EXPECT_THAT(quantized_spline_data,
- Pointwise(ControlPointsMatch(), spline_data));
+ EXPECT_EQ(quantized_spline_data.size(), spline_data.size());
+ for (size_t i = 0; i < quantized_spline_data.size(); ++i) {
+ const Spline& actual = quantized_spline_data[i];
+ const Spline& expected = spline_data[i];
+ const auto& actual_points = actual.control_points;
+ const auto& expected_points = expected.control_points;
+ EXPECT_EQ(actual_points.size(), expected_points.size());
+ for (size_t j = 0; j < actual_points.size(); ++j) {
+ EXPECT_NEAR(actual_points[j].x, expected_points[j].x, kTolerance)
+ << "spline " << i << " point " << j;
+ EXPECT_NEAR(actual_points[j].y, expected_points[j].y, kTolerance)
+ << "spline " << i << " point " << j;
+ }
+ }
BitWriter writer;
EncodeSplines(splines, &writer, kLayerSplines, HistogramParams(), nullptr);
@@ -225,8 +180,28 @@ TEST(SplinesTest, Serialization) {
const std::vector<Spline> decoded_spline_data =
DequantizeSplines(decoded_splines);
- EXPECT_THAT(decoded_spline_data,
- Pointwise(SplinesMatch(), quantized_spline_data));
+
+ EXPECT_EQ(decoded_spline_data.size(), quantized_spline_data.size());
+ for (size_t i = 0; i < decoded_spline_data.size(); ++i) {
+ const Spline& actual = decoded_spline_data[i];
+ const Spline& expected = quantized_spline_data[i];
+ const auto& actual_points = actual.control_points;
+ const auto& expected_points = expected.control_points;
+ EXPECT_EQ(actual_points.size(), expected_points.size());
+ for (size_t j = 0; j < actual_points.size(); ++j) {
+ EXPECT_NEAR(actual_points[j].x, expected_points[j].x, kTolerance)
+ << "spline " << i << " point " << j;
+ EXPECT_NEAR(actual_points[j].y, expected_points[j].y, kTolerance)
+ << "spline " << i << " point " << j;
+ }
+
+ const auto& actual_color_dct = actual.color_dct;
+ const auto& expected_color_dct = expected.color_dct;
+ for (size_t j = 0; j < actual_color_dct.size(); ++j) {
+ EXPECT_ARRAY_NEAR(actual_color_dct[j], expected_color_dct[j], kTolerance);
+ }
+ EXPECT_ARRAY_NEAR(actual.sigma_dct, expected.sigma_dct, kTolerance);
+ }
}
#ifdef JXL_CRASH_ON_ERROR
@@ -240,10 +215,10 @@ TEST(SplinesTest, TooManySplinesTest) {
std::vector<QuantizedSpline> quantized_splines;
std::vector<Spline::Point> starting_points;
for (size_t i = 0; i < kNumSplines; i++) {
- Spline spline = {
+ Spline spline{
/*control_points=*/{{1.f + i, 2}, {10.f + i, 25}, {30.f + i, 300}},
/*color_dct=*/
- {{1.f, 0.2f, 0.1f}, {35.7f, 10.3f}, {35.7f, 7.8f}},
+ {Dct32{1.f, 0.2f, 0.1f}, Dct32{35.7f, 10.3f}, Dct32{35.7f, 7.8f}},
/*sigma_dct=*/{10.f, 0.f, 0.f, 2.f}};
quantized_splines.emplace_back(spline, kQuantizationAdjustment, kYToX,
kYToB);
@@ -271,10 +246,11 @@ TEST(SplinesTest, DuplicatePoints) {
std::vector<Spline::Point> control_points{
{9, 54}, {118, 159}, {97, 3}, // Repeated.
{97, 3}, {10, 40}, {150, 25}, {120, 300}};
- Spline spline{control_points,
- /*color_dct=*/
- {{1.f, 0.2f, 0.1f}, {35.7f, 10.3f}, {35.7f, 7.8f}},
- /*sigma_dct=*/{10.f, 0.f, 0.f, 2.f}};
+ Spline spline{
+ control_points,
+ /*color_dct=*/
+ {Dct32{1.f, 0.2f, 0.1f}, Dct32{35.7f, 10.3f}, Dct32{35.7f, 7.8f}},
+ /*sigma_dct=*/{10.f, 0.f, 0.f, 2.f}};
std::vector<Spline> spline_data{spline};
std::vector<QuantizedSpline> quantized_splines;
std::vector<Spline::Point> starting_points;
@@ -286,7 +262,7 @@ TEST(SplinesTest, DuplicatePoints) {
Splines splines(kQuantizationAdjustment, std::move(quantized_splines),
std::move(starting_points));
- Image3F image(320, 320);
+ JXL_ASSIGN_OR_DIE(Image3F image, Image3F::Create(320, 320));
ZeroFillImage(&image);
EXPECT_FALSE(
splines.InitializeDrawCache(image.xsize(), image.ysize(), *cmap));
@@ -304,10 +280,10 @@ TEST(SplinesTest, Drawing) {
const Spline spline{
control_points,
/*color_dct=*/
- {{0.4989345073699951171875000f, 0.4997999966144561767578125f},
- {0.4772970676422119140625000f, 0.f, 0.5250000357627868652343750f},
- {-0.0176776945590972900390625f, 0.4900000095367431640625000f,
- 0.5250000357627868652343750f}},
+ {Dct32{0.4989345073699951171875000f, 0.4997999966144561767578125f},
+ Dct32{0.4772970676422119140625000f, 0.f, 0.5250000357627868652343750f},
+ Dct32{-0.0176776945590972900390625f, 0.4900000095367431640625000f,
+ 0.5250000357627868652343750f}},
/*sigma_dct=*/
{0.9427147507667541503906250f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.6665999889373779296875000f}};
@@ -322,13 +298,13 @@ TEST(SplinesTest, Drawing) {
Splines splines(kQuantizationAdjustment, std::move(quantized_splines),
std::move(starting_points));
- Image3F image(320, 320);
+ JXL_ASSIGN_OR_DIE(Image3F image, Image3F::Create(320, 320));
ZeroFillImage(&image);
ASSERT_TRUE(splines.InitializeDrawCache(image.xsize(), image.ysize(), *cmap));
splines.AddTo(&image, Rect(image), Rect(image));
CodecInOut io_actual;
- Image3F image2(320, 320);
+ JXL_ASSIGN_OR_DIE(Image3F image2, Image3F::Create(320, 320));
CopyImageTo(image, &image2);
io_actual.SetFromImage(std::move(image2), ColorEncoding::SRGB());
ASSERT_TRUE(io_actual.frames[0].TransformTo(io_expected.Main().c_current(),
diff --git a/third_party/jpeg-xl/lib/jxl/test_image.cc b/third_party/jpeg-xl/lib/jxl/test_image.cc
index 098e9c25a1..42f028d53a 100644
--- a/third_party/jpeg-xl/lib/jxl/test_image.cc
+++ b/third_party/jpeg-xl/lib/jxl/test_image.cc
@@ -323,7 +323,7 @@ TestImage& TestImage::SetColorEncoding(const std::string& description) {
}
TestImage& TestImage::CoalesceGIFAnimationWithAlpha() {
- extras::PackedFrame canvas = ppf_.frames[0].Copy();
+ JXL_ASSIGN_OR_DIE(extras::PackedFrame canvas, ppf_.frames[0].Copy());
JXL_CHECK(canvas.color.format.num_channels == 3);
JXL_CHECK(canvas.color.format.data_type == JXL_TYPE_UINT8);
JXL_CHECK(canvas.extra_channels.size() == 1);
@@ -331,7 +331,7 @@ TestImage& TestImage::CoalesceGIFAnimationWithAlpha() {
const extras::PackedFrame& frame = ppf_.frames[i];
JXL_CHECK(frame.extra_channels.size() == 1);
const JxlLayerInfo& layer_info = frame.frame_info.layer_info;
- extras::PackedFrame rendered = canvas.Copy();
+ JXL_ASSIGN_OR_DIE(extras::PackedFrame rendered, canvas.Copy());
uint8_t* pixels_rendered =
reinterpret_cast<uint8_t*>(rendered.color.pixels());
const uint8_t* pixels_frame =
@@ -353,7 +353,7 @@ TestImage& TestImage::CoalesceGIFAnimationWithAlpha() {
}
}
if (layer_info.save_as_reference != 0) {
- canvas = rendered.Copy();
+ JXL_ASSIGN_OR_DIE(canvas, rendered.Copy());
}
ppf_.frames[i] = std::move(rendered);
}
@@ -393,10 +393,14 @@ void TestImage::Frame::SetValue(size_t y, size_t x, size_t c, float val) {
TestImage::Frame TestImage::AddFrame() {
size_t index = ppf_.frames.size();
- extras::PackedFrame frame(ppf_.info.xsize, ppf_.info.ysize, format_);
+ JXL_ASSIGN_OR_DIE(
+ extras::PackedFrame frame,
+ extras::PackedFrame::Create(ppf_.info.xsize, ppf_.info.ysize, format_));
for (size_t i = 0; i < ppf_.extra_channels_info.size(); ++i) {
JxlPixelFormat ec_format = {1, format_.data_type, format_.endianness, 0};
- extras::PackedImage image(ppf_.info.xsize, ppf_.info.ysize, ec_format);
+ JXL_ASSIGN_OR_DIE(extras::PackedImage image,
+ extras::PackedImage::Create(ppf_.info.xsize,
+ ppf_.info.ysize, ec_format));
frame.extra_channels.emplace_back(std::move(image));
}
ppf_.frames.emplace_back(std::move(frame));
@@ -404,10 +408,12 @@ TestImage::Frame TestImage::AddFrame() {
}
TestImage::Frame TestImage::AddPreview(size_t xsize, size_t ysize) {
- extras::PackedFrame frame(xsize, ysize, format_);
+ JXL_ASSIGN_OR_DIE(extras::PackedFrame frame,
+ extras::PackedFrame::Create(xsize, ysize, format_));
for (size_t i = 0; i < ppf_.extra_channels_info.size(); ++i) {
JxlPixelFormat ec_format = {1, format_.data_type, format_.endianness, 0};
- extras::PackedImage image(xsize, ysize, ec_format);
+ JXL_ASSIGN_OR_DIE(extras::PackedImage image,
+ extras::PackedImage::Create(xsize, ysize, ec_format));
frame.extra_channels.emplace_back(std::move(image));
}
ppf_.preview_frame = make_unique<extras::PackedFrame>(std::move(frame));
diff --git a/third_party/jpeg-xl/lib/jxl/test_utils.cc b/third_party/jpeg-xl/lib/jxl/test_utils.cc
index 451f2a0a03..308efb9a13 100644
--- a/third_party/jpeg-xl/lib/jxl/test_utils.cc
+++ b/third_party/jpeg-xl/lib/jxl/test_utils.cc
@@ -228,7 +228,7 @@ bool Roundtrip(const CodecInOut* io, const CompressParams& cparams,
}
size_t Roundtrip(const extras::PackedPixelFile& ppf_in,
- extras::JXLCompressParams cparams,
+ const extras::JXLCompressParams& cparams,
extras::JXLDecompressParams dparams, ThreadPool* pool,
extras::PackedPixelFile* ppf_out) {
DefaultAcceptedFormats(dparams);
@@ -303,12 +303,12 @@ bool Near(double expected, double value, double max_dist) {
float LoadLEFloat16(const uint8_t* p) {
uint16_t bits16 = LoadLE16(p);
- return LoadFloat16(bits16);
+ return detail::LoadFloat16(bits16);
}
float LoadBEFloat16(const uint8_t* p) {
uint16_t bits16 = LoadBE16(p);
- return LoadFloat16(bits16);
+ return detail::LoadFloat16(bits16);
}
size_t GetPrecision(JxlDataType data_type) {
@@ -385,7 +385,10 @@ std::vector<double> ConvertToRGBA32(const uint8_t* pixels, size_t xsize,
for (size_t x = 0; x < xsize; ++x) {
size_t j = (y * xsize + x) * 4;
size_t i = y * stride + x * num_channels * 2;
- double r, g, b, a;
+ double r;
+ double g;
+ double b;
+ double a;
if (endianness == JXL_BIG_ENDIAN) {
r = (pixels[i + 0] << 8) + pixels[i + 1];
g = gray ? r : (pixels[i + 2] << 8) + pixels[i + 3];
@@ -413,7 +416,10 @@ std::vector<double> ConvertToRGBA32(const uint8_t* pixels, size_t xsize,
for (size_t x = 0; x < xsize; ++x) {
size_t j = (y * xsize + x) * 4;
size_t i = y * stride + x * num_channels * 4;
- double r, g, b, a;
+ double r;
+ double g;
+ double b;
+ double a;
if (endianness == JXL_BIG_ENDIAN) {
r = LoadBEFloat(pixels + i);
g = gray ? r : LoadBEFloat(pixels + i + 4);
@@ -437,7 +443,10 @@ std::vector<double> ConvertToRGBA32(const uint8_t* pixels, size_t xsize,
for (size_t x = 0; x < xsize; ++x) {
size_t j = (y * xsize + x) * 4;
size_t i = y * stride + x * num_channels * 2;
- double r, g, b, a;
+ double r;
+ double g;
+ double b;
+ double a;
if (endianness == JXL_BIG_ENDIAN) {
r = LoadBEFloat16(pixels + i);
g = gray ? r : LoadBEFloat16(pixels + i + 2);
@@ -470,8 +479,8 @@ size_t ComparePixels(const uint8_t* a, const uint8_t* b, size_t xsize,
std::vector<double> b_full = ConvertToRGBA32(b, xsize, ysize, format_b);
bool gray_a = format_a.num_channels < 3;
bool gray_b = format_b.num_channels < 3;
- bool alpha_a = !(format_a.num_channels & 1);
- bool alpha_b = !(format_b.num_channels & 1);
+ bool alpha_a = ((format_a.num_channels & 1) == 0);
+ bool alpha_b = ((format_b.num_channels & 1) == 0);
size_t bits_a = GetPrecision(format_a.data_type);
size_t bits_b = GetPrecision(format_b.data_type);
size_t bits = std::min(bits_a, bits_b);
@@ -558,6 +567,34 @@ float ButteraugliDistance(const extras::PackedPixelFile& a,
/*distmap=*/nullptr, pool);
}
+float ButteraugliDistance(const ImageBundle& rgb0, const ImageBundle& rgb1,
+ const ButteraugliParams& params,
+ const JxlCmsInterface& cms, ImageF* distmap,
+ ThreadPool* pool, bool ignore_alpha) {
+ JxlButteraugliComparator comparator(params, cms);
+ float distance;
+ JXL_CHECK(ComputeScore(rgb0, rgb1, &comparator, cms, &distance, distmap, pool,
+ ignore_alpha));
+ return distance;
+}
+
+float ButteraugliDistance(const std::vector<ImageBundle>& frames0,
+ const std::vector<ImageBundle>& frames1,
+ const ButteraugliParams& params,
+ const JxlCmsInterface& cms, ImageF* distmap,
+ ThreadPool* pool) {
+ JxlButteraugliComparator comparator(params, cms);
+ JXL_ASSERT(frames0.size() == frames1.size());
+ float max_dist = 0.0f;
+ for (size_t i = 0; i < frames0.size(); ++i) {
+ float frame_score;
+ JXL_CHECK(ComputeScore(frames0[i], frames1[i], &comparator, cms,
+ &frame_score, distmap, pool));
+ max_dist = std::max(max_dist, frame_score);
+ }
+ return max_dist;
+}
+
float Butteraugli3Norm(const extras::PackedPixelFile& a,
const extras::PackedPixelFile& b, ThreadPool* pool) {
CodecInOut io0;
@@ -683,7 +720,7 @@ Status ReadICC(BitReader* JXL_RESTRICT reader,
PaddedBytes icc_buffer;
JXL_RETURN_IF_ERROR(icc_reader.Init(reader, output_limit));
JXL_RETURN_IF_ERROR(icc_reader.Process(reader, &icc_buffer));
- Bytes(icc_buffer).AppendTo(icc);
+ Bytes(icc_buffer).AppendTo(*icc);
return true;
}
@@ -787,7 +824,7 @@ Status EncodeFile(const CompressParams& params, const CodecInOut* io,
}
PaddedBytes output = std::move(writer).TakeBytes();
- Bytes(output).AppendTo(compressed);
+ Bytes(output).AppendTo(*compressed);
return true;
}
diff --git a/third_party/jpeg-xl/lib/jxl/test_utils.h b/third_party/jpeg-xl/lib/jxl/test_utils.h
index 6734380bf5..15057cc92d 100644
--- a/third_party/jpeg-xl/lib/jxl/test_utils.h
+++ b/third_party/jpeg-xl/lib/jxl/test_utils.h
@@ -18,13 +18,13 @@
#include <ostream>
#include <vector>
-#include "lib/extras/dec/decode.h"
#include "lib/extras/dec/jxl.h"
#include "lib/extras/enc/jxl.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
+#include "lib/jxl/butteraugli/butteraugli.h"
#include "lib/jxl/codec_in_out.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/enc_params.h"
@@ -63,9 +63,8 @@ void SetThreadParallelRunner(Params params, ThreadPool* pool) {
}
}
-Status DecodeFile(extras::JXLDecompressParams dparams,
- const Span<const uint8_t> file, CodecInOut* JXL_RESTRICT io,
- ThreadPool* pool = nullptr);
+Status DecodeFile(extras::JXLDecompressParams dparams, Span<const uint8_t> file,
+ CodecInOut* JXL_RESTRICT io, ThreadPool* pool = nullptr);
bool Roundtrip(const CodecInOut* io, const CompressParams& cparams,
extras::JXLDecompressParams dparams,
@@ -74,7 +73,7 @@ bool Roundtrip(const CodecInOut* io, const CompressParams& cparams,
// Returns compressed size [bytes].
size_t Roundtrip(const extras::PackedPixelFile& ppf_in,
- extras::JXLCompressParams cparams,
+ const extras::JXLCompressParams& cparams,
extras::JXLDecompressParams dparams, ThreadPool* pool,
extras::PackedPixelFile* ppf_out);
@@ -141,6 +140,18 @@ float ButteraugliDistance(const extras::PackedPixelFile& a,
const extras::PackedPixelFile& b,
ThreadPool* pool = nullptr);
+float ButteraugliDistance(const ImageBundle& rgb0, const ImageBundle& rgb1,
+ const ButteraugliParams& params,
+ const JxlCmsInterface& cms, ImageF* distmap = nullptr,
+ ThreadPool* pool = nullptr,
+ bool ignore_alpha = false);
+
+float ButteraugliDistance(const std::vector<ImageBundle>& frames0,
+ const std::vector<ImageBundle>& frames1,
+ const ButteraugliParams& params,
+ const JxlCmsInterface& cms, ImageF* distmap = nullptr,
+ ThreadPool* pool = nullptr);
+
float Butteraugli3Norm(const extras::PackedPixelFile& a,
const extras::PackedPixelFile& b,
ThreadPool* pool = nullptr);
@@ -169,6 +180,7 @@ class ThreadPoolForTests {
}
ThreadPoolForTests(const ThreadPoolForTests&) = delete;
ThreadPoolForTests& operator&(const ThreadPoolForTests&) = delete;
+ // TODO(eustas): avoid unary `&` overload?
ThreadPool* operator&() { return pool_.get(); }
private:
@@ -188,6 +200,8 @@ Status ReadICC(BitReader* JXL_RESTRICT reader,
Status EncodeFile(const CompressParams& params, const CodecInOut* io,
std::vector<uint8_t>* compressed, ThreadPool* pool = nullptr);
+constexpr const char* BoolToCStr(bool b) { return b ? "true" : "false"; }
+
} // namespace test
bool operator==(const jxl::Bytes& a, const jxl::Bytes& b);
diff --git a/third_party/jpeg-xl/lib/jxl/testing.h b/third_party/jpeg-xl/lib/jxl/testing.h
index 5344399c4c..1fac352a78 100644
--- a/third_party/jpeg-xl/lib/jxl/testing.h
+++ b/third_party/jpeg-xl/lib/jxl/testing.h
@@ -6,15 +6,7 @@
#ifndef LIB_JXL_TESTING_H_
#define LIB_JXL_TESTING_H_
-// GTest/GMock specific macros / wrappers.
-
-// gmock unconditionally redefines those macros (to wrong values).
-// Lets include it only here and mitigate the problem.
-#pragma push_macro("PRIdS")
-#pragma push_macro("PRIuS")
-#include "gmock/gmock.h"
-#pragma pop_macro("PRIuS")
-#pragma pop_macro("PRIdS")
+// GTest specific macros / wrappers.
#include "gtest/gtest.h"
// JPEGXL_ENABLE_BOXES, JPEGXL_ENABLE_TRANSCODE_JPEG
@@ -60,9 +52,26 @@
// Ensures that we don't make our test bounds too lax, effectively disabling the
// tests.
-MATCHER_P(IsSlightlyBelow, max, "") {
- return max * 0.75 <= arg && arg <= max * 1.0;
-}
+#define EXPECT_SLIGHTLY_BELOW(A, E) \
+ { \
+ double _actual = (A); \
+ double _expected = (E); \
+ EXPECT_LE(_actual, _expected); \
+ EXPECT_GE(_actual, 0.75 * _expected); \
+ }
+
+#define EXPECT_ARRAY_NEAR(A, E, T) \
+ { \
+ const auto _actual = (A); \
+ const auto _expected = (E); \
+ const auto _tolerance = (T); \
+ size_t _n = _expected.size(); \
+ ASSERT_EQ(_actual.size(), _n); \
+ for (size_t _i = 0; _i < _n; ++_i) { \
+ EXPECT_NEAR(_actual[_i], _expected[_i], _tolerance) \
+ << "@" << _i << ": " << _actual[_i] << " !~= " << _expected[_i]; \
+ } \
+ }
#define JXL_EXPECT_OK(F) \
{ \
diff --git a/third_party/jpeg-xl/lib/jxl/toc.h b/third_party/jpeg-xl/lib/jxl/toc.h
index 00006440b7..f5b9c65763 100644
--- a/third_party/jpeg-xl/lib/jxl/toc.h
+++ b/third_party/jpeg-xl/lib/jxl/toc.h
@@ -24,7 +24,7 @@ namespace jxl {
constexpr U32Enc kTocDist(Bits(10), BitsOffset(14, 1024), BitsOffset(22, 17408),
BitsOffset(30, 4211712));
-size_t MaxBits(const size_t num_sizes);
+size_t MaxBits(size_t num_sizes);
// TODO(veluca): move these to FrameDimensions.
static JXL_INLINE size_t AcGroupIndex(size_t pass, size_t group,
diff --git a/third_party/jpeg-xl/lib/jxl/transpose-inl.h b/third_party/jpeg-xl/lib/jxl/transpose-inl.h
index 4674420737..efe7d90569 100644
--- a/third_party/jpeg-xl/lib/jxl/transpose-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/transpose-inl.h
@@ -45,9 +45,9 @@ struct TransposeSimdTag {};
// TODO(veluca): it's not super useful to have this in the SIMD namespace.
template <size_t ROWS_or_0, size_t COLS_or_0, class From, class To>
-JXL_INLINE_TRANSPOSE void GenericTransposeBlock(TransposeSimdTag<false>,
- const From& from, const To& to,
- size_t ROWSp, size_t COLSp) {
+JXL_INLINE_TRANSPOSE void GenericTransposeBlock(
+ TransposeSimdTag<false> /* tag */, const From& from, const To& to,
+ size_t ROWSp, size_t COLSp) {
size_t ROWS = ROWS_or_0 == 0 ? ROWSp : ROWS_or_0;
size_t COLS = COLS_or_0 == 0 ? COLSp : COLS_or_0;
for (size_t n = 0; n < ROWS; ++n) {
@@ -64,9 +64,9 @@ constexpr bool TransposeUseSimd(size_t ROWS, size_t COLS) {
}
template <size_t ROWS_or_0, size_t COLS_or_0, class From, class To>
-JXL_INLINE_TRANSPOSE void GenericTransposeBlock(TransposeSimdTag<true>,
- const From& from, const To& to,
- size_t ROWSp, size_t COLSp) {
+JXL_INLINE_TRANSPOSE void GenericTransposeBlock(
+ TransposeSimdTag<true> /* tag */, const From& from, const To& to,
+ size_t ROWSp, size_t COLSp) {
size_t ROWS = ROWS_or_0 == 0 ? ROWSp : ROWS_or_0;
size_t COLS = COLS_or_0 == 0 ? COLSp : COLS_or_0;
static_assert(MaxLanes(BlockDesc<8>()) == 8, "Invalid descriptor size");
@@ -128,9 +128,9 @@ constexpr bool TransposeUseSimd(size_t ROWS, size_t COLS) {
}
template <size_t ROWS_or_0, size_t COLS_or_0, class From, class To>
-JXL_INLINE_TRANSPOSE void GenericTransposeBlock(TransposeSimdTag<true>,
- const From& from, const To& to,
- size_t ROWSp, size_t COLSp) {
+JXL_INLINE_TRANSPOSE void GenericTransposeBlock(
+ TransposeSimdTag<true> /* tag */, const From& from, const To& to,
+ size_t ROWSp, size_t COLSp) {
size_t ROWS = ROWS_or_0 == 0 ? ROWSp : ROWS_or_0;
size_t COLS = COLS_or_0 == 0 ? COLSp : COLS_or_0;
static_assert(MaxLanes(BlockDesc<4>()) == 4, "Invalid descriptor size");
diff --git a/third_party/jpeg-xl/lib/jxl/version.h.in b/third_party/jpeg-xl/lib/jxl/version.h.in
index d077abec79..ad1eb24409 100644
--- a/third_party/jpeg-xl/lib/jxl/version.h.in
+++ b/third_party/jpeg-xl/lib/jxl/version.h.in
@@ -29,7 +29,7 @@
* #endif
* @endcode
*/
-#define JPEGXL_COMPUTE_NUMERIC_VERSION(major,minor,patch) ((major<<24) | (minor<<16) | (patch<<8) | 0)
+#define JPEGXL_COMPUTE_NUMERIC_VERSION(major,minor,patch) (((major)<<24) | ((minor)<<16) | ((patch)<<8) | 0)
/* Numeric representation of the version */
#define JPEGXL_NUMERIC_VERSION JPEGXL_COMPUTE_NUMERIC_VERSION(JPEGXL_MAJOR_VERSION,JPEGXL_MINOR_VERSION,JPEGXL_PATCH_VERSION)
diff --git a/third_party/jpeg-xl/lib/jxl_cms.cmake b/third_party/jpeg-xl/lib/jxl_cms.cmake
index 47757c8f3b..04980066c1 100644
--- a/third_party/jpeg-xl/lib/jxl_cms.cmake
+++ b/third_party/jpeg-xl/lib/jxl_cms.cmake
@@ -62,8 +62,10 @@ install(TARGETS jxl_cms
if (BUILD_SHARED_LIBS)
set(JPEGXL_REQUIRES_TYPE "Requires.private")
+ set(JPEGXL_CMS_PRIVATE_LIBS "-lm ${PKGCONFIG_CXX_LIB}")
else()
set(JPEGXL_REQUIRES_TYPE "Requires")
+ set(JPEGXL_CMS_PRIVATE_LIBS "-lm ${PKGCONFIG_CXX_LIB}")
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/jxl/libjxl_cms.pc.in"
diff --git a/third_party/jpeg-xl/lib/jxl_lists.bzl b/third_party/jpeg-xl/lib/jxl_lists.bzl
index bbbc444b36..6c98ca15ed 100644
--- a/third_party/jpeg-xl/lib/jxl_lists.bzl
+++ b/third_party/jpeg-xl/lib/jxl_lists.bzl
@@ -188,8 +188,6 @@ libjxl_dec_sources = [
"jxl/epf.cc",
"jxl/epf.h",
"jxl/fast_dct-inl.h",
- "jxl/fast_dct.cc",
- "jxl/fast_dct.h",
"jxl/fast_dct128-inl.h",
"jxl/fast_dct16-inl.h",
"jxl/fast_dct256-inl.h",
@@ -216,6 +214,7 @@ libjxl_dec_sources = [
"jxl/image_bundle.h",
"jxl/image_metadata.cc",
"jxl/image_metadata.h",
+ "jxl/image_ops.cc",
"jxl/image_ops.h",
"jxl/inverse_mtf-inl.h",
"jxl/lehmer_code.h",
diff --git a/third_party/jpeg-xl/lib/jxl_lists.cmake b/third_party/jpeg-xl/lib/jxl_lists.cmake
index e6bf4e5e22..d1a56f9ca8 100644
--- a/third_party/jpeg-xl/lib/jxl_lists.cmake
+++ b/third_party/jpeg-xl/lib/jxl_lists.cmake
@@ -185,8 +185,6 @@ set(JPEGXL_INTERNAL_DEC_SOURCES
jxl/epf.cc
jxl/epf.h
jxl/fast_dct-inl.h
- jxl/fast_dct.cc
- jxl/fast_dct.h
jxl/fast_dct128-inl.h
jxl/fast_dct16-inl.h
jxl/fast_dct256-inl.h
@@ -213,6 +211,7 @@ set(JPEGXL_INTERNAL_DEC_SOURCES
jxl/image_bundle.h
jxl/image_metadata.cc
jxl/image_metadata.h
+ jxl/image_ops.cc
jxl/image_ops.h
jxl/inverse_mtf-inl.h
jxl/lehmer_code.h
diff --git a/third_party/jpeg-xl/lib/jxl_tests.cmake b/third_party/jpeg-xl/lib/jxl_tests.cmake
index eec4149fba..64f807cb82 100644
--- a/third_party/jpeg-xl/lib/jxl_tests.cmake
+++ b/third_party/jpeg-xl/lib/jxl_tests.cmake
@@ -76,7 +76,6 @@ foreach (TESTFILE IN LISTS JPEGXL_INTERNAL_TESTS)
${JPEGXL_COVERAGE_FLAGS}
)
target_link_libraries(${TESTNAME}
- gmock
GTest::GTest
GTest::Main
jxl_testlib-internal
diff --git a/third_party/jpeg-xl/lib/jxl_vars.bzl b/third_party/jpeg-xl/lib/jxl_vars.bzl
index 2c8bccfdf2..fb00f6e34c 100644
--- a/third_party/jpeg-xl/lib/jxl_vars.bzl
+++ b/third_party/jpeg-xl/lib/jxl_vars.bzl
@@ -8,17 +8,18 @@
libjxl_root_package = "libjxl"
libjxl_deps_brotli = ["@brotli//:brotlidec", "@brotli//:brotlienc"]
-libjxl_deps_gif = ["@gif//:gif"]
+libjxl_deps_exr = ["@openexr//:OpenEXR"]
+libjxl_deps_gif = ["@giflib//:giflib"]
libjxl_deps_gtest = ["@googletest//:gtest_main"]
libjxl_deps_hwy = ["@highway//:hwy"]
libjxl_deps_hwy_nanobenchmark = ["@highway//:nanobenchmark"]
libjxl_deps_hwy_test_util = ["@highway//:hwy_test_util"]
libjxl_deps_jpeg = ["@libjpeg_turbo//:jpeg"]
-libjxl_deps_exr = ["@openexr//:OpenEXR"]
libjxl_deps_png = ["@libpng//:png"]
libjxl_deps_runfiles = ["@bazel_tools//tools/cpp/runfiles"]
libjxl_deps_skcms = ["@skcms//:skcms"]
libjxl_deps_testdata = ["//:testdata"]
+libjxl_deps_webp = ["@libwebp//:webp"]
libjxl_test_shards = {
"jpegli/decode_api_test": 10,
diff --git a/third_party/jpeg-xl/lib/nothing.cc b/third_party/jpeg-xl/lib/nothing.cc
new file mode 100644
index 0000000000..e65f587da6
--- /dev/null
+++ b/third_party/jpeg-xl/lib/nothing.cc
@@ -0,0 +1,7 @@
+/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+// Nothing at all. Just a compilation unit.
diff --git a/third_party/jpeg-xl/lib/threads/thread_parallel_runner.cc b/third_party/jpeg-xl/lib/threads/thread_parallel_runner.cc
index d12947ce55..558c9dbe42 100644
--- a/third_party/jpeg-xl/lib/threads/thread_parallel_runner.cc
+++ b/third_party/jpeg-xl/lib/threads/thread_parallel_runner.cc
@@ -41,11 +41,13 @@ bool ThreadMemoryManagerInit(JxlMemoryManager* self,
} else {
memset(self, 0, sizeof(*self));
}
- if (!self->alloc != !self->free) {
+ bool is_default_alloc = (self->alloc == nullptr);
+ bool is_default_free = (self->free == nullptr);
+ if (is_default_alloc != is_default_free) {
return false;
}
- if (!self->alloc) self->alloc = ThreadMemoryManagerDefaultAlloc;
- if (!self->free) self->free = ThreadMemoryManagerDefaultFree;
+ if (is_default_alloc) self->alloc = ThreadMemoryManagerDefaultAlloc;
+ if (is_default_free) self->free = ThreadMemoryManagerDefaultFree;
return true;
}
@@ -57,7 +59,7 @@ void* ThreadMemoryManagerAlloc(const JxlMemoryManager* memory_manager,
void ThreadMemoryManagerFree(const JxlMemoryManager* memory_manager,
void* address) {
- return memory_manager->free(memory_manager->opaque, address);
+ memory_manager->free(memory_manager->opaque, address);
}
} // namespace
diff --git a/third_party/jpeg-xl/lib/threads/thread_parallel_runner_internal.cc b/third_party/jpeg-xl/lib/threads/thread_parallel_runner_internal.cc
index 5f73d94897..7ffcb34428 100644
--- a/third_party/jpeg-xl/lib/threads/thread_parallel_runner_internal.cc
+++ b/third_party/jpeg-xl/lib/threads/thread_parallel_runner_internal.cc
@@ -6,6 +6,7 @@
#include "lib/threads/thread_parallel_runner_internal.h"
#include <jxl/parallel_runner.h>
+#include <jxl/types.h>
#include <algorithm>
#include <atomic>
@@ -120,9 +121,9 @@ void ThreadParallelRunner::RunRange(ThreadParallelRunner* self,
// because it avoids user-specified parameters.
for (;;) {
-#if 0
- // dynamic
- const uint32_t my_size = std::max(num_tasks / (num_worker_threads * 4), 1);
+#if JXL_FALSE
+ // dynamic
+ const uint32_t my_size = std::max(num_tasks / (num_worker_threads * 4), 1);
#else
// guided
const uint32_t num_reserved =
diff --git a/third_party/jpeg-xl/lib/threads/thread_parallel_runner_internal.h b/third_party/jpeg-xl/lib/threads/thread_parallel_runner_internal.h
index 199a5f2a8b..5b28384bf0 100644
--- a/third_party/jpeg-xl/lib/threads/thread_parallel_runner_internal.h
+++ b/third_party/jpeg-xl/lib/threads/thread_parallel_runner_internal.h
@@ -132,8 +132,8 @@ class ThreadParallelRunner {
// Attempts to reserve and perform some work from the global range of tasks,
// which is encoded within "command". Returns after all tasks are reserved.
- static void RunRange(ThreadParallelRunner* self, const WorkerCommand command,
- const int thread);
+ static void RunRange(ThreadParallelRunner* self, WorkerCommand command,
+ int thread);
static void ThreadFunc(ThreadParallelRunner* self, int thread);