blob: af90365e56dfcfebd5aef8f861e2e336f23ebf80 [file] [log] [blame]
Nick Deakin65f492a2022-11-29 22:47:40 -05001/*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <cmath>
18#include <gtest/gtest.h>
19#include <gmock/gmock.h>
Dichen Zhangdbceb0e2023-04-14 19:03:18 +000020#include <ultrahdr/gainmapmath.h>
Nick Deakin65f492a2022-11-29 22:47:40 -050021
Dichen Zhangdbceb0e2023-04-14 19:03:18 +000022namespace android::ultrahdr {
Nick Deakin65f492a2022-11-29 22:47:40 -050023
Dichen Zhang10959a42023-04-10 16:28:16 -070024class GainMapMathTest : public testing::Test {
Nick Deakin65f492a2022-11-29 22:47:40 -050025public:
Dichen Zhang10959a42023-04-10 16:28:16 -070026 GainMapMathTest();
27 ~GainMapMathTest();
Nick Deakin65f492a2022-11-29 22:47:40 -050028
29 float ComparisonEpsilon() { return 1e-4f; }
30 float LuminanceEpsilon() { return 1e-2f; }
Nick Deakin0db53ee2023-05-19 17:14:45 -040031 float YuvConversionEpsilon() { return 1.0f / (255.0f * 2.0f); }
Nick Deakin65f492a2022-11-29 22:47:40 -050032
33 Color Yuv420(uint8_t y, uint8_t u, uint8_t v) {
34 return {{{ static_cast<float>(y) / 255.0f,
35 (static_cast<float>(u) - 128.0f) / 255.0f,
36 (static_cast<float>(v) - 128.0f) / 255.0f }}};
37 }
38
39 Color P010(uint16_t y, uint16_t u, uint16_t v) {
Nick Deakin38125332022-12-12 15:48:24 -050040 return {{{ (static_cast<float>(y) - 64.0f) / 876.0f,
41 (static_cast<float>(u) - 64.0f) / 896.0f - 0.5f,
42 (static_cast<float>(v) - 64.0f) / 896.0f - 0.5f }}};
Nick Deakin65f492a2022-11-29 22:47:40 -050043 }
44
45 float Map(uint8_t e) {
Nick Deakind19e5762023-02-10 15:39:08 -050046 return static_cast<float>(e) / 255.0f;
Nick Deakin65f492a2022-11-29 22:47:40 -050047 }
48
49 Color ColorMin(Color e1, Color e2) {
50 return {{{ fmin(e1.r, e2.r), fmin(e1.g, e2.g), fmin(e1.b, e2.b) }}};
51 }
52
53 Color ColorMax(Color e1, Color e2) {
54 return {{{ fmax(e1.r, e2.r), fmax(e1.g, e2.g), fmax(e1.b, e2.b) }}};
55 }
56
57 Color RgbBlack() { return {{{ 0.0f, 0.0f, 0.0f }}}; }
58 Color RgbWhite() { return {{{ 1.0f, 1.0f, 1.0f }}}; }
59
60 Color RgbRed() { return {{{ 1.0f, 0.0f, 0.0f }}}; }
61 Color RgbGreen() { return {{{ 0.0f, 1.0f, 0.0f }}}; }
62 Color RgbBlue() { return {{{ 0.0f, 0.0f, 1.0f }}}; }
63
64 Color YuvBlack() { return {{{ 0.0f, 0.0f, 0.0f }}}; }
65 Color YuvWhite() { return {{{ 1.0f, 0.0f, 0.0f }}}; }
66
Nick Deakin0db53ee2023-05-19 17:14:45 -040067 Color SrgbYuvRed() { return {{{ 0.2126f, -0.11457f, 0.5f }}}; }
68 Color SrgbYuvGreen() { return {{{ 0.7152f, -0.38543f, -0.45415f }}}; }
69 Color SrgbYuvBlue() { return {{{ 0.0722f, 0.5f, -0.04585f }}}; }
70
71 Color P3YuvRed() { return {{{ 0.299f, -0.16874f, 0.5f }}}; }
72 Color P3YuvGreen() { return {{{ 0.587f, -0.33126f, -0.41869f }}}; }
73 Color P3YuvBlue() { return {{{ 0.114f, 0.5f, -0.08131f }}}; }
Nick Deakin65f492a2022-11-29 22:47:40 -050074
75 Color Bt2100YuvRed() { return {{{ 0.2627f, -0.13963f, 0.5f }}}; }
76 Color Bt2100YuvGreen() { return {{{ 0.6780f, -0.36037f, -0.45979f }}}; }
77 Color Bt2100YuvBlue() { return {{{ 0.0593f, 0.5f, -0.04021f }}}; }
78
79 float SrgbYuvToLuminance(Color yuv_gamma, ColorCalculationFn luminanceFn) {
80 Color rgb_gamma = srgbYuvToRgb(yuv_gamma);
81 Color rgb = srgbInvOetf(rgb_gamma);
82 float luminance_scaled = luminanceFn(rgb);
83 return luminance_scaled * kSdrWhiteNits;
84 }
85
Nick Deakin0db53ee2023-05-19 17:14:45 -040086 float P3YuvToLuminance(Color yuv_gamma, ColorCalculationFn luminanceFn) {
87 Color rgb_gamma = p3YuvToRgb(yuv_gamma);
88 Color rgb = srgbInvOetf(rgb_gamma);
89 float luminance_scaled = luminanceFn(rgb);
90 return luminance_scaled * kSdrWhiteNits;
91 }
92
Nick Deakin65f492a2022-11-29 22:47:40 -050093 float Bt2100YuvToLuminance(Color yuv_gamma, ColorTransformFn hdrInvOetf,
94 ColorTransformFn gamutConversionFn, ColorCalculationFn luminanceFn,
95 float scale_factor) {
96 Color rgb_gamma = bt2100YuvToRgb(yuv_gamma);
97 Color rgb = hdrInvOetf(rgb_gamma);
98 rgb = gamutConversionFn(rgb);
99 float luminance_scaled = luminanceFn(rgb);
100 return luminance_scaled * scale_factor;
101 }
102
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000103 Color Recover(Color yuv_gamma, float gain, ultrahdr_metadata_ptr metadata) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500104 Color rgb_gamma = srgbYuvToRgb(yuv_gamma);
105 Color rgb = srgbInvOetf(rgb_gamma);
Dichen Zhang10959a42023-04-10 16:28:16 -0700106 return applyGain(rgb, gain, metadata);
Nick Deakin65f492a2022-11-29 22:47:40 -0500107 }
108
109 jpegr_uncompressed_struct Yuv420Image() {
110 static uint8_t pixels[] = {
111 // Y
112 0x00, 0x10, 0x20, 0x30,
113 0x01, 0x11, 0x21, 0x31,
114 0x02, 0x12, 0x22, 0x32,
115 0x03, 0x13, 0x23, 0x33,
116 // U
117 0xA0, 0xA1,
118 0xA2, 0xA3,
119 // V
120 0xB0, 0xB1,
121 0xB2, 0xB3,
122 };
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000123 return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_BT709 };
Nick Deakin65f492a2022-11-29 22:47:40 -0500124 }
125
126 Color (*Yuv420Colors())[4] {
127 static Color colors[4][4] = {
128 {
129 Yuv420(0x00, 0xA0, 0xB0), Yuv420(0x10, 0xA0, 0xB0),
130 Yuv420(0x20, 0xA1, 0xB1), Yuv420(0x30, 0xA1, 0xB1),
131 }, {
132 Yuv420(0x01, 0xA0, 0xB0), Yuv420(0x11, 0xA0, 0xB0),
133 Yuv420(0x21, 0xA1, 0xB1), Yuv420(0x31, 0xA1, 0xB1),
134 }, {
135 Yuv420(0x02, 0xA2, 0xB2), Yuv420(0x12, 0xA2, 0xB2),
136 Yuv420(0x22, 0xA3, 0xB3), Yuv420(0x32, 0xA3, 0xB3),
137 }, {
138 Yuv420(0x03, 0xA2, 0xB2), Yuv420(0x13, 0xA2, 0xB2),
139 Yuv420(0x23, 0xA3, 0xB3), Yuv420(0x33, 0xA3, 0xB3),
140 },
141 };
142 return colors;
143 }
144
145 jpegr_uncompressed_struct P010Image() {
146 static uint16_t pixels[] = {
147 // Y
148 0x00 << 6, 0x10 << 6, 0x20 << 6, 0x30 << 6,
149 0x01 << 6, 0x11 << 6, 0x21 << 6, 0x31 << 6,
150 0x02 << 6, 0x12 << 6, 0x22 << 6, 0x32 << 6,
151 0x03 << 6, 0x13 << 6, 0x23 << 6, 0x33 << 6,
152 // UV
153 0xA0 << 6, 0xB0 << 6, 0xA1 << 6, 0xB1 << 6,
154 0xA2 << 6, 0xB2 << 6, 0xA3 << 6, 0xB3 << 6,
155 };
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000156 return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_BT709 };
Nick Deakin65f492a2022-11-29 22:47:40 -0500157 }
158
159 Color (*P010Colors())[4] {
160 static Color colors[4][4] = {
161 {
162 P010(0x00, 0xA0, 0xB0), P010(0x10, 0xA0, 0xB0),
163 P010(0x20, 0xA1, 0xB1), P010(0x30, 0xA1, 0xB1),
164 }, {
165 P010(0x01, 0xA0, 0xB0), P010(0x11, 0xA0, 0xB0),
166 P010(0x21, 0xA1, 0xB1), P010(0x31, 0xA1, 0xB1),
167 }, {
168 P010(0x02, 0xA2, 0xB2), P010(0x12, 0xA2, 0xB2),
169 P010(0x22, 0xA3, 0xB3), P010(0x32, 0xA3, 0xB3),
170 }, {
171 P010(0x03, 0xA2, 0xB2), P010(0x13, 0xA2, 0xB2),
172 P010(0x23, 0xA3, 0xB3), P010(0x33, 0xA3, 0xB3),
173 },
174 };
175 return colors;
176 }
177
178 jpegr_uncompressed_struct MapImage() {
179 static uint8_t pixels[] = {
180 0x00, 0x10, 0x20, 0x30,
181 0x01, 0x11, 0x21, 0x31,
182 0x02, 0x12, 0x22, 0x32,
183 0x03, 0x13, 0x23, 0x33,
184 };
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000185 return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_UNSPECIFIED };
Nick Deakin65f492a2022-11-29 22:47:40 -0500186 }
187
188 float (*MapValues())[4] {
189 static float values[4][4] = {
190 {
191 Map(0x00), Map(0x10), Map(0x20), Map(0x30),
192 }, {
193 Map(0x01), Map(0x11), Map(0x21), Map(0x31),
194 }, {
195 Map(0x02), Map(0x12), Map(0x22), Map(0x32),
196 }, {
197 Map(0x03), Map(0x13), Map(0x23), Map(0x33),
198 },
199 };
200 return values;
201 }
202
203protected:
204 virtual void SetUp();
205 virtual void TearDown();
206};
207
Dichen Zhang10959a42023-04-10 16:28:16 -0700208GainMapMathTest::GainMapMathTest() {}
209GainMapMathTest::~GainMapMathTest() {}
Nick Deakin65f492a2022-11-29 22:47:40 -0500210
Dichen Zhang10959a42023-04-10 16:28:16 -0700211void GainMapMathTest::SetUp() {}
212void GainMapMathTest::TearDown() {}
Nick Deakin65f492a2022-11-29 22:47:40 -0500213
214#define EXPECT_RGB_EQ(e1, e2) \
215 EXPECT_FLOAT_EQ((e1).r, (e2).r); \
216 EXPECT_FLOAT_EQ((e1).g, (e2).g); \
217 EXPECT_FLOAT_EQ((e1).b, (e2).b)
218
219#define EXPECT_RGB_NEAR(e1, e2) \
220 EXPECT_NEAR((e1).r, (e2).r, ComparisonEpsilon()); \
221 EXPECT_NEAR((e1).g, (e2).g, ComparisonEpsilon()); \
222 EXPECT_NEAR((e1).b, (e2).b, ComparisonEpsilon())
223
224#define EXPECT_RGB_CLOSE(e1, e2) \
225 EXPECT_NEAR((e1).r, (e2).r, ComparisonEpsilon() * 10.0f); \
226 EXPECT_NEAR((e1).g, (e2).g, ComparisonEpsilon() * 10.0f); \
227 EXPECT_NEAR((e1).b, (e2).b, ComparisonEpsilon() * 10.0f)
228
229#define EXPECT_YUV_EQ(e1, e2) \
230 EXPECT_FLOAT_EQ((e1).y, (e2).y); \
231 EXPECT_FLOAT_EQ((e1).u, (e2).u); \
232 EXPECT_FLOAT_EQ((e1).v, (e2).v)
233
234#define EXPECT_YUV_NEAR(e1, e2) \
235 EXPECT_NEAR((e1).y, (e2).y, ComparisonEpsilon()); \
236 EXPECT_NEAR((e1).u, (e2).u, ComparisonEpsilon()); \
237 EXPECT_NEAR((e1).v, (e2).v, ComparisonEpsilon())
238
239#define EXPECT_YUV_BETWEEN(e, min, max) \
240 EXPECT_THAT((e).y, testing::AllOf(testing::Ge((min).y), testing::Le((max).y))); \
241 EXPECT_THAT((e).u, testing::AllOf(testing::Ge((min).u), testing::Le((max).u))); \
242 EXPECT_THAT((e).v, testing::AllOf(testing::Ge((min).v), testing::Le((max).v)))
243
244// TODO: a bunch of these tests can be parameterized.
245
Dichen Zhang10959a42023-04-10 16:28:16 -0700246TEST_F(GainMapMathTest, ColorConstruct) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500247 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
248
249 EXPECT_FLOAT_EQ(e1.r, 0.1f);
250 EXPECT_FLOAT_EQ(e1.g, 0.2f);
251 EXPECT_FLOAT_EQ(e1.b, 0.3f);
252
253 EXPECT_FLOAT_EQ(e1.y, 0.1f);
254 EXPECT_FLOAT_EQ(e1.u, 0.2f);
255 EXPECT_FLOAT_EQ(e1.v, 0.3f);
256}
257
Dichen Zhang10959a42023-04-10 16:28:16 -0700258TEST_F(GainMapMathTest, ColorAddColor) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500259 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
260
261 Color e2 = e1 + e1;
262 EXPECT_FLOAT_EQ(e2.r, e1.r * 2.0f);
263 EXPECT_FLOAT_EQ(e2.g, e1.g * 2.0f);
264 EXPECT_FLOAT_EQ(e2.b, e1.b * 2.0f);
265
266 e2 += e1;
267 EXPECT_FLOAT_EQ(e2.r, e1.r * 3.0f);
268 EXPECT_FLOAT_EQ(e2.g, e1.g * 3.0f);
269 EXPECT_FLOAT_EQ(e2.b, e1.b * 3.0f);
270}
271
Dichen Zhang10959a42023-04-10 16:28:16 -0700272TEST_F(GainMapMathTest, ColorAddFloat) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500273 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
274
275 Color e2 = e1 + 0.1f;
276 EXPECT_FLOAT_EQ(e2.r, e1.r + 0.1f);
277 EXPECT_FLOAT_EQ(e2.g, e1.g + 0.1f);
278 EXPECT_FLOAT_EQ(e2.b, e1.b + 0.1f);
279
280 e2 += 0.1f;
281 EXPECT_FLOAT_EQ(e2.r, e1.r + 0.2f);
282 EXPECT_FLOAT_EQ(e2.g, e1.g + 0.2f);
283 EXPECT_FLOAT_EQ(e2.b, e1.b + 0.2f);
284}
285
Dichen Zhang10959a42023-04-10 16:28:16 -0700286TEST_F(GainMapMathTest, ColorSubtractColor) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500287 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
288
289 Color e2 = e1 - e1;
290 EXPECT_FLOAT_EQ(e2.r, 0.0f);
291 EXPECT_FLOAT_EQ(e2.g, 0.0f);
292 EXPECT_FLOAT_EQ(e2.b, 0.0f);
293
294 e2 -= e1;
295 EXPECT_FLOAT_EQ(e2.r, -e1.r);
296 EXPECT_FLOAT_EQ(e2.g, -e1.g);
297 EXPECT_FLOAT_EQ(e2.b, -e1.b);
298}
299
Dichen Zhang10959a42023-04-10 16:28:16 -0700300TEST_F(GainMapMathTest, ColorSubtractFloat) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500301 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
302
303 Color e2 = e1 - 0.1f;
304 EXPECT_FLOAT_EQ(e2.r, e1.r - 0.1f);
305 EXPECT_FLOAT_EQ(e2.g, e1.g - 0.1f);
306 EXPECT_FLOAT_EQ(e2.b, e1.b - 0.1f);
307
308 e2 -= 0.1f;
309 EXPECT_FLOAT_EQ(e2.r, e1.r - 0.2f);
310 EXPECT_FLOAT_EQ(e2.g, e1.g - 0.2f);
311 EXPECT_FLOAT_EQ(e2.b, e1.b - 0.2f);
312}
313
Dichen Zhang10959a42023-04-10 16:28:16 -0700314TEST_F(GainMapMathTest, ColorMultiplyFloat) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500315 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
316
317 Color e2 = e1 * 2.0f;
318 EXPECT_FLOAT_EQ(e2.r, e1.r * 2.0f);
319 EXPECT_FLOAT_EQ(e2.g, e1.g * 2.0f);
320 EXPECT_FLOAT_EQ(e2.b, e1.b * 2.0f);
321
322 e2 *= 2.0f;
323 EXPECT_FLOAT_EQ(e2.r, e1.r * 4.0f);
324 EXPECT_FLOAT_EQ(e2.g, e1.g * 4.0f);
325 EXPECT_FLOAT_EQ(e2.b, e1.b * 4.0f);
326}
327
Dichen Zhang10959a42023-04-10 16:28:16 -0700328TEST_F(GainMapMathTest, ColorDivideFloat) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500329 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
330
331 Color e2 = e1 / 2.0f;
332 EXPECT_FLOAT_EQ(e2.r, e1.r / 2.0f);
333 EXPECT_FLOAT_EQ(e2.g, e1.g / 2.0f);
334 EXPECT_FLOAT_EQ(e2.b, e1.b / 2.0f);
335
336 e2 /= 2.0f;
337 EXPECT_FLOAT_EQ(e2.r, e1.r / 4.0f);
338 EXPECT_FLOAT_EQ(e2.g, e1.g / 4.0f);
339 EXPECT_FLOAT_EQ(e2.b, e1.b / 4.0f);
340}
341
Dichen Zhang10959a42023-04-10 16:28:16 -0700342TEST_F(GainMapMathTest, SrgbLuminance) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500343 EXPECT_FLOAT_EQ(srgbLuminance(RgbBlack()), 0.0f);
344 EXPECT_FLOAT_EQ(srgbLuminance(RgbWhite()), 1.0f);
345 EXPECT_FLOAT_EQ(srgbLuminance(RgbRed()), 0.2126f);
346 EXPECT_FLOAT_EQ(srgbLuminance(RgbGreen()), 0.7152f);
347 EXPECT_FLOAT_EQ(srgbLuminance(RgbBlue()), 0.0722f);
348}
349
Dichen Zhang10959a42023-04-10 16:28:16 -0700350TEST_F(GainMapMathTest, SrgbYuvToRgb) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500351 Color rgb_black = srgbYuvToRgb(YuvBlack());
352 EXPECT_RGB_NEAR(rgb_black, RgbBlack());
353
354 Color rgb_white = srgbYuvToRgb(YuvWhite());
355 EXPECT_RGB_NEAR(rgb_white, RgbWhite());
356
357 Color rgb_r = srgbYuvToRgb(SrgbYuvRed());
358 EXPECT_RGB_NEAR(rgb_r, RgbRed());
359
360 Color rgb_g = srgbYuvToRgb(SrgbYuvGreen());
361 EXPECT_RGB_NEAR(rgb_g, RgbGreen());
362
363 Color rgb_b = srgbYuvToRgb(SrgbYuvBlue());
364 EXPECT_RGB_NEAR(rgb_b, RgbBlue());
365}
366
Dichen Zhang10959a42023-04-10 16:28:16 -0700367TEST_F(GainMapMathTest, SrgbRgbToYuv) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500368 Color yuv_black = srgbRgbToYuv(RgbBlack());
369 EXPECT_YUV_NEAR(yuv_black, YuvBlack());
370
371 Color yuv_white = srgbRgbToYuv(RgbWhite());
372 EXPECT_YUV_NEAR(yuv_white, YuvWhite());
373
374 Color yuv_r = srgbRgbToYuv(RgbRed());
375 EXPECT_YUV_NEAR(yuv_r, SrgbYuvRed());
376
377 Color yuv_g = srgbRgbToYuv(RgbGreen());
378 EXPECT_YUV_NEAR(yuv_g, SrgbYuvGreen());
379
380 Color yuv_b = srgbRgbToYuv(RgbBlue());
381 EXPECT_YUV_NEAR(yuv_b, SrgbYuvBlue());
382}
383
Dichen Zhang10959a42023-04-10 16:28:16 -0700384TEST_F(GainMapMathTest, SrgbRgbYuvRoundtrip) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500385 Color rgb_black = srgbYuvToRgb(srgbRgbToYuv(RgbBlack()));
386 EXPECT_RGB_NEAR(rgb_black, RgbBlack());
387
388 Color rgb_white = srgbYuvToRgb(srgbRgbToYuv(RgbWhite()));
389 EXPECT_RGB_NEAR(rgb_white, RgbWhite());
390
391 Color rgb_r = srgbYuvToRgb(srgbRgbToYuv(RgbRed()));
392 EXPECT_RGB_NEAR(rgb_r, RgbRed());
393
394 Color rgb_g = srgbYuvToRgb(srgbRgbToYuv(RgbGreen()));
395 EXPECT_RGB_NEAR(rgb_g, RgbGreen());
396
397 Color rgb_b = srgbYuvToRgb(srgbRgbToYuv(RgbBlue()));
398 EXPECT_RGB_NEAR(rgb_b, RgbBlue());
399}
400
Dichen Zhang10959a42023-04-10 16:28:16 -0700401TEST_F(GainMapMathTest, SrgbTransferFunction) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500402 EXPECT_FLOAT_EQ(srgbInvOetf(0.0f), 0.0f);
403 EXPECT_NEAR(srgbInvOetf(0.02f), 0.00154f, ComparisonEpsilon());
404 EXPECT_NEAR(srgbInvOetf(0.04045f), 0.00313f, ComparisonEpsilon());
405 EXPECT_NEAR(srgbInvOetf(0.5f), 0.21404f, ComparisonEpsilon());
406 EXPECT_FLOAT_EQ(srgbInvOetf(1.0f), 1.0f);
407}
408
Dichen Zhang10959a42023-04-10 16:28:16 -0700409TEST_F(GainMapMathTest, P3Luminance) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500410 EXPECT_FLOAT_EQ(p3Luminance(RgbBlack()), 0.0f);
411 EXPECT_FLOAT_EQ(p3Luminance(RgbWhite()), 1.0f);
412 EXPECT_FLOAT_EQ(p3Luminance(RgbRed()), 0.20949f);
413 EXPECT_FLOAT_EQ(p3Luminance(RgbGreen()), 0.72160f);
414 EXPECT_FLOAT_EQ(p3Luminance(RgbBlue()), 0.06891f);
415}
416
Nick Deakin0db53ee2023-05-19 17:14:45 -0400417TEST_F(GainMapMathTest, P3YuvToRgb) {
418 Color rgb_black = p3YuvToRgb(YuvBlack());
419 EXPECT_RGB_NEAR(rgb_black, RgbBlack());
420
421 Color rgb_white = p3YuvToRgb(YuvWhite());
422 EXPECT_RGB_NEAR(rgb_white, RgbWhite());
423
424 Color rgb_r = p3YuvToRgb(P3YuvRed());
425 EXPECT_RGB_NEAR(rgb_r, RgbRed());
426
427 Color rgb_g = p3YuvToRgb(P3YuvGreen());
428 EXPECT_RGB_NEAR(rgb_g, RgbGreen());
429
430 Color rgb_b = p3YuvToRgb(P3YuvBlue());
431 EXPECT_RGB_NEAR(rgb_b, RgbBlue());
432}
433
434TEST_F(GainMapMathTest, P3RgbToYuv) {
435 Color yuv_black = p3RgbToYuv(RgbBlack());
436 EXPECT_YUV_NEAR(yuv_black, YuvBlack());
437
438 Color yuv_white = p3RgbToYuv(RgbWhite());
439 EXPECT_YUV_NEAR(yuv_white, YuvWhite());
440
441 Color yuv_r = p3RgbToYuv(RgbRed());
442 EXPECT_YUV_NEAR(yuv_r, P3YuvRed());
443
444 Color yuv_g = p3RgbToYuv(RgbGreen());
445 EXPECT_YUV_NEAR(yuv_g, P3YuvGreen());
446
447 Color yuv_b = p3RgbToYuv(RgbBlue());
448 EXPECT_YUV_NEAR(yuv_b, P3YuvBlue());
449}
450
451TEST_F(GainMapMathTest, P3RgbYuvRoundtrip) {
452 Color rgb_black = p3YuvToRgb(p3RgbToYuv(RgbBlack()));
453 EXPECT_RGB_NEAR(rgb_black, RgbBlack());
454
455 Color rgb_white = p3YuvToRgb(p3RgbToYuv(RgbWhite()));
456 EXPECT_RGB_NEAR(rgb_white, RgbWhite());
457
458 Color rgb_r = p3YuvToRgb(p3RgbToYuv(RgbRed()));
459 EXPECT_RGB_NEAR(rgb_r, RgbRed());
460
461 Color rgb_g = p3YuvToRgb(p3RgbToYuv(RgbGreen()));
462 EXPECT_RGB_NEAR(rgb_g, RgbGreen());
463
464 Color rgb_b = p3YuvToRgb(p3RgbToYuv(RgbBlue()));
465 EXPECT_RGB_NEAR(rgb_b, RgbBlue());
466}
Dichen Zhang10959a42023-04-10 16:28:16 -0700467TEST_F(GainMapMathTest, Bt2100Luminance) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500468 EXPECT_FLOAT_EQ(bt2100Luminance(RgbBlack()), 0.0f);
469 EXPECT_FLOAT_EQ(bt2100Luminance(RgbWhite()), 1.0f);
470 EXPECT_FLOAT_EQ(bt2100Luminance(RgbRed()), 0.2627f);
471 EXPECT_FLOAT_EQ(bt2100Luminance(RgbGreen()), 0.6780f);
472 EXPECT_FLOAT_EQ(bt2100Luminance(RgbBlue()), 0.0593f);
473}
474
Dichen Zhang10959a42023-04-10 16:28:16 -0700475TEST_F(GainMapMathTest, Bt2100YuvToRgb) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500476 Color rgb_black = bt2100YuvToRgb(YuvBlack());
477 EXPECT_RGB_NEAR(rgb_black, RgbBlack());
478
479 Color rgb_white = bt2100YuvToRgb(YuvWhite());
480 EXPECT_RGB_NEAR(rgb_white, RgbWhite());
481
482 Color rgb_r = bt2100YuvToRgb(Bt2100YuvRed());
483 EXPECT_RGB_NEAR(rgb_r, RgbRed());
484
485 Color rgb_g = bt2100YuvToRgb(Bt2100YuvGreen());
486 EXPECT_RGB_NEAR(rgb_g, RgbGreen());
487
488 Color rgb_b = bt2100YuvToRgb(Bt2100YuvBlue());
489 EXPECT_RGB_NEAR(rgb_b, RgbBlue());
490}
491
Dichen Zhang10959a42023-04-10 16:28:16 -0700492TEST_F(GainMapMathTest, Bt2100RgbToYuv) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500493 Color yuv_black = bt2100RgbToYuv(RgbBlack());
494 EXPECT_YUV_NEAR(yuv_black, YuvBlack());
495
496 Color yuv_white = bt2100RgbToYuv(RgbWhite());
497 EXPECT_YUV_NEAR(yuv_white, YuvWhite());
498
499 Color yuv_r = bt2100RgbToYuv(RgbRed());
500 EXPECT_YUV_NEAR(yuv_r, Bt2100YuvRed());
501
502 Color yuv_g = bt2100RgbToYuv(RgbGreen());
503 EXPECT_YUV_NEAR(yuv_g, Bt2100YuvGreen());
504
505 Color yuv_b = bt2100RgbToYuv(RgbBlue());
506 EXPECT_YUV_NEAR(yuv_b, Bt2100YuvBlue());
507}
508
Dichen Zhang10959a42023-04-10 16:28:16 -0700509TEST_F(GainMapMathTest, Bt2100RgbYuvRoundtrip) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500510 Color rgb_black = bt2100YuvToRgb(bt2100RgbToYuv(RgbBlack()));
511 EXPECT_RGB_NEAR(rgb_black, RgbBlack());
512
513 Color rgb_white = bt2100YuvToRgb(bt2100RgbToYuv(RgbWhite()));
514 EXPECT_RGB_NEAR(rgb_white, RgbWhite());
515
516 Color rgb_r = bt2100YuvToRgb(bt2100RgbToYuv(RgbRed()));
517 EXPECT_RGB_NEAR(rgb_r, RgbRed());
518
519 Color rgb_g = bt2100YuvToRgb(bt2100RgbToYuv(RgbGreen()));
520 EXPECT_RGB_NEAR(rgb_g, RgbGreen());
521
522 Color rgb_b = bt2100YuvToRgb(bt2100RgbToYuv(RgbBlue()));
523 EXPECT_RGB_NEAR(rgb_b, RgbBlue());
524}
525
Nick Deakin0db53ee2023-05-19 17:14:45 -0400526TEST_F(GainMapMathTest, Bt709ToBt601YuvConversion) {
527 Color yuv_black = srgbRgbToYuv(RgbBlack());
528 EXPECT_YUV_NEAR(yuv709To601(yuv_black), YuvBlack());
529
530 Color yuv_white = srgbRgbToYuv(RgbWhite());
531 EXPECT_YUV_NEAR(yuv709To601(yuv_white), YuvWhite());
532
533 Color yuv_r = srgbRgbToYuv(RgbRed());
534 EXPECT_YUV_NEAR(yuv709To601(yuv_r), P3YuvRed());
535
536 Color yuv_g = srgbRgbToYuv(RgbGreen());
537 EXPECT_YUV_NEAR(yuv709To601(yuv_g), P3YuvGreen());
538
539 Color yuv_b = srgbRgbToYuv(RgbBlue());
540 EXPECT_YUV_NEAR(yuv709To601(yuv_b), P3YuvBlue());
541}
542
543TEST_F(GainMapMathTest, Bt709ToBt2100YuvConversion) {
544 Color yuv_black = srgbRgbToYuv(RgbBlack());
545 EXPECT_YUV_NEAR(yuv709To2100(yuv_black), YuvBlack());
546
547 Color yuv_white = srgbRgbToYuv(RgbWhite());
548 EXPECT_YUV_NEAR(yuv709To2100(yuv_white), YuvWhite());
549
550 Color yuv_r = srgbRgbToYuv(RgbRed());
551 EXPECT_YUV_NEAR(yuv709To2100(yuv_r), Bt2100YuvRed());
552
553 Color yuv_g = srgbRgbToYuv(RgbGreen());
554 EXPECT_YUV_NEAR(yuv709To2100(yuv_g), Bt2100YuvGreen());
555
556 Color yuv_b = srgbRgbToYuv(RgbBlue());
557 EXPECT_YUV_NEAR(yuv709To2100(yuv_b), Bt2100YuvBlue());
558}
559
560TEST_F(GainMapMathTest, Bt601ToBt709YuvConversion) {
561 Color yuv_black = p3RgbToYuv(RgbBlack());
562 EXPECT_YUV_NEAR(yuv601To709(yuv_black), YuvBlack());
563
564 Color yuv_white = p3RgbToYuv(RgbWhite());
565 EXPECT_YUV_NEAR(yuv601To709(yuv_white), YuvWhite());
566
567 Color yuv_r = p3RgbToYuv(RgbRed());
568 EXPECT_YUV_NEAR(yuv601To709(yuv_r), SrgbYuvRed());
569
570 Color yuv_g = p3RgbToYuv(RgbGreen());
571 EXPECT_YUV_NEAR(yuv601To709(yuv_g), SrgbYuvGreen());
572
573 Color yuv_b = p3RgbToYuv(RgbBlue());
574 EXPECT_YUV_NEAR(yuv601To709(yuv_b), SrgbYuvBlue());
575}
576
577TEST_F(GainMapMathTest, Bt601ToBt2100YuvConversion) {
578 Color yuv_black = p3RgbToYuv(RgbBlack());
579 EXPECT_YUV_NEAR(yuv601To2100(yuv_black), YuvBlack());
580
581 Color yuv_white = p3RgbToYuv(RgbWhite());
582 EXPECT_YUV_NEAR(yuv601To2100(yuv_white), YuvWhite());
583
584 Color yuv_r = p3RgbToYuv(RgbRed());
585 EXPECT_YUV_NEAR(yuv601To2100(yuv_r), Bt2100YuvRed());
586
587 Color yuv_g = p3RgbToYuv(RgbGreen());
588 EXPECT_YUV_NEAR(yuv601To2100(yuv_g), Bt2100YuvGreen());
589
590 Color yuv_b = p3RgbToYuv(RgbBlue());
591 EXPECT_YUV_NEAR(yuv601To2100(yuv_b), Bt2100YuvBlue());
592}
593
594TEST_F(GainMapMathTest, Bt2100ToBt709YuvConversion) {
595 Color yuv_black = bt2100RgbToYuv(RgbBlack());
596 EXPECT_YUV_NEAR(yuv2100To709(yuv_black), YuvBlack());
597
598 Color yuv_white = bt2100RgbToYuv(RgbWhite());
599 EXPECT_YUV_NEAR(yuv2100To709(yuv_white), YuvWhite());
600
601 Color yuv_r = bt2100RgbToYuv(RgbRed());
602 EXPECT_YUV_NEAR(yuv2100To709(yuv_r), SrgbYuvRed());
603
604 Color yuv_g = bt2100RgbToYuv(RgbGreen());
605 EXPECT_YUV_NEAR(yuv2100To709(yuv_g), SrgbYuvGreen());
606
607 Color yuv_b = bt2100RgbToYuv(RgbBlue());
608 EXPECT_YUV_NEAR(yuv2100To709(yuv_b), SrgbYuvBlue());
609}
610
611TEST_F(GainMapMathTest, Bt2100ToBt601YuvConversion) {
612 Color yuv_black = bt2100RgbToYuv(RgbBlack());
613 EXPECT_YUV_NEAR(yuv2100To601(yuv_black), YuvBlack());
614
615 Color yuv_white = bt2100RgbToYuv(RgbWhite());
616 EXPECT_YUV_NEAR(yuv2100To601(yuv_white), YuvWhite());
617
618 Color yuv_r = bt2100RgbToYuv(RgbRed());
619 EXPECT_YUV_NEAR(yuv2100To601(yuv_r), P3YuvRed());
620
621 Color yuv_g = bt2100RgbToYuv(RgbGreen());
622 EXPECT_YUV_NEAR(yuv2100To601(yuv_g), P3YuvGreen());
623
624 Color yuv_b = bt2100RgbToYuv(RgbBlue());
625 EXPECT_YUV_NEAR(yuv2100To601(yuv_b), P3YuvBlue());
626}
627
628TEST_F(GainMapMathTest, TransformYuv420) {
629 ColorTransformFn transforms[] = { yuv709To601, yuv709To2100, yuv601To709, yuv601To2100,
630 yuv2100To709, yuv2100To601 };
631 for (const ColorTransformFn& transform : transforms) {
632 jpegr_uncompressed_struct input = Yuv420Image();
633
634 size_t out_buf_size = input.width * input.height * 3 / 2;
635 std::unique_ptr<uint8_t[]> out_buf = std::make_unique<uint8_t[]>(out_buf_size);
636 memcpy(out_buf.get(), input.data, out_buf_size);
637 jpegr_uncompressed_struct output = Yuv420Image();
638 output.data = out_buf.get();
639
640 transformYuv420(&output, 1, 1, transform);
641
642 for (size_t y = 0; y < 4; ++y) {
643 for (size_t x = 0; x < 4; ++x) {
644 // Skip the last chroma sample, which we modified above
645 if (x >= 2 && y >= 2) {
646 continue;
647 }
648
649 // All other pixels should remain unchanged
650 EXPECT_YUV_EQ(getYuv420Pixel(&input, x, y), getYuv420Pixel(&output, x, y));
651 }
652 }
653
654 // modified pixels should be updated as intended by the transformYuv420 algorithm
655 Color in1 = getYuv420Pixel(&input, 2, 2);
656 Color in2 = getYuv420Pixel(&input, 3, 2);
657 Color in3 = getYuv420Pixel(&input, 2, 3);
658 Color in4 = getYuv420Pixel(&input, 3, 3);
659 Color out1 = getYuv420Pixel(&output, 2, 2);
660 Color out2 = getYuv420Pixel(&output, 3, 2);
661 Color out3 = getYuv420Pixel(&output, 2, 3);
662 Color out4 = getYuv420Pixel(&output, 3, 3);
663
664 EXPECT_NEAR(transform(in1).y, out1.y, YuvConversionEpsilon());
665 EXPECT_NEAR(transform(in2).y, out2.y, YuvConversionEpsilon());
666 EXPECT_NEAR(transform(in3).y, out3.y, YuvConversionEpsilon());
667 EXPECT_NEAR(transform(in4).y, out4.y, YuvConversionEpsilon());
668
669 Color expect_uv = (transform(in1) + transform(in2) + transform(in3) + transform(in4)) / 4.0f;
670
671 EXPECT_NEAR(expect_uv.u, out1.u, YuvConversionEpsilon());
672 EXPECT_NEAR(expect_uv.u, out2.u, YuvConversionEpsilon());
673 EXPECT_NEAR(expect_uv.u, out3.u, YuvConversionEpsilon());
674 EXPECT_NEAR(expect_uv.u, out4.u, YuvConversionEpsilon());
675
676 EXPECT_NEAR(expect_uv.v, out1.v, YuvConversionEpsilon());
677 EXPECT_NEAR(expect_uv.v, out2.v, YuvConversionEpsilon());
678 EXPECT_NEAR(expect_uv.v, out3.v, YuvConversionEpsilon());
679 EXPECT_NEAR(expect_uv.v, out4.v, YuvConversionEpsilon());
680 }
681}
682
Dichen Zhang10959a42023-04-10 16:28:16 -0700683TEST_F(GainMapMathTest, HlgOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500684 EXPECT_FLOAT_EQ(hlgOetf(0.0f), 0.0f);
685 EXPECT_NEAR(hlgOetf(0.04167f), 0.35357f, ComparisonEpsilon());
686 EXPECT_NEAR(hlgOetf(0.08333f), 0.5f, ComparisonEpsilon());
687 EXPECT_NEAR(hlgOetf(0.5f), 0.87164f, ComparisonEpsilon());
688 EXPECT_FLOAT_EQ(hlgOetf(1.0f), 1.0f);
689
690 Color e = {{{ 0.04167f, 0.08333f, 0.5f }}};
691 Color e_gamma = {{{ 0.35357f, 0.5f, 0.87164f }}};
692 EXPECT_RGB_NEAR(hlgOetf(e), e_gamma);
693}
694
Dichen Zhang10959a42023-04-10 16:28:16 -0700695TEST_F(GainMapMathTest, HlgInvOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500696 EXPECT_FLOAT_EQ(hlgInvOetf(0.0f), 0.0f);
697 EXPECT_NEAR(hlgInvOetf(0.25f), 0.02083f, ComparisonEpsilon());
698 EXPECT_NEAR(hlgInvOetf(0.5f), 0.08333f, ComparisonEpsilon());
699 EXPECT_NEAR(hlgInvOetf(0.75f), 0.26496f, ComparisonEpsilon());
700 EXPECT_FLOAT_EQ(hlgInvOetf(1.0f), 1.0f);
701
702 Color e_gamma = {{{ 0.25f, 0.5f, 0.75f }}};
703 Color e = {{{ 0.02083f, 0.08333f, 0.26496f }}};
704 EXPECT_RGB_NEAR(hlgInvOetf(e_gamma), e);
705}
706
Dichen Zhang10959a42023-04-10 16:28:16 -0700707TEST_F(GainMapMathTest, HlgTransferFunctionRoundtrip) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500708 EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(0.0f)), 0.0f);
709 EXPECT_NEAR(hlgInvOetf(hlgOetf(0.04167f)), 0.04167f, ComparisonEpsilon());
710 EXPECT_NEAR(hlgInvOetf(hlgOetf(0.08333f)), 0.08333f, ComparisonEpsilon());
711 EXPECT_NEAR(hlgInvOetf(hlgOetf(0.5f)), 0.5f, ComparisonEpsilon());
712 EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(1.0f)), 1.0f);
713}
714
Dichen Zhang10959a42023-04-10 16:28:16 -0700715TEST_F(GainMapMathTest, PqOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500716 EXPECT_FLOAT_EQ(pqOetf(0.0f), 0.0f);
717 EXPECT_NEAR(pqOetf(0.01f), 0.50808f, ComparisonEpsilon());
718 EXPECT_NEAR(pqOetf(0.5f), 0.92655f, ComparisonEpsilon());
719 EXPECT_NEAR(pqOetf(0.99f), 0.99895f, ComparisonEpsilon());
720 EXPECT_FLOAT_EQ(pqOetf(1.0f), 1.0f);
721
722 Color e = {{{ 0.01f, 0.5f, 0.99f }}};
723 Color e_gamma = {{{ 0.50808f, 0.92655f, 0.99895f }}};
724 EXPECT_RGB_NEAR(pqOetf(e), e_gamma);
725}
726
Dichen Zhang10959a42023-04-10 16:28:16 -0700727TEST_F(GainMapMathTest, PqInvOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500728 EXPECT_FLOAT_EQ(pqInvOetf(0.0f), 0.0f);
729 EXPECT_NEAR(pqInvOetf(0.01f), 2.31017e-7f, ComparisonEpsilon());
730 EXPECT_NEAR(pqInvOetf(0.5f), 0.00922f, ComparisonEpsilon());
731 EXPECT_NEAR(pqInvOetf(0.99f), 0.90903f, ComparisonEpsilon());
732 EXPECT_FLOAT_EQ(pqInvOetf(1.0f), 1.0f);
733
734 Color e_gamma = {{{ 0.01f, 0.5f, 0.99f }}};
735 Color e = {{{ 2.31017e-7f, 0.00922f, 0.90903f }}};
736 EXPECT_RGB_NEAR(pqInvOetf(e_gamma), e);
737}
738
Dichen Zhang10959a42023-04-10 16:28:16 -0700739TEST_F(GainMapMathTest, PqInvOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500740 for (int idx = 0; idx < kPqInvOETFNumEntries; idx++) {
741 float value = static_cast<float>(idx) / static_cast<float>(kPqInvOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800742 EXPECT_FLOAT_EQ(pqInvOetf(value), pqInvOetfLUT(value));
743 }
744}
745
Dichen Zhang10959a42023-04-10 16:28:16 -0700746TEST_F(GainMapMathTest, HlgInvOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500747 for (int idx = 0; idx < kHlgInvOETFNumEntries; idx++) {
748 float value = static_cast<float>(idx) / static_cast<float>(kHlgInvOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800749 EXPECT_FLOAT_EQ(hlgInvOetf(value), hlgInvOetfLUT(value));
750 }
751}
752
Dichen Zhang10959a42023-04-10 16:28:16 -0700753TEST_F(GainMapMathTest, pqOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500754 for (int idx = 0; idx < kPqOETFNumEntries; idx++) {
755 float value = static_cast<float>(idx) / static_cast<float>(kPqOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800756 EXPECT_FLOAT_EQ(pqOetf(value), pqOetfLUT(value));
757 }
758}
759
Dichen Zhang10959a42023-04-10 16:28:16 -0700760TEST_F(GainMapMathTest, hlgOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500761 for (int idx = 0; idx < kHlgOETFNumEntries; idx++) {
762 float value = static_cast<float>(idx) / static_cast<float>(kHlgOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800763 EXPECT_FLOAT_EQ(hlgOetf(value), hlgOetfLUT(value));
764 }
765}
766
Dichen Zhang10959a42023-04-10 16:28:16 -0700767TEST_F(GainMapMathTest, srgbInvOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500768 for (int idx = 0; idx < kSrgbInvOETFNumEntries; idx++) {
769 float value = static_cast<float>(idx) / static_cast<float>(kSrgbInvOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800770 EXPECT_FLOAT_EQ(srgbInvOetf(value), srgbInvOetfLUT(value));
771 }
772}
773
Dichen Zhang10959a42023-04-10 16:28:16 -0700774TEST_F(GainMapMathTest, applyGainLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500775 for (int boost = 1; boost <= 10; boost++) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000776 ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
Dichen Zhange286f1c2023-03-14 00:22:00 +0000777 .minContentBoost = 1.0f / static_cast<float>(boost) };
Dichen Zhang10959a42023-04-10 16:28:16 -0700778 GainLUT gainLUT(&metadata);
779 GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
780 for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
781 float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
782 EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
783 applyGainLUT(RgbBlack(), value, gainLUT));
784 EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
785 applyGainLUT(RgbWhite(), value, gainLUT));
786 EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
787 applyGainLUT(RgbRed(), value, gainLUT));
788 EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
789 applyGainLUT(RgbGreen(), value, gainLUT));
790 EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
791 applyGainLUT(RgbBlue(), value, gainLUT));
792 EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
793 applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
794 EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
795 applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
796 EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
797 applyGainLUT(RgbRed(), value, gainLUTWithBoost));
798 EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
799 applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
800 EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
801 applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
Nick Deakind19e5762023-02-10 15:39:08 -0500802 }
803 }
804
805 for (int boost = 1; boost <= 10; boost++) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000806 ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
Dichen Zhange286f1c2023-03-14 00:22:00 +0000807 .minContentBoost = 1.0f };
Dichen Zhang10959a42023-04-10 16:28:16 -0700808 GainLUT gainLUT(&metadata);
809 GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
810 for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
811 float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
812 EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
813 applyGainLUT(RgbBlack(), value, gainLUT));
814 EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
815 applyGainLUT(RgbWhite(), value, gainLUT));
816 EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
817 applyGainLUT(RgbRed(), value, gainLUT));
818 EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
819 applyGainLUT(RgbGreen(), value, gainLUT));
820 EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
821 applyGainLUT(RgbBlue(), value, gainLUT));
822 EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
823 applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
824 EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
825 applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
826 EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
827 applyGainLUT(RgbRed(), value, gainLUTWithBoost));
828 EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
829 applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
830 EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
831 applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
Nick Deakind19e5762023-02-10 15:39:08 -0500832 }
833 }
834
835 for (int boost = 1; boost <= 10; boost++) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000836 ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
Dichen Zhange286f1c2023-03-14 00:22:00 +0000837 .minContentBoost = 1.0f / pow(static_cast<float>(boost),
Nick Deakind19e5762023-02-10 15:39:08 -0500838 1.0f / 3.0f) };
Dichen Zhang10959a42023-04-10 16:28:16 -0700839 GainLUT gainLUT(&metadata);
840 GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
841 for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
842 float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
843 EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
844 applyGainLUT(RgbBlack(), value, gainLUT));
845 EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
846 applyGainLUT(RgbWhite(), value, gainLUT));
847 EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
848 applyGainLUT(RgbRed(), value, gainLUT));
849 EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
850 applyGainLUT(RgbGreen(), value, gainLUT));
851 EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
852 applyGainLUT(RgbBlue(), value, gainLUT));
853 EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
854 applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
855 EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
856 applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
857 EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
858 applyGainLUT(RgbRed(), value, gainLUTWithBoost));
859 EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
860 applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
861 EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
862 applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
Harish Mahendrakarf25991f2022-12-16 11:57:44 -0800863 }
864 }
865}
866
Dichen Zhang10959a42023-04-10 16:28:16 -0700867TEST_F(GainMapMathTest, PqTransferFunctionRoundtrip) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500868 EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(0.0f)), 0.0f);
869 EXPECT_NEAR(pqInvOetf(pqOetf(0.01f)), 0.01f, ComparisonEpsilon());
870 EXPECT_NEAR(pqInvOetf(pqOetf(0.5f)), 0.5f, ComparisonEpsilon());
871 EXPECT_NEAR(pqInvOetf(pqOetf(0.99f)), 0.99f, ComparisonEpsilon());
872 EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(1.0f)), 1.0f);
873}
874
Dichen Zhang10959a42023-04-10 16:28:16 -0700875TEST_F(GainMapMathTest, ColorConversionLookup) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000876 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500877 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000878 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500879 identityConversion);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000880 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500881 p3ToBt709);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000882 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500883 bt2100ToBt709);
884
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000885 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500886 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000887 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500888 bt709ToP3);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000889 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500890 identityConversion);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000891 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500892 bt2100ToP3);
893
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000894 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500895 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000896 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500897 bt709ToBt2100);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000898 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500899 p3ToBt2100);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000900 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500901 identityConversion);
902
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000903 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500904 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000905 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500906 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000907 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500908 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000909 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500910 nullptr);
911}
912
Dichen Zhang10959a42023-04-10 16:28:16 -0700913TEST_F(GainMapMathTest, EncodeGain) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000914 ultrahdr_metadata_struct metadata = { .maxContentBoost = 4.0f,
Nick Deakin0db53ee2023-05-19 17:14:45 -0400915 .minContentBoost = 1.0f / 4.0f };
Nick Deakin65f492a2022-11-29 22:47:40 -0500916
Dichen Zhang10959a42023-04-10 16:28:16 -0700917 EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 127);
918 EXPECT_EQ(encodeGain(0.0f, 1.0f, &metadata), 127);
919 EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
920 EXPECT_EQ(encodeGain(0.5f, 0.0f, &metadata), 0);
Nick Deakin65f492a2022-11-29 22:47:40 -0500921
Dichen Zhang10959a42023-04-10 16:28:16 -0700922 EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 127);
923 EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 255);
924 EXPECT_EQ(encodeGain(1.0f, 5.0f, &metadata), 255);
925 EXPECT_EQ(encodeGain(4.0f, 1.0f, &metadata), 0);
926 EXPECT_EQ(encodeGain(4.0f, 0.5f, &metadata), 0);
927 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 191);
928 EXPECT_EQ(encodeGain(2.0f, 1.0f, &metadata), 63);
Nick Deakin65f492a2022-11-29 22:47:40 -0500929
Nick Deakind19e5762023-02-10 15:39:08 -0500930 metadata.maxContentBoost = 2.0f;
931 metadata.minContentBoost = 1.0f / 2.0f;
932
Dichen Zhang10959a42023-04-10 16:28:16 -0700933 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 255);
934 EXPECT_EQ(encodeGain(2.0f, 1.0f, &metadata), 0);
935 EXPECT_EQ(encodeGain(1.0f, 1.41421f, &metadata), 191);
936 EXPECT_EQ(encodeGain(1.41421f, 1.0f, &metadata), 63);
Nick Deakind19e5762023-02-10 15:39:08 -0500937
938 metadata.maxContentBoost = 8.0f;
939 metadata.minContentBoost = 1.0f / 8.0f;
940
Dichen Zhang10959a42023-04-10 16:28:16 -0700941 EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
942 EXPECT_EQ(encodeGain(8.0f, 1.0f, &metadata), 0);
943 EXPECT_EQ(encodeGain(1.0f, 2.82843f, &metadata), 191);
944 EXPECT_EQ(encodeGain(2.82843f, 1.0f, &metadata), 63);
Nick Deakind19e5762023-02-10 15:39:08 -0500945
946 metadata.maxContentBoost = 8.0f;
947 metadata.minContentBoost = 1.0f;
948
Dichen Zhang10959a42023-04-10 16:28:16 -0700949 EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 0);
950 EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
Nick Deakind19e5762023-02-10 15:39:08 -0500951
Dichen Zhang10959a42023-04-10 16:28:16 -0700952 EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 0);
953 EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
954 EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 170);
955 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 85);
Nick Deakind19e5762023-02-10 15:39:08 -0500956
957 metadata.maxContentBoost = 8.0f;
958 metadata.minContentBoost = 0.5f;
959
Dichen Zhang10959a42023-04-10 16:28:16 -0700960 EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 63);
961 EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
Nick Deakind19e5762023-02-10 15:39:08 -0500962
Dichen Zhang10959a42023-04-10 16:28:16 -0700963 EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 63);
964 EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
965 EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 191);
966 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 127);
967 EXPECT_EQ(encodeGain(1.0f, 0.7071f, &metadata), 31);
968 EXPECT_EQ(encodeGain(1.0f, 0.5f, &metadata), 0);
Nick Deakin65f492a2022-11-29 22:47:40 -0500969}
970
Dichen Zhang10959a42023-04-10 16:28:16 -0700971TEST_F(GainMapMathTest, ApplyGain) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000972 ultrahdr_metadata_struct metadata = { .maxContentBoost = 4.0f,
Nick Deakin0db53ee2023-05-19 17:14:45 -0400973 .minContentBoost = 1.0f / 4.0f };
Dichen Zhangc6605702023-03-15 18:40:55 -0700974 float displayBoost = metadata.maxContentBoost;
Nick Deakin65f492a2022-11-29 22:47:40 -0500975
Dichen Zhang10959a42023-04-10 16:28:16 -0700976 EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.0f, &metadata), RgbBlack());
977 EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.5f, &metadata), RgbBlack());
978 EXPECT_RGB_NEAR(applyGain(RgbBlack(), 1.0f, &metadata), RgbBlack());
Nick Deakin65f492a2022-11-29 22:47:40 -0500979
Dichen Zhang10959a42023-04-10 16:28:16 -0700980 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 4.0f);
981 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.0f);
982 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
983 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.0f);
984 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 4.0f);
Nick Deakin65f492a2022-11-29 22:47:40 -0500985
Nick Deakind19e5762023-02-10 15:39:08 -0500986 metadata.maxContentBoost = 2.0f;
987 metadata.minContentBoost = 1.0f / 2.0f;
988
Dichen Zhang10959a42023-04-10 16:28:16 -0700989 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
990 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 1.41421f);
991 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
992 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 1.41421f);
993 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 2.0f);
Nick Deakind19e5762023-02-10 15:39:08 -0500994
995 metadata.maxContentBoost = 8.0f;
996 metadata.minContentBoost = 1.0f / 8.0f;
997
Dichen Zhang10959a42023-04-10 16:28:16 -0700998 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 8.0f);
999 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.82843f);
1000 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
1001 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.82843f);
1002 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001003
1004 metadata.maxContentBoost = 8.0f;
1005 metadata.minContentBoost = 1.0f;
1006
Dichen Zhang10959a42023-04-10 16:28:16 -07001007 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite());
1008 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f / 3.0f, &metadata), RgbWhite() * 2.0f);
1009 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 2.0f / 3.0f, &metadata), RgbWhite() * 4.0f);
1010 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001011
1012 metadata.maxContentBoost = 8.0f;
1013 metadata.minContentBoost = 0.5f;
1014
Dichen Zhang10959a42023-04-10 16:28:16 -07001015 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
1016 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite());
1017 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite() * 2.0f);
1018 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 4.0f);
1019 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
Nick Deakin65f492a2022-11-29 22:47:40 -05001020
1021 Color e = {{{ 0.0f, 0.5f, 1.0f }}};
Nick Deakind19e5762023-02-10 15:39:08 -05001022 metadata.maxContentBoost = 4.0f;
1023 metadata.minContentBoost = 1.0f / 4.0f;
Nick Deakin65f492a2022-11-29 22:47:40 -05001024
Dichen Zhang10959a42023-04-10 16:28:16 -07001025 EXPECT_RGB_NEAR(applyGain(e, 0.0f, &metadata), e / 4.0f);
1026 EXPECT_RGB_NEAR(applyGain(e, 0.25f, &metadata), e / 2.0f);
1027 EXPECT_RGB_NEAR(applyGain(e, 0.5f, &metadata), e);
1028 EXPECT_RGB_NEAR(applyGain(e, 0.75f, &metadata), e * 2.0f);
1029 EXPECT_RGB_NEAR(applyGain(e, 1.0f, &metadata), e * 4.0f);
Dichen Zhangc6605702023-03-15 18:40:55 -07001030
Dichen Zhang10959a42023-04-10 16:28:16 -07001031 EXPECT_RGB_EQ(applyGain(RgbBlack(), 1.0f, &metadata),
1032 applyGain(RgbBlack(), 1.0f, &metadata, displayBoost));
1033 EXPECT_RGB_EQ(applyGain(RgbWhite(), 1.0f, &metadata),
1034 applyGain(RgbWhite(), 1.0f, &metadata, displayBoost));
1035 EXPECT_RGB_EQ(applyGain(RgbRed(), 1.0f, &metadata),
1036 applyGain(RgbRed(), 1.0f, &metadata, displayBoost));
1037 EXPECT_RGB_EQ(applyGain(RgbGreen(), 1.0f, &metadata),
1038 applyGain(RgbGreen(), 1.0f, &metadata, displayBoost));
1039 EXPECT_RGB_EQ(applyGain(RgbBlue(), 1.0f, &metadata),
1040 applyGain(RgbBlue(), 1.0f, &metadata, displayBoost));
1041 EXPECT_RGB_EQ(applyGain(e, 1.0f, &metadata),
1042 applyGain(e, 1.0f, &metadata, displayBoost));
Nick Deakin65f492a2022-11-29 22:47:40 -05001043}
1044
Dichen Zhang10959a42023-04-10 16:28:16 -07001045TEST_F(GainMapMathTest, GetYuv420Pixel) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001046 jpegr_uncompressed_struct image = Yuv420Image();
1047 Color (*colors)[4] = Yuv420Colors();
1048
1049 for (size_t y = 0; y < 4; ++y) {
1050 for (size_t x = 0; x < 4; ++x) {
1051 EXPECT_YUV_NEAR(getYuv420Pixel(&image, x, y), colors[y][x]);
1052 }
1053 }
1054}
1055
Dichen Zhang10959a42023-04-10 16:28:16 -07001056TEST_F(GainMapMathTest, GetP010Pixel) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001057 jpegr_uncompressed_struct image = P010Image();
1058 Color (*colors)[4] = P010Colors();
1059
1060 for (size_t y = 0; y < 4; ++y) {
1061 for (size_t x = 0; x < 4; ++x) {
1062 EXPECT_YUV_NEAR(getP010Pixel(&image, x, y), colors[y][x]);
1063 }
1064 }
1065}
1066
Dichen Zhang10959a42023-04-10 16:28:16 -07001067TEST_F(GainMapMathTest, SampleYuv420) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001068 jpegr_uncompressed_struct image = Yuv420Image();
1069 Color (*colors)[4] = Yuv420Colors();
1070
1071 static const size_t kMapScaleFactor = 2;
1072 for (size_t y = 0; y < 4 / kMapScaleFactor; ++y) {
1073 for (size_t x = 0; x < 4 / kMapScaleFactor; ++x) {
1074 Color min = {{{ 1.0f, 1.0f, 1.0f }}};
1075 Color max = {{{ -1.0f, -1.0f, -1.0f }}};
1076
1077 for (size_t dy = 0; dy < kMapScaleFactor; ++dy) {
1078 for (size_t dx = 0; dx < kMapScaleFactor; ++dx) {
1079 Color e = colors[y * kMapScaleFactor + dy][x * kMapScaleFactor + dx];
1080 min = ColorMin(min, e);
1081 max = ColorMax(max, e);
1082 }
1083 }
1084
1085 // Instead of reimplementing the sampling algorithm, confirm that the
1086 // sample output is within the range of the min and max of the nearest
1087 // points.
1088 EXPECT_YUV_BETWEEN(sampleYuv420(&image, kMapScaleFactor, x, y), min, max);
1089 }
1090 }
1091}
1092
Dichen Zhang10959a42023-04-10 16:28:16 -07001093TEST_F(GainMapMathTest, SampleP010) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001094 jpegr_uncompressed_struct image = P010Image();
1095 Color (*colors)[4] = P010Colors();
1096
1097 static const size_t kMapScaleFactor = 2;
1098 for (size_t y = 0; y < 4 / kMapScaleFactor; ++y) {
1099 for (size_t x = 0; x < 4 / kMapScaleFactor; ++x) {
1100 Color min = {{{ 1.0f, 1.0f, 1.0f }}};
1101 Color max = {{{ -1.0f, -1.0f, -1.0f }}};
1102
1103 for (size_t dy = 0; dy < kMapScaleFactor; ++dy) {
1104 for (size_t dx = 0; dx < kMapScaleFactor; ++dx) {
1105 Color e = colors[y * kMapScaleFactor + dy][x * kMapScaleFactor + dx];
1106 min = ColorMin(min, e);
1107 max = ColorMax(max, e);
1108 }
1109 }
1110
1111 // Instead of reimplementing the sampling algorithm, confirm that the
1112 // sample output is within the range of the min and max of the nearest
1113 // points.
1114 EXPECT_YUV_BETWEEN(sampleP010(&image, kMapScaleFactor, x, y), min, max);
1115 }
1116 }
1117}
1118
Dichen Zhang10959a42023-04-10 16:28:16 -07001119TEST_F(GainMapMathTest, SampleMap) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001120 jpegr_uncompressed_struct image = MapImage();
1121 float (*values)[4] = MapValues();
1122
1123 static const size_t kMapScaleFactor = 2;
Ram Mohanfe723d62022-12-15 00:59:11 +05301124 ShepardsIDW idwTable(kMapScaleFactor);
Nick Deakin65f492a2022-11-29 22:47:40 -05001125 for (size_t y = 0; y < 4 * kMapScaleFactor; ++y) {
1126 for (size_t x = 0; x < 4 * kMapScaleFactor; ++x) {
1127 size_t x_base = x / kMapScaleFactor;
1128 size_t y_base = y / kMapScaleFactor;
1129
1130 float min = 1.0f;
1131 float max = -1.0f;
1132
1133 min = fmin(min, values[y_base][x_base]);
1134 max = fmax(max, values[y_base][x_base]);
1135 if (y_base + 1 < 4) {
1136 min = fmin(min, values[y_base + 1][x_base]);
1137 max = fmax(max, values[y_base + 1][x_base]);
1138 }
1139 if (x_base + 1 < 4) {
1140 min = fmin(min, values[y_base][x_base + 1]);
1141 max = fmax(max, values[y_base][x_base + 1]);
1142 }
1143 if (y_base + 1 < 4 && x_base + 1 < 4) {
1144 min = fmin(min, values[y_base + 1][x_base + 1]);
1145 max = fmax(max, values[y_base + 1][x_base + 1]);
1146 }
1147
1148 // Instead of reimplementing the sampling algorithm, confirm that the
1149 // sample output is within the range of the min and max of the nearest
1150 // points.
Nick Deakind19e5762023-02-10 15:39:08 -05001151 EXPECT_THAT(sampleMap(&image, kMapScaleFactor, x, y),
Nick Deakin65f492a2022-11-29 22:47:40 -05001152 testing::AllOf(testing::Ge(min), testing::Le(max)));
Nick Deakind19e5762023-02-10 15:39:08 -05001153 EXPECT_EQ(sampleMap(&image, kMapScaleFactor, x, y, idwTable),
1154 sampleMap(&image, kMapScaleFactor, x, y));
Nick Deakin65f492a2022-11-29 22:47:40 -05001155 }
1156 }
1157}
1158
Dichen Zhang10959a42023-04-10 16:28:16 -07001159TEST_F(GainMapMathTest, ColorToRgba1010102) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001160 EXPECT_EQ(colorToRgba1010102(RgbBlack()), 0x3 << 30);
1161 EXPECT_EQ(colorToRgba1010102(RgbWhite()), 0xFFFFFFFF);
1162 EXPECT_EQ(colorToRgba1010102(RgbRed()), 0x3 << 30 | 0x3ff);
1163 EXPECT_EQ(colorToRgba1010102(RgbGreen()), 0x3 << 30 | 0x3ff << 10);
1164 EXPECT_EQ(colorToRgba1010102(RgbBlue()), 0x3 << 30 | 0x3ff << 20);
1165
1166 Color e_gamma = {{{ 0.1f, 0.2f, 0.3f }}};
1167 EXPECT_EQ(colorToRgba1010102(e_gamma),
1168 0x3 << 30
1169 | static_cast<uint32_t>(0.1f * static_cast<float>(0x3ff))
1170 | static_cast<uint32_t>(0.2f * static_cast<float>(0x3ff)) << 10
1171 | static_cast<uint32_t>(0.3f * static_cast<float>(0x3ff)) << 20);
1172}
1173
Dichen Zhang10959a42023-04-10 16:28:16 -07001174TEST_F(GainMapMathTest, ColorToRgbaF16) {
Dichen Zhangf106df72023-04-04 17:44:46 +00001175 EXPECT_EQ(colorToRgbaF16(RgbBlack()), ((uint64_t) 0x3C00) << 48);
1176 EXPECT_EQ(colorToRgbaF16(RgbWhite()), 0x3C003C003C003C00);
1177 EXPECT_EQ(colorToRgbaF16(RgbRed()), (((uint64_t) 0x3C00) << 48) | ((uint64_t) 0x3C00));
1178 EXPECT_EQ(colorToRgbaF16(RgbGreen()), (((uint64_t) 0x3C00) << 48) | (((uint64_t) 0x3C00) << 16));
1179 EXPECT_EQ(colorToRgbaF16(RgbBlue()), (((uint64_t) 0x3C00) << 48) | (((uint64_t) 0x3C00) << 32));
1180
1181 Color e_gamma = {{{ 0.1f, 0.2f, 0.3f }}};
1182 EXPECT_EQ(colorToRgbaF16(e_gamma), 0x3C0034CD32662E66);
1183}
1184
Dichen Zhang10959a42023-04-10 16:28:16 -07001185TEST_F(GainMapMathTest, Float32ToFloat16) {
Dichen Zhangf106df72023-04-04 17:44:46 +00001186 EXPECT_EQ(floatToHalf(0.1f), 0x2E66);
1187 EXPECT_EQ(floatToHalf(0.0f), 0x0);
1188 EXPECT_EQ(floatToHalf(1.0f), 0x3C00);
1189 EXPECT_EQ(floatToHalf(-1.0f), 0xBC00);
1190 EXPECT_EQ(floatToHalf(0x1.fffffep127f), 0x7FFF); // float max
1191 EXPECT_EQ(floatToHalf(-0x1.fffffep127f), 0xFFFF); // float min
1192 EXPECT_EQ(floatToHalf(0x1.0p-126f), 0x0); // float zero
1193}
1194
Dichen Zhang10959a42023-04-10 16:28:16 -07001195TEST_F(GainMapMathTest, GenerateMapLuminanceSrgb) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001196 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), srgbLuminance),
1197 0.0f);
1198 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), srgbLuminance),
1199 kSdrWhiteNits);
1200 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), srgbLuminance),
1201 srgbLuminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
1202 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), srgbLuminance),
1203 srgbLuminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
1204 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), srgbLuminance),
1205 srgbLuminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1206}
1207
Dichen Zhang10959a42023-04-10 16:28:16 -07001208TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbP3) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001209 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), p3Luminance),
1210 0.0f);
1211 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), p3Luminance),
1212 kSdrWhiteNits);
1213 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), p3Luminance),
1214 p3Luminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
1215 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), p3Luminance),
1216 p3Luminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
1217 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), p3Luminance),
1218 p3Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1219}
1220
Dichen Zhang10959a42023-04-10 16:28:16 -07001221TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbBt2100) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001222 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), bt2100Luminance),
1223 0.0f);
1224 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), bt2100Luminance),
1225 kSdrWhiteNits);
1226 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), bt2100Luminance),
1227 bt2100Luminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
1228 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), bt2100Luminance),
1229 bt2100Luminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
1230 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), bt2100Luminance),
1231 bt2100Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1232}
1233
Dichen Zhang10959a42023-04-10 16:28:16 -07001234TEST_F(GainMapMathTest, GenerateMapLuminanceHlg) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001235 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), hlgInvOetf, identityConversion,
1236 bt2100Luminance, kHlgMaxNits),
1237 0.0f);
1238 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvWhite(), hlgInvOetf, identityConversion,
1239 bt2100Luminance, kHlgMaxNits),
1240 kHlgMaxNits);
1241 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvRed(), hlgInvOetf, identityConversion,
1242 bt2100Luminance, kHlgMaxNits),
1243 bt2100Luminance(RgbRed()) * kHlgMaxNits, LuminanceEpsilon());
1244 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvGreen(), hlgInvOetf, identityConversion,
1245 bt2100Luminance, kHlgMaxNits),
1246 bt2100Luminance(RgbGreen()) * kHlgMaxNits, LuminanceEpsilon());
1247 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvBlue(), hlgInvOetf, identityConversion,
1248 bt2100Luminance, kHlgMaxNits),
1249 bt2100Luminance(RgbBlue()) * kHlgMaxNits, LuminanceEpsilon());
1250}
1251
Dichen Zhang10959a42023-04-10 16:28:16 -07001252TEST_F(GainMapMathTest, GenerateMapLuminancePq) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001253 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), pqInvOetf, identityConversion,
1254 bt2100Luminance, kPqMaxNits),
1255 0.0f);
1256 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvWhite(), pqInvOetf, identityConversion,
1257 bt2100Luminance, kPqMaxNits),
1258 kPqMaxNits);
1259 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvRed(), pqInvOetf, identityConversion,
1260 bt2100Luminance, kPqMaxNits),
1261 bt2100Luminance(RgbRed()) * kPqMaxNits, LuminanceEpsilon());
1262 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvGreen(), pqInvOetf, identityConversion,
1263 bt2100Luminance, kPqMaxNits),
1264 bt2100Luminance(RgbGreen()) * kPqMaxNits, LuminanceEpsilon());
1265 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvBlue(), pqInvOetf, identityConversion,
1266 bt2100Luminance, kPqMaxNits),
1267 bt2100Luminance(RgbBlue()) * kPqMaxNits, LuminanceEpsilon());
1268}
1269
Dichen Zhang10959a42023-04-10 16:28:16 -07001270TEST_F(GainMapMathTest, ApplyMap) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001271 ultrahdr_metadata_struct metadata = { .maxContentBoost = 8.0f,
Dichen Zhange286f1c2023-03-14 00:22:00 +00001272 .minContentBoost = 1.0f / 8.0f };
Nick Deakind19e5762023-02-10 15:39:08 -05001273
1274 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001275 RgbWhite() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001276 EXPECT_RGB_EQ(Recover(YuvBlack(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001277 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001278 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001279 RgbRed() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001280 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001281 RgbGreen() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001282 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001283 RgbBlue() * 8.0f);
1284
Nick Deakind19e5762023-02-10 15:39:08 -05001285 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001286 RgbWhite() * sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001287 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001288 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001289 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001290 RgbRed() * sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001291 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001292 RgbGreen() * sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001293 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001294 RgbBlue() * sqrt(8.0f));
1295
Nick Deakind19e5762023-02-10 15:39:08 -05001296 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001297 RgbWhite());
Nick Deakind19e5762023-02-10 15:39:08 -05001298 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001299 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001300 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001301 RgbRed());
Nick Deakind19e5762023-02-10 15:39:08 -05001302 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001303 RgbGreen());
Nick Deakind19e5762023-02-10 15:39:08 -05001304 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001305 RgbBlue());
1306
Nick Deakind19e5762023-02-10 15:39:08 -05001307 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001308 RgbWhite() / sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001309 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001310 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001311 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001312 RgbRed() / sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001313 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001314 RgbGreen() / sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001315 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001316 RgbBlue() / sqrt(8.0f));
1317
Nick Deakind19e5762023-02-10 15:39:08 -05001318 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001319 RgbWhite() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001320 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001321 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001322 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001323 RgbRed() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001324 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001325 RgbGreen() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001326 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001327 RgbBlue() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001328
1329 metadata.maxContentBoost = 8.0f;
1330 metadata.minContentBoost = 1.0f;
1331
1332 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata),
1333 RgbWhite() * 8.0f);
1334 EXPECT_RGB_EQ(Recover(YuvWhite(), 2.0f / 3.0f, &metadata),
1335 RgbWhite() * 4.0f);
1336 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f / 3.0f, &metadata),
1337 RgbWhite() * 2.0f);
1338 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata),
1339 RgbWhite());
1340
1341 metadata.maxContentBoost = 8.0f;
1342 metadata.minContentBoost = 0.5f;;
1343
1344 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata),
1345 RgbWhite() * 8.0f);
1346 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.75, &metadata),
1347 RgbWhite() * 4.0f);
1348 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.5f, &metadata),
1349 RgbWhite() * 2.0f);
1350 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.25f, &metadata),
1351 RgbWhite());
1352 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata),
1353 RgbWhite() / 2.0f);
Nick Deakin65f492a2022-11-29 22:47:40 -05001354}
1355
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001356} // namespace android::ultrahdr