blob: 7c2d076992b4f919e615db9fa3b5ee6e5714e6dd [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 };
Ram Mohaneca81942023-07-29 14:41:48 +0530123 return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_BT709, pixels + 16, 4, 2 };
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 };
Ram Mohaneca81942023-07-29 14:41:48 +0530156 return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_BT709, pixels + 16, 4, 4 };
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
Ram Mohaneca81942023-07-29 14:41:48 +0530628TEST_F(GainMapMathTest, TransformYuv420) {
Nick Deakin0db53ee2023-05-19 17:14:45 -0400629 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();
Ram Mohaneca81942023-07-29 14:41:48 +0530639 output.chroma_data = out_buf.get() + input.width * input.height;
640 output.luma_stride = input.width;
641 output.chroma_stride = input.width / 2;
Nick Deakin0db53ee2023-05-19 17:14:45 -0400642
643 transformYuv420(&output, 1, 1, transform);
644
645 for (size_t y = 0; y < 4; ++y) {
646 for (size_t x = 0; x < 4; ++x) {
647 // Skip the last chroma sample, which we modified above
648 if (x >= 2 && y >= 2) {
649 continue;
650 }
651
652 // All other pixels should remain unchanged
653 EXPECT_YUV_EQ(getYuv420Pixel(&input, x, y), getYuv420Pixel(&output, x, y));
654 }
655 }
656
657 // modified pixels should be updated as intended by the transformYuv420 algorithm
658 Color in1 = getYuv420Pixel(&input, 2, 2);
659 Color in2 = getYuv420Pixel(&input, 3, 2);
660 Color in3 = getYuv420Pixel(&input, 2, 3);
661 Color in4 = getYuv420Pixel(&input, 3, 3);
662 Color out1 = getYuv420Pixel(&output, 2, 2);
663 Color out2 = getYuv420Pixel(&output, 3, 2);
664 Color out3 = getYuv420Pixel(&output, 2, 3);
665 Color out4 = getYuv420Pixel(&output, 3, 3);
666
667 EXPECT_NEAR(transform(in1).y, out1.y, YuvConversionEpsilon());
668 EXPECT_NEAR(transform(in2).y, out2.y, YuvConversionEpsilon());
669 EXPECT_NEAR(transform(in3).y, out3.y, YuvConversionEpsilon());
670 EXPECT_NEAR(transform(in4).y, out4.y, YuvConversionEpsilon());
671
672 Color expect_uv = (transform(in1) + transform(in2) + transform(in3) + transform(in4)) / 4.0f;
673
674 EXPECT_NEAR(expect_uv.u, out1.u, YuvConversionEpsilon());
675 EXPECT_NEAR(expect_uv.u, out2.u, YuvConversionEpsilon());
676 EXPECT_NEAR(expect_uv.u, out3.u, YuvConversionEpsilon());
677 EXPECT_NEAR(expect_uv.u, out4.u, YuvConversionEpsilon());
678
679 EXPECT_NEAR(expect_uv.v, out1.v, YuvConversionEpsilon());
680 EXPECT_NEAR(expect_uv.v, out2.v, YuvConversionEpsilon());
681 EXPECT_NEAR(expect_uv.v, out3.v, YuvConversionEpsilon());
682 EXPECT_NEAR(expect_uv.v, out4.v, YuvConversionEpsilon());
683 }
684}
685
Dichen Zhang10959a42023-04-10 16:28:16 -0700686TEST_F(GainMapMathTest, HlgOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500687 EXPECT_FLOAT_EQ(hlgOetf(0.0f), 0.0f);
688 EXPECT_NEAR(hlgOetf(0.04167f), 0.35357f, ComparisonEpsilon());
689 EXPECT_NEAR(hlgOetf(0.08333f), 0.5f, ComparisonEpsilon());
690 EXPECT_NEAR(hlgOetf(0.5f), 0.87164f, ComparisonEpsilon());
691 EXPECT_FLOAT_EQ(hlgOetf(1.0f), 1.0f);
692
693 Color e = {{{ 0.04167f, 0.08333f, 0.5f }}};
694 Color e_gamma = {{{ 0.35357f, 0.5f, 0.87164f }}};
695 EXPECT_RGB_NEAR(hlgOetf(e), e_gamma);
696}
697
Dichen Zhang10959a42023-04-10 16:28:16 -0700698TEST_F(GainMapMathTest, HlgInvOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500699 EXPECT_FLOAT_EQ(hlgInvOetf(0.0f), 0.0f);
700 EXPECT_NEAR(hlgInvOetf(0.25f), 0.02083f, ComparisonEpsilon());
701 EXPECT_NEAR(hlgInvOetf(0.5f), 0.08333f, ComparisonEpsilon());
702 EXPECT_NEAR(hlgInvOetf(0.75f), 0.26496f, ComparisonEpsilon());
703 EXPECT_FLOAT_EQ(hlgInvOetf(1.0f), 1.0f);
704
705 Color e_gamma = {{{ 0.25f, 0.5f, 0.75f }}};
706 Color e = {{{ 0.02083f, 0.08333f, 0.26496f }}};
707 EXPECT_RGB_NEAR(hlgInvOetf(e_gamma), e);
708}
709
Dichen Zhang10959a42023-04-10 16:28:16 -0700710TEST_F(GainMapMathTest, HlgTransferFunctionRoundtrip) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500711 EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(0.0f)), 0.0f);
712 EXPECT_NEAR(hlgInvOetf(hlgOetf(0.04167f)), 0.04167f, ComparisonEpsilon());
713 EXPECT_NEAR(hlgInvOetf(hlgOetf(0.08333f)), 0.08333f, ComparisonEpsilon());
714 EXPECT_NEAR(hlgInvOetf(hlgOetf(0.5f)), 0.5f, ComparisonEpsilon());
715 EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(1.0f)), 1.0f);
716}
717
Dichen Zhang10959a42023-04-10 16:28:16 -0700718TEST_F(GainMapMathTest, PqOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500719 EXPECT_FLOAT_EQ(pqOetf(0.0f), 0.0f);
720 EXPECT_NEAR(pqOetf(0.01f), 0.50808f, ComparisonEpsilon());
721 EXPECT_NEAR(pqOetf(0.5f), 0.92655f, ComparisonEpsilon());
722 EXPECT_NEAR(pqOetf(0.99f), 0.99895f, ComparisonEpsilon());
723 EXPECT_FLOAT_EQ(pqOetf(1.0f), 1.0f);
724
725 Color e = {{{ 0.01f, 0.5f, 0.99f }}};
726 Color e_gamma = {{{ 0.50808f, 0.92655f, 0.99895f }}};
727 EXPECT_RGB_NEAR(pqOetf(e), e_gamma);
728}
729
Dichen Zhang10959a42023-04-10 16:28:16 -0700730TEST_F(GainMapMathTest, PqInvOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500731 EXPECT_FLOAT_EQ(pqInvOetf(0.0f), 0.0f);
732 EXPECT_NEAR(pqInvOetf(0.01f), 2.31017e-7f, ComparisonEpsilon());
733 EXPECT_NEAR(pqInvOetf(0.5f), 0.00922f, ComparisonEpsilon());
734 EXPECT_NEAR(pqInvOetf(0.99f), 0.90903f, ComparisonEpsilon());
735 EXPECT_FLOAT_EQ(pqInvOetf(1.0f), 1.0f);
736
737 Color e_gamma = {{{ 0.01f, 0.5f, 0.99f }}};
738 Color e = {{{ 2.31017e-7f, 0.00922f, 0.90903f }}};
739 EXPECT_RGB_NEAR(pqInvOetf(e_gamma), e);
740}
741
Dichen Zhang10959a42023-04-10 16:28:16 -0700742TEST_F(GainMapMathTest, PqInvOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500743 for (int idx = 0; idx < kPqInvOETFNumEntries; idx++) {
744 float value = static_cast<float>(idx) / static_cast<float>(kPqInvOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800745 EXPECT_FLOAT_EQ(pqInvOetf(value), pqInvOetfLUT(value));
746 }
747}
748
Dichen Zhang10959a42023-04-10 16:28:16 -0700749TEST_F(GainMapMathTest, HlgInvOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500750 for (int idx = 0; idx < kHlgInvOETFNumEntries; idx++) {
751 float value = static_cast<float>(idx) / static_cast<float>(kHlgInvOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800752 EXPECT_FLOAT_EQ(hlgInvOetf(value), hlgInvOetfLUT(value));
753 }
754}
755
Dichen Zhang10959a42023-04-10 16:28:16 -0700756TEST_F(GainMapMathTest, pqOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500757 for (int idx = 0; idx < kPqOETFNumEntries; idx++) {
758 float value = static_cast<float>(idx) / static_cast<float>(kPqOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800759 EXPECT_FLOAT_EQ(pqOetf(value), pqOetfLUT(value));
760 }
761}
762
Dichen Zhang10959a42023-04-10 16:28:16 -0700763TEST_F(GainMapMathTest, hlgOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500764 for (int idx = 0; idx < kHlgOETFNumEntries; idx++) {
765 float value = static_cast<float>(idx) / static_cast<float>(kHlgOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800766 EXPECT_FLOAT_EQ(hlgOetf(value), hlgOetfLUT(value));
767 }
768}
769
Dichen Zhang10959a42023-04-10 16:28:16 -0700770TEST_F(GainMapMathTest, srgbInvOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500771 for (int idx = 0; idx < kSrgbInvOETFNumEntries; idx++) {
772 float value = static_cast<float>(idx) / static_cast<float>(kSrgbInvOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800773 EXPECT_FLOAT_EQ(srgbInvOetf(value), srgbInvOetfLUT(value));
774 }
775}
776
Dichen Zhang10959a42023-04-10 16:28:16 -0700777TEST_F(GainMapMathTest, applyGainLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500778 for (int boost = 1; boost <= 10; boost++) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000779 ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
Dichen Zhange286f1c2023-03-14 00:22:00 +0000780 .minContentBoost = 1.0f / static_cast<float>(boost) };
Dichen Zhang10959a42023-04-10 16:28:16 -0700781 GainLUT gainLUT(&metadata);
782 GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
783 for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
784 float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
785 EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
786 applyGainLUT(RgbBlack(), value, gainLUT));
787 EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
788 applyGainLUT(RgbWhite(), value, gainLUT));
789 EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
790 applyGainLUT(RgbRed(), value, gainLUT));
791 EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
792 applyGainLUT(RgbGreen(), value, gainLUT));
793 EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
794 applyGainLUT(RgbBlue(), value, gainLUT));
795 EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
796 applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
797 EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
798 applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
799 EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
800 applyGainLUT(RgbRed(), value, gainLUTWithBoost));
801 EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
802 applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
803 EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
804 applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
Nick Deakind19e5762023-02-10 15:39:08 -0500805 }
806 }
807
808 for (int boost = 1; boost <= 10; boost++) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000809 ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
Dichen Zhange286f1c2023-03-14 00:22:00 +0000810 .minContentBoost = 1.0f };
Dichen Zhang10959a42023-04-10 16:28:16 -0700811 GainLUT gainLUT(&metadata);
812 GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
813 for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
814 float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
815 EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
816 applyGainLUT(RgbBlack(), value, gainLUT));
817 EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
818 applyGainLUT(RgbWhite(), value, gainLUT));
819 EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
820 applyGainLUT(RgbRed(), value, gainLUT));
821 EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
822 applyGainLUT(RgbGreen(), value, gainLUT));
823 EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
824 applyGainLUT(RgbBlue(), value, gainLUT));
825 EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
826 applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
827 EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
828 applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
829 EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
830 applyGainLUT(RgbRed(), value, gainLUTWithBoost));
831 EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
832 applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
833 EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
834 applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
Nick Deakind19e5762023-02-10 15:39:08 -0500835 }
836 }
837
838 for (int boost = 1; boost <= 10; boost++) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000839 ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
Dichen Zhange286f1c2023-03-14 00:22:00 +0000840 .minContentBoost = 1.0f / pow(static_cast<float>(boost),
Nick Deakind19e5762023-02-10 15:39:08 -0500841 1.0f / 3.0f) };
Dichen Zhang10959a42023-04-10 16:28:16 -0700842 GainLUT gainLUT(&metadata);
843 GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
844 for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
845 float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
846 EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
847 applyGainLUT(RgbBlack(), value, gainLUT));
848 EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
849 applyGainLUT(RgbWhite(), value, gainLUT));
850 EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
851 applyGainLUT(RgbRed(), value, gainLUT));
852 EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
853 applyGainLUT(RgbGreen(), value, gainLUT));
854 EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
855 applyGainLUT(RgbBlue(), value, gainLUT));
856 EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
857 applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
858 EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
859 applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
860 EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
861 applyGainLUT(RgbRed(), value, gainLUTWithBoost));
862 EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
863 applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
864 EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
865 applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
Harish Mahendrakarf25991f2022-12-16 11:57:44 -0800866 }
867 }
868}
869
Dichen Zhang10959a42023-04-10 16:28:16 -0700870TEST_F(GainMapMathTest, PqTransferFunctionRoundtrip) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500871 EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(0.0f)), 0.0f);
872 EXPECT_NEAR(pqInvOetf(pqOetf(0.01f)), 0.01f, ComparisonEpsilon());
873 EXPECT_NEAR(pqInvOetf(pqOetf(0.5f)), 0.5f, ComparisonEpsilon());
874 EXPECT_NEAR(pqInvOetf(pqOetf(0.99f)), 0.99f, ComparisonEpsilon());
875 EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(1.0f)), 1.0f);
876}
877
Dichen Zhang10959a42023-04-10 16:28:16 -0700878TEST_F(GainMapMathTest, ColorConversionLookup) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000879 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500880 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000881 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500882 identityConversion);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000883 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500884 p3ToBt709);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000885 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500886 bt2100ToBt709);
887
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000888 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500889 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000890 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500891 bt709ToP3);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000892 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500893 identityConversion);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000894 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500895 bt2100ToP3);
896
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000897 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500898 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000899 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500900 bt709ToBt2100);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000901 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500902 p3ToBt2100);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000903 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500904 identityConversion);
905
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000906 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500907 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000908 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500909 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000910 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500911 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000912 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500913 nullptr);
914}
915
Dichen Zhang10959a42023-04-10 16:28:16 -0700916TEST_F(GainMapMathTest, EncodeGain) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000917 ultrahdr_metadata_struct metadata = { .maxContentBoost = 4.0f,
Nick Deakin0db53ee2023-05-19 17:14:45 -0400918 .minContentBoost = 1.0f / 4.0f };
Nick Deakin65f492a2022-11-29 22:47:40 -0500919
Dichen Zhang10959a42023-04-10 16:28:16 -0700920 EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 127);
921 EXPECT_EQ(encodeGain(0.0f, 1.0f, &metadata), 127);
922 EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
923 EXPECT_EQ(encodeGain(0.5f, 0.0f, &metadata), 0);
Nick Deakin65f492a2022-11-29 22:47:40 -0500924
Dichen Zhang10959a42023-04-10 16:28:16 -0700925 EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 127);
926 EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 255);
927 EXPECT_EQ(encodeGain(1.0f, 5.0f, &metadata), 255);
928 EXPECT_EQ(encodeGain(4.0f, 1.0f, &metadata), 0);
929 EXPECT_EQ(encodeGain(4.0f, 0.5f, &metadata), 0);
930 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 191);
931 EXPECT_EQ(encodeGain(2.0f, 1.0f, &metadata), 63);
Nick Deakin65f492a2022-11-29 22:47:40 -0500932
Nick Deakind19e5762023-02-10 15:39:08 -0500933 metadata.maxContentBoost = 2.0f;
934 metadata.minContentBoost = 1.0f / 2.0f;
935
Dichen Zhang10959a42023-04-10 16:28:16 -0700936 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 255);
937 EXPECT_EQ(encodeGain(2.0f, 1.0f, &metadata), 0);
938 EXPECT_EQ(encodeGain(1.0f, 1.41421f, &metadata), 191);
939 EXPECT_EQ(encodeGain(1.41421f, 1.0f, &metadata), 63);
Nick Deakind19e5762023-02-10 15:39:08 -0500940
941 metadata.maxContentBoost = 8.0f;
942 metadata.minContentBoost = 1.0f / 8.0f;
943
Dichen Zhang10959a42023-04-10 16:28:16 -0700944 EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
945 EXPECT_EQ(encodeGain(8.0f, 1.0f, &metadata), 0);
946 EXPECT_EQ(encodeGain(1.0f, 2.82843f, &metadata), 191);
947 EXPECT_EQ(encodeGain(2.82843f, 1.0f, &metadata), 63);
Nick Deakind19e5762023-02-10 15:39:08 -0500948
949 metadata.maxContentBoost = 8.0f;
950 metadata.minContentBoost = 1.0f;
951
Dichen Zhang10959a42023-04-10 16:28:16 -0700952 EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 0);
953 EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
Nick Deakind19e5762023-02-10 15:39:08 -0500954
Dichen Zhang10959a42023-04-10 16:28:16 -0700955 EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 0);
956 EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
957 EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 170);
958 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 85);
Nick Deakind19e5762023-02-10 15:39:08 -0500959
960 metadata.maxContentBoost = 8.0f;
961 metadata.minContentBoost = 0.5f;
962
Dichen Zhang10959a42023-04-10 16:28:16 -0700963 EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 63);
964 EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
Nick Deakind19e5762023-02-10 15:39:08 -0500965
Dichen Zhang10959a42023-04-10 16:28:16 -0700966 EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 63);
967 EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
968 EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 191);
969 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 127);
970 EXPECT_EQ(encodeGain(1.0f, 0.7071f, &metadata), 31);
971 EXPECT_EQ(encodeGain(1.0f, 0.5f, &metadata), 0);
Nick Deakin65f492a2022-11-29 22:47:40 -0500972}
973
Dichen Zhang10959a42023-04-10 16:28:16 -0700974TEST_F(GainMapMathTest, ApplyGain) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000975 ultrahdr_metadata_struct metadata = { .maxContentBoost = 4.0f,
Nick Deakin0db53ee2023-05-19 17:14:45 -0400976 .minContentBoost = 1.0f / 4.0f };
Dichen Zhangc6605702023-03-15 18:40:55 -0700977 float displayBoost = metadata.maxContentBoost;
Nick Deakin65f492a2022-11-29 22:47:40 -0500978
Dichen Zhang10959a42023-04-10 16:28:16 -0700979 EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.0f, &metadata), RgbBlack());
980 EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.5f, &metadata), RgbBlack());
981 EXPECT_RGB_NEAR(applyGain(RgbBlack(), 1.0f, &metadata), RgbBlack());
Nick Deakin65f492a2022-11-29 22:47:40 -0500982
Dichen Zhang10959a42023-04-10 16:28:16 -0700983 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 4.0f);
984 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.0f);
985 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
986 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.0f);
987 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 4.0f);
Nick Deakin65f492a2022-11-29 22:47:40 -0500988
Nick Deakind19e5762023-02-10 15:39:08 -0500989 metadata.maxContentBoost = 2.0f;
990 metadata.minContentBoost = 1.0f / 2.0f;
991
Dichen Zhang10959a42023-04-10 16:28:16 -0700992 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
993 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 1.41421f);
994 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
995 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 1.41421f);
996 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 2.0f);
Nick Deakind19e5762023-02-10 15:39:08 -0500997
998 metadata.maxContentBoost = 8.0f;
999 metadata.minContentBoost = 1.0f / 8.0f;
1000
Dichen Zhang10959a42023-04-10 16:28:16 -07001001 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 8.0f);
1002 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.82843f);
1003 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
1004 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.82843f);
1005 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001006
1007 metadata.maxContentBoost = 8.0f;
1008 metadata.minContentBoost = 1.0f;
1009
Dichen Zhang10959a42023-04-10 16:28:16 -07001010 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite());
1011 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f / 3.0f, &metadata), RgbWhite() * 2.0f);
1012 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 2.0f / 3.0f, &metadata), RgbWhite() * 4.0f);
1013 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001014
1015 metadata.maxContentBoost = 8.0f;
1016 metadata.minContentBoost = 0.5f;
1017
Dichen Zhang10959a42023-04-10 16:28:16 -07001018 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
1019 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite());
1020 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite() * 2.0f);
1021 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 4.0f);
1022 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
Nick Deakin65f492a2022-11-29 22:47:40 -05001023
1024 Color e = {{{ 0.0f, 0.5f, 1.0f }}};
Nick Deakind19e5762023-02-10 15:39:08 -05001025 metadata.maxContentBoost = 4.0f;
1026 metadata.minContentBoost = 1.0f / 4.0f;
Nick Deakin65f492a2022-11-29 22:47:40 -05001027
Dichen Zhang10959a42023-04-10 16:28:16 -07001028 EXPECT_RGB_NEAR(applyGain(e, 0.0f, &metadata), e / 4.0f);
1029 EXPECT_RGB_NEAR(applyGain(e, 0.25f, &metadata), e / 2.0f);
1030 EXPECT_RGB_NEAR(applyGain(e, 0.5f, &metadata), e);
1031 EXPECT_RGB_NEAR(applyGain(e, 0.75f, &metadata), e * 2.0f);
1032 EXPECT_RGB_NEAR(applyGain(e, 1.0f, &metadata), e * 4.0f);
Dichen Zhangc6605702023-03-15 18:40:55 -07001033
Dichen Zhang10959a42023-04-10 16:28:16 -07001034 EXPECT_RGB_EQ(applyGain(RgbBlack(), 1.0f, &metadata),
1035 applyGain(RgbBlack(), 1.0f, &metadata, displayBoost));
1036 EXPECT_RGB_EQ(applyGain(RgbWhite(), 1.0f, &metadata),
1037 applyGain(RgbWhite(), 1.0f, &metadata, displayBoost));
1038 EXPECT_RGB_EQ(applyGain(RgbRed(), 1.0f, &metadata),
1039 applyGain(RgbRed(), 1.0f, &metadata, displayBoost));
1040 EXPECT_RGB_EQ(applyGain(RgbGreen(), 1.0f, &metadata),
1041 applyGain(RgbGreen(), 1.0f, &metadata, displayBoost));
1042 EXPECT_RGB_EQ(applyGain(RgbBlue(), 1.0f, &metadata),
1043 applyGain(RgbBlue(), 1.0f, &metadata, displayBoost));
1044 EXPECT_RGB_EQ(applyGain(e, 1.0f, &metadata),
1045 applyGain(e, 1.0f, &metadata, displayBoost));
Nick Deakin65f492a2022-11-29 22:47:40 -05001046}
1047
Ram Mohaneca81942023-07-29 14:41:48 +05301048TEST_F(GainMapMathTest, GetYuv420Pixel) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001049 jpegr_uncompressed_struct image = Yuv420Image();
1050 Color (*colors)[4] = Yuv420Colors();
1051
1052 for (size_t y = 0; y < 4; ++y) {
1053 for (size_t x = 0; x < 4; ++x) {
1054 EXPECT_YUV_NEAR(getYuv420Pixel(&image, x, y), colors[y][x]);
1055 }
1056 }
1057}
1058
Ram Mohaneca81942023-07-29 14:41:48 +05301059TEST_F(GainMapMathTest, GetP010Pixel) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001060 jpegr_uncompressed_struct image = P010Image();
1061 Color (*colors)[4] = P010Colors();
1062
1063 for (size_t y = 0; y < 4; ++y) {
1064 for (size_t x = 0; x < 4; ++x) {
1065 EXPECT_YUV_NEAR(getP010Pixel(&image, x, y), colors[y][x]);
1066 }
1067 }
1068}
1069
Ram Mohaneca81942023-07-29 14:41:48 +05301070TEST_F(GainMapMathTest, SampleYuv420) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001071 jpegr_uncompressed_struct image = Yuv420Image();
1072 Color (*colors)[4] = Yuv420Colors();
1073
1074 static const size_t kMapScaleFactor = 2;
1075 for (size_t y = 0; y < 4 / kMapScaleFactor; ++y) {
1076 for (size_t x = 0; x < 4 / kMapScaleFactor; ++x) {
1077 Color min = {{{ 1.0f, 1.0f, 1.0f }}};
1078 Color max = {{{ -1.0f, -1.0f, -1.0f }}};
1079
1080 for (size_t dy = 0; dy < kMapScaleFactor; ++dy) {
1081 for (size_t dx = 0; dx < kMapScaleFactor; ++dx) {
1082 Color e = colors[y * kMapScaleFactor + dy][x * kMapScaleFactor + dx];
1083 min = ColorMin(min, e);
1084 max = ColorMax(max, e);
1085 }
1086 }
1087
1088 // Instead of reimplementing the sampling algorithm, confirm that the
1089 // sample output is within the range of the min and max of the nearest
1090 // points.
1091 EXPECT_YUV_BETWEEN(sampleYuv420(&image, kMapScaleFactor, x, y), min, max);
1092 }
1093 }
1094}
1095
Ram Mohaneca81942023-07-29 14:41:48 +05301096TEST_F(GainMapMathTest, SampleP010) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001097 jpegr_uncompressed_struct image = P010Image();
1098 Color (*colors)[4] = P010Colors();
1099
1100 static const size_t kMapScaleFactor = 2;
1101 for (size_t y = 0; y < 4 / kMapScaleFactor; ++y) {
1102 for (size_t x = 0; x < 4 / kMapScaleFactor; ++x) {
1103 Color min = {{{ 1.0f, 1.0f, 1.0f }}};
1104 Color max = {{{ -1.0f, -1.0f, -1.0f }}};
1105
1106 for (size_t dy = 0; dy < kMapScaleFactor; ++dy) {
1107 for (size_t dx = 0; dx < kMapScaleFactor; ++dx) {
1108 Color e = colors[y * kMapScaleFactor + dy][x * kMapScaleFactor + dx];
1109 min = ColorMin(min, e);
1110 max = ColorMax(max, e);
1111 }
1112 }
1113
1114 // Instead of reimplementing the sampling algorithm, confirm that the
1115 // sample output is within the range of the min and max of the nearest
1116 // points.
1117 EXPECT_YUV_BETWEEN(sampleP010(&image, kMapScaleFactor, x, y), min, max);
1118 }
1119 }
1120}
1121
Dichen Zhang10959a42023-04-10 16:28:16 -07001122TEST_F(GainMapMathTest, SampleMap) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001123 jpegr_uncompressed_struct image = MapImage();
1124 float (*values)[4] = MapValues();
1125
1126 static const size_t kMapScaleFactor = 2;
Ram Mohanfe723d62022-12-15 00:59:11 +05301127 ShepardsIDW idwTable(kMapScaleFactor);
Nick Deakin65f492a2022-11-29 22:47:40 -05001128 for (size_t y = 0; y < 4 * kMapScaleFactor; ++y) {
1129 for (size_t x = 0; x < 4 * kMapScaleFactor; ++x) {
1130 size_t x_base = x / kMapScaleFactor;
1131 size_t y_base = y / kMapScaleFactor;
1132
1133 float min = 1.0f;
1134 float max = -1.0f;
1135
1136 min = fmin(min, values[y_base][x_base]);
1137 max = fmax(max, values[y_base][x_base]);
1138 if (y_base + 1 < 4) {
1139 min = fmin(min, values[y_base + 1][x_base]);
1140 max = fmax(max, values[y_base + 1][x_base]);
1141 }
1142 if (x_base + 1 < 4) {
1143 min = fmin(min, values[y_base][x_base + 1]);
1144 max = fmax(max, values[y_base][x_base + 1]);
1145 }
1146 if (y_base + 1 < 4 && x_base + 1 < 4) {
1147 min = fmin(min, values[y_base + 1][x_base + 1]);
1148 max = fmax(max, values[y_base + 1][x_base + 1]);
1149 }
1150
1151 // Instead of reimplementing the sampling algorithm, confirm that the
1152 // sample output is within the range of the min and max of the nearest
1153 // points.
Nick Deakind19e5762023-02-10 15:39:08 -05001154 EXPECT_THAT(sampleMap(&image, kMapScaleFactor, x, y),
Nick Deakin65f492a2022-11-29 22:47:40 -05001155 testing::AllOf(testing::Ge(min), testing::Le(max)));
Nick Deakind19e5762023-02-10 15:39:08 -05001156 EXPECT_EQ(sampleMap(&image, kMapScaleFactor, x, y, idwTable),
1157 sampleMap(&image, kMapScaleFactor, x, y));
Nick Deakin65f492a2022-11-29 22:47:40 -05001158 }
1159 }
1160}
1161
Dichen Zhang10959a42023-04-10 16:28:16 -07001162TEST_F(GainMapMathTest, ColorToRgba1010102) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001163 EXPECT_EQ(colorToRgba1010102(RgbBlack()), 0x3 << 30);
1164 EXPECT_EQ(colorToRgba1010102(RgbWhite()), 0xFFFFFFFF);
1165 EXPECT_EQ(colorToRgba1010102(RgbRed()), 0x3 << 30 | 0x3ff);
1166 EXPECT_EQ(colorToRgba1010102(RgbGreen()), 0x3 << 30 | 0x3ff << 10);
1167 EXPECT_EQ(colorToRgba1010102(RgbBlue()), 0x3 << 30 | 0x3ff << 20);
1168
1169 Color e_gamma = {{{ 0.1f, 0.2f, 0.3f }}};
1170 EXPECT_EQ(colorToRgba1010102(e_gamma),
1171 0x3 << 30
1172 | static_cast<uint32_t>(0.1f * static_cast<float>(0x3ff))
1173 | static_cast<uint32_t>(0.2f * static_cast<float>(0x3ff)) << 10
1174 | static_cast<uint32_t>(0.3f * static_cast<float>(0x3ff)) << 20);
1175}
1176
Dichen Zhang10959a42023-04-10 16:28:16 -07001177TEST_F(GainMapMathTest, ColorToRgbaF16) {
Dichen Zhangf106df72023-04-04 17:44:46 +00001178 EXPECT_EQ(colorToRgbaF16(RgbBlack()), ((uint64_t) 0x3C00) << 48);
1179 EXPECT_EQ(colorToRgbaF16(RgbWhite()), 0x3C003C003C003C00);
1180 EXPECT_EQ(colorToRgbaF16(RgbRed()), (((uint64_t) 0x3C00) << 48) | ((uint64_t) 0x3C00));
1181 EXPECT_EQ(colorToRgbaF16(RgbGreen()), (((uint64_t) 0x3C00) << 48) | (((uint64_t) 0x3C00) << 16));
1182 EXPECT_EQ(colorToRgbaF16(RgbBlue()), (((uint64_t) 0x3C00) << 48) | (((uint64_t) 0x3C00) << 32));
1183
1184 Color e_gamma = {{{ 0.1f, 0.2f, 0.3f }}};
1185 EXPECT_EQ(colorToRgbaF16(e_gamma), 0x3C0034CD32662E66);
1186}
1187
Dichen Zhang10959a42023-04-10 16:28:16 -07001188TEST_F(GainMapMathTest, Float32ToFloat16) {
Dichen Zhangf106df72023-04-04 17:44:46 +00001189 EXPECT_EQ(floatToHalf(0.1f), 0x2E66);
1190 EXPECT_EQ(floatToHalf(0.0f), 0x0);
1191 EXPECT_EQ(floatToHalf(1.0f), 0x3C00);
1192 EXPECT_EQ(floatToHalf(-1.0f), 0xBC00);
1193 EXPECT_EQ(floatToHalf(0x1.fffffep127f), 0x7FFF); // float max
1194 EXPECT_EQ(floatToHalf(-0x1.fffffep127f), 0xFFFF); // float min
1195 EXPECT_EQ(floatToHalf(0x1.0p-126f), 0x0); // float zero
1196}
1197
Dichen Zhang10959a42023-04-10 16:28:16 -07001198TEST_F(GainMapMathTest, GenerateMapLuminanceSrgb) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001199 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), srgbLuminance),
1200 0.0f);
1201 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), srgbLuminance),
1202 kSdrWhiteNits);
1203 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), srgbLuminance),
1204 srgbLuminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
1205 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), srgbLuminance),
1206 srgbLuminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
1207 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), srgbLuminance),
1208 srgbLuminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1209}
1210
Dichen Zhang10959a42023-04-10 16:28:16 -07001211TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbP3) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001212 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), p3Luminance),
1213 0.0f);
1214 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), p3Luminance),
1215 kSdrWhiteNits);
1216 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), p3Luminance),
1217 p3Luminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
1218 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), p3Luminance),
1219 p3Luminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
1220 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), p3Luminance),
1221 p3Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1222}
1223
Dichen Zhang10959a42023-04-10 16:28:16 -07001224TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbBt2100) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001225 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), bt2100Luminance),
1226 0.0f);
1227 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), bt2100Luminance),
1228 kSdrWhiteNits);
1229 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), bt2100Luminance),
1230 bt2100Luminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
1231 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), bt2100Luminance),
1232 bt2100Luminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
1233 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), bt2100Luminance),
1234 bt2100Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1235}
1236
Dichen Zhang10959a42023-04-10 16:28:16 -07001237TEST_F(GainMapMathTest, GenerateMapLuminanceHlg) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001238 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), hlgInvOetf, identityConversion,
1239 bt2100Luminance, kHlgMaxNits),
1240 0.0f);
1241 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvWhite(), hlgInvOetf, identityConversion,
1242 bt2100Luminance, kHlgMaxNits),
1243 kHlgMaxNits);
1244 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvRed(), hlgInvOetf, identityConversion,
1245 bt2100Luminance, kHlgMaxNits),
1246 bt2100Luminance(RgbRed()) * kHlgMaxNits, LuminanceEpsilon());
1247 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvGreen(), hlgInvOetf, identityConversion,
1248 bt2100Luminance, kHlgMaxNits),
1249 bt2100Luminance(RgbGreen()) * kHlgMaxNits, LuminanceEpsilon());
1250 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvBlue(), hlgInvOetf, identityConversion,
1251 bt2100Luminance, kHlgMaxNits),
1252 bt2100Luminance(RgbBlue()) * kHlgMaxNits, LuminanceEpsilon());
1253}
1254
Dichen Zhang10959a42023-04-10 16:28:16 -07001255TEST_F(GainMapMathTest, GenerateMapLuminancePq) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001256 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), pqInvOetf, identityConversion,
1257 bt2100Luminance, kPqMaxNits),
1258 0.0f);
1259 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvWhite(), pqInvOetf, identityConversion,
1260 bt2100Luminance, kPqMaxNits),
1261 kPqMaxNits);
1262 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvRed(), pqInvOetf, identityConversion,
1263 bt2100Luminance, kPqMaxNits),
1264 bt2100Luminance(RgbRed()) * kPqMaxNits, LuminanceEpsilon());
1265 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvGreen(), pqInvOetf, identityConversion,
1266 bt2100Luminance, kPqMaxNits),
1267 bt2100Luminance(RgbGreen()) * kPqMaxNits, LuminanceEpsilon());
1268 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvBlue(), pqInvOetf, identityConversion,
1269 bt2100Luminance, kPqMaxNits),
1270 bt2100Luminance(RgbBlue()) * kPqMaxNits, LuminanceEpsilon());
1271}
1272
Dichen Zhang10959a42023-04-10 16:28:16 -07001273TEST_F(GainMapMathTest, ApplyMap) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001274 ultrahdr_metadata_struct metadata = { .maxContentBoost = 8.0f,
Dichen Zhange286f1c2023-03-14 00:22:00 +00001275 .minContentBoost = 1.0f / 8.0f };
Nick Deakind19e5762023-02-10 15:39:08 -05001276
1277 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001278 RgbWhite() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001279 EXPECT_RGB_EQ(Recover(YuvBlack(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001280 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001281 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001282 RgbRed() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001283 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001284 RgbGreen() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001285 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001286 RgbBlue() * 8.0f);
1287
Nick Deakind19e5762023-02-10 15:39:08 -05001288 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001289 RgbWhite() * sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001290 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001291 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001292 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001293 RgbRed() * sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001294 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001295 RgbGreen() * sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001296 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001297 RgbBlue() * sqrt(8.0f));
1298
Nick Deakind19e5762023-02-10 15:39:08 -05001299 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001300 RgbWhite());
Nick Deakind19e5762023-02-10 15:39:08 -05001301 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001302 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001303 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001304 RgbRed());
Nick Deakind19e5762023-02-10 15:39:08 -05001305 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001306 RgbGreen());
Nick Deakind19e5762023-02-10 15:39:08 -05001307 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001308 RgbBlue());
1309
Nick Deakind19e5762023-02-10 15:39:08 -05001310 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001311 RgbWhite() / sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001312 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001313 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001314 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001315 RgbRed() / sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001316 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001317 RgbGreen() / sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001318 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001319 RgbBlue() / sqrt(8.0f));
1320
Nick Deakind19e5762023-02-10 15:39:08 -05001321 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001322 RgbWhite() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001323 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001324 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001325 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001326 RgbRed() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001327 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001328 RgbGreen() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001329 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001330 RgbBlue() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001331
1332 metadata.maxContentBoost = 8.0f;
1333 metadata.minContentBoost = 1.0f;
1334
1335 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata),
1336 RgbWhite() * 8.0f);
1337 EXPECT_RGB_EQ(Recover(YuvWhite(), 2.0f / 3.0f, &metadata),
1338 RgbWhite() * 4.0f);
1339 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f / 3.0f, &metadata),
1340 RgbWhite() * 2.0f);
1341 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata),
1342 RgbWhite());
1343
1344 metadata.maxContentBoost = 8.0f;
1345 metadata.minContentBoost = 0.5f;;
1346
1347 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata),
1348 RgbWhite() * 8.0f);
1349 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.75, &metadata),
1350 RgbWhite() * 4.0f);
1351 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.5f, &metadata),
1352 RgbWhite() * 2.0f);
1353 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.25f, &metadata),
1354 RgbWhite());
1355 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata),
1356 RgbWhite() / 2.0f);
Nick Deakin65f492a2022-11-29 22:47:40 -05001357}
1358
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001359} // namespace android::ultrahdr