blob: c45665382139864bb75bc0d40307bbcddc109c06 [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; }
31
32 Color Yuv420(uint8_t y, uint8_t u, uint8_t v) {
33 return {{{ static_cast<float>(y) / 255.0f,
34 (static_cast<float>(u) - 128.0f) / 255.0f,
35 (static_cast<float>(v) - 128.0f) / 255.0f }}};
36 }
37
38 Color P010(uint16_t y, uint16_t u, uint16_t v) {
Nick Deakin38125332022-12-12 15:48:24 -050039 return {{{ (static_cast<float>(y) - 64.0f) / 876.0f,
40 (static_cast<float>(u) - 64.0f) / 896.0f - 0.5f,
41 (static_cast<float>(v) - 64.0f) / 896.0f - 0.5f }}};
Nick Deakin65f492a2022-11-29 22:47:40 -050042 }
43
44 float Map(uint8_t e) {
Nick Deakind19e5762023-02-10 15:39:08 -050045 return static_cast<float>(e) / 255.0f;
Nick Deakin65f492a2022-11-29 22:47:40 -050046 }
47
48 Color ColorMin(Color e1, Color e2) {
49 return {{{ fmin(e1.r, e2.r), fmin(e1.g, e2.g), fmin(e1.b, e2.b) }}};
50 }
51
52 Color ColorMax(Color e1, Color e2) {
53 return {{{ fmax(e1.r, e2.r), fmax(e1.g, e2.g), fmax(e1.b, e2.b) }}};
54 }
55
56 Color RgbBlack() { return {{{ 0.0f, 0.0f, 0.0f }}}; }
57 Color RgbWhite() { return {{{ 1.0f, 1.0f, 1.0f }}}; }
58
59 Color RgbRed() { return {{{ 1.0f, 0.0f, 0.0f }}}; }
60 Color RgbGreen() { return {{{ 0.0f, 1.0f, 0.0f }}}; }
61 Color RgbBlue() { return {{{ 0.0f, 0.0f, 1.0f }}}; }
62
63 Color YuvBlack() { return {{{ 0.0f, 0.0f, 0.0f }}}; }
64 Color YuvWhite() { return {{{ 1.0f, 0.0f, 0.0f }}}; }
65
66 Color SrgbYuvRed() { return {{{ 0.299f, -0.1687f, 0.5f }}}; }
67 Color SrgbYuvGreen() { return {{{ 0.587f, -0.3313f, -0.4187f }}}; }
68 Color SrgbYuvBlue() { return {{{ 0.114f, 0.5f, -0.0813f }}}; }
69
70 Color Bt2100YuvRed() { return {{{ 0.2627f, -0.13963f, 0.5f }}}; }
71 Color Bt2100YuvGreen() { return {{{ 0.6780f, -0.36037f, -0.45979f }}}; }
72 Color Bt2100YuvBlue() { return {{{ 0.0593f, 0.5f, -0.04021f }}}; }
73
74 float SrgbYuvToLuminance(Color yuv_gamma, ColorCalculationFn luminanceFn) {
75 Color rgb_gamma = srgbYuvToRgb(yuv_gamma);
76 Color rgb = srgbInvOetf(rgb_gamma);
77 float luminance_scaled = luminanceFn(rgb);
78 return luminance_scaled * kSdrWhiteNits;
79 }
80
81 float Bt2100YuvToLuminance(Color yuv_gamma, ColorTransformFn hdrInvOetf,
82 ColorTransformFn gamutConversionFn, ColorCalculationFn luminanceFn,
83 float scale_factor) {
84 Color rgb_gamma = bt2100YuvToRgb(yuv_gamma);
85 Color rgb = hdrInvOetf(rgb_gamma);
86 rgb = gamutConversionFn(rgb);
87 float luminance_scaled = luminanceFn(rgb);
88 return luminance_scaled * scale_factor;
89 }
90
Dichen Zhangdbceb0e2023-04-14 19:03:18 +000091 Color Recover(Color yuv_gamma, float gain, ultrahdr_metadata_ptr metadata) {
Nick Deakin65f492a2022-11-29 22:47:40 -050092 Color rgb_gamma = srgbYuvToRgb(yuv_gamma);
93 Color rgb = srgbInvOetf(rgb_gamma);
Dichen Zhang10959a42023-04-10 16:28:16 -070094 return applyGain(rgb, gain, metadata);
Nick Deakin65f492a2022-11-29 22:47:40 -050095 }
96
97 jpegr_uncompressed_struct Yuv420Image() {
98 static uint8_t pixels[] = {
99 // Y
100 0x00, 0x10, 0x20, 0x30,
101 0x01, 0x11, 0x21, 0x31,
102 0x02, 0x12, 0x22, 0x32,
103 0x03, 0x13, 0x23, 0x33,
104 // U
105 0xA0, 0xA1,
106 0xA2, 0xA3,
107 // V
108 0xB0, 0xB1,
109 0xB2, 0xB3,
110 };
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000111 return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_BT709 };
Nick Deakin65f492a2022-11-29 22:47:40 -0500112 }
113
114 Color (*Yuv420Colors())[4] {
115 static Color colors[4][4] = {
116 {
117 Yuv420(0x00, 0xA0, 0xB0), Yuv420(0x10, 0xA0, 0xB0),
118 Yuv420(0x20, 0xA1, 0xB1), Yuv420(0x30, 0xA1, 0xB1),
119 }, {
120 Yuv420(0x01, 0xA0, 0xB0), Yuv420(0x11, 0xA0, 0xB0),
121 Yuv420(0x21, 0xA1, 0xB1), Yuv420(0x31, 0xA1, 0xB1),
122 }, {
123 Yuv420(0x02, 0xA2, 0xB2), Yuv420(0x12, 0xA2, 0xB2),
124 Yuv420(0x22, 0xA3, 0xB3), Yuv420(0x32, 0xA3, 0xB3),
125 }, {
126 Yuv420(0x03, 0xA2, 0xB2), Yuv420(0x13, 0xA2, 0xB2),
127 Yuv420(0x23, 0xA3, 0xB3), Yuv420(0x33, 0xA3, 0xB3),
128 },
129 };
130 return colors;
131 }
132
133 jpegr_uncompressed_struct P010Image() {
134 static uint16_t pixels[] = {
135 // Y
136 0x00 << 6, 0x10 << 6, 0x20 << 6, 0x30 << 6,
137 0x01 << 6, 0x11 << 6, 0x21 << 6, 0x31 << 6,
138 0x02 << 6, 0x12 << 6, 0x22 << 6, 0x32 << 6,
139 0x03 << 6, 0x13 << 6, 0x23 << 6, 0x33 << 6,
140 // UV
141 0xA0 << 6, 0xB0 << 6, 0xA1 << 6, 0xB1 << 6,
142 0xA2 << 6, 0xB2 << 6, 0xA3 << 6, 0xB3 << 6,
143 };
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000144 return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_BT709 };
Nick Deakin65f492a2022-11-29 22:47:40 -0500145 }
146
147 Color (*P010Colors())[4] {
148 static Color colors[4][4] = {
149 {
150 P010(0x00, 0xA0, 0xB0), P010(0x10, 0xA0, 0xB0),
151 P010(0x20, 0xA1, 0xB1), P010(0x30, 0xA1, 0xB1),
152 }, {
153 P010(0x01, 0xA0, 0xB0), P010(0x11, 0xA0, 0xB0),
154 P010(0x21, 0xA1, 0xB1), P010(0x31, 0xA1, 0xB1),
155 }, {
156 P010(0x02, 0xA2, 0xB2), P010(0x12, 0xA2, 0xB2),
157 P010(0x22, 0xA3, 0xB3), P010(0x32, 0xA3, 0xB3),
158 }, {
159 P010(0x03, 0xA2, 0xB2), P010(0x13, 0xA2, 0xB2),
160 P010(0x23, 0xA3, 0xB3), P010(0x33, 0xA3, 0xB3),
161 },
162 };
163 return colors;
164 }
165
166 jpegr_uncompressed_struct MapImage() {
167 static uint8_t pixels[] = {
168 0x00, 0x10, 0x20, 0x30,
169 0x01, 0x11, 0x21, 0x31,
170 0x02, 0x12, 0x22, 0x32,
171 0x03, 0x13, 0x23, 0x33,
172 };
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000173 return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_UNSPECIFIED };
Nick Deakin65f492a2022-11-29 22:47:40 -0500174 }
175
176 float (*MapValues())[4] {
177 static float values[4][4] = {
178 {
179 Map(0x00), Map(0x10), Map(0x20), Map(0x30),
180 }, {
181 Map(0x01), Map(0x11), Map(0x21), Map(0x31),
182 }, {
183 Map(0x02), Map(0x12), Map(0x22), Map(0x32),
184 }, {
185 Map(0x03), Map(0x13), Map(0x23), Map(0x33),
186 },
187 };
188 return values;
189 }
190
191protected:
192 virtual void SetUp();
193 virtual void TearDown();
194};
195
Dichen Zhang10959a42023-04-10 16:28:16 -0700196GainMapMathTest::GainMapMathTest() {}
197GainMapMathTest::~GainMapMathTest() {}
Nick Deakin65f492a2022-11-29 22:47:40 -0500198
Dichen Zhang10959a42023-04-10 16:28:16 -0700199void GainMapMathTest::SetUp() {}
200void GainMapMathTest::TearDown() {}
Nick Deakin65f492a2022-11-29 22:47:40 -0500201
202#define EXPECT_RGB_EQ(e1, e2) \
203 EXPECT_FLOAT_EQ((e1).r, (e2).r); \
204 EXPECT_FLOAT_EQ((e1).g, (e2).g); \
205 EXPECT_FLOAT_EQ((e1).b, (e2).b)
206
207#define EXPECT_RGB_NEAR(e1, e2) \
208 EXPECT_NEAR((e1).r, (e2).r, ComparisonEpsilon()); \
209 EXPECT_NEAR((e1).g, (e2).g, ComparisonEpsilon()); \
210 EXPECT_NEAR((e1).b, (e2).b, ComparisonEpsilon())
211
212#define EXPECT_RGB_CLOSE(e1, e2) \
213 EXPECT_NEAR((e1).r, (e2).r, ComparisonEpsilon() * 10.0f); \
214 EXPECT_NEAR((e1).g, (e2).g, ComparisonEpsilon() * 10.0f); \
215 EXPECT_NEAR((e1).b, (e2).b, ComparisonEpsilon() * 10.0f)
216
217#define EXPECT_YUV_EQ(e1, e2) \
218 EXPECT_FLOAT_EQ((e1).y, (e2).y); \
219 EXPECT_FLOAT_EQ((e1).u, (e2).u); \
220 EXPECT_FLOAT_EQ((e1).v, (e2).v)
221
222#define EXPECT_YUV_NEAR(e1, e2) \
223 EXPECT_NEAR((e1).y, (e2).y, ComparisonEpsilon()); \
224 EXPECT_NEAR((e1).u, (e2).u, ComparisonEpsilon()); \
225 EXPECT_NEAR((e1).v, (e2).v, ComparisonEpsilon())
226
227#define EXPECT_YUV_BETWEEN(e, min, max) \
228 EXPECT_THAT((e).y, testing::AllOf(testing::Ge((min).y), testing::Le((max).y))); \
229 EXPECT_THAT((e).u, testing::AllOf(testing::Ge((min).u), testing::Le((max).u))); \
230 EXPECT_THAT((e).v, testing::AllOf(testing::Ge((min).v), testing::Le((max).v)))
231
232// TODO: a bunch of these tests can be parameterized.
233
Dichen Zhang10959a42023-04-10 16:28:16 -0700234TEST_F(GainMapMathTest, ColorConstruct) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500235 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
236
237 EXPECT_FLOAT_EQ(e1.r, 0.1f);
238 EXPECT_FLOAT_EQ(e1.g, 0.2f);
239 EXPECT_FLOAT_EQ(e1.b, 0.3f);
240
241 EXPECT_FLOAT_EQ(e1.y, 0.1f);
242 EXPECT_FLOAT_EQ(e1.u, 0.2f);
243 EXPECT_FLOAT_EQ(e1.v, 0.3f);
244}
245
Dichen Zhang10959a42023-04-10 16:28:16 -0700246TEST_F(GainMapMathTest, ColorAddColor) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500247 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
248
249 Color e2 = e1 + e1;
250 EXPECT_FLOAT_EQ(e2.r, e1.r * 2.0f);
251 EXPECT_FLOAT_EQ(e2.g, e1.g * 2.0f);
252 EXPECT_FLOAT_EQ(e2.b, e1.b * 2.0f);
253
254 e2 += e1;
255 EXPECT_FLOAT_EQ(e2.r, e1.r * 3.0f);
256 EXPECT_FLOAT_EQ(e2.g, e1.g * 3.0f);
257 EXPECT_FLOAT_EQ(e2.b, e1.b * 3.0f);
258}
259
Dichen Zhang10959a42023-04-10 16:28:16 -0700260TEST_F(GainMapMathTest, ColorAddFloat) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500261 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
262
263 Color e2 = e1 + 0.1f;
264 EXPECT_FLOAT_EQ(e2.r, e1.r + 0.1f);
265 EXPECT_FLOAT_EQ(e2.g, e1.g + 0.1f);
266 EXPECT_FLOAT_EQ(e2.b, e1.b + 0.1f);
267
268 e2 += 0.1f;
269 EXPECT_FLOAT_EQ(e2.r, e1.r + 0.2f);
270 EXPECT_FLOAT_EQ(e2.g, e1.g + 0.2f);
271 EXPECT_FLOAT_EQ(e2.b, e1.b + 0.2f);
272}
273
Dichen Zhang10959a42023-04-10 16:28:16 -0700274TEST_F(GainMapMathTest, ColorSubtractColor) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500275 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
276
277 Color e2 = e1 - e1;
278 EXPECT_FLOAT_EQ(e2.r, 0.0f);
279 EXPECT_FLOAT_EQ(e2.g, 0.0f);
280 EXPECT_FLOAT_EQ(e2.b, 0.0f);
281
282 e2 -= e1;
283 EXPECT_FLOAT_EQ(e2.r, -e1.r);
284 EXPECT_FLOAT_EQ(e2.g, -e1.g);
285 EXPECT_FLOAT_EQ(e2.b, -e1.b);
286}
287
Dichen Zhang10959a42023-04-10 16:28:16 -0700288TEST_F(GainMapMathTest, ColorSubtractFloat) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500289 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
290
291 Color e2 = e1 - 0.1f;
292 EXPECT_FLOAT_EQ(e2.r, e1.r - 0.1f);
293 EXPECT_FLOAT_EQ(e2.g, e1.g - 0.1f);
294 EXPECT_FLOAT_EQ(e2.b, e1.b - 0.1f);
295
296 e2 -= 0.1f;
297 EXPECT_FLOAT_EQ(e2.r, e1.r - 0.2f);
298 EXPECT_FLOAT_EQ(e2.g, e1.g - 0.2f);
299 EXPECT_FLOAT_EQ(e2.b, e1.b - 0.2f);
300}
301
Dichen Zhang10959a42023-04-10 16:28:16 -0700302TEST_F(GainMapMathTest, ColorMultiplyFloat) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500303 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
304
305 Color e2 = e1 * 2.0f;
306 EXPECT_FLOAT_EQ(e2.r, e1.r * 2.0f);
307 EXPECT_FLOAT_EQ(e2.g, e1.g * 2.0f);
308 EXPECT_FLOAT_EQ(e2.b, e1.b * 2.0f);
309
310 e2 *= 2.0f;
311 EXPECT_FLOAT_EQ(e2.r, e1.r * 4.0f);
312 EXPECT_FLOAT_EQ(e2.g, e1.g * 4.0f);
313 EXPECT_FLOAT_EQ(e2.b, e1.b * 4.0f);
314}
315
Dichen Zhang10959a42023-04-10 16:28:16 -0700316TEST_F(GainMapMathTest, ColorDivideFloat) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500317 Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
318
319 Color e2 = e1 / 2.0f;
320 EXPECT_FLOAT_EQ(e2.r, e1.r / 2.0f);
321 EXPECT_FLOAT_EQ(e2.g, e1.g / 2.0f);
322 EXPECT_FLOAT_EQ(e2.b, e1.b / 2.0f);
323
324 e2 /= 2.0f;
325 EXPECT_FLOAT_EQ(e2.r, e1.r / 4.0f);
326 EXPECT_FLOAT_EQ(e2.g, e1.g / 4.0f);
327 EXPECT_FLOAT_EQ(e2.b, e1.b / 4.0f);
328}
329
Dichen Zhang10959a42023-04-10 16:28:16 -0700330TEST_F(GainMapMathTest, SrgbLuminance) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500331 EXPECT_FLOAT_EQ(srgbLuminance(RgbBlack()), 0.0f);
332 EXPECT_FLOAT_EQ(srgbLuminance(RgbWhite()), 1.0f);
333 EXPECT_FLOAT_EQ(srgbLuminance(RgbRed()), 0.2126f);
334 EXPECT_FLOAT_EQ(srgbLuminance(RgbGreen()), 0.7152f);
335 EXPECT_FLOAT_EQ(srgbLuminance(RgbBlue()), 0.0722f);
336}
337
Dichen Zhang10959a42023-04-10 16:28:16 -0700338TEST_F(GainMapMathTest, SrgbYuvToRgb) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500339 Color rgb_black = srgbYuvToRgb(YuvBlack());
340 EXPECT_RGB_NEAR(rgb_black, RgbBlack());
341
342 Color rgb_white = srgbYuvToRgb(YuvWhite());
343 EXPECT_RGB_NEAR(rgb_white, RgbWhite());
344
345 Color rgb_r = srgbYuvToRgb(SrgbYuvRed());
346 EXPECT_RGB_NEAR(rgb_r, RgbRed());
347
348 Color rgb_g = srgbYuvToRgb(SrgbYuvGreen());
349 EXPECT_RGB_NEAR(rgb_g, RgbGreen());
350
351 Color rgb_b = srgbYuvToRgb(SrgbYuvBlue());
352 EXPECT_RGB_NEAR(rgb_b, RgbBlue());
353}
354
Dichen Zhang10959a42023-04-10 16:28:16 -0700355TEST_F(GainMapMathTest, SrgbRgbToYuv) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500356 Color yuv_black = srgbRgbToYuv(RgbBlack());
357 EXPECT_YUV_NEAR(yuv_black, YuvBlack());
358
359 Color yuv_white = srgbRgbToYuv(RgbWhite());
360 EXPECT_YUV_NEAR(yuv_white, YuvWhite());
361
362 Color yuv_r = srgbRgbToYuv(RgbRed());
363 EXPECT_YUV_NEAR(yuv_r, SrgbYuvRed());
364
365 Color yuv_g = srgbRgbToYuv(RgbGreen());
366 EXPECT_YUV_NEAR(yuv_g, SrgbYuvGreen());
367
368 Color yuv_b = srgbRgbToYuv(RgbBlue());
369 EXPECT_YUV_NEAR(yuv_b, SrgbYuvBlue());
370}
371
Dichen Zhang10959a42023-04-10 16:28:16 -0700372TEST_F(GainMapMathTest, SrgbRgbYuvRoundtrip) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500373 Color rgb_black = srgbYuvToRgb(srgbRgbToYuv(RgbBlack()));
374 EXPECT_RGB_NEAR(rgb_black, RgbBlack());
375
376 Color rgb_white = srgbYuvToRgb(srgbRgbToYuv(RgbWhite()));
377 EXPECT_RGB_NEAR(rgb_white, RgbWhite());
378
379 Color rgb_r = srgbYuvToRgb(srgbRgbToYuv(RgbRed()));
380 EXPECT_RGB_NEAR(rgb_r, RgbRed());
381
382 Color rgb_g = srgbYuvToRgb(srgbRgbToYuv(RgbGreen()));
383 EXPECT_RGB_NEAR(rgb_g, RgbGreen());
384
385 Color rgb_b = srgbYuvToRgb(srgbRgbToYuv(RgbBlue()));
386 EXPECT_RGB_NEAR(rgb_b, RgbBlue());
387}
388
Dichen Zhang10959a42023-04-10 16:28:16 -0700389TEST_F(GainMapMathTest, SrgbTransferFunction) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500390 EXPECT_FLOAT_EQ(srgbInvOetf(0.0f), 0.0f);
391 EXPECT_NEAR(srgbInvOetf(0.02f), 0.00154f, ComparisonEpsilon());
392 EXPECT_NEAR(srgbInvOetf(0.04045f), 0.00313f, ComparisonEpsilon());
393 EXPECT_NEAR(srgbInvOetf(0.5f), 0.21404f, ComparisonEpsilon());
394 EXPECT_FLOAT_EQ(srgbInvOetf(1.0f), 1.0f);
395}
396
Dichen Zhang10959a42023-04-10 16:28:16 -0700397TEST_F(GainMapMathTest, P3Luminance) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500398 EXPECT_FLOAT_EQ(p3Luminance(RgbBlack()), 0.0f);
399 EXPECT_FLOAT_EQ(p3Luminance(RgbWhite()), 1.0f);
400 EXPECT_FLOAT_EQ(p3Luminance(RgbRed()), 0.20949f);
401 EXPECT_FLOAT_EQ(p3Luminance(RgbGreen()), 0.72160f);
402 EXPECT_FLOAT_EQ(p3Luminance(RgbBlue()), 0.06891f);
403}
404
Dichen Zhang10959a42023-04-10 16:28:16 -0700405TEST_F(GainMapMathTest, Bt2100Luminance) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500406 EXPECT_FLOAT_EQ(bt2100Luminance(RgbBlack()), 0.0f);
407 EXPECT_FLOAT_EQ(bt2100Luminance(RgbWhite()), 1.0f);
408 EXPECT_FLOAT_EQ(bt2100Luminance(RgbRed()), 0.2627f);
409 EXPECT_FLOAT_EQ(bt2100Luminance(RgbGreen()), 0.6780f);
410 EXPECT_FLOAT_EQ(bt2100Luminance(RgbBlue()), 0.0593f);
411}
412
Dichen Zhang10959a42023-04-10 16:28:16 -0700413TEST_F(GainMapMathTest, Bt2100YuvToRgb) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500414 Color rgb_black = bt2100YuvToRgb(YuvBlack());
415 EXPECT_RGB_NEAR(rgb_black, RgbBlack());
416
417 Color rgb_white = bt2100YuvToRgb(YuvWhite());
418 EXPECT_RGB_NEAR(rgb_white, RgbWhite());
419
420 Color rgb_r = bt2100YuvToRgb(Bt2100YuvRed());
421 EXPECT_RGB_NEAR(rgb_r, RgbRed());
422
423 Color rgb_g = bt2100YuvToRgb(Bt2100YuvGreen());
424 EXPECT_RGB_NEAR(rgb_g, RgbGreen());
425
426 Color rgb_b = bt2100YuvToRgb(Bt2100YuvBlue());
427 EXPECT_RGB_NEAR(rgb_b, RgbBlue());
428}
429
Dichen Zhang10959a42023-04-10 16:28:16 -0700430TEST_F(GainMapMathTest, Bt2100RgbToYuv) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500431 Color yuv_black = bt2100RgbToYuv(RgbBlack());
432 EXPECT_YUV_NEAR(yuv_black, YuvBlack());
433
434 Color yuv_white = bt2100RgbToYuv(RgbWhite());
435 EXPECT_YUV_NEAR(yuv_white, YuvWhite());
436
437 Color yuv_r = bt2100RgbToYuv(RgbRed());
438 EXPECT_YUV_NEAR(yuv_r, Bt2100YuvRed());
439
440 Color yuv_g = bt2100RgbToYuv(RgbGreen());
441 EXPECT_YUV_NEAR(yuv_g, Bt2100YuvGreen());
442
443 Color yuv_b = bt2100RgbToYuv(RgbBlue());
444 EXPECT_YUV_NEAR(yuv_b, Bt2100YuvBlue());
445}
446
Dichen Zhang10959a42023-04-10 16:28:16 -0700447TEST_F(GainMapMathTest, Bt2100RgbYuvRoundtrip) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500448 Color rgb_black = bt2100YuvToRgb(bt2100RgbToYuv(RgbBlack()));
449 EXPECT_RGB_NEAR(rgb_black, RgbBlack());
450
451 Color rgb_white = bt2100YuvToRgb(bt2100RgbToYuv(RgbWhite()));
452 EXPECT_RGB_NEAR(rgb_white, RgbWhite());
453
454 Color rgb_r = bt2100YuvToRgb(bt2100RgbToYuv(RgbRed()));
455 EXPECT_RGB_NEAR(rgb_r, RgbRed());
456
457 Color rgb_g = bt2100YuvToRgb(bt2100RgbToYuv(RgbGreen()));
458 EXPECT_RGB_NEAR(rgb_g, RgbGreen());
459
460 Color rgb_b = bt2100YuvToRgb(bt2100RgbToYuv(RgbBlue()));
461 EXPECT_RGB_NEAR(rgb_b, RgbBlue());
462}
463
Dichen Zhang10959a42023-04-10 16:28:16 -0700464TEST_F(GainMapMathTest, HlgOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500465 EXPECT_FLOAT_EQ(hlgOetf(0.0f), 0.0f);
466 EXPECT_NEAR(hlgOetf(0.04167f), 0.35357f, ComparisonEpsilon());
467 EXPECT_NEAR(hlgOetf(0.08333f), 0.5f, ComparisonEpsilon());
468 EXPECT_NEAR(hlgOetf(0.5f), 0.87164f, ComparisonEpsilon());
469 EXPECT_FLOAT_EQ(hlgOetf(1.0f), 1.0f);
470
471 Color e = {{{ 0.04167f, 0.08333f, 0.5f }}};
472 Color e_gamma = {{{ 0.35357f, 0.5f, 0.87164f }}};
473 EXPECT_RGB_NEAR(hlgOetf(e), e_gamma);
474}
475
Dichen Zhang10959a42023-04-10 16:28:16 -0700476TEST_F(GainMapMathTest, HlgInvOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500477 EXPECT_FLOAT_EQ(hlgInvOetf(0.0f), 0.0f);
478 EXPECT_NEAR(hlgInvOetf(0.25f), 0.02083f, ComparisonEpsilon());
479 EXPECT_NEAR(hlgInvOetf(0.5f), 0.08333f, ComparisonEpsilon());
480 EXPECT_NEAR(hlgInvOetf(0.75f), 0.26496f, ComparisonEpsilon());
481 EXPECT_FLOAT_EQ(hlgInvOetf(1.0f), 1.0f);
482
483 Color e_gamma = {{{ 0.25f, 0.5f, 0.75f }}};
484 Color e = {{{ 0.02083f, 0.08333f, 0.26496f }}};
485 EXPECT_RGB_NEAR(hlgInvOetf(e_gamma), e);
486}
487
Dichen Zhang10959a42023-04-10 16:28:16 -0700488TEST_F(GainMapMathTest, HlgTransferFunctionRoundtrip) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500489 EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(0.0f)), 0.0f);
490 EXPECT_NEAR(hlgInvOetf(hlgOetf(0.04167f)), 0.04167f, ComparisonEpsilon());
491 EXPECT_NEAR(hlgInvOetf(hlgOetf(0.08333f)), 0.08333f, ComparisonEpsilon());
492 EXPECT_NEAR(hlgInvOetf(hlgOetf(0.5f)), 0.5f, ComparisonEpsilon());
493 EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(1.0f)), 1.0f);
494}
495
Dichen Zhang10959a42023-04-10 16:28:16 -0700496TEST_F(GainMapMathTest, PqOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500497 EXPECT_FLOAT_EQ(pqOetf(0.0f), 0.0f);
498 EXPECT_NEAR(pqOetf(0.01f), 0.50808f, ComparisonEpsilon());
499 EXPECT_NEAR(pqOetf(0.5f), 0.92655f, ComparisonEpsilon());
500 EXPECT_NEAR(pqOetf(0.99f), 0.99895f, ComparisonEpsilon());
501 EXPECT_FLOAT_EQ(pqOetf(1.0f), 1.0f);
502
503 Color e = {{{ 0.01f, 0.5f, 0.99f }}};
504 Color e_gamma = {{{ 0.50808f, 0.92655f, 0.99895f }}};
505 EXPECT_RGB_NEAR(pqOetf(e), e_gamma);
506}
507
Dichen Zhang10959a42023-04-10 16:28:16 -0700508TEST_F(GainMapMathTest, PqInvOetf) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500509 EXPECT_FLOAT_EQ(pqInvOetf(0.0f), 0.0f);
510 EXPECT_NEAR(pqInvOetf(0.01f), 2.31017e-7f, ComparisonEpsilon());
511 EXPECT_NEAR(pqInvOetf(0.5f), 0.00922f, ComparisonEpsilon());
512 EXPECT_NEAR(pqInvOetf(0.99f), 0.90903f, ComparisonEpsilon());
513 EXPECT_FLOAT_EQ(pqInvOetf(1.0f), 1.0f);
514
515 Color e_gamma = {{{ 0.01f, 0.5f, 0.99f }}};
516 Color e = {{{ 2.31017e-7f, 0.00922f, 0.90903f }}};
517 EXPECT_RGB_NEAR(pqInvOetf(e_gamma), e);
518}
519
Dichen Zhang10959a42023-04-10 16:28:16 -0700520TEST_F(GainMapMathTest, PqInvOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500521 for (int idx = 0; idx < kPqInvOETFNumEntries; idx++) {
522 float value = static_cast<float>(idx) / static_cast<float>(kPqInvOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800523 EXPECT_FLOAT_EQ(pqInvOetf(value), pqInvOetfLUT(value));
524 }
525}
526
Dichen Zhang10959a42023-04-10 16:28:16 -0700527TEST_F(GainMapMathTest, HlgInvOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500528 for (int idx = 0; idx < kHlgInvOETFNumEntries; idx++) {
529 float value = static_cast<float>(idx) / static_cast<float>(kHlgInvOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800530 EXPECT_FLOAT_EQ(hlgInvOetf(value), hlgInvOetfLUT(value));
531 }
532}
533
Dichen Zhang10959a42023-04-10 16:28:16 -0700534TEST_F(GainMapMathTest, pqOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500535 for (int idx = 0; idx < kPqOETFNumEntries; idx++) {
536 float value = static_cast<float>(idx) / static_cast<float>(kPqOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800537 EXPECT_FLOAT_EQ(pqOetf(value), pqOetfLUT(value));
538 }
539}
540
Dichen Zhang10959a42023-04-10 16:28:16 -0700541TEST_F(GainMapMathTest, hlgOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500542 for (int idx = 0; idx < kHlgOETFNumEntries; idx++) {
543 float value = static_cast<float>(idx) / static_cast<float>(kHlgOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800544 EXPECT_FLOAT_EQ(hlgOetf(value), hlgOetfLUT(value));
545 }
546}
547
Dichen Zhang10959a42023-04-10 16:28:16 -0700548TEST_F(GainMapMathTest, srgbInvOetfLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500549 for (int idx = 0; idx < kSrgbInvOETFNumEntries; idx++) {
550 float value = static_cast<float>(idx) / static_cast<float>(kSrgbInvOETFNumEntries - 1);
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800551 EXPECT_FLOAT_EQ(srgbInvOetf(value), srgbInvOetfLUT(value));
552 }
553}
554
Dichen Zhang10959a42023-04-10 16:28:16 -0700555TEST_F(GainMapMathTest, applyGainLUT) {
Nick Deakind19e5762023-02-10 15:39:08 -0500556 for (int boost = 1; boost <= 10; boost++) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000557 ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
Dichen Zhange286f1c2023-03-14 00:22:00 +0000558 .minContentBoost = 1.0f / static_cast<float>(boost) };
Dichen Zhang10959a42023-04-10 16:28:16 -0700559 GainLUT gainLUT(&metadata);
560 GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
561 for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
562 float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
563 EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
564 applyGainLUT(RgbBlack(), value, gainLUT));
565 EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
566 applyGainLUT(RgbWhite(), value, gainLUT));
567 EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
568 applyGainLUT(RgbRed(), value, gainLUT));
569 EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
570 applyGainLUT(RgbGreen(), value, gainLUT));
571 EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
572 applyGainLUT(RgbBlue(), value, gainLUT));
573 EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
574 applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
575 EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
576 applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
577 EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
578 applyGainLUT(RgbRed(), value, gainLUTWithBoost));
579 EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
580 applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
581 EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
582 applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
Nick Deakind19e5762023-02-10 15:39:08 -0500583 }
584 }
585
586 for (int boost = 1; boost <= 10; boost++) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000587 ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
Dichen Zhange286f1c2023-03-14 00:22:00 +0000588 .minContentBoost = 1.0f };
Dichen Zhang10959a42023-04-10 16:28:16 -0700589 GainLUT gainLUT(&metadata);
590 GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
591 for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
592 float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
593 EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
594 applyGainLUT(RgbBlack(), value, gainLUT));
595 EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
596 applyGainLUT(RgbWhite(), value, gainLUT));
597 EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
598 applyGainLUT(RgbRed(), value, gainLUT));
599 EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
600 applyGainLUT(RgbGreen(), value, gainLUT));
601 EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
602 applyGainLUT(RgbBlue(), value, gainLUT));
603 EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
604 applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
605 EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
606 applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
607 EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
608 applyGainLUT(RgbRed(), value, gainLUTWithBoost));
609 EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
610 applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
611 EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
612 applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
Nick Deakind19e5762023-02-10 15:39:08 -0500613 }
614 }
615
616 for (int boost = 1; boost <= 10; boost++) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000617 ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
Dichen Zhange286f1c2023-03-14 00:22:00 +0000618 .minContentBoost = 1.0f / pow(static_cast<float>(boost),
Nick Deakind19e5762023-02-10 15:39:08 -0500619 1.0f / 3.0f) };
Dichen Zhang10959a42023-04-10 16:28:16 -0700620 GainLUT gainLUT(&metadata);
621 GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
622 for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
623 float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
624 EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
625 applyGainLUT(RgbBlack(), value, gainLUT));
626 EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
627 applyGainLUT(RgbWhite(), value, gainLUT));
628 EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
629 applyGainLUT(RgbRed(), value, gainLUT));
630 EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
631 applyGainLUT(RgbGreen(), value, gainLUT));
632 EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
633 applyGainLUT(RgbBlue(), value, gainLUT));
634 EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
635 applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
636 EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
637 applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
638 EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
639 applyGainLUT(RgbRed(), value, gainLUTWithBoost));
640 EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
641 applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
642 EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
643 applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
Harish Mahendrakarf25991f2022-12-16 11:57:44 -0800644 }
645 }
646}
647
Dichen Zhang10959a42023-04-10 16:28:16 -0700648TEST_F(GainMapMathTest, PqTransferFunctionRoundtrip) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500649 EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(0.0f)), 0.0f);
650 EXPECT_NEAR(pqInvOetf(pqOetf(0.01f)), 0.01f, ComparisonEpsilon());
651 EXPECT_NEAR(pqInvOetf(pqOetf(0.5f)), 0.5f, ComparisonEpsilon());
652 EXPECT_NEAR(pqInvOetf(pqOetf(0.99f)), 0.99f, ComparisonEpsilon());
653 EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(1.0f)), 1.0f);
654}
655
Dichen Zhang10959a42023-04-10 16:28:16 -0700656TEST_F(GainMapMathTest, ColorConversionLookup) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000657 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500658 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000659 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500660 identityConversion);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000661 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500662 p3ToBt709);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000663 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500664 bt2100ToBt709);
665
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000666 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500667 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000668 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500669 bt709ToP3);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000670 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500671 identityConversion);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000672 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500673 bt2100ToP3);
674
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000675 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500676 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000677 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500678 bt709ToBt2100);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000679 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500680 p3ToBt2100);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000681 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500682 identityConversion);
683
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000684 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
Nick Deakin65f492a2022-11-29 22:47:40 -0500685 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000686 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_BT709),
Nick Deakin65f492a2022-11-29 22:47:40 -0500687 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000688 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_P3),
Nick Deakin65f492a2022-11-29 22:47:40 -0500689 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000690 EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_BT2100),
Nick Deakin65f492a2022-11-29 22:47:40 -0500691 nullptr);
692}
693
Dichen Zhang10959a42023-04-10 16:28:16 -0700694TEST_F(GainMapMathTest, EncodeGain) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000695 ultrahdr_metadata_struct metadata = { .maxContentBoost = 4.0f,
Dichen Zhange286f1c2023-03-14 00:22:00 +0000696 .minContentBoost = 1.0f / 4.0f };
Nick Deakin65f492a2022-11-29 22:47:40 -0500697
Dichen Zhang10959a42023-04-10 16:28:16 -0700698 EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 127);
699 EXPECT_EQ(encodeGain(0.0f, 1.0f, &metadata), 127);
700 EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
701 EXPECT_EQ(encodeGain(0.5f, 0.0f, &metadata), 0);
Nick Deakin65f492a2022-11-29 22:47:40 -0500702
Dichen Zhang10959a42023-04-10 16:28:16 -0700703 EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 127);
704 EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 255);
705 EXPECT_EQ(encodeGain(1.0f, 5.0f, &metadata), 255);
706 EXPECT_EQ(encodeGain(4.0f, 1.0f, &metadata), 0);
707 EXPECT_EQ(encodeGain(4.0f, 0.5f, &metadata), 0);
708 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 191);
709 EXPECT_EQ(encodeGain(2.0f, 1.0f, &metadata), 63);
Nick Deakin65f492a2022-11-29 22:47:40 -0500710
Nick Deakind19e5762023-02-10 15:39:08 -0500711 metadata.maxContentBoost = 2.0f;
712 metadata.minContentBoost = 1.0f / 2.0f;
713
Dichen Zhang10959a42023-04-10 16:28:16 -0700714 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 255);
715 EXPECT_EQ(encodeGain(2.0f, 1.0f, &metadata), 0);
716 EXPECT_EQ(encodeGain(1.0f, 1.41421f, &metadata), 191);
717 EXPECT_EQ(encodeGain(1.41421f, 1.0f, &metadata), 63);
Nick Deakind19e5762023-02-10 15:39:08 -0500718
719 metadata.maxContentBoost = 8.0f;
720 metadata.minContentBoost = 1.0f / 8.0f;
721
Dichen Zhang10959a42023-04-10 16:28:16 -0700722 EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
723 EXPECT_EQ(encodeGain(8.0f, 1.0f, &metadata), 0);
724 EXPECT_EQ(encodeGain(1.0f, 2.82843f, &metadata), 191);
725 EXPECT_EQ(encodeGain(2.82843f, 1.0f, &metadata), 63);
Nick Deakind19e5762023-02-10 15:39:08 -0500726
727 metadata.maxContentBoost = 8.0f;
728 metadata.minContentBoost = 1.0f;
729
Dichen Zhang10959a42023-04-10 16:28:16 -0700730 EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 0);
731 EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
Nick Deakind19e5762023-02-10 15:39:08 -0500732
Dichen Zhang10959a42023-04-10 16:28:16 -0700733 EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 0);
734 EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
735 EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 170);
736 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 85);
Nick Deakind19e5762023-02-10 15:39:08 -0500737
738 metadata.maxContentBoost = 8.0f;
739 metadata.minContentBoost = 0.5f;
740
Dichen Zhang10959a42023-04-10 16:28:16 -0700741 EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 63);
742 EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
Nick Deakind19e5762023-02-10 15:39:08 -0500743
Dichen Zhang10959a42023-04-10 16:28:16 -0700744 EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 63);
745 EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
746 EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 191);
747 EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 127);
748 EXPECT_EQ(encodeGain(1.0f, 0.7071f, &metadata), 31);
749 EXPECT_EQ(encodeGain(1.0f, 0.5f, &metadata), 0);
Nick Deakin65f492a2022-11-29 22:47:40 -0500750}
751
Dichen Zhang10959a42023-04-10 16:28:16 -0700752TEST_F(GainMapMathTest, ApplyGain) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000753 ultrahdr_metadata_struct metadata = { .maxContentBoost = 4.0f,
Dichen Zhange286f1c2023-03-14 00:22:00 +0000754 .minContentBoost = 1.0f / 4.0f };
Dichen Zhangc6605702023-03-15 18:40:55 -0700755 float displayBoost = metadata.maxContentBoost;
Nick Deakin65f492a2022-11-29 22:47:40 -0500756
Dichen Zhang10959a42023-04-10 16:28:16 -0700757 EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.0f, &metadata), RgbBlack());
758 EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.5f, &metadata), RgbBlack());
759 EXPECT_RGB_NEAR(applyGain(RgbBlack(), 1.0f, &metadata), RgbBlack());
Nick Deakin65f492a2022-11-29 22:47:40 -0500760
Dichen Zhang10959a42023-04-10 16:28:16 -0700761 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 4.0f);
762 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.0f);
763 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
764 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.0f);
765 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 4.0f);
Nick Deakin65f492a2022-11-29 22:47:40 -0500766
Nick Deakind19e5762023-02-10 15:39:08 -0500767 metadata.maxContentBoost = 2.0f;
768 metadata.minContentBoost = 1.0f / 2.0f;
769
Dichen Zhang10959a42023-04-10 16:28:16 -0700770 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
771 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 1.41421f);
772 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
773 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 1.41421f);
774 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 2.0f);
Nick Deakind19e5762023-02-10 15:39:08 -0500775
776 metadata.maxContentBoost = 8.0f;
777 metadata.minContentBoost = 1.0f / 8.0f;
778
Dichen Zhang10959a42023-04-10 16:28:16 -0700779 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 8.0f);
780 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.82843f);
781 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
782 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.82843f);
783 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -0500784
785 metadata.maxContentBoost = 8.0f;
786 metadata.minContentBoost = 1.0f;
787
Dichen Zhang10959a42023-04-10 16:28:16 -0700788 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite());
789 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f / 3.0f, &metadata), RgbWhite() * 2.0f);
790 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 2.0f / 3.0f, &metadata), RgbWhite() * 4.0f);
791 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -0500792
793 metadata.maxContentBoost = 8.0f;
794 metadata.minContentBoost = 0.5f;
795
Dichen Zhang10959a42023-04-10 16:28:16 -0700796 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
797 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite());
798 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite() * 2.0f);
799 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 4.0f);
800 EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
Nick Deakin65f492a2022-11-29 22:47:40 -0500801
802 Color e = {{{ 0.0f, 0.5f, 1.0f }}};
Nick Deakind19e5762023-02-10 15:39:08 -0500803 metadata.maxContentBoost = 4.0f;
804 metadata.minContentBoost = 1.0f / 4.0f;
Nick Deakin65f492a2022-11-29 22:47:40 -0500805
Dichen Zhang10959a42023-04-10 16:28:16 -0700806 EXPECT_RGB_NEAR(applyGain(e, 0.0f, &metadata), e / 4.0f);
807 EXPECT_RGB_NEAR(applyGain(e, 0.25f, &metadata), e / 2.0f);
808 EXPECT_RGB_NEAR(applyGain(e, 0.5f, &metadata), e);
809 EXPECT_RGB_NEAR(applyGain(e, 0.75f, &metadata), e * 2.0f);
810 EXPECT_RGB_NEAR(applyGain(e, 1.0f, &metadata), e * 4.0f);
Dichen Zhangc6605702023-03-15 18:40:55 -0700811
Dichen Zhang10959a42023-04-10 16:28:16 -0700812 EXPECT_RGB_EQ(applyGain(RgbBlack(), 1.0f, &metadata),
813 applyGain(RgbBlack(), 1.0f, &metadata, displayBoost));
814 EXPECT_RGB_EQ(applyGain(RgbWhite(), 1.0f, &metadata),
815 applyGain(RgbWhite(), 1.0f, &metadata, displayBoost));
816 EXPECT_RGB_EQ(applyGain(RgbRed(), 1.0f, &metadata),
817 applyGain(RgbRed(), 1.0f, &metadata, displayBoost));
818 EXPECT_RGB_EQ(applyGain(RgbGreen(), 1.0f, &metadata),
819 applyGain(RgbGreen(), 1.0f, &metadata, displayBoost));
820 EXPECT_RGB_EQ(applyGain(RgbBlue(), 1.0f, &metadata),
821 applyGain(RgbBlue(), 1.0f, &metadata, displayBoost));
822 EXPECT_RGB_EQ(applyGain(e, 1.0f, &metadata),
823 applyGain(e, 1.0f, &metadata, displayBoost));
Nick Deakin65f492a2022-11-29 22:47:40 -0500824}
825
Dichen Zhang10959a42023-04-10 16:28:16 -0700826TEST_F(GainMapMathTest, GetYuv420Pixel) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500827 jpegr_uncompressed_struct image = Yuv420Image();
828 Color (*colors)[4] = Yuv420Colors();
829
830 for (size_t y = 0; y < 4; ++y) {
831 for (size_t x = 0; x < 4; ++x) {
832 EXPECT_YUV_NEAR(getYuv420Pixel(&image, x, y), colors[y][x]);
833 }
834 }
835}
836
Dichen Zhang10959a42023-04-10 16:28:16 -0700837TEST_F(GainMapMathTest, GetP010Pixel) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500838 jpegr_uncompressed_struct image = P010Image();
839 Color (*colors)[4] = P010Colors();
840
841 for (size_t y = 0; y < 4; ++y) {
842 for (size_t x = 0; x < 4; ++x) {
843 EXPECT_YUV_NEAR(getP010Pixel(&image, x, y), colors[y][x]);
844 }
845 }
846}
847
Dichen Zhang10959a42023-04-10 16:28:16 -0700848TEST_F(GainMapMathTest, SampleYuv420) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500849 jpegr_uncompressed_struct image = Yuv420Image();
850 Color (*colors)[4] = Yuv420Colors();
851
852 static const size_t kMapScaleFactor = 2;
853 for (size_t y = 0; y < 4 / kMapScaleFactor; ++y) {
854 for (size_t x = 0; x < 4 / kMapScaleFactor; ++x) {
855 Color min = {{{ 1.0f, 1.0f, 1.0f }}};
856 Color max = {{{ -1.0f, -1.0f, -1.0f }}};
857
858 for (size_t dy = 0; dy < kMapScaleFactor; ++dy) {
859 for (size_t dx = 0; dx < kMapScaleFactor; ++dx) {
860 Color e = colors[y * kMapScaleFactor + dy][x * kMapScaleFactor + dx];
861 min = ColorMin(min, e);
862 max = ColorMax(max, e);
863 }
864 }
865
866 // Instead of reimplementing the sampling algorithm, confirm that the
867 // sample output is within the range of the min and max of the nearest
868 // points.
869 EXPECT_YUV_BETWEEN(sampleYuv420(&image, kMapScaleFactor, x, y), min, max);
870 }
871 }
872}
873
Dichen Zhang10959a42023-04-10 16:28:16 -0700874TEST_F(GainMapMathTest, SampleP010) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500875 jpegr_uncompressed_struct image = P010Image();
876 Color (*colors)[4] = P010Colors();
877
878 static const size_t kMapScaleFactor = 2;
879 for (size_t y = 0; y < 4 / kMapScaleFactor; ++y) {
880 for (size_t x = 0; x < 4 / kMapScaleFactor; ++x) {
881 Color min = {{{ 1.0f, 1.0f, 1.0f }}};
882 Color max = {{{ -1.0f, -1.0f, -1.0f }}};
883
884 for (size_t dy = 0; dy < kMapScaleFactor; ++dy) {
885 for (size_t dx = 0; dx < kMapScaleFactor; ++dx) {
886 Color e = colors[y * kMapScaleFactor + dy][x * kMapScaleFactor + dx];
887 min = ColorMin(min, e);
888 max = ColorMax(max, e);
889 }
890 }
891
892 // Instead of reimplementing the sampling algorithm, confirm that the
893 // sample output is within the range of the min and max of the nearest
894 // points.
895 EXPECT_YUV_BETWEEN(sampleP010(&image, kMapScaleFactor, x, y), min, max);
896 }
897 }
898}
899
Dichen Zhang10959a42023-04-10 16:28:16 -0700900TEST_F(GainMapMathTest, SampleMap) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500901 jpegr_uncompressed_struct image = MapImage();
902 float (*values)[4] = MapValues();
903
904 static const size_t kMapScaleFactor = 2;
Ram Mohanfe723d62022-12-15 00:59:11 +0530905 ShepardsIDW idwTable(kMapScaleFactor);
Nick Deakin65f492a2022-11-29 22:47:40 -0500906 for (size_t y = 0; y < 4 * kMapScaleFactor; ++y) {
907 for (size_t x = 0; x < 4 * kMapScaleFactor; ++x) {
908 size_t x_base = x / kMapScaleFactor;
909 size_t y_base = y / kMapScaleFactor;
910
911 float min = 1.0f;
912 float max = -1.0f;
913
914 min = fmin(min, values[y_base][x_base]);
915 max = fmax(max, values[y_base][x_base]);
916 if (y_base + 1 < 4) {
917 min = fmin(min, values[y_base + 1][x_base]);
918 max = fmax(max, values[y_base + 1][x_base]);
919 }
920 if (x_base + 1 < 4) {
921 min = fmin(min, values[y_base][x_base + 1]);
922 max = fmax(max, values[y_base][x_base + 1]);
923 }
924 if (y_base + 1 < 4 && x_base + 1 < 4) {
925 min = fmin(min, values[y_base + 1][x_base + 1]);
926 max = fmax(max, values[y_base + 1][x_base + 1]);
927 }
928
929 // Instead of reimplementing the sampling algorithm, confirm that the
930 // sample output is within the range of the min and max of the nearest
931 // points.
Nick Deakind19e5762023-02-10 15:39:08 -0500932 EXPECT_THAT(sampleMap(&image, kMapScaleFactor, x, y),
Nick Deakin65f492a2022-11-29 22:47:40 -0500933 testing::AllOf(testing::Ge(min), testing::Le(max)));
Nick Deakind19e5762023-02-10 15:39:08 -0500934 EXPECT_EQ(sampleMap(&image, kMapScaleFactor, x, y, idwTable),
935 sampleMap(&image, kMapScaleFactor, x, y));
Nick Deakin65f492a2022-11-29 22:47:40 -0500936 }
937 }
938}
939
Dichen Zhang10959a42023-04-10 16:28:16 -0700940TEST_F(GainMapMathTest, ColorToRgba1010102) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500941 EXPECT_EQ(colorToRgba1010102(RgbBlack()), 0x3 << 30);
942 EXPECT_EQ(colorToRgba1010102(RgbWhite()), 0xFFFFFFFF);
943 EXPECT_EQ(colorToRgba1010102(RgbRed()), 0x3 << 30 | 0x3ff);
944 EXPECT_EQ(colorToRgba1010102(RgbGreen()), 0x3 << 30 | 0x3ff << 10);
945 EXPECT_EQ(colorToRgba1010102(RgbBlue()), 0x3 << 30 | 0x3ff << 20);
946
947 Color e_gamma = {{{ 0.1f, 0.2f, 0.3f }}};
948 EXPECT_EQ(colorToRgba1010102(e_gamma),
949 0x3 << 30
950 | static_cast<uint32_t>(0.1f * static_cast<float>(0x3ff))
951 | static_cast<uint32_t>(0.2f * static_cast<float>(0x3ff)) << 10
952 | static_cast<uint32_t>(0.3f * static_cast<float>(0x3ff)) << 20);
953}
954
Dichen Zhang10959a42023-04-10 16:28:16 -0700955TEST_F(GainMapMathTest, ColorToRgbaF16) {
Dichen Zhangf106df72023-04-04 17:44:46 +0000956 EXPECT_EQ(colorToRgbaF16(RgbBlack()), ((uint64_t) 0x3C00) << 48);
957 EXPECT_EQ(colorToRgbaF16(RgbWhite()), 0x3C003C003C003C00);
958 EXPECT_EQ(colorToRgbaF16(RgbRed()), (((uint64_t) 0x3C00) << 48) | ((uint64_t) 0x3C00));
959 EXPECT_EQ(colorToRgbaF16(RgbGreen()), (((uint64_t) 0x3C00) << 48) | (((uint64_t) 0x3C00) << 16));
960 EXPECT_EQ(colorToRgbaF16(RgbBlue()), (((uint64_t) 0x3C00) << 48) | (((uint64_t) 0x3C00) << 32));
961
962 Color e_gamma = {{{ 0.1f, 0.2f, 0.3f }}};
963 EXPECT_EQ(colorToRgbaF16(e_gamma), 0x3C0034CD32662E66);
964}
965
Dichen Zhang10959a42023-04-10 16:28:16 -0700966TEST_F(GainMapMathTest, Float32ToFloat16) {
Dichen Zhangf106df72023-04-04 17:44:46 +0000967 EXPECT_EQ(floatToHalf(0.1f), 0x2E66);
968 EXPECT_EQ(floatToHalf(0.0f), 0x0);
969 EXPECT_EQ(floatToHalf(1.0f), 0x3C00);
970 EXPECT_EQ(floatToHalf(-1.0f), 0xBC00);
971 EXPECT_EQ(floatToHalf(0x1.fffffep127f), 0x7FFF); // float max
972 EXPECT_EQ(floatToHalf(-0x1.fffffep127f), 0xFFFF); // float min
973 EXPECT_EQ(floatToHalf(0x1.0p-126f), 0x0); // float zero
974}
975
Dichen Zhang10959a42023-04-10 16:28:16 -0700976TEST_F(GainMapMathTest, GenerateMapLuminanceSrgb) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500977 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), srgbLuminance),
978 0.0f);
979 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), srgbLuminance),
980 kSdrWhiteNits);
981 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), srgbLuminance),
982 srgbLuminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
983 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), srgbLuminance),
984 srgbLuminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
985 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), srgbLuminance),
986 srgbLuminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
987}
988
Dichen Zhang10959a42023-04-10 16:28:16 -0700989TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbP3) {
Nick Deakin65f492a2022-11-29 22:47:40 -0500990 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), p3Luminance),
991 0.0f);
992 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), p3Luminance),
993 kSdrWhiteNits);
994 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), p3Luminance),
995 p3Luminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
996 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), p3Luminance),
997 p3Luminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
998 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), p3Luminance),
999 p3Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1000}
1001
Dichen Zhang10959a42023-04-10 16:28:16 -07001002TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbBt2100) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001003 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), bt2100Luminance),
1004 0.0f);
1005 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), bt2100Luminance),
1006 kSdrWhiteNits);
1007 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), bt2100Luminance),
1008 bt2100Luminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
1009 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), bt2100Luminance),
1010 bt2100Luminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
1011 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), bt2100Luminance),
1012 bt2100Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1013}
1014
Dichen Zhang10959a42023-04-10 16:28:16 -07001015TEST_F(GainMapMathTest, GenerateMapLuminanceHlg) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001016 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), hlgInvOetf, identityConversion,
1017 bt2100Luminance, kHlgMaxNits),
1018 0.0f);
1019 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvWhite(), hlgInvOetf, identityConversion,
1020 bt2100Luminance, kHlgMaxNits),
1021 kHlgMaxNits);
1022 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvRed(), hlgInvOetf, identityConversion,
1023 bt2100Luminance, kHlgMaxNits),
1024 bt2100Luminance(RgbRed()) * kHlgMaxNits, LuminanceEpsilon());
1025 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvGreen(), hlgInvOetf, identityConversion,
1026 bt2100Luminance, kHlgMaxNits),
1027 bt2100Luminance(RgbGreen()) * kHlgMaxNits, LuminanceEpsilon());
1028 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvBlue(), hlgInvOetf, identityConversion,
1029 bt2100Luminance, kHlgMaxNits),
1030 bt2100Luminance(RgbBlue()) * kHlgMaxNits, LuminanceEpsilon());
1031}
1032
Dichen Zhang10959a42023-04-10 16:28:16 -07001033TEST_F(GainMapMathTest, GenerateMapLuminancePq) {
Nick Deakin65f492a2022-11-29 22:47:40 -05001034 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), pqInvOetf, identityConversion,
1035 bt2100Luminance, kPqMaxNits),
1036 0.0f);
1037 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvWhite(), pqInvOetf, identityConversion,
1038 bt2100Luminance, kPqMaxNits),
1039 kPqMaxNits);
1040 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvRed(), pqInvOetf, identityConversion,
1041 bt2100Luminance, kPqMaxNits),
1042 bt2100Luminance(RgbRed()) * kPqMaxNits, LuminanceEpsilon());
1043 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvGreen(), pqInvOetf, identityConversion,
1044 bt2100Luminance, kPqMaxNits),
1045 bt2100Luminance(RgbGreen()) * kPqMaxNits, LuminanceEpsilon());
1046 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvBlue(), pqInvOetf, identityConversion,
1047 bt2100Luminance, kPqMaxNits),
1048 bt2100Luminance(RgbBlue()) * kPqMaxNits, LuminanceEpsilon());
1049}
1050
Dichen Zhang10959a42023-04-10 16:28:16 -07001051TEST_F(GainMapMathTest, ApplyMap) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001052 ultrahdr_metadata_struct metadata = { .maxContentBoost = 8.0f,
Dichen Zhange286f1c2023-03-14 00:22:00 +00001053 .minContentBoost = 1.0f / 8.0f };
Nick Deakind19e5762023-02-10 15:39:08 -05001054
1055 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001056 RgbWhite() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001057 EXPECT_RGB_EQ(Recover(YuvBlack(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001058 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001059 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001060 RgbRed() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001061 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001062 RgbGreen() * 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001063 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 1.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001064 RgbBlue() * 8.0f);
1065
Nick Deakind19e5762023-02-10 15:39:08 -05001066 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001067 RgbWhite() * sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001068 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001069 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001070 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001071 RgbRed() * sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001072 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001073 RgbGreen() * sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001074 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.75f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001075 RgbBlue() * sqrt(8.0f));
1076
Nick Deakind19e5762023-02-10 15:39:08 -05001077 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001078 RgbWhite());
Nick Deakind19e5762023-02-10 15:39:08 -05001079 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001080 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001081 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001082 RgbRed());
Nick Deakind19e5762023-02-10 15:39:08 -05001083 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001084 RgbGreen());
Nick Deakind19e5762023-02-10 15:39:08 -05001085 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.5f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001086 RgbBlue());
1087
Nick Deakind19e5762023-02-10 15:39:08 -05001088 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001089 RgbWhite() / sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001090 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001091 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001092 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001093 RgbRed() / sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001094 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001095 RgbGreen() / sqrt(8.0f));
Nick Deakind19e5762023-02-10 15:39:08 -05001096 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.25f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001097 RgbBlue() / sqrt(8.0f));
1098
Nick Deakind19e5762023-02-10 15:39:08 -05001099 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001100 RgbWhite() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001101 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001102 RgbBlack());
Nick Deakind19e5762023-02-10 15:39:08 -05001103 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001104 RgbRed() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001105 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001106 RgbGreen() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001107 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.0f, &metadata),
Nick Deakin65f492a2022-11-29 22:47:40 -05001108 RgbBlue() / 8.0f);
Nick Deakind19e5762023-02-10 15:39:08 -05001109
1110 metadata.maxContentBoost = 8.0f;
1111 metadata.minContentBoost = 1.0f;
1112
1113 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata),
1114 RgbWhite() * 8.0f);
1115 EXPECT_RGB_EQ(Recover(YuvWhite(), 2.0f / 3.0f, &metadata),
1116 RgbWhite() * 4.0f);
1117 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f / 3.0f, &metadata),
1118 RgbWhite() * 2.0f);
1119 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata),
1120 RgbWhite());
1121
1122 metadata.maxContentBoost = 8.0f;
1123 metadata.minContentBoost = 0.5f;;
1124
1125 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata),
1126 RgbWhite() * 8.0f);
1127 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.75, &metadata),
1128 RgbWhite() * 4.0f);
1129 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.5f, &metadata),
1130 RgbWhite() * 2.0f);
1131 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.25f, &metadata),
1132 RgbWhite());
1133 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata),
1134 RgbWhite() / 2.0f);
Nick Deakin65f492a2022-11-29 22:47:40 -05001135}
1136
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001137} // namespace android::ultrahdr