diff options
Diffstat (limited to 'third_party/jpeg-xl/lib/jxl')
67 files changed, 576 insertions, 521 deletions
diff --git a/third_party/jpeg-xl/lib/jxl/alpha_test.cc b/third_party/jpeg-xl/lib/jxl/alpha_test.cc index a93254f3dd..6e26e77be6 100644 --- a/third_party/jpeg-xl/lib/jxl/alpha_test.cc +++ b/third_party/jpeg-xl/lib/jxl/alpha_test.cc @@ -13,6 +13,16 @@ namespace jxl { namespace { +AlphaBlendingInputLayer makeAbil(const Color& rgb, const float& a) { + const float* data = rgb.data(); + return {data, data + 1, data + 2, &a}; +} + +AlphaBlendingOutput makeAbo(Color& rgb, float& a) { + float* data = rgb.data(); + return {data, data + 1, data + 2, &a}; +} + TEST(AlphaTest, BlendingWithNonPremultiplied) { const Color bg_rgb{100, 110, 120}; const float bg_a = 180.f / 255; @@ -22,16 +32,16 @@ TEST(AlphaTest, BlendingWithNonPremultiplied) { 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, + /*bg=*/makeAbil(bg_rgb, bg_a), + /*fg=*/makeAbil(fg_rgb, fg_a), + /*out=*/makeAbo(out_rgb, out_a), 1, /*alpha_is_premultiplied=*/false, /*clamp=*/false); 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, + /*bg=*/makeAbil(bg_rgb, bg_a), + /*fg=*/makeAbil(fg_rgb, fg_a2), + /*out=*/makeAbo(out_rgb, out_a), 1, /*alpha_is_premultiplied=*/false, /*clamp=*/true); EXPECT_ARRAY_NEAR(out_rgb, fg_rgb, 0.05f); EXPECT_NEAR(out_a, 1.0f, 1e-5); @@ -46,16 +56,16 @@ TEST(AlphaTest, BlendingWithPremultiplied) { 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, + /*bg=*/makeAbil(bg_rgb, bg_a), + /*fg=*/makeAbil(fg_rgb, fg_a), + /*out=*/makeAbo(out_rgb, out_a), 1, /*alpha_is_premultiplied=*/true, /*clamp=*/false); 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, + /*bg=*/makeAbil(bg_rgb, bg_a), + /*fg=*/makeAbil(fg_rgb, fg_a2), + /*out=*/makeAbo(out_rgb, out_a), 1, /*alpha_is_premultiplied=*/true, /*clamp=*/true); EXPECT_ARRAY_NEAR(out_rgb, fg_rgb, 0.05f); EXPECT_NEAR(out_a, 1.0f, 1e-5); diff --git a/third_party/jpeg-xl/lib/jxl/bit_reader_test.cc b/third_party/jpeg-xl/lib/jxl/bit_reader_test.cc index 22a20649e0..802da855fa 100644 --- a/third_party/jpeg-xl/lib/jxl/bit_reader_test.cc +++ b/third_party/jpeg-xl/lib/jxl/bit_reader_test.cc @@ -53,7 +53,7 @@ struct Symbol { TEST(BitReaderTest, TestRoundTrip) { test::ThreadPoolForTests pool(8); EXPECT_TRUE(RunOnPool( - &pool, 0, 1000, ThreadPool::NoInit, + pool.get(), 0, 1000, ThreadPool::NoInit, [](const uint32_t task, size_t /* thread */) { constexpr size_t kMaxBits = 8000; BitWriter writer; @@ -87,7 +87,7 @@ TEST(BitReaderTest, TestRoundTrip) { TEST(BitReaderTest, TestSkip) { test::ThreadPoolForTests pool(8); EXPECT_TRUE(RunOnPool( - &pool, 0, 96, ThreadPool::NoInit, + pool.get(), 0, 96, ThreadPool::NoInit, [](const uint32_t task, size_t /* thread */) { constexpr size_t kSize = 100; diff --git a/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.h b/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.h index e0bfd354e1..487db2bdce 100644 --- a/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.h +++ b/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.h @@ -8,12 +8,10 @@ #ifndef LIB_JXL_BUTTERAUGLI_BUTTERAUGLI_H_ #define LIB_JXL_BUTTERAUGLI_BUTTERAUGLI_H_ -#include <stdint.h> #include <stdlib.h> #include <string.h> #include <atomic> -#include <cmath> #include <cstddef> #include <memory> @@ -21,7 +19,10 @@ #include "lib/jxl/base/status.h" #include "lib/jxl/image.h" +#if !defined(BUTTERAUGLI_ENABLE_CHECKS) #define BUTTERAUGLI_ENABLE_CHECKS 0 +#endif + #define BUTTERAUGLI_RESTRICT JXL_RESTRICT // This is the main interface to butteraugli image similarity diff --git a/third_party/jpeg-xl/lib/jxl/cache_aligned.cc b/third_party/jpeg-xl/lib/jxl/cache_aligned.cc index 8a95634d68..814b538cf6 100644 --- a/third_party/jpeg-xl/lib/jxl/cache_aligned.cc +++ b/third_party/jpeg-xl/lib/jxl/cache_aligned.cc @@ -128,11 +128,12 @@ void* CacheAligned::Allocate(const size_t payload_size, size_t offset) { const uintptr_t payload = aligned + offset; // still aligned // Stash `allocated` and payload_size inside header for use by Free(). - AllocationHeader* header = reinterpret_cast<AllocationHeader*>(payload) - 1; + AllocationHeader* header = + reinterpret_cast<AllocationHeader*>(payload) - 1; // NOLINT header->allocated = allocated; header->allocated_size = allocated_size; - return JXL_ASSUME_ALIGNED(reinterpret_cast<void*>(payload), 64); + return JXL_ASSUME_ALIGNED(reinterpret_cast<void*>(payload), 64); // NOLINT } void CacheAligned::Free(const void* aligned_pointer) { @@ -142,7 +143,7 @@ void CacheAligned::Free(const void* aligned_pointer) { const uintptr_t payload = reinterpret_cast<uintptr_t>(aligned_pointer); JXL_ASSERT(payload % kAlignment == 0); const AllocationHeader* header = - reinterpret_cast<const AllocationHeader*>(payload) - 1; + reinterpret_cast<const AllocationHeader*>(payload) - 1; // NOLINT // Subtract (2's complement negation). bytes_in_use.fetch_add(~header->allocated_size + 1, 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 7f59e688d0..a787bd11d8 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 @@ -183,12 +183,12 @@ static Status ToneMapPixel(const JxlColorEncoding& c, const float in[3], const float f_y = lab_f(xyz[1] / kYn); const float f_z = lab_f(xyz[2] / kZn); - pcslab_out[0] = - static_cast<uint8_t>(.5f + 255.f * Clamp1(1.16f * f_y - .16f, 0.f, 1.f)); + pcslab_out[0] = static_cast<uint8_t>( + std::lroundf(255.f * Clamp1(1.16f * f_y - .16f, 0.f, 1.f))); pcslab_out[1] = static_cast<uint8_t>( - .5f + 128.f + Clamp1(500 * (f_x - f_y), -128.f, 127.f)); + std::lroundf(128.f + Clamp1(500 * (f_x - f_y), -128.f, 127.f))); pcslab_out[2] = static_cast<uint8_t>( - .5f + 128.f + Clamp1(200 * (f_y - f_z), -128.f, 127.f)); + std::lroundf(128.f + Clamp1(200 * (f_y - f_z), -128.f, 127.f))); return true; } @@ -581,7 +581,8 @@ static void CreateICCCurvCurvTag(const std::vector<uint16_t>& curve, } // Writes 12 + 4*params.size() bytes -static Status CreateICCCurvParaTag(std::vector<float> params, size_t curve_type, +static Status CreateICCCurvParaTag(const std::vector<float>& params, + size_t curve_type, std::vector<uint8_t>* tags) { WriteICCTag("para", tags->size(), tags); WriteICCUint32(0, tags->size(), tags); @@ -637,7 +638,7 @@ static Status CreateICCLutAtoBTagForXYB(std::vector<uint8_t>* tags) { for (size_t ib = 0; ib < 2; ++ib) { const jxl::cms::ColorCube0D& out_f = cube[ix][iy][ib]; for (int i = 0; i < 3; ++i) { - int32_t val = static_cast<int32_t>(0.5f + 65535 * out_f[i]); + int32_t val = static_cast<int32_t>(std::lroundf(65535 * out_f[i])); JXL_DASSERT(val >= 0 && val <= 65535); WriteICCUint16(val, tags->size(), tags); } 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 81f301a31d..1f85dcca41 100644 --- a/third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h +++ b/third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h @@ -22,8 +22,8 @@ class Rec2408ToneMapperBase { explicit Rec2408ToneMapperBase(std::pair<float, float> source_range, std::pair<float, float> target_range, const Vector3& primaries_luminances) - : source_range_(source_range), - target_range_(target_range), + : source_range_(std::move(source_range)), + target_range_(std::move(target_range)), red_Y_(primaries_luminances[0]), green_Y_(primaries_luminances[1]), blue_Y_(primaries_luminances[2]) {} @@ -56,7 +56,7 @@ class Rec2408ToneMapperBase { } protected: - float InvEOTF(const float luminance) const { + static float InvEOTF(const float luminance) { return TF_PQ_Base::EncodedFromDisplay(/*display_intensity_target=*/1.0, luminance); } diff --git a/third_party/jpeg-xl/lib/jxl/cms/transfer_functions-inl.h b/third_party/jpeg-xl/lib/jxl/cms/transfer_functions-inl.h index 84bcbb45ed..133e624c08 100644 --- a/third_party/jpeg-xl/lib/jxl/cms/transfer_functions-inl.h +++ b/third_party/jpeg-xl/lib/jxl/cms/transfer_functions-inl.h @@ -69,7 +69,7 @@ class TF_HLG : TF_HLG_Base { class TF_709 { public: - JXL_INLINE double EncodedFromDisplay(const double d) const { + static JXL_INLINE double EncodedFromDisplay(const double d) { if (d < kThresh) return kMulLow * d; return kMulHi * std::pow(d, kPowHi) + kSub; } 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 b2d47c73f9..77cbe56926 100644 --- a/third_party/jpeg-xl/lib/jxl/color_management_test.cc +++ b/third_party/jpeg-xl/lib/jxl/color_management_test.cc @@ -434,7 +434,7 @@ TEST_F(ColorManagementTest, GoldenXYBCube) { for (size_t ib = 0; ib < 2; ++ib) { const jxl::cms::ColorCube0D& out_f = cube[ix][iy][ib]; for (int i = 0; i < 3; ++i) { - int32_t val = static_cast<int32_t>(0.5f + 65535 * out_f[i]); + int32_t val = static_cast<int32_t>(std::lroundf(65535 * out_f[i])); ASSERT_TRUE(val >= 0 && val <= 65535); actual.push_back(val); } diff --git a/third_party/jpeg-xl/lib/jxl/convolve_test.cc b/third_party/jpeg-xl/lib/jxl/convolve_test.cc index 09cbdc12a6..084398c5e1 100644 --- a/third_party/jpeg-xl/lib/jxl/convolve_test.cc +++ b/third_party/jpeg-xl/lib/jxl/convolve_test.cc @@ -161,7 +161,7 @@ void TestConvolve() { test::ThreadPoolForTests pool(4); EXPECT_EQ(true, RunOnPool( - &pool, kConvolveMaxRadius, 40, ThreadPool::NoInit, + pool.get(), kConvolveMaxRadius, 40, ThreadPool::NoInit, [](const uint32_t task, size_t /*thread*/) { const size_t xsize = task; Rng rng(129 + 13 * xsize); @@ -176,15 +176,15 @@ void TestConvolve() { JXL_DEBUG(JXL_DEBUG_CONVOLVE, "Sym3------------------"); VerifySymmetric3(xsize, ysize, null_pool, &rng); - VerifySymmetric3(xsize, ysize, &pool3, &rng); + VerifySymmetric3(xsize, ysize, pool3.get(), &rng); JXL_DEBUG(JXL_DEBUG_CONVOLVE, "Sym5------------------"); VerifySymmetric5(xsize, ysize, null_pool, &rng); - VerifySymmetric5(xsize, ysize, &pool3, &rng); + VerifySymmetric5(xsize, ysize, pool3.get(), &rng); JXL_DEBUG(JXL_DEBUG_CONVOLVE, "Sep5------------------"); VerifySeparable5(xsize, ysize, null_pool, &rng); - VerifySeparable5(xsize, ysize, &pool3, &rng); + VerifySeparable5(xsize, ysize, pool3.get(), &rng); } }, "TestConvolve")); diff --git a/third_party/jpeg-xl/lib/jxl/dct_for_test.h b/third_party/jpeg-xl/lib/jxl/dct_for_test.h index 58dd75e20e..b0cbffacad 100644 --- a/third_party/jpeg-xl/lib/jxl/dct_for_test.h +++ b/third_party/jpeg-xl/lib/jxl/dct_for_test.h @@ -22,7 +22,7 @@ static inline double alpha(int u) { return u == 0 ? 0.7071067811865475 : 1.0; } // N-DCT on M columns, divided by sqrt(N). Matches the definition in the spec. template <size_t N, size_t M> -void DCT1D(double block[N * M], double out[N * M]) { +void DCT1D(const double block[N * M], double out[N * M]) { std::vector<double> matrix(N * N); const double scale = std::sqrt(2.0) / N; for (size_t y = 0; y < N; y++) { @@ -43,7 +43,7 @@ void DCT1D(double block[N * M], double out[N * M]) { // N-IDCT on M columns, multiplied by sqrt(N). Matches the definition in the // spec. template <size_t N, size_t M> -void IDCT1D(double block[N * M], double out[N * M]) { +void IDCT1D(const double block[N * M], double out[N * M]) { std::vector<double> matrix(N * N); const double scale = std::sqrt(2.0); for (size_t y = 0; y < N; y++) { @@ -63,7 +63,7 @@ void IDCT1D(double block[N * M], double out[N * M]) { } template <size_t N, size_t M> -void TransposeBlock(double in[N * M], double out[M * N]) { +void TransposeBlock(const double in[N * M], double out[M * N]) { for (size_t x = 0; x < N; x++) { for (size_t y = 0; y < M; y++) { out[y * N + x] = in[x * M + y]; diff --git a/third_party/jpeg-xl/lib/jxl/dct_test.cc b/third_party/jpeg-xl/lib/jxl/dct_test.cc index e4982e2f45..57ce9291e2 100644 --- a/third_party/jpeg-xl/lib/jxl/dct_test.cc +++ b/third_party/jpeg-xl/lib/jxl/dct_test.cc @@ -160,7 +160,7 @@ void TestInverseT(float accuracy) { test::ThreadPoolForTests pool(N < 32 ? 0 : 8); enum { kBlockSize = N * N }; EXPECT_TRUE(RunOnPool( - &pool, 0, kBlockSize, ThreadPool::NoInit, + pool.get(), 0, kBlockSize, ThreadPool::NoInit, [accuracy](const uint32_t task, size_t /*thread*/) { const size_t i = static_cast<size_t>(task); HWY_ALIGN float x[kBlockSize] = {0.0f}; diff --git a/third_party/jpeg-xl/lib/jxl/dec_cache.cc b/third_party/jpeg-xl/lib/jxl/dec_cache.cc index 2a89420018..639857d4f8 100644 --- a/third_party/jpeg-xl/lib/jxl/dec_cache.cc +++ b/third_party/jpeg-xl/lib/jxl/dec_cache.cc @@ -125,8 +125,8 @@ Status PassesDecoderState::PreparePipeline(const FrameHeader& frame_header, if (frame_header.CanBeReferenced() && frame_header.save_before_color_transform) { - builder.AddStage(GetWriteToImageBundleStage( - &frame_storage_for_referencing, output_encoding_info.color_encoding)); + builder.AddStage(GetWriteToImageBundleStage(&frame_storage_for_referencing, + output_encoding_info)); } bool has_alpha = false; @@ -181,7 +181,7 @@ Status PassesDecoderState::PreparePipeline(const FrameHeader& frame_header, linear = false; } builder.AddStage(GetWriteToImageBundleStage( - &frame_storage_for_referencing, output_encoding_info.color_encoding)); + &frame_storage_for_referencing, output_encoding_info)); } if (options.render_spotcolors && @@ -228,7 +228,7 @@ Status PassesDecoderState::PreparePipeline(const FrameHeader& frame_header, if ((output_encoding_info.color_encoding_is_original) || (!output_encoding_info.cms_set) || mixing_color_and_grey) { // in those cases we only need a linear stage in other cases we attempt - // to obtain an cms stage: the cases are + // to obtain a cms stage: the cases are // - output_encoding_info.color_encoding_is_original: no cms stage // needed because it would be a no-op // - !output_encoding_info.cms_set: can't use the cms, so no point in @@ -255,8 +255,8 @@ Status PassesDecoderState::PreparePipeline(const FrameHeader& frame_header, has_alpha, unpremul_alpha, alpha_c, undo_orientation, extra_output)); } else { - builder.AddStage(GetWriteToImageBundleStage( - decoded, output_encoding_info.color_encoding)); + builder.AddStage( + GetWriteToImageBundleStage(decoded, output_encoding_info)); } } JXL_ASSIGN_OR_RETURN(render_pipeline, diff --git a/third_party/jpeg-xl/lib/jxl/dec_modular.cc b/third_party/jpeg-xl/lib/jxl/dec_modular.cc index 49561e6ec2..80cc9d1360 100644 --- a/third_party/jpeg-xl/lib/jxl/dec_modular.cc +++ b/third_party/jpeg-xl/lib/jxl/dec_modular.cc @@ -362,7 +362,7 @@ Status ModularFrameDecoder::DecodeGroup( // Undo global transforms that have been pushed to the group level if (!use_full_image) { JXL_ASSERT(render_pipeline_input); - for (auto t : global_transform) { + for (const auto& t : global_transform) { JXL_RETURN_IF_ERROR(t.Inverse(gi, global_header.wp_header)); } JXL_RETURN_IF_ERROR(ModularImageToDecodedRect( diff --git a/third_party/jpeg-xl/lib/jxl/decode_test.cc b/third_party/jpeg-xl/lib/jxl/decode_test.cc index 33176cfd66..99b5871ccd 100644 --- a/third_party/jpeg-xl/lib/jxl/decode_test.cc +++ b/third_party/jpeg-xl/lib/jxl/decode_test.cc @@ -2475,7 +2475,7 @@ void TestPartialStream(bool reconstructible_jpeg) { TEST(DecodeTest, PixelPartialTest) { TestPartialStream(false); } // Tests the return status when trying to decode JPEG bytes on incomplete file. -TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGPartialTest)) { +JXL_TRANSCODE_JPEG_TEST(DecodeTest, JPEGPartialTest) { TEST_LIBJPEG_SUPPORT(); TestPartialStream(true); } @@ -4195,7 +4195,7 @@ TEST(DecodeTest, InputHandlingTestOneShot) { } } -TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(InputHandlingTestJPEGOneshot)) { +JXL_TRANSCODE_JPEG_TEST(DecodeTest, InputHandlingTestJPEGOneshot) { TEST_LIBJPEG_SUPPORT(); size_t xsize = 123; size_t ysize = 77; @@ -4976,7 +4976,7 @@ void VerifyJPEGReconstruction(jxl::Span<const uint8_t> container, EXPECT_EQ(0, memcmp(reconstructed_buffer.data(), jpeg_bytes.data(), used)); } -TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructTestCodestream)) { +JXL_TRANSCODE_JPEG_TEST(DecodeTest, JPEGReconstructTestCodestream) { TEST_LIBJPEG_SUPPORT(); size_t xsize = 123; size_t ysize = 77; @@ -4994,7 +4994,7 @@ TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructTestCodestream)) { VerifyJPEGReconstruction(jxl::Bytes(compressed), jxl::Bytes(jpeg_codestream)); } -TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionTest)) { +JXL_TRANSCODE_JPEG_TEST(DecodeTest, JPEGReconstructionTest) { const std::string jpeg_path = "jxl/flower/flower.png.im_q85_420.jpg"; const std::vector<uint8_t> orig = jxl::test::ReadTestData(jpeg_path); jxl::CodecInOut orig_io; @@ -5024,7 +5024,7 @@ TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionTest)) { VerifyJPEGReconstruction(jxl::Bytes(container), jxl::Bytes(orig)); } -TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionMetadataTest)) { +JXL_TRANSCODE_JPEG_TEST(DecodeTest, JPEGReconstructionMetadataTest) { const std::string jpeg_path = "jxl/jpeg_reconstruction/1x1_exif_xmp.jpg"; const std::string jxl_path = "jxl/jpeg_reconstruction/1x1_exif_xmp.jxl"; const std::vector<uint8_t> jpeg = jxl::test::ReadTestData(jpeg_path); @@ -5135,7 +5135,7 @@ TEST(DecodeTest, ExtentedBoxSizeTest) { JxlDecoderDestroy(dec); } -TEST(DecodeTest, JXL_BOXES_TEST(BoxTest)) { +JXL_BOXES_TEST(DecodeTest, BoxTest) { size_t xsize = 1; size_t ysize = 1; std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0); @@ -5212,7 +5212,7 @@ TEST(DecodeTest, JXL_BOXES_TEST(BoxTest)) { JxlDecoderDestroy(dec); } -TEST(DecodeTest, JXL_BOXES_TEST(ExifBrobBoxTest)) { +JXL_BOXES_TEST(DecodeTest, ExifBrobBoxTest) { size_t xsize = 1; size_t ysize = 1; std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0); @@ -5394,7 +5394,7 @@ TEST(DecodeTest, JXL_BOXES_TEST(ExifBrobBoxTest)) { } } -TEST(DecodeTest, JXL_BOXES_TEST(PartialCodestreamBoxTest)) { +JXL_BOXES_TEST(DecodeTest, PartialCodestreamBoxTest) { size_t xsize = 23; size_t ysize = 81; std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0); 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 e80771248e..4f1d2dadb5 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 @@ -149,9 +149,9 @@ Status ProcessTile(const CompressParams& cparams, float* JXL_RESTRICT row_out = sqrsum_00_row + y * sqrsum_00_stride; for (size_t x = 0; x < rect.xsize() * 2; x++) { auto sum = Zero(df4); - for (size_t iy = 0; iy < 4; iy++) { + for (auto& row : rows_in) { for (size_t ix = 0; ix < 4; ix += Lanes(df4)) { - sum = Add(sum, LoadU(df4, rows_in[iy] + x * 4 + ix + 2)); + sum = Add(sum, LoadU(df4, row + x * 4 + ix + 2)); } } row_out[x] = GetLane(Sqrt(SumOfLanes(df4, sum))) * (1.0f / 4.0f); 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 58d0d00eaa..1797139428 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc +++ b/third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc @@ -202,8 +202,8 @@ size_t TOCBucket(size_t group_size) { size_t TOCSize(const std::vector<size_t>& group_sizes) { size_t toc_bits = 0; - for (size_t i = 0; i < group_sizes.size(); i++) { - toc_bits += kTOCBits[TOCBucket(group_sizes[i])]; + for (size_t group_size : group_sizes) { + toc_bits += kTOCBits[TOCBucket(group_size)]; } return (toc_bits + 7) / 8; } @@ -328,8 +328,8 @@ struct PrefixCode { template <typename T> static void ComputeCodeLengthsNonZeroImpl(const uint64_t* freqs, size_t n, size_t precision, T infty, - uint8_t* min_limit, - uint8_t* max_limit, + const uint8_t* min_limit, + const uint8_t* max_limit, uint8_t* nbits) { assert(precision < 15); assert(n <= kMaxNumSymbols); @@ -454,8 +454,8 @@ struct PrefixCode { uint8_t min_lengths[kNumLZ77] = {}; uint8_t l = 15 - level1_nbits[numraw]; uint8_t max_lengths[kNumLZ77]; - for (size_t i = 0; i < kNumLZ77; i++) { - max_lengths[i] = l; + for (uint8_t& max_length : max_lengths) { + max_length = l; } size_t num_lz77 = kNumLZ77; while (num_lz77 > 0 && lz77_counts[num_lz77 - 1] == 0) num_lz77--; @@ -487,11 +487,11 @@ struct PrefixCode { void WriteTo(BitWriter* writer) const { uint64_t code_length_counts[18] = {}; code_length_counts[17] = 3 + 2 * (kNumLZ77 - 1); - for (size_t i = 0; i < kNumRawSymbols; i++) { - code_length_counts[raw_nbits[i]]++; + for (uint8_t raw_nbit : raw_nbits) { + code_length_counts[raw_nbit]++; } - for (size_t i = 0; i < kNumLZ77; i++) { - code_length_counts[lz77_nbits[i]]++; + for (uint8_t lz77_nbit : lz77_nbits) { + code_length_counts[lz77_nbit]++; } uint8_t code_length_nbits[18] = {}; uint8_t code_length_nbits_min[18] = {}; @@ -527,9 +527,8 @@ struct PrefixCode { code_length_bits, 18); // Encode raw bit code lengths. // Max bits written in this loop: 19 * 5 = 95 - for (size_t i = 0; i < kNumRawSymbols; i++) { - writer->Write(code_length_nbits[raw_nbits[i]], - code_length_bits[raw_nbits[i]]); + for (uint8_t raw_nbit : raw_nbits) { + writer->Write(code_length_nbits[raw_nbit], code_length_bits[raw_nbit]); } size_t num_lz77 = kNumLZ77; while (lz77_nbits[num_lz77 - 1] == 0) { @@ -590,8 +589,8 @@ struct JxlFastLosslessFrameState { size_t JxlFastLosslessOutputSize(const JxlFastLosslessFrameState* frame) { size_t total_size_groups = 0; - for (size_t i = 0; i < frame->group_data.size(); i++) { - total_size_groups += SectionSize(frame->group_data[i]); + for (const auto& section : frame->group_data) { + total_size_groups += SectionSize(section); } return frame->header.bytes_written + total_size_groups; } @@ -719,11 +718,10 @@ void JxlFastLosslessPrepareHeader(JxlFastLosslessFrameState* frame, output->Write(1, 0); // No TOC permutation output->ZeroPadToByte(); // TOC is byte-aligned. assert(add_image_header || output->bytes_written <= kMaxFrameHeaderSize); - for (size_t i = 0; i < frame->group_sizes.size(); i++) { - size_t sz = frame->group_sizes[i]; - size_t bucket = TOCBucket(sz); + for (size_t group_size : frame->group_sizes) { + size_t bucket = TOCBucket(group_size); output->Write(2, bucket); - output->Write(kTOCBits[bucket] - 2, sz - kGroupSizeOffset[bucket]); + output->Write(kTOCBits[bucket] - 2, group_size - kGroupSizeOffset[bucket]); } output->ZeroPadToByte(); // Groups are byte-aligned. } diff --git a/third_party/jpeg-xl/lib/jxl/enc_frame.cc b/third_party/jpeg-xl/lib/jxl/enc_frame.cc index 8587e1aed2..2a3389921b 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_frame.cc +++ b/third_party/jpeg-xl/lib/jxl/enc_frame.cc @@ -1786,8 +1786,8 @@ size_t TOCBucket(size_t group_size) { size_t TOCSize(const std::vector<size_t>& group_sizes) { size_t toc_bits = 0; - for (size_t i = 0; i < group_sizes.size(); i++) { - toc_bits += kTOCBits[TOCBucket(group_sizes[i])]; + for (size_t group_size : group_sizes) { + toc_bits += kTOCBits[TOCBucket(group_size)]; } return (toc_bits + 7) / 8; } @@ -1795,8 +1795,8 @@ size_t TOCSize(const std::vector<size_t>& group_sizes) { PaddedBytes EncodeTOC(const std::vector<size_t>& group_sizes, AuxOut* aux_out) { BitWriter writer; BitWriter::Allotment allotment(&writer, 32 * group_sizes.size()); - for (size_t i = 0; i < group_sizes.size(); i++) { - JXL_CHECK(U32Coder::Write(kTocDist, group_sizes[i], &writer)); + for (size_t group_size : group_sizes) { + JXL_CHECK(U32Coder::Write(kTocDist, group_size, &writer)); } writer.ZeroPadToByte(); // before first group allotment.ReclaimAndCharge(&writer, kLayerTOC, aux_out); @@ -1854,13 +1854,13 @@ void RemoveUnusedHistograms(std::vector<uint8_t>& context_map, EntropyEncodingData& codes) { std::vector<int> remap(256, -1); std::vector<uint8_t> inv_remap; - for (size_t i = 0; i < context_map.size(); ++i) { - const uint8_t histo_ix = context_map[i]; + for (uint8_t& context : context_map) { + const uint8_t histo_ix = context; if (remap[histo_ix] == -1) { remap[histo_ix] = inv_remap.size(); inv_remap.push_back(histo_ix); } - context_map[i] = remap[histo_ix]; + context = remap[histo_ix]; } EntropyEncodingData new_codes; new_codes.use_prefix_code = codes.use_prefix_code; diff --git a/third_party/jpeg-xl/lib/jxl/enc_group.cc b/third_party/jpeg-xl/lib/jxl/enc_group.cc index 1967fdaba9..2b60643e7c 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_group.cc +++ b/third_party/jpeg-xl/lib/jxl/enc_group.cc @@ -43,7 +43,7 @@ using hwy::HWY_NAMESPACE::Round; void QuantizeBlockAC(const Quantizer& quantizer, const bool error_diffusion, size_t c, float qm_multiplier, size_t quant_kind, size_t xsize, size_t ysize, float* thresholds, - const float* JXL_RESTRICT block_in, int32_t* quant, + const float* JXL_RESTRICT block_in, const int32_t* quant, int32_t* JXL_RESTRICT block_out) { const float* JXL_RESTRICT qm = quantizer.InvDequantMatrix(quant_kind, c); float qac = quantizer.Scale() * (*quant); @@ -322,10 +322,8 @@ void QuantizeRoundtripYBlockAC(PassesEncoderState* enc_state, const size_t size, int quant_orig = *quant; float val[3] = {enc_state->x_qm_multiplier, 1.0f, enc_state->b_qm_multiplier}; - int clut[3] = {1, 0, 2}; - for (int ii = 0; ii < 3; ++ii) { + for (int c : {1, 0, 2}) { float thres[4] = {0.58f, 0.64f, 0.64f, 0.64f}; - int c = clut[ii]; *quant = quant_orig; AdjustQuantBlockAC(quantizer, c, val[c], quant_kind, xsize, ysize, &thres[0], inout + c * size, quant); 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 a29fb3f299..c3899600e5 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_icc_codec.cc +++ b/third_party/jpeg-xl/lib/jxl/enc_icc_codec.cc @@ -127,8 +127,8 @@ Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result) { } if (size <= kICCHeaderSize) { EncodeVarInt(0, result); // 0 commands - for (size_t i = 0; i < data.size(); i++) { - result->push_back(data[i]); + for (uint8_t b : data) { + result->push_back(b); } return true; } @@ -403,11 +403,11 @@ Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result) { data.push_back(icc[last0++]); } } - for (size_t i = 0; i < commands_add.size(); i++) { - commands.push_back(commands_add[i]); + for (uint8_t b : commands_add) { + commands.push_back(b); } - for (size_t i = 0; i < data_add.size(); i++) { - data.push_back(data_add[i]); + for (uint8_t b : data_add) { + data.push_back(b); } last0 = pos; } @@ -417,11 +417,11 @@ Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result) { } EncodeVarInt(commands.size(), result); - for (size_t i = 0; i < commands.size(); i++) { - result->push_back(commands[i]); + for (uint8_t b : commands) { + result->push_back(b); } - for (size_t i = 0; i < data.size(); i++) { - result->push_back(data[i]); + for (uint8_t b : data) { + result->push_back(b); } return true; diff --git a/third_party/jpeg-xl/lib/jxl/enc_modular.cc b/third_party/jpeg-xl/lib/jxl/enc_modular.cc index dbd62d4a01..35fac3c827 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_modular.cc +++ b/third_party/jpeg-xl/lib/jxl/enc_modular.cc @@ -300,13 +300,12 @@ bool do_transform(Image& image, const Transform& tr, bool maybe_do_transform(Image& image, const Transform& tr, const CompressParams& cparams, - const weighted::Header& wp_header, + const weighted::Header& wp_header, float cost_before, 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); @@ -321,6 +320,110 @@ bool maybe_do_transform(Image& image, const Transform& tr, return did_it; } +void try_palettes(Image& gi, int& max_bitdepth, int& maxval, + const CompressParams& cparams_, float channel_colors_percent, + jxl::ThreadPool* pool = nullptr) { + float cost_before = 0.f; + size_t did_palette = 0; + float nb_pixels = gi.channel[0].w * gi.channel[0].h; + int nb_chans = gi.channel.size() - gi.nb_meta_channels; + // arbitrary estimate: 4.8 bpp for 8-bit RGB + float arbitrary_bpp_estimate = 0.2f * gi.bitdepth * nb_chans; + + if (cparams_.palette_colors != 0 || cparams_.lossy_palette) { + // when not estimating, assume some arbitrary bpp + cost_before = cparams_.speed_tier <= SpeedTier::kSquirrel + ? EstimateCost(gi) + : nb_pixels * arbitrary_bpp_estimate; + // all-channel palette (e.g. RGBA) + if (nb_chans > 1) { + Transform maybe_palette(TransformId::kPalette); + maybe_palette.begin_c = gi.nb_meta_channels; + maybe_palette.num_c = nb_chans; + // Heuristic choice of max colors for a palette: + // max_colors = nb_pixels * estimated_bpp_without_palette * 0.0005 + + // + nb_pixels / 128 + 128 + // (estimated_bpp_without_palette = cost_before / nb_pixels) + // Rationale: small image with large palette is not effective; + // also if the entropy (estimated bpp) is low (e.g. mostly solid/gradient + // areas), palette is less useful and may even be counterproductive. + maybe_palette.nb_colors = std::min( + static_cast<int>(cost_before * 0.0005f + nb_pixels / 128 + 128), + 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); + if (maybe_palette.lossy_palette) { + maybe_palette.predictor = Predictor::Average4; + } + // TODO(veluca): use a custom weighted header if using the weighted + // predictor. + if (maybe_do_transform(gi, maybe_palette, cparams_, weighted::Header(), + cost_before, pool, cparams_.options.zero_tokens)) { + did_palette = 1; + }; + } + // all-minus-one-channel palette (RGB with separate alpha, or CMY with + // separate K) + if (!did_palette && nb_chans > 3) { + Transform maybe_palette_3(TransformId::kPalette); + maybe_palette_3.begin_c = gi.nb_meta_channels; + maybe_palette_3.num_c = nb_chans - 1; + maybe_palette_3.nb_colors = std::min( + static_cast<int>(cost_before * 0.0005f + nb_pixels / 128 + 128), + 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 = Predictor::Average4; + } + if (maybe_do_transform(gi, maybe_palette_3, cparams_, weighted::Header(), + cost_before, pool, cparams_.options.zero_tokens)) { + did_palette = 1; + } + } + } + + if (channel_colors_percent > 0) { + // single channel palette (like FLIF's ChannelCompact) + size_t nb_channels = gi.channel.size() - gi.nb_meta_channels - did_palette; + int orig_bitdepth = max_bitdepth; + max_bitdepth = 0; + if (nb_channels > 0 && (did_palette || cost_before == 0)) { + cost_before = + cparams_.speed_tier < SpeedTier::kSquirrel ? EstimateCost(gi) : 0; + } + for (size_t i = did_palette; i < nb_channels + did_palette; i++) { + int32_t min; + int32_t max; + compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max); + 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; + maybe_palette_1.num_c = 1; + // simple heuristic: if less than X percent of the values in the range + // actually occur, it is probably worth it to do a compaction + // (but only if the channel palette is less than 6% the size of the + // image itself) + maybe_palette_1.nb_colors = + std::min(static_cast<int>(nb_pixels / 16), + static_cast<int>(channel_colors_percent / 100. * colors)); + if (maybe_do_transform(gi, maybe_palette_1, cparams_, weighted::Header(), + cost_before, 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; + int ch_bitdepth = + (max > 0 ? CeilLog2Nonzero(static_cast<uint32_t>(max)) : 0); + if (ch_bitdepth > max_bitdepth) max_bitdepth = ch_bitdepth; + } else { + max_bitdepth = orig_bitdepth; + } + } + } +} + } // namespace ModularFrameEncoder::ModularFrameEncoder(const FrameHeader& frame_header, @@ -479,7 +582,6 @@ ModularFrameEncoder::ModularFrameEncoder(const FrameHeader& frame_header, cparams_.options.predictor = Predictor::Gradient; } } else { - delta_pred_ = cparams_.options.predictor; if (cparams_.lossy_palette) cparams_.options.predictor = Predictor::Zero; } if (!cparams_.ModularPartIsLossless()) { @@ -624,6 +726,7 @@ Status ModularFrameEncoder::ComputeEncodingData( pixel_type* const JXL_RESTRICT row_out = gi.channel[c_out].Row(y); pixel_type* const JXL_RESTRICT row_Y = gi.channel[0].Row(y); for (size_t x = 0; x < xsize; ++x) { + // TODO(eustas): check if std::roundf is appropriate row_out[x] = row_in[x] * factor + 0.5f; row_out[x] -= row_Y[x]; // zero the lsb of B @@ -720,81 +823,16 @@ Status ModularFrameEncoder::ComputeEncodingData( cparams_.lossy_palette = false; } - // Global 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(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); - if (maybe_palette.lossy_palette) { - maybe_palette.predictor = delta_pred_; - } - // TODO(veluca): use a custom weighted header if using the weighted - // predictor. - 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) - if (gi.channel.size() - gi.nb_meta_channels > 3) { - 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(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_; - } - maybe_do_transform(gi, maybe_palette_3, cparams_, weighted::Header(), - pool, cparams_.options.zero_tokens); - } - } - - // Global channel palette - if (!groupwise && cparams_.channel_colors_pre_transform_percent > 0 && - !cparams_.lossy_palette && + // Global palette transforms + float channel_colors_percent = 0; + if (!cparams_.lossy_palette && (cparams_.speed_tier <= SpeedTier::kThunder || (do_color && metadata.bit_depth.bits_per_sample > 8))) { - // single channel palette (like FLIF's ChannelCompact) - size_t nb_channels = gi.channel.size() - gi.nb_meta_channels; - int orig_bitdepth = max_bitdepth; - max_bitdepth = 0; - for (size_t i = 0; i < nb_channels; i++) { - int32_t min; - int32_t max; - compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max); - 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; - maybe_palette_1.num_c = 1; - // simple heuristic: if less than X percent of the values in the range - // actually occur, it is probably worth it to do a compaction - // (but only if the channel palette is less than 6% the size of the - // image itself) - maybe_palette_1.nb_colors = std::min( - 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; - int ch_bitdepth = - (max > 0 ? CeilLog2Nonzero(static_cast<uint32_t>(max)) : 0); - if (ch_bitdepth > max_bitdepth) max_bitdepth = ch_bitdepth; - } else - max_bitdepth = orig_bitdepth; - } + channel_colors_percent = cparams_.channel_colors_pre_transform_percent; + } + if (!groupwise) { + try_palettes(gi, max_bitdepth, maxval, cparams_, channel_colors_percent, + pool); } // don't do an RCT if we're short on bits @@ -1318,61 +1356,17 @@ Status ModularFrameEncoder::PrepareStreamParams(const Rect& rect, if (gi.channel.empty()) return true; // Do some per-group transforms - // Local palette + // Local palette transforms // TODO(veluca): make this work with quantize-after-prediction in lossy // mode. - if (cparams_.butteraugli_distance == 0.f && cparams_.palette_colors != 0 && + if (cparams_.butteraugli_distance == 0.f && !cparams_.lossy_palette && cparams_.speed_tier < SpeedTier::kCheetah) { - // 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::abs(cparams_.palette_colors); - maybe_palette.ordered_palette = cparams_.palette_colors >= 0; - maybe_do_transform(gi, maybe_palette, cparams_, weighted::Header()); - } - // all-minus-one-channel palette (RGB with separate alpha, or CMY with - // separate K) - if (gi.channel.size() - gi.nb_meta_channels > 3) { - 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::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 = Predictor::Weighted; - } - maybe_do_transform(gi, maybe_palette_3, cparams_, weighted::Header()); - } - } - - // Local channel palette - if (cparams_.channel_colors_percent > 0 && - cparams_.butteraugli_distance == 0.f && !cparams_.lossy_palette && - cparams_.speed_tier < SpeedTier::kCheetah && - !(cparams_.responsive && cparams_.decoding_speed_tier >= 1)) { - // 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; - int32_t max; - compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max); - 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; - maybe_palette_1.num_c = 1; - // simple heuristic: if less than X percent of the values in the range - // 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( - 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()); + int max_bitdepth = 0, maxval = 0; // don't care about that here + float channel_color_percent = 0; + if (!(cparams_.responsive && cparams_.decoding_speed_tier >= 1)) { + channel_color_percent = cparams_.channel_colors_percent; } + try_palettes(gi, max_bitdepth, maxval, cparams_, channel_color_percent); } } diff --git a/third_party/jpeg-xl/lib/jxl/enc_modular.h b/third_party/jpeg-xl/lib/jxl/enc_modular.h index 8e2015b226..c7a8421982 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_modular.h +++ b/third_party/jpeg-xl/lib/jxl/enc_modular.h @@ -107,7 +107,6 @@ class ModularFrameEncoder { std::vector<size_t> tree_splits_; std::vector<std::vector<uint32_t>> gi_channel_; std::vector<size_t> image_widths_; - Predictor delta_pred_ = Predictor::Average4; struct GroupParams { Rect rect; diff --git a/third_party/jpeg-xl/lib/jxl/enc_params.h b/third_party/jpeg-xl/lib/jxl/enc_params.h index 162c59d04c..5e3ff7789c 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_params.h +++ b/third_party/jpeg-xl/lib/jxl/enc_params.h @@ -106,9 +106,12 @@ struct CompressParams { // modular mode options below ModularOptions options; + + // TODO(eustas): use Override? 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 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 f19ba0dd9e..6fc5f7f49e 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc +++ b/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc @@ -237,9 +237,9 @@ StatusOr<std::vector<PatchInfo>> FindTextLikePatches( auto is_same = [&opsin_rows, opsin_stride](std::pair<uint32_t, uint32_t> p1, std::pair<uint32_t, uint32_t> p2) { - for (size_t c = 0; c < 3; c++) { - float v1 = opsin_rows[c][p1.second * opsin_stride + p1.first]; - float v2 = opsin_rows[c][p2.second * opsin_stride + p2.first]; + for (auto& opsin_row : opsin_rows) { + float v1 = opsin_row[p1.second * opsin_stride + p1.first]; + float v2 = opsin_row[p2.second * opsin_stride + p2.first]; if (std::fabs(v1 - v2) > 1e-4) { return false; } @@ -556,8 +556,8 @@ StatusOr<std::vector<PatchInfo>> FindTextLikePatches( size_t max_patch_size = 0; - for (size_t i = 0; i < info.size(); i++) { - size_t pixels = info[i].first.xsize * info[i].first.ysize; + for (const auto& patch : info) { + size_t pixels = patch.first.xsize * patch.first.ysize; if (pixels > max_patch_size) max_patch_size = pixels; } @@ -605,10 +605,10 @@ Status FindBestPatchDictionary(const Image3F& opsin, size_t max_y_size = 0; size_t total_pixels = 0; - for (size_t i = 0; i < info.size(); i++) { - size_t pixels = info[i].first.xsize * info[i].first.ysize; - if (max_x_size < info[i].first.xsize) max_x_size = info[i].first.xsize; - if (max_y_size < info[i].first.ysize) max_y_size = info[i].first.ysize; + for (const auto& patch : info) { + size_t pixels = patch.first.xsize * patch.first.ysize; + if (max_x_size < patch.first.xsize) max_x_size = patch.first.xsize; + if (max_y_size < patch.first.ysize) max_y_size = patch.first.ysize; total_pixels += pixels; } 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 35e49d5993..978dfd5925 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_quant_weights.cc +++ b/third_party/jpeg-xl/lib/jxl/enc_quant_weights.cc @@ -116,9 +116,9 @@ Status DequantMatricesEncode(const DequantMatrices& matrices, BitWriter* writer, bool all_default = true; const std::vector<QuantEncoding>& encodings = matrices.encodings(); - for (size_t i = 0; i < encodings.size(); i++) { - if (encodings[i].mode != QuantEncoding::kQuantModeLibrary || - encodings[i].predefined != 0) { + for (const auto& encoding : encodings) { + if (encoding.mode != QuantEncoding::kQuantModeLibrary || + encoding.predefined != 0) { all_default = false; } } diff --git a/third_party/jpeg-xl/lib/jxl/enc_splines.cc b/third_party/jpeg-xl/lib/jxl/enc_splines.cc index fa15648ca5..186f19da93 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_splines.cc +++ b/third_party/jpeg-xl/lib/jxl/enc_splines.cc @@ -34,8 +34,8 @@ class QuantizedSplineEncoder { tokens->emplace_back(kDCTContext, PackSigned(dct[i])); } }; - for (int c = 0; c < 3; ++c) { - encode_dct(spline.color_dct_[c]); + for (const auto& dct : spline.color_dct_) { + encode_dct(dct); } encode_dct(spline.sigma_dct_); } diff --git a/third_party/jpeg-xl/lib/jxl/enc_toc.cc b/third_party/jpeg-xl/lib/jxl/enc_toc.cc index e79298ef31..4ecba8fdb1 100644 --- a/third_party/jpeg-xl/lib/jxl/enc_toc.cc +++ b/third_party/jpeg-xl/lib/jxl/enc_toc.cc @@ -32,9 +32,9 @@ Status WriteGroupOffsets(const std::vector<BitWriter>& group_codes, } writer->ZeroPadToByte(); // before TOC entries - for (size_t i = 0; i < group_codes.size(); i++) { - JXL_ASSERT(group_codes[i].BitsWritten() % kBitsPerByte == 0); - const size_t group_size = group_codes[i].BitsWritten() / kBitsPerByte; + for (const auto& bw : group_codes) { + JXL_ASSERT(bw.BitsWritten() % kBitsPerByte == 0); + const size_t group_size = bw.BitsWritten() / kBitsPerByte; JXL_RETURN_IF_ERROR(U32Coder::Write(kTocDist, group_size, writer)); } writer->ZeroPadToByte(); // before first group diff --git a/third_party/jpeg-xl/lib/jxl/encode.cc b/third_party/jpeg-xl/lib/jxl/encode.cc index 4dbbeba4e7..28a925dfc1 100644 --- a/third_party/jpeg-xl/lib/jxl/encode.cc +++ b/third_party/jpeg-xl/lib/jxl/encode.cc @@ -549,8 +549,8 @@ int VerifyLevelSettings(const JxlEncoder* enc, std::string* debug_string) { if (debug_string) *debug_string = "Too many extra channels"; return 10; } - for (size_t i = 0; i < m.extra_channel_info.size(); ++i) { - if (m.extra_channel_info[i].type == jxl::ExtraChannel::kBlack) { + for (const auto& eci : m.extra_channel_info) { + if (eci.type == jxl::ExtraChannel::kBlack) { if (debug_string) *debug_string = "CMYK channel not allowed"; return 10; } @@ -1514,6 +1514,10 @@ float JxlEncoderDistanceFromQuality(float quality) { JxlEncoderStatus JxlEncoderFrameSettingsSetOption( JxlEncoderFrameSettings* frame_settings, JxlEncoderFrameSettingId option, int64_t value) { + // Tri-state to bool convertors. + const auto default_to_true = [](int64_t v) { return v != 0; }; + const auto default_to_false = [](int64_t v) { return v == 1; }; + // check if value is -1, 0 or 1 for Override-type options switch (option) { case JXL_ENC_FRAME_SETTING_NOISE: @@ -1680,7 +1684,7 @@ JxlEncoderStatus JxlEncoderFrameSettingsSetOption( // See the logic in cjxl. Similar for other settings. This should be // handled in the encoder during JxlEncoderProcessOutput (or, // alternatively, in the cjxl binary like now) - frame_settings->values.cparams.lossy_palette = (value == 1); + frame_settings->values.cparams.lossy_palette = default_to_false(value); break; case JXL_ENC_FRAME_SETTING_COLOR_TRANSFORM: if (value < -1 || value > 2) { @@ -1734,11 +1738,8 @@ JxlEncoderStatus JxlEncoderFrameSettingsSetOption( } break; case JXL_ENC_FRAME_SETTING_JPEG_RECON_CFL: - if (value == -1) { - frame_settings->values.cparams.force_cfl_jpeg_recompression = true; - } else { - frame_settings->values.cparams.force_cfl_jpeg_recompression = value; - } + frame_settings->values.cparams.force_cfl_jpeg_recompression = + default_to_true(value); break; case JXL_ENC_FRAME_INDEX_BOX: if (value < 0 || value > 1) { @@ -1752,7 +1753,8 @@ JxlEncoderStatus JxlEncoderFrameSettingsSetOption( "Float option, try setting it with " "JxlEncoderFrameSettingsSetFloatOption"); case JXL_ENC_FRAME_SETTING_JPEG_COMPRESS_BOXES: - frame_settings->values.cparams.jpeg_compress_boxes = value; + frame_settings->values.cparams.jpeg_compress_boxes = + default_to_true(value); break; case JXL_ENC_FRAME_SETTING_BUFFERING: if (value < -1 || value > 3) { @@ -1762,20 +1764,21 @@ JxlEncoderStatus JxlEncoderFrameSettingsSetOption( frame_settings->values.cparams.buffering = value; break; case JXL_ENC_FRAME_SETTING_JPEG_KEEP_EXIF: - frame_settings->values.cparams.jpeg_keep_exif = value; + frame_settings->values.cparams.jpeg_keep_exif = default_to_true(value); break; case JXL_ENC_FRAME_SETTING_JPEG_KEEP_XMP: - frame_settings->values.cparams.jpeg_keep_xmp = value; + frame_settings->values.cparams.jpeg_keep_xmp = default_to_true(value); break; case JXL_ENC_FRAME_SETTING_JPEG_KEEP_JUMBF: - frame_settings->values.cparams.jpeg_keep_jumbf = value; + frame_settings->values.cparams.jpeg_keep_jumbf = default_to_true(value); break; case JXL_ENC_FRAME_SETTING_USE_FULL_IMAGE_HEURISTICS: if (value < 0 || value > 1) { return JXL_API_ERROR(frame_settings->enc, JXL_ENC_ERR_NOT_SUPPORTED, "Option value has to be 0 or 1"); } - frame_settings->values.cparams.use_full_image_heuristics = value; + frame_settings->values.cparams.use_full_image_heuristics = + default_to_false(value); break; default: diff --git a/third_party/jpeg-xl/lib/jxl/encode_test.cc b/third_party/jpeg-xl/lib/jxl/encode_test.cc index 3e519cc45d..0aef5f8aff 100644 --- a/third_party/jpeg-xl/lib/jxl/encode_test.cc +++ b/third_party/jpeg-xl/lib/jxl/encode_test.cc @@ -304,7 +304,7 @@ TEST(EncodeTest, CmsTest) { EXPECT_TRUE(cms_called); } -TEST(EncodeTest, frame_settingsTest) { +TEST(EncodeTest, FrameSettingsTest) { { JxlEncoderPtr enc = JxlEncoderMake(nullptr); EXPECT_NE(nullptr, enc.get()); @@ -451,7 +451,7 @@ TEST(EncodeTest, frame_settingsTest) { JxlEncoderFrameSettingsCreate(enc.get(), nullptr); EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetFrameLossless(frame_settings, JXL_TRUE)); - VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3000, false); + VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3600, false); EXPECT_EQ(true, enc->last_used_cparams.IsLossless()); } @@ -838,20 +838,20 @@ TEST(EncodeTest, SingleFrameBoundedJXLCTest) { bool found_jxlc = false; bool found_jxlp = false; // The encoder is allowed to either emit a jxlc or one or more jxlp. - for (size_t i = 0; i < container.boxes.size(); ++i) { - if (memcmp("jxlc", container.boxes[i].type, 4) == 0) { + for (const auto& box : container.boxes) { + if (memcmp("jxlc", box.type, 4) == 0) { EXPECT_EQ(false, found_jxlc); // Max 1 jxlc EXPECT_EQ(false, found_jxlp); // Can't mix jxlc and jxlp found_jxlc = true; } - if (memcmp("jxlp", container.boxes[i].type, 4) == 0) { + if (memcmp("jxlp", box.type, 4) == 0) { EXPECT_EQ(false, found_jxlc); // Can't mix jxlc and jxlp found_jxlp = true; } // The encoder shouldn't create an unbounded box in this case, with the // single frame it knows the full size in time, so can help make decoding // more efficient by giving the full box size of the final box. - EXPECT_EQ(true, container.boxes[i].data_size_given); + EXPECT_EQ(true, box.data_size_given); } EXPECT_EQ(true, found_jxlc || found_jxlp); } @@ -940,7 +940,7 @@ TEST(EncodeTest, CodestreamLevelVerificationTest) { EXPECT_EQ(JXL_ENC_ERROR, JxlEncoderSetBasicInfo(enc.get(), &basic_info)); } -TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionTest)) { +JXL_TRANSCODE_JPEG_TEST(EncodeTest, JPEGReconstructionTest) { const std::string jpeg_path = "jxl/flower/flower.png.im_q85_420.jpg"; const std::vector<uint8_t> orig = jxl::test::ReadTestData(jpeg_path); @@ -980,7 +980,7 @@ TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionTest)) { EXPECT_EQ(0, memcmp(decoded_jpeg_bytes.data(), orig.data(), orig.size())); } -TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(ProgressiveJPEGReconstructionTest)) { +JXL_TRANSCODE_JPEG_TEST(EncodeTest, ProgressiveJPEGReconstructionTest) { const std::string jpeg_path = "jxl/flower/flower.png.im_q85_420.jpg"; const std::vector<uint8_t> orig = jxl::test::ReadTestData(jpeg_path); @@ -1345,7 +1345,7 @@ TEST(EncodeTest, CroppedFrameTest) { struct EncodeBoxTest : public testing::TestWithParam<std::tuple<bool, size_t>> { }; -TEST_P(EncodeBoxTest, JXL_BOXES_TEST(BoxTest)) { +JXL_BOXES_TEST_P(EncodeBoxTest, BoxTest) { // Test with uncompressed boxes and with brob boxes bool compress_box = std::get<0>(GetParam()); size_t xml_box_size = std::get<1>(GetParam()); @@ -1485,7 +1485,7 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P( jxl::kLargeBoxContentSizeThreshold + 77)), nameBoxTest); -TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGFrameTest)) { +JXL_TRANSCODE_JPEG_TEST(EncodeTest, JPEGFrameTest) { TEST_LIBJPEG_SUPPORT(); for (int skip_basic_info = 0; skip_basic_info < 2; skip_basic_info++) { for (int skip_color_encoding = 0; skip_color_encoding < 2; diff --git a/third_party/jpeg-xl/lib/jxl/entropy_coder_test.cc b/third_party/jpeg-xl/lib/jxl/entropy_coder_test.cc index d32fe1b26b..0389490d8e 100644 --- a/third_party/jpeg-xl/lib/jxl/entropy_coder_test.cc +++ b/third_party/jpeg-xl/lib/jxl/entropy_coder_test.cc @@ -27,7 +27,7 @@ TEST(EntropyCoderTest, PackUnpack) { struct MockBitReader { uint32_t nbits, bits; void Consume(uint32_t nbits) {} - uint32_t PeekBits(uint32_t n) { + uint32_t PeekBits(uint32_t n) const { EXPECT_EQ(n, nbits); return bits; } diff --git a/third_party/jpeg-xl/lib/jxl/gradient_test.cc b/third_party/jpeg-xl/lib/jxl/gradient_test.cc index d2c83619fc..e09b34603f 100644 --- a/third_party/jpeg-xl/lib/jxl/gradient_test.cc +++ b/third_party/jpeg-xl/lib/jxl/gradient_test.cc @@ -186,13 +186,13 @@ constexpr bool fast_mode = true; TEST(GradientTest, SteepGradient) { test::ThreadPoolForTests pool(8); // Relatively steep gradients, colors from the sky of stp.png - TestGradient(&pool, 0xd99d58, 0x889ab1, 512, 512, 90, fast_mode, 3.0); + TestGradient(pool.get(), 0xd99d58, 0x889ab1, 512, 512, 90, fast_mode, 3.0); } TEST(GradientTest, SubtleGradient) { test::ThreadPoolForTests pool(8); // Very subtle gradient - TestGradient(&pool, 0xb89b7b, 0xa89b8d, 512, 512, 90, fast_mode, 4.0); + TestGradient(pool.get(), 0xb89b7b, 0xa89b8d, 512, 512, 90, fast_mode, 4.0); } } // namespace diff --git a/third_party/jpeg-xl/lib/jxl/icc_codec.h b/third_party/jpeg-xl/lib/jxl/icc_codec.h index 8b880c7d3b..3b0b0c041b 100644 --- a/third_party/jpeg-xl/lib/jxl/icc_codec.h +++ b/third_party/jpeg-xl/lib/jxl/icc_codec.h @@ -28,7 +28,7 @@ struct ICCReader { } private: - Status CheckEOI(BitReader* reader); + static Status CheckEOI(BitReader* reader); size_t i_ = 0; size_t bits_to_skip_ = 0; size_t used_bits_base_ = 0; diff --git a/third_party/jpeg-xl/lib/jxl/jpeg/dec_jpeg_data.cc b/third_party/jpeg-xl/lib/jxl/jpeg/dec_jpeg_data.cc index 9763786453..a971eb3dcc 100644 --- a/third_party/jpeg-xl/lib/jxl/jpeg/dec_jpeg_data.cc +++ b/third_party/jpeg-xl/lib/jxl/jpeg/dec_jpeg_data.cc @@ -106,15 +106,14 @@ Status DecodeJPEGData(Span<const uint8_t> encoded, JPEGData* jpeg_data) { } } // TODO(eustas): actually inject ICC profile and check it fits perfectly. - for (size_t i = 0; i < jpeg_data->com_data.size(); i++) { - auto& marker = jpeg_data->com_data[i]; + for (auto& marker : jpeg_data->com_data) { JXL_RETURN_IF_ERROR(br_read(marker)); if (marker[1] * 256u + marker[2] + 1u != marker.size()) { return JXL_FAILURE("Incorrect marker size"); } } - for (size_t i = 0; i < jpeg_data->inter_marker_data.size(); i++) { - JXL_RETURN_IF_ERROR(br_read(jpeg_data->inter_marker_data[i])); + for (auto& data : jpeg_data->inter_marker_data) { + JXL_RETURN_IF_ERROR(br_read(data)); } JXL_RETURN_IF_ERROR(br_read(jpeg_data->tail_data)); 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 31bb2dda23..77c8b885e1 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 @@ -385,8 +385,8 @@ bool EncodeDHT(const JPEGData& jpg, SerializationState* state) { for (size_t i = state->dht_index; i < huffman_code.size(); ++i) { const JPEGHuffmanCode& huff = huffman_code[i]; marker_len += kJpegHuffmanMaxBitLength; - for (size_t j = 0; j < huff.counts.size(); ++j) { - marker_len += huff.counts[j]; + for (uint32_t count : huff.counts) { + marker_len += count; } if (huff.is_last) break; } 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 d311908415..d7c6c2ad78 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 @@ -173,8 +173,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++) { - const auto& marker = jpeg_data.app_data[i]; + for (const auto& marker : jpeg_data.app_data) { if (marker.empty() || marker[0] != kApp1) { continue; } @@ -318,11 +317,11 @@ Status EncodeJPEGData(JPEGData& jpeg_data, std::vector<uint8_t>* bytes, } total_data += jpeg_data.app_data[i].size(); } - for (size_t i = 0; i < jpeg_data.com_data.size(); i++) { - total_data += jpeg_data.com_data[i].size(); + for (const auto& data : jpeg_data.com_data) { + total_data += data.size(); } - for (size_t i = 0; i < jpeg_data.inter_marker_data.size(); i++) { - total_data += jpeg_data.inter_marker_data[i].size(); + for (const auto& data : jpeg_data.inter_marker_data) { + total_data += data.size(); } total_data += jpeg_data.tail_data.size(); size_t brotli_capacity = BrotliEncoderMaxCompressedSize(total_data); @@ -365,11 +364,11 @@ Status EncodeJPEGData(JPEGData& jpeg_data, std::vector<uint8_t>* bytes, } br_append(jpeg_data.app_data[i], /*last=*/false); } - for (size_t i = 0; i < jpeg_data.com_data.size(); i++) { - br_append(jpeg_data.com_data[i], /*last=*/false); + for (const auto& data : jpeg_data.com_data) { + br_append(data, /*last=*/false); } - for (size_t i = 0; i < jpeg_data.inter_marker_data.size(); i++) { - br_append(jpeg_data.inter_marker_data[i], /*last=*/false); + for (const auto& data : jpeg_data.inter_marker_data) { + br_append(data, /*last=*/false); } br_append(jpeg_data.tail_data, /*last=*/true); BrotliEncoderDestroyInstance(brotli_enc); 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 d1e8476db6..8208bba675 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 @@ -92,21 +92,21 @@ bool ProcessSOF(const uint8_t* data, const size_t len, JpegReadMode mode, std::vector<bool> ids_seen(256, false); int max_h_samp_factor = 1; int max_v_samp_factor = 1; - for (size_t i = 0; i < jpg->components.size(); ++i) { + for (auto& component : jpg->components) { const int id = ReadUint8(data, pos); if (ids_seen[id]) { // (cf. section B.2.2, syntax of Ci) return JXL_FAILURE("Duplicate ID %d in SOF.", id); } ids_seen[id] = true; - jpg->components[i].id = id; + component.id = id; int factor = ReadUint8(data, pos); int h_samp_factor = factor >> 4; int v_samp_factor = factor & 0xf; JXL_JPEG_VERIFY_INPUT(h_samp_factor, 1, kBrunsliMaxSampling, SAMP_FACTOR); JXL_JPEG_VERIFY_INPUT(v_samp_factor, 1, kBrunsliMaxSampling, SAMP_FACTOR); - jpg->components[i].h_samp_factor = h_samp_factor; - jpg->components[i].v_samp_factor = v_samp_factor; - jpg->components[i].quant_idx = ReadUint8(data, pos); + component.h_samp_factor = h_samp_factor; + component.v_samp_factor = v_samp_factor; + component.quant_idx = ReadUint8(data, pos); max_h_samp_factor = std::max(max_h_samp_factor, h_samp_factor); max_v_samp_factor = std::max(max_v_samp_factor, v_samp_factor); } @@ -116,18 +116,17 @@ bool ProcessSOF(const uint8_t* data, const size_t len, JpegReadMode mode, int MCU_rows = DivCeil(jpg->height, max_v_samp_factor * 8); int MCU_cols = DivCeil(jpg->width, max_h_samp_factor * 8); // Compute the block dimensions for each component. - for (size_t i = 0; i < jpg->components.size(); ++i) { - JPEGComponent* c = &jpg->components[i]; - if (max_h_samp_factor % c->h_samp_factor != 0 || - max_v_samp_factor % c->v_samp_factor != 0) { + for (JPEGComponent& c : jpg->components) { + if (max_h_samp_factor % c.h_samp_factor != 0 || + max_v_samp_factor % c.v_samp_factor != 0) { return JXL_FAILURE("Non-integral subsampling ratios."); } - c->width_in_blocks = MCU_cols * c->h_samp_factor; - c->height_in_blocks = MCU_rows * c->v_samp_factor; + c.width_in_blocks = MCU_cols * c.h_samp_factor; + c.height_in_blocks = MCU_rows * c.v_samp_factor; const uint64_t num_blocks = - static_cast<uint64_t>(c->width_in_blocks) * c->height_in_blocks; + static_cast<uint64_t>(c.width_in_blocks) * c.height_in_blocks; if (mode == JpegReadMode::kReadAll) { - c->coeffs.resize(num_blocks * kDCTBlockSize); + c.coeffs.resize(num_blocks * kDCTBlockSize); } } JXL_JPEG_VERIFY_MARKER_END(); @@ -192,8 +191,8 @@ bool ProcessSOS(const uint8_t* data, const size_t len, size_t* pos, for (size_t i = 0; i < comps_in_scan; ++i) { bool found_dc_table = false; bool found_ac_table = false; - for (size_t j = 0; j < jpg->huffman_code.size(); ++j) { - uint32_t slot_id = jpg->huffman_code[j].slot_id; + for (const auto& code : jpg->huffman_code) { + uint32_t slot_id = code.slot_id; if (slot_id == scan_info.components[i].dc_tbl_idx) { found_dc_table = true; } else if (slot_id == scan_info.components[i].ac_tbl_idx + 16) { @@ -757,11 +756,9 @@ bool ProcessScan(const uint8_t* data, const size_t len, bool is_interleaved = (scan_info->num_components > 1); int max_h_samp_factor = 1; int max_v_samp_factor = 1; - for (size_t i = 0; i < jpg->components.size(); ++i) { - max_h_samp_factor = - std::max(max_h_samp_factor, jpg->components[i].h_samp_factor); - max_v_samp_factor = - std::max(max_v_samp_factor, jpg->components[i].v_samp_factor); + for (const auto& component : jpg->components) { + max_h_samp_factor = std::max(max_h_samp_factor, component.h_samp_factor); + max_v_samp_factor = std::max(max_v_samp_factor, component.v_samp_factor); } int MCU_rows = DivCeil(jpg->height, max_v_samp_factor * 8); 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 aeb9914cca..3217115acb 100644 --- a/third_party/jpeg-xl/lib/jxl/jpeg/jpeg_data.cc +++ b/third_party/jpeg-xl/lib/jxl/jpeg/jpeg_data.cc @@ -78,8 +78,8 @@ Status JPEGData::VisitFields(Visitor* visitor) { if (marker_order.size() > 16384) { return JXL_FAILURE("Too many markers: %" PRIuS "\n", marker_order.size()); } - for (size_t i = 0; i < marker_order.size(); i++) { - JXL_RETURN_IF_ERROR(VisitMarker(&marker_order[i], visitor, &info)); + for (uint8_t& marker : marker_order) { + JXL_RETURN_IF_ERROR(VisitMarker(&marker, visitor, &info)); } if (!marker_order.empty()) { // Last marker should always be EOI marker. @@ -175,8 +175,8 @@ Status JPEGData::VisitFields(Visitor* visitor) { components.resize(num_components); } if (component_type == JPEGComponentType::kCustom) { - for (size_t i = 0; i < components.size(); i++) { - JXL_RETURN_IF_ERROR(visitor->Bits(8, 0, &components[i].id)); + for (auto& component : components) { + JXL_RETURN_IF_ERROR(visitor->Bits(8, 0, &component.id)); } } else if (component_type == JPEGComponentType::kGray) { components[0].id = 1; @@ -322,11 +322,11 @@ Status JPEGData::VisitFields(Visitor* visitor) { scan.extra_zero_runs.resize(num_extra_zero_runs); } last_block_idx = -1; - for (size_t i = 0; i < scan.extra_zero_runs.size(); ++i) { - uint32_t& block_idx = scan.extra_zero_runs[i].block_idx; - JXL_RETURN_IF_ERROR(visitor->U32( - Val(1), BitsOffset(2, 2), BitsOffset(4, 5), BitsOffset(8, 20), 1, - &scan.extra_zero_runs[i].num_extra_zero_runs)); + for (auto& extra_zero_run : scan.extra_zero_runs) { + uint32_t& block_idx = extra_zero_run.block_idx; + JXL_RETURN_IF_ERROR(visitor->U32(Val(1), BitsOffset(2, 2), + BitsOffset(4, 5), BitsOffset(8, 20), 1, + &extra_zero_run.num_extra_zero_runs)); block_idx -= last_block_idx + 1; JXL_RETURN_IF_ERROR(visitor->U32(Val(0), BitsOffset(3, 1), BitsOffset(5, 9), BitsOffset(28, 41), 0, diff --git a/third_party/jpeg-xl/lib/jxl/jxl_test.cc b/third_party/jpeg-xl/lib/jxl/jxl_test.cc index b0933d5d50..cf9857f462 100644 --- a/third_party/jpeg-xl/lib/jxl/jxl_test.cc +++ b/third_party/jpeg-xl/lib/jxl/jxl_test.cc @@ -179,7 +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), 203300, 2000); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 203300, + 2000); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 340); } @@ -286,8 +287,8 @@ TEST(JxlTest, RoundtripMultiGroup) { cparams.distance = target_distance; PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), expected_size, - 700); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), + expected_size, 700); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), expected_distance); }; @@ -302,7 +303,7 @@ TEST(JxlTest, RoundtripRGBToGrayscale) { ThreadPoolForTests pool(4); const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png"); CodecInOut io; - ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool)); + ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get())); io.ShrinkTo(600, 1024); CompressParams cparams; @@ -316,7 +317,7 @@ TEST(JxlTest, RoundtripRGBToGrayscale) { EXPECT_FALSE(io.Main().IsGray()); size_t compressed_size; JXL_EXPECT_OK( - Roundtrip(&io, cparams, dparams, &io2, _, &compressed_size, &pool)); + Roundtrip(&io, cparams, dparams, &io2, _, &compressed_size, pool.get())); EXPECT_LE(compressed_size, 65000u); EXPECT_TRUE(io2.Main().IsGray()); @@ -341,7 +342,7 @@ TEST(JxlTest, RoundtripRGBToGrayscale) { EXPECT_SLIGHTLY_BELOW( ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), *JxlGetDefaultCms(), - /*distmap=*/nullptr, &pool), + /*distmap=*/nullptr, pool.get()), 1.4); } @@ -355,11 +356,12 @@ TEST(JxlTest, RoundtripLargeFast) { cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 7); // kSquirrel PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 503000, 12000); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 503000, + 12000); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 78); } -TEST(JxlTest, JXL_X86_64_TEST(RoundtripLargeEmptyModular)) { +JXL_X86_64_TEST(JxlTest, RoundtripLargeEmptyModular) { ThreadPoolForTests pool(8); TestImage t; t.SetDimensions(4096, 4096).SetDataType(JXL_TYPE_UINT8).SetChannels(4); @@ -380,7 +382,7 @@ TEST(JxlTest, JXL_X86_64_TEST(RoundtripLargeEmptyModular)) { cparams.AddOption(JXL_ENC_FRAME_SETTING_DECODING_SPEED, 2); PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 3474795, + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 3474795, 100000); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), #if JXL_HIGH_PRECISION @@ -403,8 +405,8 @@ TEST(JxlTest, RoundtripOutputColorSpace) { 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_NEAR(Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out), + 503000, 12000); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 78); } @@ -421,7 +423,8 @@ TEST(JxlTest, RoundtripDotsForceEpf) { cparams.AddOption(JXL_ENC_FRAME_SETTING_DOTS, 1); PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 41355, 300); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 41355, + 300); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 18); } @@ -443,10 +446,10 @@ TEST(JxlTest, RoundtripD2Consistent) { t.SetDimensions(xsize, 15); PackedPixelFile ppf2; - const size_t size2 = Roundtrip(t.ppf(), cparams, {}, &pool, &ppf2); + const size_t size2 = Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf2); PackedPixelFile ppf3; - const size_t size3 = Roundtrip(t.ppf(), cparams, {}, &pool, &ppf3); + const size_t size3 = Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf3); // Exact same compressed size. EXPECT_EQ(size2, size3); @@ -471,7 +474,7 @@ TEST(JxlTest, RoundtripLargeConsistent) { auto roundtrip_and_compare = [&]() { ThreadPoolForTests pool(8); PackedPixelFile ppf2; - size_t size = Roundtrip(t.ppf(), cparams, {}, &pool, &ppf2); + size_t size = Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf2); double dist = ComputeDistance2(t.ppf(), ppf2); return std::tuple<size_t, double>(size, dist); }; @@ -985,7 +988,7 @@ TEST(JxlTest, RoundtripAlpha16) { 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_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 3666, 120); EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.65); } @@ -1000,7 +1003,7 @@ JXLCompressParams CompressParamsForLossless() { } } // namespace -TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8)) { +JXL_SLOW_TEST(JxlTest, RoundtripLossless8) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_srgb8.png"); @@ -1012,11 +1015,11 @@ TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8)) { dparams.accepted_formats.push_back(t.ppf().frames[0].color.format); PackedPixelFile ppf_out; - EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), 223058); + EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out), 223058); EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0); } -TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8ThunderGradient)) { +JXL_SLOW_TEST(JxlTest, RoundtripLossless8ThunderGradient) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_srgb8.png"); @@ -1030,11 +1033,11 @@ TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8ThunderGradient)) { dparams.accepted_formats.push_back(t.ppf().frames[0].color.format); PackedPixelFile ppf_out; - EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), 261684); + EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out), 261684); EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0); } -TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8LightningGradient)) { +JXL_SLOW_TEST(JxlTest, RoundtripLossless8LightningGradient) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_srgb8.png"); @@ -1048,12 +1051,12 @@ TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8LightningGradient)) { PackedPixelFile ppf_out; // Lax comparison because different SIMD will cause different compression. - EXPECT_SLIGHTLY_BELOW(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), - 286848u); + EXPECT_SLIGHTLY_BELOW( + Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out), 286848u); EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0); } -TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8Falcon)) { +JXL_SLOW_TEST(JxlTest, RoundtripLossless8Falcon) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_srgb8.png"); @@ -1066,7 +1069,7 @@ TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8Falcon)) { dparams.accepted_formats.push_back(t.ppf().frames[0].color.format); PackedPixelFile ppf_out; - EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), 230766); + EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out), 230766); EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0); } @@ -1348,15 +1351,15 @@ void RoundtripJpegToPixels(const std::vector<uint8_t>& jpeg_in, nullptr, ppf_out, nullptr)); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression444)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression444) { ThreadPoolForTests pool(8); 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), 568891u, 20); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 568891u, 20); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionToPixels) { TEST_LIBJPEG_SUPPORT(); ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = @@ -1365,11 +1368,11 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels)) { t.DecodeFromBytes(orig); PackedPixelFile ppf_out; - RoundtripJpegToPixels(orig, {}, &pool, &ppf_out); + RoundtripJpegToPixels(orig, {}, pool.get(), &ppf_out); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 12); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionToPixels420) { TEST_LIBJPEG_SUPPORT(); ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = @@ -1378,12 +1381,12 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420)) { t.DecodeFromBytes(orig); PackedPixelFile ppf_out; - RoundtripJpegToPixels(orig, {}, &pool, &ppf_out); + RoundtripJpegToPixels(orig, {}, pool.get(), &ppf_out); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 11); } -TEST(JxlTest, - JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420EarlyFlush)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, + RoundtripJpegRecompressionToPixels420EarlyFlush) { TEST_LIBJPEG_SUPPORT(); ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = @@ -1395,12 +1398,11 @@ TEST(JxlTest, dparams.max_downsampling = 8; PackedPixelFile ppf_out; - RoundtripJpegToPixels(orig, dparams, &pool, &ppf_out); + RoundtripJpegToPixels(orig, dparams, pool.get(), &ppf_out); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 4410); } -TEST(JxlTest, - JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420Mul16)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionToPixels420Mul16) { TEST_LIBJPEG_SUPPORT(); ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = @@ -1409,12 +1411,11 @@ TEST(JxlTest, t.DecodeFromBytes(orig); PackedPixelFile ppf_out; - RoundtripJpegToPixels(orig, {}, &pool, &ppf_out); + RoundtripJpegToPixels(orig, {}, pool.get(), &ppf_out); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 4); } -TEST(JxlTest, - JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels_asymmetric)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionToPixelsAsymmetric) { TEST_LIBJPEG_SUPPORT(); ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = @@ -1423,102 +1424,100 @@ TEST(JxlTest, t.DecodeFromBytes(orig); PackedPixelFile ppf_out; - RoundtripJpegToPixels(orig, {}, &pool, &ppf_out); + RoundtripJpegToPixels(orig, {}, pool.get(), &ppf_out); EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 10); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionGray)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionGray) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png.im_q85_gray.jpg"); // JPEG size is 456,528 bytes. - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 387496u, 200); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 387496u, 200); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression420)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression420) { ThreadPoolForTests pool(8); 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), 455510u, 20); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 455510u, 20); } -TEST(JxlTest, - JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression_luma_subsample)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionLumaSubsample) { ThreadPoolForTests pool(8); 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), 325310u, 20); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 325310u, 20); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression444_12)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression444wh12) { // 444 JPEG that has an interesting sampling-factor (1x2, 1x2, 1x2). ThreadPoolForTests pool(8); 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), 569630u, 20); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 569630u, 20); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression422)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression422) { ThreadPoolForTests pool(8); 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), 499236u, 20); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 499236u, 20); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression440)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression440) { ThreadPoolForTests pool(8); 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), 501101u, 20); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 501101u, 20); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression_asymmetric)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionAsymmetric) { // 2x vertical downsample of one chroma channel, 2x horizontal downsample of // the other. ThreadPoolForTests pool(8); 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), 500548u, 20); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 500548u, 20); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression420Progr)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression420Progr) { ThreadPoolForTests pool(8); 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), 455454u, 20); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 455454u, 20); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionMetadata)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionMetadata) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("jxl/jpeg_reconstruction/1x1_exif_xmp.jpg"); // JPEG size is 4290 bytes // 1370 on 386, so higher margin. - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 1334u, 100); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 1334u, 100); } -TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionRestarts)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionRestarts) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("jxl/jpeg_reconstruction/bicycles_restarts.jpg"); // JPEG size is 87478 bytes - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 76054u, 30); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 76054u, 30); } -TEST(JxlTest, - JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionOrientationICC)) { +JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionOrientationICC) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("jxl/jpeg_reconstruction/sideways_bench.jpg"); // JPEG size is 15252 bytes - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 12000u, 470); + EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 12000u, 470); // TODO(jon): investigate why 'Cross-compiling i686-linux-gnu' produces a // larger result } @@ -1535,7 +1534,8 @@ TEST(JxlTest, RoundtripProgressive) { cparams.AddOption(JXL_ENC_FRAME_SETTING_RESPONSIVE, 1); PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 70544, 750); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 70544, + 750); EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.4); } @@ -1552,7 +1552,8 @@ TEST(JxlTest, RoundtripProgressiveLevel2Slow) { cparams.AddOption(JXL_ENC_FRAME_SETTING_RESPONSIVE, 1); PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 76666, 1000); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 76666, + 1000); EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.17); } @@ -1639,7 +1640,7 @@ TEST_P(JxlTest, LosslessSmallFewColors) { dparams.accepted_formats.push_back(t.ppf().frames[0].color.format); PackedPixelFile ppf_out; - Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out); + Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out); EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0); } @@ -1708,7 +1709,7 @@ TEST_P(JxlStreamingTest, Roundtrip) { ThreadPoolForTests pool(8); PackedPixelFile ppf_out; - Roundtrip(image.ppf(), cparams, {}, &pool, &ppf_out); + Roundtrip(image.ppf(), cparams, {}, pool.get(), &ppf_out); EXPECT_GT(jxl::test::ComputePSNR(image.ppf(), ppf_out), p.max_psnr()); } @@ -1763,7 +1764,7 @@ class JxlStreamingEncodingTest : public ::testing::TestWithParam<StreamingEncodingTestParam> {}; // This is broken on mingw32, so we only enable it for x86_64 now. -TEST_P(JxlStreamingEncodingTest, JXL_X86_64_TEST(StreamingSamePixels)) { +JXL_X86_64_TEST_P(JxlStreamingEncodingTest, StreamingSamePixels) { const auto param = GetParam(); const std::vector<uint8_t> orig = ReadTestData(param.file); @@ -1780,11 +1781,11 @@ TEST_P(JxlStreamingEncodingTest, JXL_X86_64_TEST(StreamingSamePixels)) { ThreadPoolForTests pool(8); PackedPixelFile ppf_out; - Roundtrip(image.ppf(), cparams, {}, &pool, &ppf_out); + Roundtrip(image.ppf(), cparams, {}, pool.get(), &ppf_out); cparams.AddOption(JXL_ENC_FRAME_SETTING_BUFFERING, 3); PackedPixelFile ppf_out_streaming; - Roundtrip(image.ppf(), cparams, {}, &pool, &ppf_out_streaming); + Roundtrip(image.ppf(), cparams, {}, pool.get(), &ppf_out_streaming); EXPECT_TRUE(jxl::test::SamePixels(ppf_out, ppf_out_streaming)); } diff --git a/third_party/jpeg-xl/lib/jxl/lehmer_code_test.cc b/third_party/jpeg-xl/lib/jxl/lehmer_code_test.cc index acda762545..c7752d8cfc 100644 --- a/third_party/jpeg-xl/lib/jxl/lehmer_code_test.cc +++ b/third_party/jpeg-xl/lib/jxl/lehmer_code_test.cc @@ -88,10 +88,10 @@ void RoundtripSizeRange(ThreadPool* pool, uint32_t begin, uint32_t end) { TEST(LehmerCodeTest, TestRoundtrips) { test::ThreadPoolForTests pool(8); - RoundtripSizeRange<uint16_t>(&pool, 1, 1026); + RoundtripSizeRange<uint16_t>(pool.get(), 1, 1026); // Ensures PermutationT can fit > 16 bit values. - RoundtripSizeRange<uint32_t>(&pool, 65536, 65540); + RoundtripSizeRange<uint32_t>(pool.get(), 65536, 65540); } } // namespace 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 7bec5128fc..df54a9425e 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 @@ -63,7 +63,7 @@ struct State { pixel_type_w pred = 0; // *before* removing the added bits. std::vector<uint32_t> pred_errors[kNumPredictors]; std::vector<int32_t> error; - const Header header; + const Header &header; // Allows to approximate division by a number from 1 to 64. // for (int i = 0; i < 64; i++) divlookup[i] = (1 << 24) / (i + 1); @@ -82,7 +82,7 @@ struct State { return static_cast<uint64_t>(x) << kPredExtraBits; } - State(Header header, size_t xsize, size_t ysize) : header(header) { + State(const 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 (auto &pred_error : pred_errors) { 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 de629ad038..23100bba8b 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 @@ -197,7 +197,7 @@ void FindBestSplit(TreeSamples &tree_samples, float threshold, float rcost = std::numeric_limits<float>::max(); Predictor lpred = Predictor::Zero; Predictor rpred = Predictor::Zero; - float Cost() { return lcost + rcost; } + float Cost() const { return lcost + rcost; } }; SplitInfo best_split_static_constant; @@ -242,14 +242,14 @@ void FindBestSplit(TreeSamples &tree_samples, float threshold, // The multiplier ranges cut halfway through the current ranges of static // 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++) { + for (const auto &mmi : mul_info) { uint32_t axis; uint32_t val; IntersectionType t = - BoxIntersects(static_prop_range, mul_info[i].range, axis, val); + BoxIntersects(static_prop_range, mmi.range, axis, val); if (t == IntersectionType::kNone) continue; if (t == IntersectionType::kInside) { - (*tree)[pos].multiplier = mul_info[i].multiplier; + (*tree)[pos].multiplier = mmi.multiplier; break; } if (t == IntersectionType::kPartial) { 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 bb690b74ba..7e7aa019e3 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc @@ -113,7 +113,7 @@ FlatTree FilterTree(const Tree &global_tree, } } - for (size_t j = 0; j < 2; j++) mark_property(flat.properties[j]); + for (int16_t property : flat.properties) mark_property(property); mark_property(flat.property0); output.push_back(flat); } @@ -159,9 +159,9 @@ Status DecodeModularChannelMAANS(BitReader *br, ANSSymbolReader *reader, // From here on, tree lookup returns a *clustered* context ID. // This avoids an extra memory lookup after tree traversal. - for (size_t i = 0; i < tree.size(); i++) { - if (tree[i].property0 == -1) { - tree[i].childID = context_map[tree[i].childID]; + for (auto &node : tree) { + if (node.property0 == -1) { + node.childID = context_map[node.childID]; } } @@ -538,8 +538,8 @@ Status ModularDecode(BitReader *br, Image &image, GroupHeader &header, // Don't do/undo transforms if header is incomplete. header.transforms.clear(); image.transform = header.transforms; - for (size_t c = 0; c < image.channel.size(); c++) { - ZeroFillImage(&image.channel[c].plane); + for (auto &ch : image.channel) { + ZeroFillImage(&ch.plane); } return Status(StatusCode::kNotEnoughBytes); } 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 24c64f5aad..7f9399d3c4 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 @@ -68,8 +68,8 @@ static int QuantizeColorToImplicitPaletteIndex( int index = 0; if (high_quality) { int multiplier = 1; - for (size_t c = 0; c < color.size(); c++) { - int quantized = ((kLargeCube - 1) * color[c] + (1 << (bit_depth - 1))) / + for (int value : color) { + int quantized = ((kLargeCube - 1) * value + (1 << (bit_depth - 1))) / ((1 << bit_depth) - 1); JXL_ASSERT((quantized % kLargeCube) == quantized); index += quantized * multiplier; @@ -78,8 +78,7 @@ static int QuantizeColorToImplicitPaletteIndex( return index + palette_size + kLargeCubeOffset; } else { int multiplier = 1; - for (size_t c = 0; c < color.size(); c++) { - int value = color[c]; + for (int value : color) { value -= 1 << (std::max(0, bit_depth - 3)); value = std::max(0, value); int quantized = ((kLargeCube - 1) * value + (1 << (bit_depth - 1))) / @@ -171,6 +170,7 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, size_t w = input.channel[begin_c].w; size_t h = input.channel[begin_c].h; + if (!lossy && nb_colors < 2) return false; if (!lossy && nb == 1) { // Channel palette special case @@ -321,6 +321,20 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, } } + std::map<std::vector<pixel_type>, bool> implicit_color; + std::vector<std::vector<pixel_type>> implicit_colors; + implicit_colors.reserve(palette_internal::kImplicitPaletteSize); + for (size_t k = 0; k < palette_internal::kImplicitPaletteSize; k++) { + for (size_t i = 0; i < nb; i++) { + color[i] = palette_internal::GetPaletteValue(nullptr, k, i, 0, 0, + input.bitdepth); + } + implicit_color[color] = true; + implicit_colors.push_back(color); + } + + std::map<std::vector<pixel_type>, size_t> color_freq_map; + uint32_t implicit_colors_used = 0; for (size_t y = 0; y < h; y++) { for (uint32_t c = 0; c < nb; c++) { p_in[c] = input.channel[begin_c + c].Row(y); @@ -332,15 +346,39 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, } const bool new_color = candidate_palette.insert(color).second; if (new_color) { - candidate_palette_imageorder.push_back(color); - } - if (candidate_palette.size() > nb_colors) { - return false; // too many colors + if (implicit_color[color]) { + implicit_colors_used++; + } else { + candidate_palette_imageorder.push_back(color); + if (candidate_palette_imageorder.size() > nb_colors) { + return false; // too many colors + } + } } + color_freq_map[color] += 1; } } - nb_colors = nb_deltas + candidate_palette.size(); + nb_colors = nb_deltas + candidate_palette_imageorder.size(); + + // not useful to make a single-color palette + if (!lossy && nb_colors + implicit_colors_used == 1) return false; + // TODO(jon): if this happens (e.g. solid white group), special-case it for + // faster encode + + for (size_t k = 0; k < palette_internal::kImplicitPaletteSize; k++) { + color = implicit_colors[k]; + // still add the color to the explicit palette if it is frequent enough + if (color_freq_map[color] > 10) { + nb_colors++; + candidate_palette_imageorder.push_back(color); + } + } + for (size_t k = 0; k < palette_internal::kImplicitPaletteSize; k++) { + color = implicit_colors[k]; + inv_palette[color] = nb_colors + k; + } + JXL_DEBUG_V(6, "Channels %i-%i can be represented using a %i-color palette.", begin_c, end_c, nb_colors); @@ -360,25 +398,33 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, } } } - + // Separate the palette in two buckets, first the common colors, then the + // rare colors. + // Within each bucket, the colors are sorted on luma (times alpha). + float freq_threshold = 4; // arbitrary threshold int x = 0; if (ordered && nb >= 3) { JXL_DEBUG_V(7, "Palette of %i colors, using luma order", nb_colors); // sort on luma (multiplied by alpha if available) std::sort(candidate_palette_imageorder.begin(), candidate_palette_imageorder.end(), - [](std::vector<pixel_type> ap, std::vector<pixel_type> bp) { + [&](std::vector<pixel_type> ap, std::vector<pixel_type> bp) { 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); if (bp.size() > 3) by *= 1.f + bp[3]; + // put common colors first, transparent dark to opaque bright, + // then rare colors, bright to dark + ay = color_freq_map[ap] > freq_threshold ? -ay : ay; + by = color_freq_map[bp] > freq_threshold ? -by : by; return ay < by; }); } else { JXL_DEBUG_V(7, "Palette of %i colors, using image order", nb_colors); } + for (auto pcol : candidate_palette_imageorder) { JXL_DEBUG_V(9, " Color %i : ", x); for (size_t i = 0; i < nb; i++) { @@ -398,10 +444,10 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, // beneficial for both precision and encoding speed. std::vector<std::vector<float>> error_row[3]; if (lossy) { - for (int i = 0; i < 3; ++i) { - error_row[i].resize(nb); + for (auto &row : error_row) { + row.resize(nb); for (size_t c = 0; c < nb; ++c) { - error_row[i][c].resize(w + 4); + row[c].resize(w + 4); } } } @@ -424,13 +470,11 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, std::vector<pixel_type> ideal_residual(nb, 0); std::vector<pixel_type> quantized_val(nb); std::vector<pixel_type> predictions(nb); - static const double kDiffusionMultiplier[] = {0.55, 0.75}; - for (int diffusion_index = 0; diffusion_index < 2; ++diffusion_index) { + for (double diffusion_multiplier : {0.55, 0.75}) { for (size_t c = 0; c < nb; c++) { color_with_error[c] = p_in[c][x] + (palette_iteration_data.final_run ? 1 : 0) * - kDiffusionMultiplier[diffusion_index] * - error_row[0][c][x + 2]; + diffusion_multiplier * error_row[0][c][x + 2]; color[c] = Clamp1(lroundf(color_with_error[c]), 0l, (1l << input.bitdepth) - 1); } 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 0d924c0ace..7371830743 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 @@ -124,13 +124,13 @@ Status FwdSqueeze(Image &input, std::vector<SqueezeParams> parameters, } // if nothing to do, don't do squeeze if (parameters.empty()) return false; - for (size_t i = 0; i < parameters.size(); i++) { + for (auto ¶meter : parameters) { JXL_RETURN_IF_ERROR( - CheckMetaSqueezeParams(parameters[i], input.channel.size())); - bool horizontal = parameters[i].horizontal; - bool in_place = parameters[i].in_place; - uint32_t beginc = parameters[i].begin_c; - uint32_t endc = parameters[i].begin_c + parameters[i].num_c - 1; + CheckMetaSqueezeParams(parameter, input.channel.size())); + bool horizontal = parameter.horizontal; + bool in_place = parameter.in_place; + uint32_t beginc = parameter.begin_c; + uint32_t endc = parameter.begin_c + parameter.num_c - 1; uint32_t offset; if (in_place) { offset = endc + 1; 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 e0405a2162..2a9e5c71f4 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h @@ -30,6 +30,8 @@ static constexpr int kSmallCube = 4; static constexpr int kSmallCubeBits = 2; // kSmallCube ** 3 static constexpr int kLargeCubeOffset = kSmallCube * kSmallCube * kSmallCube; +static constexpr int kImplicitPaletteSize = + kLargeCubeOffset + kLargeCube * kLargeCube * kLargeCube; static inline pixel_type Scale(uint64_t value, uint64_t bit_depth, uint64_t denom) { 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 580829741a..b71c8dc248 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc @@ -385,21 +385,21 @@ void DefaultSqueezeParameters(std::vector<SqueezeParams> *parameters, params.in_place = true; if (!wide) { - if (h > JXL_MAX_FIRST_PREVIEW_SIZE) { + if (h > kMaxFirstPreviewSize) { params.horizontal = false; parameters->push_back(params); h = (h + 1) / 2; JXL_DEBUG_V(7, "Vertical (%" PRIuS "x%" PRIuS "), ", w, h); } } - while (w > JXL_MAX_FIRST_PREVIEW_SIZE || h > JXL_MAX_FIRST_PREVIEW_SIZE) { - if (w > JXL_MAX_FIRST_PREVIEW_SIZE) { + while (w > kMaxFirstPreviewSize || h > kMaxFirstPreviewSize) { + if (w > kMaxFirstPreviewSize) { params.horizontal = true; parameters->push_back(params); w = (w + 1) / 2; JXL_DEBUG_V(7, "Horizontal (%" PRIuS "x%" PRIuS "), ", w, h); } - if (h > JXL_MAX_FIRST_PREVIEW_SIZE) { + if (h > kMaxFirstPreviewSize) { params.horizontal = false; parameters->push_back(params); h = (h + 1) / 2; @@ -424,13 +424,13 @@ Status MetaSqueeze(Image &image, std::vector<SqueezeParams> *parameters) { DefaultSqueezeParameters(parameters, image); } - for (size_t i = 0; i < parameters->size(); i++) { + for (auto ¶meter : *parameters) { JXL_RETURN_IF_ERROR( - CheckMetaSqueezeParams((*parameters)[i], image.channel.size())); - bool horizontal = (*parameters)[i].horizontal; - bool in_place = (*parameters)[i].in_place; - uint32_t beginc = (*parameters)[i].begin_c; - uint32_t endc = (*parameters)[i].begin_c + (*parameters)[i].num_c - 1; + CheckMetaSqueezeParams(parameter, image.channel.size())); + bool horizontal = parameter.horizontal; + bool in_place = parameter.in_place; + uint32_t beginc = parameter.begin_c; + uint32_t endc = parameter.begin_c + parameter.num_c - 1; uint32_t offset; if (beginc < image.nb_meta_channels) { @@ -441,7 +441,7 @@ Status MetaSqueeze(Image &image, std::vector<SqueezeParams> *parameters) { return JXL_FAILURE( "Invalid squeeze: meta channels require in-place residuals"); } - image.nb_meta_channels += (*parameters)[i].num_c; + image.nb_meta_channels += parameter.num_c; } if (in_place) { offset = endc + 1; 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 bbd16c59c0..f0333da6fd 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h @@ -29,10 +29,10 @@ #include "lib/jxl/modular/modular_image.h" #include "lib/jxl/modular/transform/transform.h" -#define JXL_MAX_FIRST_PREVIEW_SIZE 8 - namespace jxl { +constexpr size_t kMaxFirstPreviewSize = 8; + /* int avg=(A+B)>>1; int diff=(A-B); diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.cc index 33f7a10cc9..a609cfb3fb 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.cc @@ -23,7 +23,7 @@ Transform::Transform(TransformId id) { } Status Transform::Inverse(Image &input, const weighted::Header &wp_header, - ThreadPool *pool) { + ThreadPool *pool) const { JXL_DEBUG_V(6, "Input channels (%" PRIuS ", %" PRIuS " meta): ", input.channel.size(), input.nb_meta_channels); switch (id) { 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 b68861706f..70c383834a 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h @@ -134,7 +134,7 @@ class Transform : public Fields { JXL_FIELDS_NAME(Transform) Status Inverse(Image &input, const weighted::Header &wp_header, - ThreadPool *pool = nullptr); + ThreadPool *pool = nullptr) const; Status MetaApply(Image &input); }; diff --git a/third_party/jpeg-xl/lib/jxl/modular_test.cc b/third_party/jpeg-xl/lib/jxl/modular_test.cc index bd1a947493..ceebf59c0b 100644 --- a/third_party/jpeg-xl/lib/jxl/modular_test.cc +++ b/third_party/jpeg-xl/lib/jxl/modular_test.cc @@ -80,15 +80,15 @@ void TestLosslessGroups(size_t group_size_shift) { TEST(ModularTest, RoundtripLosslessGroups128) { TestLosslessGroups(0); } -TEST(ModularTest, JXL_TSAN_SLOW_TEST(RoundtripLosslessGroups512)) { +JXL_TSAN_SLOW_TEST(ModularTest, RoundtripLosslessGroups512) { TestLosslessGroups(2); } -TEST(ModularTest, JXL_TSAN_SLOW_TEST(RoundtripLosslessGroups1024)) { +JXL_TSAN_SLOW_TEST(ModularTest, RoundtripLosslessGroups1024) { TestLosslessGroups(3); } -TEST(ModularTest, RoundtripLosslessCustomWP_PermuteRCT) { +TEST(ModularTest, RoundtripLosslessCustomWpPermuteRCT) { const std::vector<uint8_t> orig = ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png"); TestImage t; @@ -144,6 +144,7 @@ TEST(ModularTest, RoundtripLossyDeltaPaletteWP) { cparams.SetLossless(); cparams.lossy_palette = true; cparams.palette_colors = 0; + // TODO(jon): this is currently ignored, and Avg4 is always used instead cparams.options.predictor = jxl::Predictor::Weighted; CodecInOut io_out; @@ -154,12 +155,12 @@ TEST(ModularTest, RoundtripLossyDeltaPaletteWP) { size_t compressed_size; JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io_out, _, &compressed_size)); - EXPECT_LE(compressed_size, 7000u); + EXPECT_LE(compressed_size, 6500u); EXPECT_SLIGHTLY_BELOW( ButteraugliDistance(io.frames, io_out.frames, ButteraugliParams(), *JxlGetDefaultCms(), /*distmap=*/nullptr), - 10.1); + 1.5); } TEST(ModularTest, RoundtripLossy) { @@ -346,8 +347,8 @@ TEST_P(ModularTestParam, RoundtripLossless) { const float* in = io.Main().color()->PlaneRow(c, y); const float* out = io2.Main().color()->PlaneRow(c, y); for (size_t x = 0; x < xsize; x++) { - uint32_t uin = in[x] * factor + 0.5; - uint32_t uout = out[x] * factor + 0.5; + uint32_t uin = std::lroundf(in[x] * factor); + uint32_t uout = std::lroundf(out[x] * factor); // check that the integer values are identical if (uin != uout) different++; } diff --git a/third_party/jpeg-xl/lib/jxl/passes_test.cc b/third_party/jpeg-xl/lib/jxl/passes_test.cc index cb9164706f..e7a7547a0c 100644 --- a/third_party/jpeg-xl/lib/jxl/passes_test.cc +++ b/third_party/jpeg-xl/lib/jxl/passes_test.cc @@ -80,7 +80,7 @@ TEST(PassesTest, RoundtripMultiGroupPasses) { CodecInOut io; { ThreadPoolForTests pool(4); - ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool)); + ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get())); } io.ShrinkTo(600, 1024); // partial X, full Y group @@ -92,11 +92,11 @@ TEST(PassesTest, RoundtripMultiGroupPasses) { cparams.SetCms(*JxlGetDefaultCms()); CodecInOut io2; JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _, - /* compressed_size */ nullptr, &pool)); + /* compressed_size */ nullptr, pool.get())); EXPECT_SLIGHTLY_BELOW( ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), *JxlGetDefaultCms(), - /*distmap=*/nullptr, &pool), + /*distmap=*/nullptr, pool.get()), target_distance + threshold); }; @@ -108,7 +108,7 @@ TEST(PassesTest, RoundtripLargeFastPasses) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png"); CodecInOut io; - ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool)); + ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get())); CompressParams cparams; cparams.speed_tier = SpeedTier::kSquirrel; @@ -117,7 +117,7 @@ TEST(PassesTest, RoundtripLargeFastPasses) { CodecInOut io2; JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _, - /* compressed_size */ nullptr, &pool)); + /* compressed_size */ nullptr, pool.get())); } // Checks for differing size/distance in two consecutive runs of distance 2, @@ -127,7 +127,7 @@ TEST(PassesTest, RoundtripProgressiveConsistent) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png"); CodecInOut io; - ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool)); + ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get())); CompressParams cparams; cparams.speed_tier = SpeedTier::kSquirrel; @@ -141,11 +141,11 @@ TEST(PassesTest, RoundtripProgressiveConsistent) { CodecInOut io2; size_t size2; - JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _, &size2, &pool)); + JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _, &size2, pool.get())); CodecInOut io3; size_t size3; - JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io3, _, &size3, &pool)); + JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io3, _, &size3, pool.get())); // Exact same compressed size. EXPECT_EQ(size2, size3); @@ -153,10 +153,10 @@ TEST(PassesTest, RoundtripProgressiveConsistent) { // Exact same distance. const float dist2 = ButteraugliDistance( io.frames, io2.frames, ButteraugliParams(), *JxlGetDefaultCms(), - /*distmap=*/nullptr, &pool); + /*distmap=*/nullptr, pool.get()); const float dist3 = ButteraugliDistance( io.frames, io3.frames, ButteraugliParams(), *JxlGetDefaultCms(), - /*distmap=*/nullptr, &pool); + /*distmap=*/nullptr, pool.get()); EXPECT_EQ(dist2, dist3); } } @@ -166,7 +166,7 @@ TEST(PassesTest, AllDownsampleFeasible) { const std::vector<uint8_t> orig = ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png"); CodecInOut io; - ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool)); + ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get())); std::vector<uint8_t> compressed; @@ -174,7 +174,7 @@ TEST(PassesTest, AllDownsampleFeasible) { cparams.speed_tier = SpeedTier::kSquirrel; cparams.progressive_mode = Override::kOn; cparams.butteraugli_distance = 1.0; - ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool)); + ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get())); EXPECT_LE(compressed.size(), 240000u); float target_butteraugli[9] = {}; @@ -202,7 +202,7 @@ TEST(PassesTest, AllDownsampleFeasible) { target_butteraugli[downsampling]) << "downsampling: " << downsampling; }; - EXPECT_TRUE(RunOnPool(&pool, 0, downsamplings.size(), ThreadPool::NoInit, + EXPECT_TRUE(RunOnPool(pool.get(), 0, downsamplings.size(), ThreadPool::NoInit, check, "TestDownsampling")); } @@ -211,7 +211,7 @@ TEST(PassesTest, AllDownsampleFeasibleQProgressive) { const std::vector<uint8_t> orig = ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png"); CodecInOut io; - ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool)); + ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get())); std::vector<uint8_t> compressed; @@ -219,7 +219,7 @@ TEST(PassesTest, AllDownsampleFeasibleQProgressive) { cparams.speed_tier = SpeedTier::kSquirrel; cparams.qprogressive_mode = Override::kOn; cparams.butteraugli_distance = 1.0; - ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool)); + ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get())); EXPECT_LE(compressed.size(), 220000u); @@ -247,7 +247,7 @@ TEST(PassesTest, AllDownsampleFeasibleQProgressive) { target_butteraugli[downsampling]) << "downsampling: " << downsampling; }; - EXPECT_TRUE(RunOnPool(&pool, 0, downsamplings.size(), ThreadPool::NoInit, + EXPECT_TRUE(RunOnPool(pool.get(), 0, downsamplings.size(), ThreadPool::NoInit, check, "TestQProgressive")); } @@ -256,7 +256,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectlyGrayscale) { const std::vector<uint8_t> orig = ReadTestData( "external/wesaturate/500px/cvo9xd_keong_macan_grayscale.png"); CodecInOut io_orig; - ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, &pool)); + ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, pool.get())); Rect rect(0, 0, io_orig.xsize(), 128); // need 2 DC groups for the DC frame to actually be progressive. JXL_ASSIGN_OR_DIE(Image3F large, Image3F::Create(4242, rect.ysize())); @@ -274,7 +274,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectlyGrayscale) { cparams.responsive = JXL_TRUE; cparams.qprogressive_mode = Override::kOn; cparams.butteraugli_distance = 1.0; - ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool)); + ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get())); EXPECT_LE(compressed.size(), 10000u); @@ -300,7 +300,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectly) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png"); CodecInOut io_orig; - ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, &pool)); + ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, pool.get())); Rect rect(0, 0, io_orig.xsize(), 128); // need 2 DC groups for the DC frame to actually be progressive. JXL_ASSIGN_OR_DIE(Image3F large, Image3F::Create(4242, rect.ysize())); @@ -317,7 +317,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectly) { cparams.responsive = JXL_TRUE; cparams.qprogressive_mode = Override::kOn; cparams.butteraugli_distance = 1.0; - ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool)); + ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get())); EXPECT_LE(compressed.size(), 220000u); @@ -343,7 +343,7 @@ TEST(PassesTest, NonProgressiveDCImage) { ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png"); CodecInOut io; - ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool)); + ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get())); std::vector<uint8_t> compressed; @@ -351,14 +351,15 @@ TEST(PassesTest, NonProgressiveDCImage) { cparams.speed_tier = SpeedTier::kSquirrel; cparams.progressive_mode = Override::kOff; cparams.butteraugli_distance = 2.0; - ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool)); + ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get())); // Even in non-progressive mode, it should be possible to return a DC-only // image. extras::JXLDecompressParams dparams; dparams.max_downsampling = 100; CodecInOut output; - ASSERT_TRUE(test::DecodeFile(dparams, Bytes(compressed), &output, &pool)); + ASSERT_TRUE( + test::DecodeFile(dparams, Bytes(compressed), &output, pool.get())); EXPECT_EQ(output.xsize(), io.xsize()); EXPECT_EQ(output.ysize(), io.ysize()); } 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 e92cbf2151..776a1c776d 100644 --- a/third_party/jpeg-xl/lib/jxl/quant_weights_test.cc +++ b/third_party/jpeg-xl/lib/jxl/quant_weights_test.cc @@ -164,7 +164,7 @@ TEST(QuantWeightsTest, RAW) { QuantEncoding::Library(0)); std::vector<int> matrix(3 * 32 * 32); Rng rng(0); - for (size_t i = 0; i < matrix.size(); i++) matrix[i] = rng.UniformI(1, 256); + for (int& v : matrix) v = rng.UniformI(1, 256); encodings[DequantMatrices::kQuantTable[AcStrategy::DCT32X32]] = QuantEncoding::RAW(matrix, 2); RoundtripMatrices(encodings); 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 14bd363110..09e3dbab76 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 @@ -20,7 +20,7 @@ void RenderPipeline::Builder::AddStage( 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 + // Check that the last stage is not a kInOut stage for any channel, and that // there is at least one stage. JXL_ASSERT(!stages_.empty()); for (size_t c = 0; c < num_c_; c++) { 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 7f5a8ef00f..77ddb3d430 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 @@ -22,12 +22,12 @@ Status SimpleRenderPipeline::PrepareForThreadsInternal(size_t num, 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++) { + for (auto& entry : channel_shifts_[0]) { 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))); + ImageF ch, + ImageF::Create( + ch_size(frame_dimensions_.xsize_upsampled, entry.first), + ch_size(frame_dimensions_.ysize_upsampled, entry.second))); channel_data_.push_back(std::move(ch)); msan::PoisonImage(channel_data_.back()); } 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 3202a03e44..9ce65e1644 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 @@ -45,7 +45,7 @@ class CmsStage : public RenderPipelineStage { 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 + // TODO(firsching): handle grey case separately // interleave float* JXL_RESTRICT row0 = GetInputRow(input_rows, 0, 0); float* JXL_RESTRICT row1 = GetInputRow(input_rows, 1, 0); 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 d3030b02cb..b281e41794 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 @@ -40,10 +40,10 @@ JXL_INLINE Vec<DF> Weight(Vec<DF> sad, Vec<DF> inv_sigma, Vec<DF> thres) { // this filter a 7x7 filter. class EPF0Stage : public RenderPipelineStage { public: - EPF0Stage(const LoopFilter& lf, const ImageF& sigma) + EPF0Stage(LoopFilter lf, const ImageF& sigma) : RenderPipelineStage(RenderPipelineStage::Settings::Symmetric( /*shift=*/0, /*border=*/3)), - lf_(lf), + lf_(std::move(lf)), sigma_(&sigma) {} template <bool aligned> @@ -72,7 +72,7 @@ class EPF0Stage : public RenderPipelineStage { DF df; using V = decltype(Zero(df)); - V t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, tA, tB; + V t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, tA, tB; // NOLINT V* sads[12] = {&t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9, &tA, &tB}; xextra = RoundUpTo(xextra, Lanes(df)); @@ -114,7 +114,7 @@ class EPF0Stage : public RenderPipelineStage { const auto sm = Load(df, sad_mul + ix); const auto inv_sigma = Mul(Set(df, row_sigma[bx]), sm); - for (size_t i = 0; i < 12; i++) *sads[i] = Zero(df); + for (auto& sad : sads) *sad = Zero(df); constexpr std::array<int, 2> sads_off[12] = { {{-2, 0}}, {{-1, -1}}, {{-1, 0}}, {{-1, 1}}, {{0, -2}}, {{0, -1}}, {{0, 1}}, {{0, 2}}, {{1, -1}}, {{1, 0}}, {{1, 1}}, {{2, 0}}, @@ -128,12 +128,10 @@ class EPF0Stage : public RenderPipelineStage { auto sad = Zero(df); constexpr std::array<int, 2> plus_off[] = { {{0, 0}}, {{-1, 0}}, {{0, -1}}, {{1, 0}}, {{0, 1}}}; - for (size_t j = 0; j < 5; j++) { - const auto r11 = - LoadU(df, rows[c][3 + plus_off[j][0]] + x + plus_off[j][1]); - const auto c11 = - LoadU(df, rows[c][3 + sads_off[i][0] + plus_off[j][0]] + x + - sads_off[i][1] + plus_off[j][1]); + for (const auto& off : plus_off) { + const auto r11 = LoadU(df, rows[c][3 + off[0]] + x + off[1]); + const auto c11 = LoadU(df, rows[c][3 + sads_off[i][0] + off[0]] + + x + sads_off[i][1] + off[1]); sad = Add(sad, AbsDiff(r11, c11)); } *sads[i] = MulAdd(sad, scale, *sads[i]); @@ -181,10 +179,10 @@ class EPF0Stage : public RenderPipelineStage { // makes this filter a 5x5 filter. class EPF1Stage : public RenderPipelineStage { public: - EPF1Stage(const LoopFilter& lf, const ImageF& sigma) + EPF1Stage(LoopFilter lf, const ImageF& sigma) : RenderPipelineStage(RenderPipelineStage::Settings::Symmetric( /*shift=*/0, /*border=*/2)), - lf_(lf), + lf_(std::move(lf)), sigma_(&sigma) {} template <bool aligned> @@ -362,10 +360,10 @@ class EPF1Stage : public RenderPipelineStage { // filter. class EPF2Stage : public RenderPipelineStage { public: - EPF2Stage(const LoopFilter& lf, const ImageF& sigma) + EPF2Stage(LoopFilter lf, const ImageF& sigma) : RenderPipelineStage(RenderPipelineStage::Settings::Symmetric( /*shift=*/0, /*border=*/1)), - lf_(lf), + lf_(std::move(lf)), sigma_(&sigma) {} template <bool aligned> 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 897b20c4c6..e868f9f8e0 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 @@ -110,7 +110,7 @@ class UpsamplingStage : public RenderPipelineStage { ssize_t x0, ssize_t x1) const { static HWY_FULL(float) df; using V = hwy::HWY_NAMESPACE::Vec<HWY_FULL(float)>; - V ups0, ups1, ups2, ups3, ups4, ups5, ups6, ups7; + V ups0, ups1, ups2, ups3, ups4, ups5, ups6, ups7; // NOLINT (void)ups2, (void)ups3, (void)ups4, (void)ups5, (void)ups6, (void)ups7; // Once we have C++17 available, change this back to `V* ups[N]` and // initialize using `if constexpr` below. 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 c5a91e8efd..05cdd786a9 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 @@ -11,6 +11,7 @@ #include "lib/jxl/base/common.h" #include "lib/jxl/base/status.h" #include "lib/jxl/dec_cache.h" +#include "lib/jxl/dec_xyb.h" #include "lib/jxl/image.h" #include "lib/jxl/image_bundle.h" #include "lib/jxl/sanitizers.h" @@ -556,11 +557,11 @@ HWY_EXPORT(GetWriteToOutputStage); namespace { class WriteToImageBundleStage : public RenderPipelineStage { public: - explicit WriteToImageBundleStage(ImageBundle* image_bundle, - ColorEncoding color_encoding) + explicit WriteToImageBundleStage( + ImageBundle* image_bundle, const OutputEncodingInfo& output_encoding_info) : RenderPipelineStage(RenderPipelineStage::Settings()), image_bundle_(image_bundle), - color_encoding_(std::move(color_encoding)) {} + color_encoding_(output_encoding_info.color_encoding) {} Status SetInputSizes( const std::vector<std::pair<size_t, size_t>>& input_sizes) override { @@ -658,9 +659,9 @@ class WriteToImage3FStage : public RenderPipelineStage { } // namespace std::unique_ptr<RenderPipelineStage> GetWriteToImageBundleStage( - ImageBundle* image_bundle, ColorEncoding color_encoding) { + ImageBundle* image_bundle, const OutputEncodingInfo& output_encoding_info) { return jxl::make_unique<WriteToImageBundleStage>(image_bundle, - std::move(color_encoding)); + output_encoding_info); } std::unique_ptr<RenderPipelineStage> GetWriteToImage3FStage(Image3F* image) { diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.h index c5f844ebe8..ba2c51ee97 100644 --- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.h +++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.h @@ -9,13 +9,14 @@ #include <functional> #include "lib/jxl/dec_cache.h" +#include "lib/jxl/dec_xyb.h" #include "lib/jxl/image_bundle.h" #include "lib/jxl/render_pipeline/render_pipeline_stage.h" namespace jxl { std::unique_ptr<RenderPipelineStage> GetWriteToImageBundleStage( - ImageBundle* image_bundle, ColorEncoding color_encoding); + ImageBundle* image_bundle, const OutputEncodingInfo& output_encoding_info); // Gets a stage to write color channels to an Image3F. std::unique_ptr<RenderPipelineStage> GetWriteToImage3FStage(Image3F* image); diff --git a/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc b/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc index a4a87bebb7..07e43e4ddf 100644 --- a/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc +++ b/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc @@ -941,7 +941,7 @@ TEST(RoundtripTest, TestICCProfile) { JxlDecoderDestroy(dec); } -TEST(RoundtripTest, JXL_TRANSCODE_JPEG_TEST(TestJPEGReconstruction)) { +JXL_TRANSCODE_JPEG_TEST(RoundtripTest, TestJPEGReconstruction) { TEST_LIBJPEG_SUPPORT(); const std::string jpeg_path = "jxl/flower/flower.png.im_q85_420.jpg"; const std::vector<uint8_t> orig = jxl::test::ReadTestData(jpeg_path); 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 381367b54d..8783faec8f 100644 --- a/third_party/jpeg-xl/lib/jxl/speed_tier_test.cc +++ b/third_party/jpeg-xl/lib/jxl/speed_tier_test.cc @@ -82,7 +82,6 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P( TEST_P(SpeedTierTest, Roundtrip) { const SpeedTierTestParams& params = GetParam(); - test::ThreadPoolForTests pool(8); const std::vector<uint8_t> orig = jxl::test::ReadTestData( "external/wesaturate/500px/u76c0g_bliznaca_srgb8.png"); test::TestImage t; diff --git a/third_party/jpeg-xl/lib/jxl/splines.cc b/third_party/jpeg-xl/lib/jxl/splines.cc index 1d4fc69e3e..2df2160d76 100644 --- a/third_party/jpeg-xl/lib/jxl/splines.cc +++ b/third_party/jpeg-xl/lib/jxl/splines.cc @@ -94,11 +94,11 @@ void DrawSegment(DF df, const SplineSegment& segment, const bool add, void DrawSegment(const SplineSegment& segment, const bool add, const size_t y, const ssize_t x0, ssize_t x1, float* JXL_RESTRICT rows[3]) { - ssize_t x = - std::max<ssize_t>(x0, segment.center_x - segment.maximum_distance + 0.5f); + ssize_t x = std::max<ssize_t>( + x0, std::llround(segment.center_x - segment.maximum_distance)); // one-past-the-end - x1 = - std::min<ssize_t>(x1, segment.center_x + segment.maximum_distance + 1.5f); + x1 = std::min<ssize_t>( + x1, std::llround(segment.center_x + segment.maximum_distance) + 1); HWY_FULL(float) df; for (; x + static_cast<ssize_t>(Lanes(df)) <= x1; x += Lanes(df)) { DrawSegment(df, segment, add, y, x, rows); @@ -550,8 +550,8 @@ Status QuantizedSpline::Decode(const std::vector<uint8_t>& context_map, } return true; }; - for (int c = 0; c < 3; ++c) { - JXL_RETURN_IF_ERROR(decode_dct(color_dct_[c])); + for (auto& dct : color_dct_) { + JXL_RETURN_IF_ERROR(decode_dct(dct)); } JXL_RETURN_IF_ERROR(decode_dct(sigma_dct_)); return true; diff --git a/third_party/jpeg-xl/lib/jxl/test_image.cc b/third_party/jpeg-xl/lib/jxl/test_image.cc index 42f028d53a..d2e17c6ab0 100644 --- a/third_party/jpeg-xl/lib/jxl/test_image.cc +++ b/third_party/jpeg-xl/lib/jxl/test_image.cc @@ -288,8 +288,7 @@ TestImage& TestImage::SetAllBitDepths(uint32_t bits_per_sample, ppf_.info.alpha_bits = bits_per_sample; ppf_.info.alpha_exponent_bits = exponent_bits_per_sample; } - for (size_t i = 0; i < ppf_.extra_channels_info.size(); ++i) { - extras::PackedExtraChannel& ec = ppf_.extra_channels_info[i]; + for (auto& ec : ppf_.extra_channels_info) { ec.ec_info.bits_per_sample = bits_per_sample; ec.ec_info.exponent_bits_per_sample = exponent_bits_per_sample; } diff --git a/third_party/jpeg-xl/lib/jxl/test_utils.h b/third_party/jpeg-xl/lib/jxl/test_utils.h index 15057cc92d..dc50490174 100644 --- a/third_party/jpeg-xl/lib/jxl/test_utils.h +++ b/third_party/jpeg-xl/lib/jxl/test_utils.h @@ -180,8 +180,7 @@ class ThreadPoolForTests { } ThreadPoolForTests(const ThreadPoolForTests&) = delete; ThreadPoolForTests& operator&(const ThreadPoolForTests&) = delete; - // TODO(eustas): avoid unary `&` overload? - ThreadPool* operator&() { return pool_.get(); } + ThreadPool* get() { return pool_.get(); } private: JxlThreadParallelRunnerPtr runner_; diff --git a/third_party/jpeg-xl/lib/jxl/testing.h b/third_party/jpeg-xl/lib/jxl/testing.h index 1fac352a78..6e4978eb60 100644 --- a/third_party/jpeg-xl/lib/jxl/testing.h +++ b/third_party/jpeg-xl/lib/jxl/testing.h @@ -13,33 +13,37 @@ #include "lib/jxl/common.h" #ifdef JXL_DISABLE_SLOW_TESTS -#define JXL_SLOW_TEST(X) DISABLED_##X +#define JXL_SLOW_TEST(T, C) TEST(T, DISABLED_##C) #else -#define JXL_SLOW_TEST(X) X +#define JXL_SLOW_TEST(T, C) TEST(T, C) #endif // JXL_DISABLE_SLOW_TESTS #if JPEGXL_ENABLE_TRANSCODE_JPEG -#define JXL_TRANSCODE_JPEG_TEST(X) X +#define JXL_TRANSCODE_JPEG_TEST(T, C) TEST(T, C) #else -#define JXL_TRANSCODE_JPEG_TEST(X) DISABLED_##X +#define JXL_TRANSCODE_JPEG_TEST(T, C) TEST(T, DISABLED_##C) #endif // JPEGXL_ENABLE_TRANSCODE_JPEG #if JPEGXL_ENABLE_BOXES -#define JXL_BOXES_TEST(X) X +#define JXL_BOXES_TEST(T, C) TEST(T, C) +#define JXL_BOXES_TEST_P(T, C) TEST_P(T, C) #else -#define JXL_BOXES_TEST(X) DISABLED_##X +#define JXL_BOXES_TEST(T, C) TEST(T, DISABLED_##C) +#define JXL_BOXES_TEST_P(T, C) TEST_P(T, DISABLED_##C) #endif // JPEGXL_ENABLE_BOXES #ifdef THREAD_SANITIZER -#define JXL_TSAN_SLOW_TEST(X) DISABLED_##X +#define JXL_TSAN_SLOW_TEST(T, C) TEST(T, DISABLED_##C) #else -#define JXL_TSAN_SLOW_TEST(X) X +#define JXL_TSAN_SLOW_TEST(T, C) TEST(T, C) #endif // THREAD_SANITIZER #if defined(__x86_64__) -#define JXL_X86_64_TEST(X) X +#define JXL_X86_64_TEST(T, C) TEST(T, C) +#define JXL_X86_64_TEST_P(T, C) TEST_P(T, C) #else -#define JXL_X86_64_TEST(X) DISABLED_##X +#define JXL_X86_64_TEST(T, C) TEST(T, DISABLED_##C) +#define JXL_X86_64_TEST_P(T, C) TEST_P(T, C) #endif // defined(__x86_64__) // googletest before 1.10 didn't define INSTANTIATE_TEST_SUITE_P() but instead diff --git a/third_party/jpeg-xl/lib/jxl/tf_gbench.cc b/third_party/jpeg-xl/lib/jxl/tf_gbench.cc index e93a936c90..6cfd3734bb 100644 --- a/third_party/jpeg-xl/lib/jxl/tf_gbench.cc +++ b/third_party/jpeg-xl/lib/jxl/tf_gbench.cc @@ -46,7 +46,9 @@ namespace { #define RUN_BENCHMARK_SCALAR(F, I) \ constexpr size_t kNum = 1 << 12; \ /* Three parallel runs, as this will run on R, G and B. */ \ - float sum1 = 0, sum2 = 0, sum3 = 0; \ + float sum1 = 0; \ + float sum2 = 0; \ + float sum3 = 0; \ for (auto _ : state) { \ float x = 1e-5; \ float v1 = 1e-5; \ diff --git a/third_party/jpeg-xl/lib/jxl/version.h.in b/third_party/jpeg-xl/lib/jxl/version.h.in index ad1eb24409..b5a462e52e 100644 --- a/third_party/jpeg-xl/lib/jxl/version.h.in +++ b/third_party/jpeg-xl/lib/jxl/version.h.in @@ -32,7 +32,7 @@ #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) +#define JPEGXL_NUMERIC_VERSION JPEGXL_COMPUTE_NUMERIC_VERSION(JPEGXL_MAJOR_VERSION, JPEGXL_MINOR_VERSION, JPEGXL_PATCH_VERSION) #endif /* JXL_VERSION_H_ */ diff --git a/third_party/jpeg-xl/lib/jxl/xorshift128plus_test.cc b/third_party/jpeg-xl/lib/jxl/xorshift128plus_test.cc index 2ee4535284..c68ce4bb3b 100644 --- a/third_party/jpeg-xl/lib/jxl/xorshift128plus_test.cc +++ b/third_party/jpeg-xl/lib/jxl/xorshift128plus_test.cc @@ -294,7 +294,7 @@ void TestFloat() { const uint32_t kMaxSeed = 4096; #endif // JXL_DISABLE_SLOW_TESTS EXPECT_TRUE(RunOnPool( - &pool, 0, kMaxSeed, ThreadPool::NoInit, + pool.get(), 0, kMaxSeed, ThreadPool::NoInit, [](const uint32_t seed, size_t /*thread*/) { HWY_ALIGN Xorshift128Plus rng(seed); @@ -340,7 +340,7 @@ void TestNotZero() { const uint32_t kMaxSeed = 2000; #endif // JXL_DISABLE_SLOW_TESTS EXPECT_TRUE(RunOnPool( - &pool, 0, kMaxSeed, ThreadPool::NoInit, + pool.get(), 0, kMaxSeed, ThreadPool::NoInit, [](const uint32_t task, size_t /*thread*/) { HWY_ALIGN uint64_t lanes[Xorshift128Plus::N]; |