tone_mapping_test.cc (5487B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #undef HWY_TARGET_INCLUDE 7 #define HWY_TARGET_INCLUDE "lib/jxl/cms/tone_mapping_test.cc" 8 #include "lib/jxl/cms/tone_mapping.h" 9 10 #include <cstdio> 11 #include <hwy/foreach_target.h> 12 13 #include "lib/jxl/base/random.h" 14 #include "lib/jxl/cms/tone_mapping-inl.h" 15 #include "lib/jxl/testing.h" 16 17 // Test utils 18 #include <hwy/highway.h> 19 #include <hwy/tests/hwy_gtest.h> 20 HWY_BEFORE_NAMESPACE(); 21 namespace jxl { 22 namespace HWY_NAMESPACE { 23 namespace { 24 25 HWY_NOINLINE void TestRec2408ToneMap() { 26 constexpr size_t kNumTrials = 1 << 23; 27 Rng rng(1); 28 float max_abs_err = 0; 29 HWY_FULL(float) d; 30 for (size_t i = 0; i < kNumTrials; i++) { 31 float src = 11000.0 + rng.UniformF(-150.0f, 150.0f); 32 float tgt = 250 + rng.UniformF(-5.0f, 5.0f); 33 Vector3 luminances{rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f), 34 rng.UniformF(0.2f, 0.4f)}; 35 Color rgb{rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f), 36 rng.UniformF(0.0f, 1.0f)}; 37 Rec2408ToneMapper<decltype(d)> tone_mapper({0.0f, src}, {0.0f, tgt}, 38 luminances); 39 auto r = Set(d, rgb[0]); 40 auto g = Set(d, rgb[1]); 41 auto b = Set(d, rgb[2]); 42 tone_mapper.ToneMap(&r, &g, &b); 43 Rec2408ToneMapperBase tone_mapper_base({0.0f, src}, {0.0f, tgt}, 44 luminances); 45 tone_mapper_base.ToneMap(rgb); 46 const float actual_r = GetLane(r); 47 const float expected_r = rgb[0]; 48 const float abs_err_r = std::abs(expected_r - actual_r); 49 EXPECT_LT(abs_err_r, 2.75e-5); 50 const float actual_g = GetLane(g); 51 const float expected_g = rgb[1]; 52 const float abs_err_g = std::abs(expected_g - actual_g); 53 EXPECT_LT(abs_err_g, 2.75e-5); 54 const float actual_b = GetLane(b); 55 const float expected_b = rgb[2]; 56 const float abs_err_b = std::abs(expected_b - actual_b); 57 EXPECT_LT(abs_err_b, 2.75e-5); 58 max_abs_err = std::max({max_abs_err, abs_err_r, abs_err_g, abs_err_b}); 59 } 60 printf("max abs err %e\n", static_cast<double>(max_abs_err)); 61 } 62 63 HWY_NOINLINE void TestHlgOotfApply() { 64 constexpr size_t kNumTrials = 1 << 23; 65 Rng rng(1); 66 float max_abs_err = 0; 67 HWY_FULL(float) d; 68 for (size_t i = 0; i < kNumTrials; i++) { 69 float src = 300.0 + rng.UniformF(-50.0f, 50.0f); 70 float tgt = 80 + rng.UniformF(-5.0f, 5.0f); 71 Vector3 luminances{rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f), 72 rng.UniformF(0.2f, 0.4f)}; 73 Color rgb{rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f), 74 rng.UniformF(0.0f, 1.0f)}; 75 HlgOOTF ootf(src, tgt, luminances); 76 auto r = Set(d, rgb[0]); 77 auto g = Set(d, rgb[1]); 78 auto b = Set(d, rgb[2]); 79 ootf.Apply(&r, &g, &b); 80 HlgOOTF_Base ootf_base(src, tgt, luminances); 81 ootf_base.Apply(rgb); 82 const float actual_r = GetLane(r); 83 const float expected_r = rgb[0]; 84 const float abs_err_r = std::abs(expected_r - actual_r); 85 EXPECT_LT(abs_err_r, 7.2e-7); 86 const float actual_g = GetLane(g); 87 const float expected_g = rgb[1]; 88 const float abs_err_g = std::abs(expected_g - actual_g); 89 EXPECT_LT(abs_err_g, 7.2e-7); 90 const float actual_b = GetLane(b); 91 const float expected_b = rgb[2]; 92 const float abs_err_b = std::abs(expected_b - actual_b); 93 EXPECT_LT(abs_err_b, 7.2e-7); 94 max_abs_err = std::max({max_abs_err, abs_err_r, abs_err_g, abs_err_b}); 95 } 96 printf("max abs err %e\n", static_cast<double>(max_abs_err)); 97 } 98 99 HWY_NOINLINE void TestGamutMap() { 100 constexpr size_t kNumTrials = 1 << 23; 101 Rng rng(1); 102 float max_abs_err = 0; 103 HWY_FULL(float) d; 104 for (size_t i = 0; i < kNumTrials; i++) { 105 float preserve_saturation = rng.UniformF(0.2f, 0.4f); 106 Vector3 luminances{rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f), 107 rng.UniformF(0.2f, 0.4f)}; 108 Color rgb{rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f), 109 rng.UniformF(0.0f, 1.0f)}; 110 auto r = Set(d, rgb[0]); 111 auto g = Set(d, rgb[1]); 112 auto b = Set(d, rgb[2]); 113 GamutMap(&r, &g, &b, luminances, preserve_saturation); 114 GamutMapScalar(rgb, luminances, preserve_saturation); 115 const float actual_r = GetLane(r); 116 const float expected_r = rgb[0]; 117 const float abs_err_r = std::abs(expected_r - actual_r); 118 EXPECT_LT(abs_err_r, 1e-10); 119 const float actual_g = GetLane(g); 120 const float expected_g = rgb[1]; 121 const float abs_err_g = std::abs(expected_g - actual_g); 122 EXPECT_LT(abs_err_g, 1e-10); 123 const float actual_b = GetLane(b); 124 const float expected_b = rgb[2]; 125 const float abs_err_b = std::abs(expected_b - actual_b); 126 EXPECT_LT(abs_err_b, 1e-10); 127 max_abs_err = std::max({max_abs_err, abs_err_r, abs_err_g, abs_err_b}); 128 } 129 printf("max abs err %e\n", static_cast<double>(max_abs_err)); 130 } 131 132 } // namespace 133 // NOLINTNEXTLINE(google-readability-namespace-comments) 134 } // namespace HWY_NAMESPACE 135 } // namespace jxl 136 HWY_AFTER_NAMESPACE(); 137 138 #if HWY_ONCE 139 namespace jxl { 140 141 class ToneMappingTargetTest : public hwy::TestWithParamTarget {}; 142 HWY_TARGET_INSTANTIATE_TEST_SUITE_P(ToneMappingTargetTest); 143 144 HWY_EXPORT_AND_TEST_P(ToneMappingTargetTest, TestRec2408ToneMap); 145 HWY_EXPORT_AND_TEST_P(ToneMappingTargetTest, TestHlgOotfApply); 146 HWY_EXPORT_AND_TEST_P(ToneMappingTargetTest, TestGamutMap); 147 148 } // namespace jxl 149 #endif // HWY_ONCE