blob: 0d0e4fcea3ffb56768ddd2e6af6352f39e8c91a7 [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>
20#include <jpegrecoverymap/recoverymapmath.h>
21
22namespace android::recoverymap {
23
24class RecoveryMapMathTest : public testing::Test {
25public:
26 RecoveryMapMathTest();
27 ~RecoveryMapMathTest();
28
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) {
45 return (static_cast<float>(e) - 127.5f) / 127.5f;
46 }
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
91 Color Recover(Color yuv_gamma, float recovery, float range_scaling_factor) {
92 Color rgb_gamma = srgbYuvToRgb(yuv_gamma);
93 Color rgb = srgbInvOetf(rgb_gamma);
94 return applyRecovery(rgb, recovery, range_scaling_factor);
95 }
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 };
111 return { pixels, 4, 4, JPEGR_COLORGAMUT_BT709 };
112 }
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 };
144 return { pixels, 4, 4, JPEGR_COLORGAMUT_BT709 };
145 }
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 };
173 return { pixels, 4, 4, JPEGR_COLORGAMUT_UNSPECIFIED };
174 }
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
196RecoveryMapMathTest::RecoveryMapMathTest() {}
197RecoveryMapMathTest::~RecoveryMapMathTest() {}
198
199void RecoveryMapMathTest::SetUp() {}
200void RecoveryMapMathTest::TearDown() {}
201
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
234TEST_F(RecoveryMapMathTest, ColorConstruct) {
235 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
246TEST_F(RecoveryMapMathTest, ColorAddColor) {
247 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
260TEST_F(RecoveryMapMathTest, ColorAddFloat) {
261 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
274TEST_F(RecoveryMapMathTest, ColorSubtractColor) {
275 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
288TEST_F(RecoveryMapMathTest, ColorSubtractFloat) {
289 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
302TEST_F(RecoveryMapMathTest, ColorMultiplyFloat) {
303 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
316TEST_F(RecoveryMapMathTest, ColorDivideFloat) {
317 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
330TEST_F(RecoveryMapMathTest, SrgbLuminance) {
331 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
338TEST_F(RecoveryMapMathTest, SrgbYuvToRgb) {
339 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
355TEST_F(RecoveryMapMathTest, SrgbRgbToYuv) {
356 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
372TEST_F(RecoveryMapMathTest, SrgbRgbYuvRoundtrip) {
373 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
389TEST_F(RecoveryMapMathTest, SrgbTransferFunction) {
390 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
397TEST_F(RecoveryMapMathTest, P3Luminance) {
398 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
405TEST_F(RecoveryMapMathTest, Bt2100Luminance) {
406 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
413TEST_F(RecoveryMapMathTest, Bt2100YuvToRgb) {
414 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
430TEST_F(RecoveryMapMathTest, Bt2100RgbToYuv) {
431 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
447TEST_F(RecoveryMapMathTest, Bt2100RgbYuvRoundtrip) {
448 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
464TEST_F(RecoveryMapMathTest, HlgOetf) {
465 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
476TEST_F(RecoveryMapMathTest, HlgInvOetf) {
477 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
488TEST_F(RecoveryMapMathTest, HlgTransferFunctionRoundtrip) {
489 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
496TEST_F(RecoveryMapMathTest, PqOetf) {
497 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
508TEST_F(RecoveryMapMathTest, PqInvOetf) {
509 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
Harish Mahendrakar555a06b2022-12-14 09:37:27 -0800520TEST_F(RecoveryMapMathTest, PqInvOetfLUT) {
521 float increment = 1.0 / 1024.0;
522 float value = 0.0f;
523 for (int idx = 0; idx < 1024; idx++, value += increment) {
524 EXPECT_FLOAT_EQ(pqInvOetf(value), pqInvOetfLUT(value));
525 }
526}
527
528TEST_F(RecoveryMapMathTest, HlgInvOetfLUT) {
529 float increment = 1.0 / 1024.0;
530 float value = 0.0f;
531 for (int idx = 0; idx < 1024; idx++, value += increment) {
532 EXPECT_FLOAT_EQ(hlgInvOetf(value), hlgInvOetfLUT(value));
533 }
534}
535
536TEST_F(RecoveryMapMathTest, pqOetfLUT) {
537 float increment = 1.0 / 1024.0;
538 float value = 0.0f;
539 for (int idx = 0; idx < 1024; idx++, value += increment) {
540 EXPECT_FLOAT_EQ(pqOetf(value), pqOetfLUT(value));
541 }
542}
543
544TEST_F(RecoveryMapMathTest, hlgOetfLUT) {
545 float increment = 1.0 / 1024.0;
546 float value = 0.0f;
547 for (int idx = 0; idx < 1024; idx++, value += increment) {
548 EXPECT_FLOAT_EQ(hlgOetf(value), hlgOetfLUT(value));
549 }
550}
551
552TEST_F(RecoveryMapMathTest, srgbInvOetfLUT) {
553 float increment = 1.0 / 1024.0;
554 float value = 0.0f;
555 for (int idx = 0; idx < 1024; idx++, value += increment) {
556 EXPECT_FLOAT_EQ(srgbInvOetf(value), srgbInvOetfLUT(value));
557 }
558}
559
Nick Deakin65f492a2022-11-29 22:47:40 -0500560TEST_F(RecoveryMapMathTest, PqTransferFunctionRoundtrip) {
561 EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(0.0f)), 0.0f);
562 EXPECT_NEAR(pqInvOetf(pqOetf(0.01f)), 0.01f, ComparisonEpsilon());
563 EXPECT_NEAR(pqInvOetf(pqOetf(0.5f)), 0.5f, ComparisonEpsilon());
564 EXPECT_NEAR(pqInvOetf(pqOetf(0.99f)), 0.99f, ComparisonEpsilon());
565 EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(1.0f)), 1.0f);
566}
567
568TEST_F(RecoveryMapMathTest, ColorConversionLookup) {
569 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_UNSPECIFIED),
570 nullptr);
571 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_BT709),
572 identityConversion);
573 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_P3),
574 p3ToBt709);
575 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_BT2100),
576 bt2100ToBt709);
577
578 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_UNSPECIFIED),
579 nullptr);
580 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_BT709),
581 bt709ToP3);
582 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_P3),
583 identityConversion);
584 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_BT2100),
585 bt2100ToP3);
586
587 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_UNSPECIFIED),
588 nullptr);
589 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_BT709),
590 bt709ToBt2100);
591 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_P3),
592 p3ToBt2100);
593 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_BT2100),
594 identityConversion);
595
596 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_UNSPECIFIED),
597 nullptr);
598 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_BT709),
599 nullptr);
600 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_P3),
601 nullptr);
602 EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_BT2100),
603 nullptr);
604}
605
606TEST_F(RecoveryMapMathTest, EncodeRecovery) {
607 EXPECT_EQ(encodeRecovery(0.0f, 0.0f, 4.0f), 127);
608 EXPECT_EQ(encodeRecovery(0.0f, 1.0f, 4.0f), 127);
609 EXPECT_EQ(encodeRecovery(1.0f, 0.0f, 4.0f), 0);
610 EXPECT_EQ(encodeRecovery(0.5f, 0.0f, 4.0f), 0);
611
612 EXPECT_EQ(encodeRecovery(1.0f, 1.0f, 4.0f), 127);
613 EXPECT_EQ(encodeRecovery(1.0f, 4.0f, 4.0f), 255);
614 EXPECT_EQ(encodeRecovery(1.0f, 5.0f, 4.0f), 255);
615 EXPECT_EQ(encodeRecovery(4.0f, 1.0f, 4.0f), 0);
616 EXPECT_EQ(encodeRecovery(4.0f, 0.5f, 4.0f), 0);
617 EXPECT_EQ(encodeRecovery(1.0f, 2.0f, 4.0f), 191);
618 EXPECT_EQ(encodeRecovery(2.0f, 1.0f, 4.0f), 63);
619
620 EXPECT_EQ(encodeRecovery(1.0f, 2.0f, 2.0f), 255);
621 EXPECT_EQ(encodeRecovery(2.0f, 1.0f, 2.0f), 0);
622 EXPECT_EQ(encodeRecovery(1.0f, 1.41421f, 2.0f), 191);
623 EXPECT_EQ(encodeRecovery(1.41421f, 1.0f, 2.0f), 63);
624
625 EXPECT_EQ(encodeRecovery(1.0f, 8.0f, 8.0f), 255);
626 EXPECT_EQ(encodeRecovery(8.0f, 1.0f, 8.0f), 0);
627 EXPECT_EQ(encodeRecovery(1.0f, 2.82843f, 8.0f), 191);
628 EXPECT_EQ(encodeRecovery(2.82843f, 1.0f, 8.0f), 63);
629}
630
631TEST_F(RecoveryMapMathTest, ApplyRecovery) {
632 EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), -1.0f, 4.0f), RgbBlack());
633 EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), 0.0f, 4.0f), RgbBlack());
634 EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), 1.0f, 4.0f), RgbBlack());
635
636 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), -1.0f, 4.0f), RgbWhite() / 4.0f);
637 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), -0.5f, 4.0f), RgbWhite() / 2.0f);
638 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, 4.0f), RgbWhite());
639 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, 4.0f), RgbWhite() * 2.0f);
640 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, 4.0f), RgbWhite() * 4.0f);
641
642 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), -1.0f, 2.0f), RgbWhite() / 2.0f);
643 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), -0.5f, 2.0f), RgbWhite() / 1.41421f);
644 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, 2.0f), RgbWhite());
645 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, 2.0f), RgbWhite() * 1.41421f);
646 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, 2.0f), RgbWhite() * 2.0f);
647
648 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), -1.0f, 8.0f), RgbWhite() / 8.0f);
649 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), -0.5f, 8.0f), RgbWhite() / 2.82843f);
650 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, 8.0f), RgbWhite());
651 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, 8.0f), RgbWhite() * 2.82843f);
652 EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, 8.0f), RgbWhite() * 8.0f);
653
654 Color e = {{{ 0.0f, 0.5f, 1.0f }}};
655
656 EXPECT_RGB_NEAR(applyRecovery(e, -1.0f, 4.0f), e / 4.0f);
657 EXPECT_RGB_NEAR(applyRecovery(e, -0.5f, 4.0f), e / 2.0f);
658 EXPECT_RGB_NEAR(applyRecovery(e, 0.0f, 4.0f), e);
659 EXPECT_RGB_NEAR(applyRecovery(e, 0.5f, 4.0f), e * 2.0f);
660 EXPECT_RGB_NEAR(applyRecovery(e, 1.0f, 4.0f), e * 4.0f);
661}
662
663TEST_F(RecoveryMapMathTest, GetYuv420Pixel) {
664 jpegr_uncompressed_struct image = Yuv420Image();
665 Color (*colors)[4] = Yuv420Colors();
666
667 for (size_t y = 0; y < 4; ++y) {
668 for (size_t x = 0; x < 4; ++x) {
669 EXPECT_YUV_NEAR(getYuv420Pixel(&image, x, y), colors[y][x]);
670 }
671 }
672}
673
674TEST_F(RecoveryMapMathTest, GetP010Pixel) {
675 jpegr_uncompressed_struct image = P010Image();
676 Color (*colors)[4] = P010Colors();
677
678 for (size_t y = 0; y < 4; ++y) {
679 for (size_t x = 0; x < 4; ++x) {
680 EXPECT_YUV_NEAR(getP010Pixel(&image, x, y), colors[y][x]);
681 }
682 }
683}
684
685TEST_F(RecoveryMapMathTest, SampleYuv420) {
686 jpegr_uncompressed_struct image = Yuv420Image();
687 Color (*colors)[4] = Yuv420Colors();
688
689 static const size_t kMapScaleFactor = 2;
690 for (size_t y = 0; y < 4 / kMapScaleFactor; ++y) {
691 for (size_t x = 0; x < 4 / kMapScaleFactor; ++x) {
692 Color min = {{{ 1.0f, 1.0f, 1.0f }}};
693 Color max = {{{ -1.0f, -1.0f, -1.0f }}};
694
695 for (size_t dy = 0; dy < kMapScaleFactor; ++dy) {
696 for (size_t dx = 0; dx < kMapScaleFactor; ++dx) {
697 Color e = colors[y * kMapScaleFactor + dy][x * kMapScaleFactor + dx];
698 min = ColorMin(min, e);
699 max = ColorMax(max, e);
700 }
701 }
702
703 // Instead of reimplementing the sampling algorithm, confirm that the
704 // sample output is within the range of the min and max of the nearest
705 // points.
706 EXPECT_YUV_BETWEEN(sampleYuv420(&image, kMapScaleFactor, x, y), min, max);
707 }
708 }
709}
710
711TEST_F(RecoveryMapMathTest, SampleP010) {
712 jpegr_uncompressed_struct image = P010Image();
713 Color (*colors)[4] = P010Colors();
714
715 static const size_t kMapScaleFactor = 2;
716 for (size_t y = 0; y < 4 / kMapScaleFactor; ++y) {
717 for (size_t x = 0; x < 4 / kMapScaleFactor; ++x) {
718 Color min = {{{ 1.0f, 1.0f, 1.0f }}};
719 Color max = {{{ -1.0f, -1.0f, -1.0f }}};
720
721 for (size_t dy = 0; dy < kMapScaleFactor; ++dy) {
722 for (size_t dx = 0; dx < kMapScaleFactor; ++dx) {
723 Color e = colors[y * kMapScaleFactor + dy][x * kMapScaleFactor + dx];
724 min = ColorMin(min, e);
725 max = ColorMax(max, e);
726 }
727 }
728
729 // Instead of reimplementing the sampling algorithm, confirm that the
730 // sample output is within the range of the min and max of the nearest
731 // points.
732 EXPECT_YUV_BETWEEN(sampleP010(&image, kMapScaleFactor, x, y), min, max);
733 }
734 }
735}
736
737TEST_F(RecoveryMapMathTest, SampleMap) {
738 jpegr_uncompressed_struct image = MapImage();
739 float (*values)[4] = MapValues();
740
741 static const size_t kMapScaleFactor = 2;
Ram Mohanfe723d62022-12-15 00:59:11 +0530742 ShepardsIDW idwTable(kMapScaleFactor);
Nick Deakin65f492a2022-11-29 22:47:40 -0500743 for (size_t y = 0; y < 4 * kMapScaleFactor; ++y) {
744 for (size_t x = 0; x < 4 * kMapScaleFactor; ++x) {
745 size_t x_base = x / kMapScaleFactor;
746 size_t y_base = y / kMapScaleFactor;
747
748 float min = 1.0f;
749 float max = -1.0f;
750
751 min = fmin(min, values[y_base][x_base]);
752 max = fmax(max, values[y_base][x_base]);
753 if (y_base + 1 < 4) {
754 min = fmin(min, values[y_base + 1][x_base]);
755 max = fmax(max, values[y_base + 1][x_base]);
756 }
757 if (x_base + 1 < 4) {
758 min = fmin(min, values[y_base][x_base + 1]);
759 max = fmax(max, values[y_base][x_base + 1]);
760 }
761 if (y_base + 1 < 4 && x_base + 1 < 4) {
762 min = fmin(min, values[y_base + 1][x_base + 1]);
763 max = fmax(max, values[y_base + 1][x_base + 1]);
764 }
765
766 // Instead of reimplementing the sampling algorithm, confirm that the
767 // sample output is within the range of the min and max of the nearest
768 // points.
Ram Mohanfe723d62022-12-15 00:59:11 +0530769 EXPECT_THAT(sampleMap(&image, kMapScaleFactor, x, y, idwTable),
Nick Deakin65f492a2022-11-29 22:47:40 -0500770 testing::AllOf(testing::Ge(min), testing::Le(max)));
771 }
772 }
773}
774
775TEST_F(RecoveryMapMathTest, ColorToRgba1010102) {
776 EXPECT_EQ(colorToRgba1010102(RgbBlack()), 0x3 << 30);
777 EXPECT_EQ(colorToRgba1010102(RgbWhite()), 0xFFFFFFFF);
778 EXPECT_EQ(colorToRgba1010102(RgbRed()), 0x3 << 30 | 0x3ff);
779 EXPECT_EQ(colorToRgba1010102(RgbGreen()), 0x3 << 30 | 0x3ff << 10);
780 EXPECT_EQ(colorToRgba1010102(RgbBlue()), 0x3 << 30 | 0x3ff << 20);
781
782 Color e_gamma = {{{ 0.1f, 0.2f, 0.3f }}};
783 EXPECT_EQ(colorToRgba1010102(e_gamma),
784 0x3 << 30
785 | static_cast<uint32_t>(0.1f * static_cast<float>(0x3ff))
786 | static_cast<uint32_t>(0.2f * static_cast<float>(0x3ff)) << 10
787 | static_cast<uint32_t>(0.3f * static_cast<float>(0x3ff)) << 20);
788}
789
790TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgb) {
791 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), srgbLuminance),
792 0.0f);
793 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), srgbLuminance),
794 kSdrWhiteNits);
795 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), srgbLuminance),
796 srgbLuminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
797 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), srgbLuminance),
798 srgbLuminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
799 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), srgbLuminance),
800 srgbLuminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
801}
802
803TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgbP3) {
804 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), p3Luminance),
805 0.0f);
806 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), p3Luminance),
807 kSdrWhiteNits);
808 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), p3Luminance),
809 p3Luminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
810 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), p3Luminance),
811 p3Luminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
812 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), p3Luminance),
813 p3Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
814}
815
816TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgbBt2100) {
817 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), bt2100Luminance),
818 0.0f);
819 EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), bt2100Luminance),
820 kSdrWhiteNits);
821 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), bt2100Luminance),
822 bt2100Luminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
823 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), bt2100Luminance),
824 bt2100Luminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
825 EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), bt2100Luminance),
826 bt2100Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
827}
828
829TEST_F(RecoveryMapMathTest, GenerateMapLuminanceHlg) {
830 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), hlgInvOetf, identityConversion,
831 bt2100Luminance, kHlgMaxNits),
832 0.0f);
833 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvWhite(), hlgInvOetf, identityConversion,
834 bt2100Luminance, kHlgMaxNits),
835 kHlgMaxNits);
836 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvRed(), hlgInvOetf, identityConversion,
837 bt2100Luminance, kHlgMaxNits),
838 bt2100Luminance(RgbRed()) * kHlgMaxNits, LuminanceEpsilon());
839 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvGreen(), hlgInvOetf, identityConversion,
840 bt2100Luminance, kHlgMaxNits),
841 bt2100Luminance(RgbGreen()) * kHlgMaxNits, LuminanceEpsilon());
842 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvBlue(), hlgInvOetf, identityConversion,
843 bt2100Luminance, kHlgMaxNits),
844 bt2100Luminance(RgbBlue()) * kHlgMaxNits, LuminanceEpsilon());
845}
846
847TEST_F(RecoveryMapMathTest, GenerateMapLuminancePq) {
848 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), pqInvOetf, identityConversion,
849 bt2100Luminance, kPqMaxNits),
850 0.0f);
851 EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvWhite(), pqInvOetf, identityConversion,
852 bt2100Luminance, kPqMaxNits),
853 kPqMaxNits);
854 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvRed(), pqInvOetf, identityConversion,
855 bt2100Luminance, kPqMaxNits),
856 bt2100Luminance(RgbRed()) * kPqMaxNits, LuminanceEpsilon());
857 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvGreen(), pqInvOetf, identityConversion,
858 bt2100Luminance, kPqMaxNits),
859 bt2100Luminance(RgbGreen()) * kPqMaxNits, LuminanceEpsilon());
860 EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvBlue(), pqInvOetf, identityConversion,
861 bt2100Luminance, kPqMaxNits),
862 bt2100Luminance(RgbBlue()) * kPqMaxNits, LuminanceEpsilon());
863}
864
Nick Deakin65f492a2022-11-29 22:47:40 -0500865TEST_F(RecoveryMapMathTest, ApplyMap) {
866 EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, 8.0f),
867 RgbWhite() * 8.0f);
868 EXPECT_RGB_EQ(Recover(YuvBlack(), 1.0f, 8.0f),
869 RgbBlack());
870 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 1.0f, 8.0f),
871 RgbRed() * 8.0f);
872 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 1.0f, 8.0f),
873 RgbGreen() * 8.0f);
874 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 1.0f, 8.0f),
875 RgbBlue() * 8.0f);
876
877 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.5f, 8.0f),
878 RgbWhite() * sqrt(8.0f));
879 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.5f, 8.0f),
880 RgbBlack());
881 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.5f, 8.0f),
882 RgbRed() * sqrt(8.0f));
883 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.5f, 8.0f),
884 RgbGreen() * sqrt(8.0f));
885 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.5f, 8.0f),
886 RgbBlue() * sqrt(8.0f));
887
888 EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, 8.0f),
889 RgbWhite());
890 EXPECT_RGB_EQ(Recover(YuvBlack(), 0.0f, 8.0f),
891 RgbBlack());
892 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.0f, 8.0f),
893 RgbRed());
894 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.0f, 8.0f),
895 RgbGreen());
896 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.0f, 8.0f),
897 RgbBlue());
898
899 EXPECT_RGB_EQ(Recover(YuvWhite(), -0.5f, 8.0f),
900 RgbWhite() / sqrt(8.0f));
901 EXPECT_RGB_EQ(Recover(YuvBlack(), -0.5f, 8.0f),
902 RgbBlack());
903 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), -0.5f, 8.0f),
904 RgbRed() / sqrt(8.0f));
905 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), -0.5f, 8.0f),
906 RgbGreen() / sqrt(8.0f));
907 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), -0.5f, 8.0f),
908 RgbBlue() / sqrt(8.0f));
909
910 EXPECT_RGB_EQ(Recover(YuvWhite(), -1.0f, 8.0f),
911 RgbWhite() / 8.0f);
912 EXPECT_RGB_EQ(Recover(YuvBlack(), -1.0f, 8.0f),
913 RgbBlack());
914 EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), -1.0f, 8.0f),
915 RgbRed() / 8.0f);
916 EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), -1.0f, 8.0f),
917 RgbGreen() / 8.0f);
918 EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), -1.0f, 8.0f),
919 RgbBlue() / 8.0f);
920}
921
922} // namespace android::recoverymap