tone_mapping_test.cc (5511B)
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 float luminances[3] = {rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f), 34 rng.UniformF(0.2f, 0.4f)}; 35 float rgb[3] = {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, src}, {0, tgt}, luminances); 38 auto r = Set(d, rgb[0]); 39 auto g = Set(d, rgb[1]); 40 auto b = Set(d, rgb[2]); 41 tone_mapper.ToneMap(&r, &g, &b); 42 Rec2408ToneMapperBase tone_mapper_base({0, src}, {0, tgt}, luminances); 43 tone_mapper_base.ToneMap(&rgb[0], &rgb[1], &rgb[2]); 44 const float actual_r = GetLane(r); 45 const float expected_r = rgb[0]; 46 const float abs_err_r = std::abs(expected_r - actual_r); 47 EXPECT_LT(abs_err_r, 2.75e-5); 48 const float actual_g = GetLane(g); 49 const float expected_g = rgb[1]; 50 const float abs_err_g = std::abs(expected_g - actual_g); 51 EXPECT_LT(abs_err_g, 2.75e-5); 52 const float actual_b = GetLane(b); 53 const float expected_b = rgb[2]; 54 const float abs_err_b = std::abs(expected_b - actual_b); 55 EXPECT_LT(abs_err_b, 2.75e-5); 56 max_abs_err = std::max({max_abs_err, abs_err_r, abs_err_g, abs_err_b}); 57 } 58 printf("max abs err %e\n", static_cast<double>(max_abs_err)); 59 } 60 61 HWY_NOINLINE void TestHlgOotfApply() { 62 constexpr size_t kNumTrials = 1 << 23; 63 Rng rng(1); 64 float max_abs_err = 0; 65 HWY_FULL(float) d; 66 for (size_t i = 0; i < kNumTrials; i++) { 67 float src = 300.0 + rng.UniformF(-50.0f, 50.0f); 68 float tgt = 80 + rng.UniformF(-5.0f, 5.0f); 69 float luminances[3] = {rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f), 70 rng.UniformF(0.2f, 0.4f)}; 71 float rgb[3] = {rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f), 72 rng.UniformF(0.0f, 1.0f)}; 73 HlgOOTF ootf(src, tgt, luminances); 74 auto r = Set(d, rgb[0]); 75 auto g = Set(d, rgb[1]); 76 auto b = Set(d, rgb[2]); 77 ootf.Apply(&r, &g, &b); 78 HlgOOTF_Base ootf_base(src, tgt, luminances); 79 ootf_base.Apply(&rgb[0], &rgb[1], &rgb[2]); 80 const float actual_r = GetLane(r); 81 const float expected_r = rgb[0]; 82 const float abs_err_r = std::abs(expected_r - actual_r); 83 EXPECT_LT(abs_err_r, 7.2e-7); 84 const float actual_g = GetLane(g); 85 const float expected_g = rgb[1]; 86 const float abs_err_g = std::abs(expected_g - actual_g); 87 EXPECT_LT(abs_err_g, 7.2e-7); 88 const float actual_b = GetLane(b); 89 const float expected_b = rgb[2]; 90 const float abs_err_b = std::abs(expected_b - actual_b); 91 EXPECT_LT(abs_err_b, 7.2e-7); 92 max_abs_err = std::max({max_abs_err, abs_err_r, abs_err_g, abs_err_b}); 93 } 94 printf("max abs err %e\n", static_cast<double>(max_abs_err)); 95 } 96 97 HWY_NOINLINE void TestGamutMap() { 98 constexpr size_t kNumTrials = 1 << 23; 99 Rng rng(1); 100 float max_abs_err = 0; 101 HWY_FULL(float) d; 102 for (size_t i = 0; i < kNumTrials; i++) { 103 float preserve_saturation = rng.UniformF(0.2f, 0.4f); 104 float luminances[3] = {rng.UniformF(0.2f, 0.4f), rng.UniformF(0.2f, 0.4f), 105 rng.UniformF(0.2f, 0.4f)}; 106 float rgb[3] = {rng.UniformF(0.0f, 1.0f), rng.UniformF(0.0f, 1.0f), 107 rng.UniformF(0.0f, 1.0f)}; 108 auto r = Set(d, rgb[0]); 109 auto g = Set(d, rgb[1]); 110 auto b = Set(d, rgb[2]); 111 GamutMap(&r, &g, &b, luminances, preserve_saturation); 112 GamutMapScalar(&rgb[0], &rgb[1], &rgb[2], luminances, preserve_saturation); 113 const float actual_r = GetLane(r); 114 const float expected_r = rgb[0]; 115 const float abs_err_r = std::abs(expected_r - actual_r); 116 EXPECT_LT(abs_err_r, 1e-10); 117 const float actual_g = GetLane(g); 118 const float expected_g = rgb[1]; 119 const float abs_err_g = std::abs(expected_g - actual_g); 120 EXPECT_LT(abs_err_g, 1e-10); 121 const float actual_b = GetLane(b); 122 const float expected_b = rgb[2]; 123 const float abs_err_b = std::abs(expected_b - actual_b); 124 EXPECT_LT(abs_err_b, 1e-10); 125 max_abs_err = std::max({max_abs_err, abs_err_r, abs_err_g, abs_err_b}); 126 } 127 printf("max abs err %e\n", static_cast<double>(max_abs_err)); 128 } 129 130 } // namespace 131 // NOLINTNEXTLINE(google-readability-namespace-comments) 132 } // namespace HWY_NAMESPACE 133 } // namespace jxl 134 HWY_AFTER_NAMESPACE(); 135 136 #if HWY_ONCE 137 namespace jxl { 138 139 class ToneMappingTargetTest : public hwy::TestWithParamTarget {}; 140 HWY_TARGET_INSTANTIATE_TEST_SUITE_P(ToneMappingTargetTest); 141 142 HWY_EXPORT_AND_TEST_P(ToneMappingTargetTest, TestRec2408ToneMap); 143 HWY_EXPORT_AND_TEST_P(ToneMappingTargetTest, TestHlgOotfApply); 144 HWY_EXPORT_AND_TEST_P(ToneMappingTargetTest, TestGamutMap); 145 146 } // namespace jxl 147 #endif // HWY_ONCE