xref: /aosp_15_r20/external/libultrahdr/tests/gainmapmath_test.cpp (revision 89a0ef05262152531a00a15832a2d3b1e3990773)
1*89a0ef05SAndroid Build Coastguard Worker /*
2*89a0ef05SAndroid Build Coastguard Worker  * Copyright 2022 The Android Open Source Project
3*89a0ef05SAndroid Build Coastguard Worker  *
4*89a0ef05SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*89a0ef05SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*89a0ef05SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*89a0ef05SAndroid Build Coastguard Worker  *
8*89a0ef05SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*89a0ef05SAndroid Build Coastguard Worker  *
10*89a0ef05SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*89a0ef05SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*89a0ef05SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*89a0ef05SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*89a0ef05SAndroid Build Coastguard Worker  * limitations under the License.
15*89a0ef05SAndroid Build Coastguard Worker  */
16*89a0ef05SAndroid Build Coastguard Worker 
17*89a0ef05SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*89a0ef05SAndroid Build Coastguard Worker #include <gmock/gmock.h>
19*89a0ef05SAndroid Build Coastguard Worker 
20*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/gainmapmath.h"
21*89a0ef05SAndroid Build Coastguard Worker 
22*89a0ef05SAndroid Build Coastguard Worker namespace ultrahdr {
23*89a0ef05SAndroid Build Coastguard Worker 
24*89a0ef05SAndroid Build Coastguard Worker class GainMapMathTest : public testing::Test {
25*89a0ef05SAndroid Build Coastguard Worker  public:
26*89a0ef05SAndroid Build Coastguard Worker   GainMapMathTest();
27*89a0ef05SAndroid Build Coastguard Worker   ~GainMapMathTest();
28*89a0ef05SAndroid Build Coastguard Worker 
ComparisonEpsilon()29*89a0ef05SAndroid Build Coastguard Worker   float ComparisonEpsilon() { return 1e-4f; }
LuminanceEpsilon()30*89a0ef05SAndroid Build Coastguard Worker   float LuminanceEpsilon() { return 1e-2f; }
YuvConversionEpsilon()31*89a0ef05SAndroid Build Coastguard Worker   float YuvConversionEpsilon() { return 1.0f / (255.0f * 2.0f); }
32*89a0ef05SAndroid Build Coastguard Worker 
Yuv420(uint8_t y,uint8_t u,uint8_t v)33*89a0ef05SAndroid Build Coastguard Worker   Color Yuv420(uint8_t y, uint8_t u, uint8_t v) {
34*89a0ef05SAndroid Build Coastguard Worker     return {{{static_cast<float>(y) * (1 / 255.0f), static_cast<float>(u - 128) * (1 / 255.0f),
35*89a0ef05SAndroid Build Coastguard Worker               static_cast<float>(v - 128) * (1 / 255.0f)}}};
36*89a0ef05SAndroid Build Coastguard Worker   }
37*89a0ef05SAndroid Build Coastguard Worker 
P010(uint16_t y,uint16_t u,uint16_t v)38*89a0ef05SAndroid Build Coastguard Worker   Color P010(uint16_t y, uint16_t u, uint16_t v) {
39*89a0ef05SAndroid Build Coastguard Worker     return {{{static_cast<float>(y - 64) * (1 / 876.0f),
40*89a0ef05SAndroid Build Coastguard Worker               static_cast<float>(u - 64) * (1 / 896.0f) - 0.5f,
41*89a0ef05SAndroid Build Coastguard Worker               static_cast<float>(v - 64) * (1 / 896.0f) - 0.5f}}};
42*89a0ef05SAndroid Build Coastguard Worker   }
43*89a0ef05SAndroid Build Coastguard Worker 
44*89a0ef05SAndroid Build Coastguard Worker   // Using int16_t allows for testing fixed-point implementations.
45*89a0ef05SAndroid Build Coastguard Worker   struct Pixel {
46*89a0ef05SAndroid Build Coastguard Worker     int16_t y;
47*89a0ef05SAndroid Build Coastguard Worker     int16_t u;
48*89a0ef05SAndroid Build Coastguard Worker     int16_t v;
49*89a0ef05SAndroid Build Coastguard Worker   };
50*89a0ef05SAndroid Build Coastguard Worker 
getYuv420Pixel_uint(uhdr_raw_image_t * image,size_t x,size_t y)51*89a0ef05SAndroid Build Coastguard Worker   Pixel getYuv420Pixel_uint(uhdr_raw_image_t* image, size_t x, size_t y) {
52*89a0ef05SAndroid Build Coastguard Worker     uint8_t* luma_data = reinterpret_cast<uint8_t*>(image->planes[UHDR_PLANE_Y]);
53*89a0ef05SAndroid Build Coastguard Worker     size_t luma_stride = image->stride[UHDR_PLANE_Y];
54*89a0ef05SAndroid Build Coastguard Worker     uint8_t* cb_data = reinterpret_cast<uint8_t*>(image->planes[UHDR_PLANE_U]);
55*89a0ef05SAndroid Build Coastguard Worker     size_t cb_stride = image->stride[UHDR_PLANE_U];
56*89a0ef05SAndroid Build Coastguard Worker     uint8_t* cr_data = reinterpret_cast<uint8_t*>(image->planes[UHDR_PLANE_V]);
57*89a0ef05SAndroid Build Coastguard Worker     size_t cr_stride = image->stride[UHDR_PLANE_V];
58*89a0ef05SAndroid Build Coastguard Worker 
59*89a0ef05SAndroid Build Coastguard Worker     size_t pixel_y_idx = x + y * luma_stride;
60*89a0ef05SAndroid Build Coastguard Worker     size_t pixel_cb_idx = x / 2 + (y / 2) * cb_stride;
61*89a0ef05SAndroid Build Coastguard Worker     size_t pixel_cr_idx = x / 2 + (y / 2) * cr_stride;
62*89a0ef05SAndroid Build Coastguard Worker 
63*89a0ef05SAndroid Build Coastguard Worker     uint8_t y_uint = luma_data[pixel_y_idx];
64*89a0ef05SAndroid Build Coastguard Worker     uint8_t u_uint = cb_data[pixel_cb_idx];
65*89a0ef05SAndroid Build Coastguard Worker     uint8_t v_uint = cr_data[pixel_cr_idx];
66*89a0ef05SAndroid Build Coastguard Worker 
67*89a0ef05SAndroid Build Coastguard Worker     return {y_uint, u_uint, v_uint};
68*89a0ef05SAndroid Build Coastguard Worker   }
69*89a0ef05SAndroid Build Coastguard Worker 
Map(uint8_t e)70*89a0ef05SAndroid Build Coastguard Worker   float Map(uint8_t e) { return static_cast<float>(e) / 255.0f; }
71*89a0ef05SAndroid Build Coastguard Worker 
ColorMin(Color e1,Color e2)72*89a0ef05SAndroid Build Coastguard Worker   Color ColorMin(Color e1, Color e2) {
73*89a0ef05SAndroid Build Coastguard Worker     return {{{fminf(e1.r, e2.r), fminf(e1.g, e2.g), fminf(e1.b, e2.b)}}};
74*89a0ef05SAndroid Build Coastguard Worker   }
75*89a0ef05SAndroid Build Coastguard Worker 
ColorMax(Color e1,Color e2)76*89a0ef05SAndroid Build Coastguard Worker   Color ColorMax(Color e1, Color e2) {
77*89a0ef05SAndroid Build Coastguard Worker     return {{{fmaxf(e1.r, e2.r), fmaxf(e1.g, e2.g), fmaxf(e1.b, e2.b)}}};
78*89a0ef05SAndroid Build Coastguard Worker   }
79*89a0ef05SAndroid Build Coastguard Worker 
RgbBlack()80*89a0ef05SAndroid Build Coastguard Worker   Color RgbBlack() { return {{{0.0f, 0.0f, 0.0f}}}; }
RgbWhite()81*89a0ef05SAndroid Build Coastguard Worker   Color RgbWhite() { return {{{1.0f, 1.0f, 1.0f}}}; }
82*89a0ef05SAndroid Build Coastguard Worker 
RgbRed()83*89a0ef05SAndroid Build Coastguard Worker   Color RgbRed() { return {{{1.0f, 0.0f, 0.0f}}}; }
RgbGreen()84*89a0ef05SAndroid Build Coastguard Worker   Color RgbGreen() { return {{{0.0f, 1.0f, 0.0f}}}; }
RgbBlue()85*89a0ef05SAndroid Build Coastguard Worker   Color RgbBlue() { return {{{0.0f, 0.0f, 1.0f}}}; }
86*89a0ef05SAndroid Build Coastguard Worker 
YuvBlack()87*89a0ef05SAndroid Build Coastguard Worker   Color YuvBlack() { return {{{0.0f, 0.0f, 0.0f}}}; }
YuvWhite()88*89a0ef05SAndroid Build Coastguard Worker   Color YuvWhite() { return {{{1.0f, 0.0f, 0.0f}}}; }
89*89a0ef05SAndroid Build Coastguard Worker 
SrgbYuvRed()90*89a0ef05SAndroid Build Coastguard Worker   Color SrgbYuvRed() { return {{{0.2126f, -0.11457f, 0.5f}}}; }
SrgbYuvGreen()91*89a0ef05SAndroid Build Coastguard Worker   Color SrgbYuvGreen() { return {{{0.7152f, -0.38543f, -0.45415f}}}; }
SrgbYuvBlue()92*89a0ef05SAndroid Build Coastguard Worker   Color SrgbYuvBlue() { return {{{0.0722f, 0.5f, -0.04585f}}}; }
93*89a0ef05SAndroid Build Coastguard Worker 
P3YuvRed()94*89a0ef05SAndroid Build Coastguard Worker   Color P3YuvRed() { return {{{0.299f, -0.16874f, 0.5f}}}; }
P3YuvGreen()95*89a0ef05SAndroid Build Coastguard Worker   Color P3YuvGreen() { return {{{0.587f, -0.33126f, -0.41869f}}}; }
P3YuvBlue()96*89a0ef05SAndroid Build Coastguard Worker   Color P3YuvBlue() { return {{{0.114f, 0.5f, -0.08131f}}}; }
97*89a0ef05SAndroid Build Coastguard Worker 
Bt2100YuvRed()98*89a0ef05SAndroid Build Coastguard Worker   Color Bt2100YuvRed() { return {{{0.2627f, -0.13963f, 0.5f}}}; }
Bt2100YuvGreen()99*89a0ef05SAndroid Build Coastguard Worker   Color Bt2100YuvGreen() { return {{{0.6780f, -0.36037f, -0.45979f}}}; }
Bt2100YuvBlue()100*89a0ef05SAndroid Build Coastguard Worker   Color Bt2100YuvBlue() { return {{{0.0593f, 0.5f, -0.04021f}}}; }
101*89a0ef05SAndroid Build Coastguard Worker 
102*89a0ef05SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
103*89a0ef05SAndroid Build Coastguard Worker   // Reference values for when using fixed-point arithmetic.
104*89a0ef05SAndroid Build Coastguard Worker 
RgbBlackPixel()105*89a0ef05SAndroid Build Coastguard Worker   Pixel RgbBlackPixel() { return {0, 0, 0}; }
RgbWhitePixel()106*89a0ef05SAndroid Build Coastguard Worker   Pixel RgbWhitePixel() { return {255, 255, 255}; }
107*89a0ef05SAndroid Build Coastguard Worker 
RgbRedPixel()108*89a0ef05SAndroid Build Coastguard Worker   Pixel RgbRedPixel() { return {255, 0, 0}; }
RgbGreenPixel()109*89a0ef05SAndroid Build Coastguard Worker   Pixel RgbGreenPixel() { return {0, 255, 0}; }
RgbBluePixel()110*89a0ef05SAndroid Build Coastguard Worker   Pixel RgbBluePixel() { return {0, 0, 255}; }
111*89a0ef05SAndroid Build Coastguard Worker 
YuvBlackPixel()112*89a0ef05SAndroid Build Coastguard Worker   Pixel YuvBlackPixel() { return {0, 0, 0}; }
YuvWhitePixel()113*89a0ef05SAndroid Build Coastguard Worker   Pixel YuvWhitePixel() { return {255, 0, 0}; }
114*89a0ef05SAndroid Build Coastguard Worker 
SrgbYuvRedPixel()115*89a0ef05SAndroid Build Coastguard Worker   Pixel SrgbYuvRedPixel() { return {54, -29, 128}; }
SrgbYuvGreenPixel()116*89a0ef05SAndroid Build Coastguard Worker   Pixel SrgbYuvGreenPixel() { return {182, -98, -116}; }
SrgbYuvBluePixel()117*89a0ef05SAndroid Build Coastguard Worker   Pixel SrgbYuvBluePixel() { return {18, 128, -12}; }
118*89a0ef05SAndroid Build Coastguard Worker 
P3YuvRedPixel()119*89a0ef05SAndroid Build Coastguard Worker   Pixel P3YuvRedPixel() { return {76, -43, 128}; }
P3YuvGreenPixel()120*89a0ef05SAndroid Build Coastguard Worker   Pixel P3YuvGreenPixel() { return {150, -84, -107}; }
P3YuvBluePixel()121*89a0ef05SAndroid Build Coastguard Worker   Pixel P3YuvBluePixel() { return {29, 128, -21}; }
122*89a0ef05SAndroid Build Coastguard Worker 
Bt2100YuvRedPixel()123*89a0ef05SAndroid Build Coastguard Worker   Pixel Bt2100YuvRedPixel() { return {67, -36, 128}; }
Bt2100YuvGreenPixel()124*89a0ef05SAndroid Build Coastguard Worker   Pixel Bt2100YuvGreenPixel() { return {173, -92, -117}; }
Bt2100YuvBluePixel()125*89a0ef05SAndroid Build Coastguard Worker   Pixel Bt2100YuvBluePixel() { return {15, 128, -10}; }
126*89a0ef05SAndroid Build Coastguard Worker 
SrgbYuvToLuminance(Color yuv_gamma,LuminanceFn luminanceFn)127*89a0ef05SAndroid Build Coastguard Worker   float SrgbYuvToLuminance(Color yuv_gamma, LuminanceFn luminanceFn) {
128*89a0ef05SAndroid Build Coastguard Worker     Color rgb_gamma = srgbYuvToRgb(yuv_gamma);
129*89a0ef05SAndroid Build Coastguard Worker     Color rgb = srgbInvOetf(rgb_gamma);
130*89a0ef05SAndroid Build Coastguard Worker     float luminance_scaled = luminanceFn(rgb);
131*89a0ef05SAndroid Build Coastguard Worker     return luminance_scaled * kSdrWhiteNits;
132*89a0ef05SAndroid Build Coastguard Worker   }
133*89a0ef05SAndroid Build Coastguard Worker 
P3YuvToLuminance(Color yuv_gamma,LuminanceFn luminanceFn)134*89a0ef05SAndroid Build Coastguard Worker   float P3YuvToLuminance(Color yuv_gamma, LuminanceFn luminanceFn) {
135*89a0ef05SAndroid Build Coastguard Worker     Color rgb_gamma = p3YuvToRgb(yuv_gamma);
136*89a0ef05SAndroid Build Coastguard Worker     Color rgb = srgbInvOetf(rgb_gamma);
137*89a0ef05SAndroid Build Coastguard Worker     float luminance_scaled = luminanceFn(rgb);
138*89a0ef05SAndroid Build Coastguard Worker     return luminance_scaled * kSdrWhiteNits;
139*89a0ef05SAndroid Build Coastguard Worker   }
140*89a0ef05SAndroid Build Coastguard Worker 
Bt2100YuvToLuminance(Color yuv_gamma,ColorTransformFn hdrInvOetf,ColorTransformFn gamutConversionFn,LuminanceFn luminanceFn,float scale_factor)141*89a0ef05SAndroid Build Coastguard Worker   float Bt2100YuvToLuminance(Color yuv_gamma, ColorTransformFn hdrInvOetf,
142*89a0ef05SAndroid Build Coastguard Worker                              ColorTransformFn gamutConversionFn, LuminanceFn luminanceFn,
143*89a0ef05SAndroid Build Coastguard Worker                              float scale_factor) {
144*89a0ef05SAndroid Build Coastguard Worker     Color rgb_gamma = bt2100YuvToRgb(yuv_gamma);
145*89a0ef05SAndroid Build Coastguard Worker     Color rgb = hdrInvOetf(rgb_gamma);
146*89a0ef05SAndroid Build Coastguard Worker     rgb = gamutConversionFn(rgb);
147*89a0ef05SAndroid Build Coastguard Worker     float luminance_scaled = luminanceFn(rgb);
148*89a0ef05SAndroid Build Coastguard Worker     return luminance_scaled * scale_factor;
149*89a0ef05SAndroid Build Coastguard Worker   }
150*89a0ef05SAndroid Build Coastguard Worker 
Recover(Color yuv_gamma,float gain,uhdr_gainmap_metadata_ext_t * metadata)151*89a0ef05SAndroid Build Coastguard Worker   Color Recover(Color yuv_gamma, float gain, uhdr_gainmap_metadata_ext_t* metadata) {
152*89a0ef05SAndroid Build Coastguard Worker     Color rgb_gamma = srgbYuvToRgb(yuv_gamma);
153*89a0ef05SAndroid Build Coastguard Worker     Color rgb = srgbInvOetf(rgb_gamma);
154*89a0ef05SAndroid Build Coastguard Worker     return applyGain(rgb, gain, metadata);
155*89a0ef05SAndroid Build Coastguard Worker   }
156*89a0ef05SAndroid Build Coastguard Worker 
Yuv420Image()157*89a0ef05SAndroid Build Coastguard Worker   uhdr_raw_image_t Yuv420Image() {
158*89a0ef05SAndroid Build Coastguard Worker     static uint8_t pixels[] = {
159*89a0ef05SAndroid Build Coastguard Worker         // Y
160*89a0ef05SAndroid Build Coastguard Worker         0x00,
161*89a0ef05SAndroid Build Coastguard Worker         0x10,
162*89a0ef05SAndroid Build Coastguard Worker         0x20,
163*89a0ef05SAndroid Build Coastguard Worker         0x30,
164*89a0ef05SAndroid Build Coastguard Worker         0x01,
165*89a0ef05SAndroid Build Coastguard Worker         0x11,
166*89a0ef05SAndroid Build Coastguard Worker         0x21,
167*89a0ef05SAndroid Build Coastguard Worker         0x31,
168*89a0ef05SAndroid Build Coastguard Worker         0x02,
169*89a0ef05SAndroid Build Coastguard Worker         0x12,
170*89a0ef05SAndroid Build Coastguard Worker         0x22,
171*89a0ef05SAndroid Build Coastguard Worker         0x32,
172*89a0ef05SAndroid Build Coastguard Worker         0x03,
173*89a0ef05SAndroid Build Coastguard Worker         0x13,
174*89a0ef05SAndroid Build Coastguard Worker         0x23,
175*89a0ef05SAndroid Build Coastguard Worker         0x33,
176*89a0ef05SAndroid Build Coastguard Worker         // U
177*89a0ef05SAndroid Build Coastguard Worker         0xA0,
178*89a0ef05SAndroid Build Coastguard Worker         0xA1,
179*89a0ef05SAndroid Build Coastguard Worker         0xA2,
180*89a0ef05SAndroid Build Coastguard Worker         0xA3,
181*89a0ef05SAndroid Build Coastguard Worker         // V
182*89a0ef05SAndroid Build Coastguard Worker         0xB0,
183*89a0ef05SAndroid Build Coastguard Worker         0xB1,
184*89a0ef05SAndroid Build Coastguard Worker         0xB2,
185*89a0ef05SAndroid Build Coastguard Worker         0xB3,
186*89a0ef05SAndroid Build Coastguard Worker     };
187*89a0ef05SAndroid Build Coastguard Worker     uhdr_raw_image_t img;
188*89a0ef05SAndroid Build Coastguard Worker     img.cg = UHDR_CG_BT_709;
189*89a0ef05SAndroid Build Coastguard Worker     img.ct = UHDR_CT_SRGB;
190*89a0ef05SAndroid Build Coastguard Worker     img.range = UHDR_CR_FULL_RANGE;
191*89a0ef05SAndroid Build Coastguard Worker     img.fmt = UHDR_IMG_FMT_12bppYCbCr420;
192*89a0ef05SAndroid Build Coastguard Worker     img.w = 4;
193*89a0ef05SAndroid Build Coastguard Worker     img.h = 4;
194*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_Y] = pixels;
195*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_U] = pixels + 16;
196*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_V] = pixels + 16 + 4;
197*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_Y] = 4;
198*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_U] = 2;
199*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_V] = 2;
200*89a0ef05SAndroid Build Coastguard Worker     return img;
201*89a0ef05SAndroid Build Coastguard Worker   }
202*89a0ef05SAndroid Build Coastguard Worker 
Yuv420Image32x4()203*89a0ef05SAndroid Build Coastguard Worker   uhdr_raw_image_t Yuv420Image32x4() {
204*89a0ef05SAndroid Build Coastguard Worker     // clang-format off
205*89a0ef05SAndroid Build Coastguard Worker     static uint8_t pixels[] = {
206*89a0ef05SAndroid Build Coastguard Worker     // Y
207*89a0ef05SAndroid Build Coastguard Worker     0x0, 0x10, 0x20, 0x30, 0x1, 0x11, 0x21, 0x31, 0x2, 0x12, 0x22, 0x32, 0x3, 0x13, 0x23, 0x33,
208*89a0ef05SAndroid Build Coastguard Worker     0x4, 0x14, 0x24, 0x34, 0x5, 0x15, 0x25, 0x35, 0x6, 0x16, 0x26, 0x36, 0x7, 0x17, 0x27, 0x37,
209*89a0ef05SAndroid Build Coastguard Worker     0x8, 0x18, 0x28, 0x38, 0x9, 0x19, 0x29, 0x39, 0xa, 0x1a, 0x2a, 0x3a, 0xb, 0x1b, 0x2b, 0x3b,
210*89a0ef05SAndroid Build Coastguard Worker     0xc, 0x1c, 0x2c, 0x3c, 0xd, 0x1d, 0x2d, 0x3d, 0xe, 0x1e, 0x2e, 0x3e, 0xf, 0x1f, 0x2f, 0x3f,
211*89a0ef05SAndroid Build Coastguard Worker     0x10, 0x20, 0x30, 0x40, 0x11, 0x21, 0x31, 0x41, 0x12, 0x22, 0x32, 0x42, 0x13, 0x23, 0x33, 0x43,
212*89a0ef05SAndroid Build Coastguard Worker     0x14, 0x24, 0x34, 0x44, 0x15, 0x25, 0x35, 0x45, 0x16, 0x26, 0x36, 0x46, 0x17, 0x27, 0x37, 0x47,
213*89a0ef05SAndroid Build Coastguard Worker     0x18, 0x28, 0x38, 0x48, 0x19, 0x29, 0x39, 0x49, 0x1a, 0x2a, 0x3a, 0x4a, 0x1b, 0x2b, 0x3b, 0x4b,
214*89a0ef05SAndroid Build Coastguard Worker     0x1c, 0x2c, 0x3c, 0x4c, 0x1d, 0x2d, 0x3d, 0x4d, 0x1e, 0x2e, 0x3e, 0x4e, 0x1f, 0x2f, 0x3f, 0x4f,
215*89a0ef05SAndroid Build Coastguard Worker     // U
216*89a0ef05SAndroid Build Coastguard Worker     0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
217*89a0ef05SAndroid Build Coastguard Worker     0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBB, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
218*89a0ef05SAndroid Build Coastguard Worker     // V
219*89a0ef05SAndroid Build Coastguard Worker     0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCC, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
220*89a0ef05SAndroid Build Coastguard Worker     0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDD, 0xDD, 0xDC, 0xDD, 0xDE, 0xDF,
221*89a0ef05SAndroid Build Coastguard Worker     };
222*89a0ef05SAndroid Build Coastguard Worker     // clang-format on
223*89a0ef05SAndroid Build Coastguard Worker     uhdr_raw_image_t img;
224*89a0ef05SAndroid Build Coastguard Worker     img.cg = UHDR_CG_BT_709;
225*89a0ef05SAndroid Build Coastguard Worker     img.ct = UHDR_CT_SRGB;
226*89a0ef05SAndroid Build Coastguard Worker     img.range = UHDR_CR_FULL_RANGE;
227*89a0ef05SAndroid Build Coastguard Worker     img.fmt = UHDR_IMG_FMT_12bppYCbCr420;
228*89a0ef05SAndroid Build Coastguard Worker     img.w = 32;
229*89a0ef05SAndroid Build Coastguard Worker     img.h = 4;
230*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_Y] = pixels;
231*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_U] = pixels + 128;
232*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_V] = pixels + 128 + 32;
233*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_Y] = 32;
234*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_U] = 16;
235*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_V] = 16;
236*89a0ef05SAndroid Build Coastguard Worker     return img;
237*89a0ef05SAndroid Build Coastguard Worker   }
238*89a0ef05SAndroid Build Coastguard Worker 
Yuv420Colors()239*89a0ef05SAndroid Build Coastguard Worker   Color (*Yuv420Colors())[4] {
240*89a0ef05SAndroid Build Coastguard Worker     static Color colors[4][4] = {
241*89a0ef05SAndroid Build Coastguard Worker         {
242*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x00, 0xA0, 0xB0),
243*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x10, 0xA0, 0xB0),
244*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x20, 0xA1, 0xB1),
245*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x30, 0xA1, 0xB1),
246*89a0ef05SAndroid Build Coastguard Worker         },
247*89a0ef05SAndroid Build Coastguard Worker         {
248*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x01, 0xA0, 0xB0),
249*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x11, 0xA0, 0xB0),
250*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x21, 0xA1, 0xB1),
251*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x31, 0xA1, 0xB1),
252*89a0ef05SAndroid Build Coastguard Worker         },
253*89a0ef05SAndroid Build Coastguard Worker         {
254*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x02, 0xA2, 0xB2),
255*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x12, 0xA2, 0xB2),
256*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x22, 0xA3, 0xB3),
257*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x32, 0xA3, 0xB3),
258*89a0ef05SAndroid Build Coastguard Worker         },
259*89a0ef05SAndroid Build Coastguard Worker         {
260*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x03, 0xA2, 0xB2),
261*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x13, 0xA2, 0xB2),
262*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x23, 0xA3, 0xB3),
263*89a0ef05SAndroid Build Coastguard Worker             Yuv420(0x33, 0xA3, 0xB3),
264*89a0ef05SAndroid Build Coastguard Worker         },
265*89a0ef05SAndroid Build Coastguard Worker     };
266*89a0ef05SAndroid Build Coastguard Worker     return colors;
267*89a0ef05SAndroid Build Coastguard Worker   }
268*89a0ef05SAndroid Build Coastguard Worker 
269*89a0ef05SAndroid Build Coastguard Worker   uhdr_raw_image_t P010Image() {
270*89a0ef05SAndroid Build Coastguard Worker     static uint16_t pixels[] = {
271*89a0ef05SAndroid Build Coastguard Worker         // Y
272*89a0ef05SAndroid Build Coastguard Worker         0x00 << 6,
273*89a0ef05SAndroid Build Coastguard Worker         0x10 << 6,
274*89a0ef05SAndroid Build Coastguard Worker         0x20 << 6,
275*89a0ef05SAndroid Build Coastguard Worker         0x30 << 6,
276*89a0ef05SAndroid Build Coastguard Worker         0x01 << 6,
277*89a0ef05SAndroid Build Coastguard Worker         0x11 << 6,
278*89a0ef05SAndroid Build Coastguard Worker         0x21 << 6,
279*89a0ef05SAndroid Build Coastguard Worker         0x31 << 6,
280*89a0ef05SAndroid Build Coastguard Worker         0x02 << 6,
281*89a0ef05SAndroid Build Coastguard Worker         0x12 << 6,
282*89a0ef05SAndroid Build Coastguard Worker         0x22 << 6,
283*89a0ef05SAndroid Build Coastguard Worker         0x32 << 6,
284*89a0ef05SAndroid Build Coastguard Worker         0x03 << 6,
285*89a0ef05SAndroid Build Coastguard Worker         0x13 << 6,
286*89a0ef05SAndroid Build Coastguard Worker         0x23 << 6,
287*89a0ef05SAndroid Build Coastguard Worker         0x33 << 6,
288*89a0ef05SAndroid Build Coastguard Worker         // UV
289*89a0ef05SAndroid Build Coastguard Worker         0xA0 << 6,
290*89a0ef05SAndroid Build Coastguard Worker         0xB0 << 6,
291*89a0ef05SAndroid Build Coastguard Worker         0xA1 << 6,
292*89a0ef05SAndroid Build Coastguard Worker         0xB1 << 6,
293*89a0ef05SAndroid Build Coastguard Worker         0xA2 << 6,
294*89a0ef05SAndroid Build Coastguard Worker         0xB2 << 6,
295*89a0ef05SAndroid Build Coastguard Worker         0xA3 << 6,
296*89a0ef05SAndroid Build Coastguard Worker         0xB3 << 6,
297*89a0ef05SAndroid Build Coastguard Worker     };
298*89a0ef05SAndroid Build Coastguard Worker     uhdr_raw_image_t img;
299*89a0ef05SAndroid Build Coastguard Worker     img.cg = UHDR_CG_BT_709;
300*89a0ef05SAndroid Build Coastguard Worker     img.ct = UHDR_CT_HLG;
301*89a0ef05SAndroid Build Coastguard Worker     img.range = UHDR_CR_LIMITED_RANGE;
302*89a0ef05SAndroid Build Coastguard Worker     img.fmt = UHDR_IMG_FMT_24bppYCbCrP010;
303*89a0ef05SAndroid Build Coastguard Worker     img.w = 4;
304*89a0ef05SAndroid Build Coastguard Worker     img.h = 4;
305*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_Y] = pixels;
306*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_UV] = pixels + 16;
307*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_V] = nullptr;
308*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_Y] = 4;
309*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_UV] = 4;
310*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_V] = 0;
311*89a0ef05SAndroid Build Coastguard Worker     return img;
312*89a0ef05SAndroid Build Coastguard Worker   }
313*89a0ef05SAndroid Build Coastguard Worker 
__anon7bd5a46c0202null314*89a0ef05SAndroid Build Coastguard Worker   Color (*P010Colors())[4] {
315*89a0ef05SAndroid Build Coastguard Worker     static Color colors[4][4] = {
316*89a0ef05SAndroid Build Coastguard Worker         {
317*89a0ef05SAndroid Build Coastguard Worker             P010(0x00, 0xA0, 0xB0),
318*89a0ef05SAndroid Build Coastguard Worker             P010(0x10, 0xA0, 0xB0),
319*89a0ef05SAndroid Build Coastguard Worker             P010(0x20, 0xA1, 0xB1),
320*89a0ef05SAndroid Build Coastguard Worker             P010(0x30, 0xA1, 0xB1),
321*89a0ef05SAndroid Build Coastguard Worker         },
322*89a0ef05SAndroid Build Coastguard Worker         {
323*89a0ef05SAndroid Build Coastguard Worker             P010(0x01, 0xA0, 0xB0),
324*89a0ef05SAndroid Build Coastguard Worker             P010(0x11, 0xA0, 0xB0),
325*89a0ef05SAndroid Build Coastguard Worker             P010(0x21, 0xA1, 0xB1),
326*89a0ef05SAndroid Build Coastguard Worker             P010(0x31, 0xA1, 0xB1),
327*89a0ef05SAndroid Build Coastguard Worker         },
328*89a0ef05SAndroid Build Coastguard Worker         {
329*89a0ef05SAndroid Build Coastguard Worker             P010(0x02, 0xA2, 0xB2),
330*89a0ef05SAndroid Build Coastguard Worker             P010(0x12, 0xA2, 0xB2),
331*89a0ef05SAndroid Build Coastguard Worker             P010(0x22, 0xA3, 0xB3),
332*89a0ef05SAndroid Build Coastguard Worker             P010(0x32, 0xA3, 0xB3),
333*89a0ef05SAndroid Build Coastguard Worker         },
334*89a0ef05SAndroid Build Coastguard Worker         {
335*89a0ef05SAndroid Build Coastguard Worker             P010(0x03, 0xA2, 0xB2),
336*89a0ef05SAndroid Build Coastguard Worker             P010(0x13, 0xA2, 0xB2),
337*89a0ef05SAndroid Build Coastguard Worker             P010(0x23, 0xA3, 0xB3),
338*89a0ef05SAndroid Build Coastguard Worker             P010(0x33, 0xA3, 0xB3),
339*89a0ef05SAndroid Build Coastguard Worker         },
340*89a0ef05SAndroid Build Coastguard Worker     };
341*89a0ef05SAndroid Build Coastguard Worker     return colors;
342*89a0ef05SAndroid Build Coastguard Worker   }
343*89a0ef05SAndroid Build Coastguard Worker 
344*89a0ef05SAndroid Build Coastguard Worker   uhdr_raw_image_t MapImage() {
345*89a0ef05SAndroid Build Coastguard Worker     static uint8_t pixels[] = {
346*89a0ef05SAndroid Build Coastguard Worker         0x00, 0x10, 0x20, 0x30, 0x01, 0x11, 0x21, 0x31,
347*89a0ef05SAndroid Build Coastguard Worker         0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33,
348*89a0ef05SAndroid Build Coastguard Worker     };
349*89a0ef05SAndroid Build Coastguard Worker 
350*89a0ef05SAndroid Build Coastguard Worker     uhdr_raw_image_t img;
351*89a0ef05SAndroid Build Coastguard Worker     img.cg = UHDR_CG_UNSPECIFIED;
352*89a0ef05SAndroid Build Coastguard Worker     img.ct = UHDR_CT_UNSPECIFIED;
353*89a0ef05SAndroid Build Coastguard Worker     img.range = UHDR_CR_UNSPECIFIED;
354*89a0ef05SAndroid Build Coastguard Worker     img.fmt = UHDR_IMG_FMT_8bppYCbCr400;
355*89a0ef05SAndroid Build Coastguard Worker     img.w = 4;
356*89a0ef05SAndroid Build Coastguard Worker     img.h = 4;
357*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_Y] = pixels;
358*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_U] = nullptr;
359*89a0ef05SAndroid Build Coastguard Worker     img.planes[UHDR_PLANE_V] = nullptr;
360*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_Y] = 4;
361*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_U] = 0;
362*89a0ef05SAndroid Build Coastguard Worker     img.stride[UHDR_PLANE_V] = 0;
363*89a0ef05SAndroid Build Coastguard Worker     return img;
364*89a0ef05SAndroid Build Coastguard Worker   }
365*89a0ef05SAndroid Build Coastguard Worker 
__anon7bd5a46c0302null366*89a0ef05SAndroid Build Coastguard Worker   float (*MapValues())[4] {
367*89a0ef05SAndroid Build Coastguard Worker     static float values[4][4] = {
368*89a0ef05SAndroid Build Coastguard Worker         {
369*89a0ef05SAndroid Build Coastguard Worker             Map(0x00),
370*89a0ef05SAndroid Build Coastguard Worker             Map(0x10),
371*89a0ef05SAndroid Build Coastguard Worker             Map(0x20),
372*89a0ef05SAndroid Build Coastguard Worker             Map(0x30),
373*89a0ef05SAndroid Build Coastguard Worker         },
374*89a0ef05SAndroid Build Coastguard Worker         {
375*89a0ef05SAndroid Build Coastguard Worker             Map(0x01),
376*89a0ef05SAndroid Build Coastguard Worker             Map(0x11),
377*89a0ef05SAndroid Build Coastguard Worker             Map(0x21),
378*89a0ef05SAndroid Build Coastguard Worker             Map(0x31),
379*89a0ef05SAndroid Build Coastguard Worker         },
380*89a0ef05SAndroid Build Coastguard Worker         {
381*89a0ef05SAndroid Build Coastguard Worker             Map(0x02),
382*89a0ef05SAndroid Build Coastguard Worker             Map(0x12),
383*89a0ef05SAndroid Build Coastguard Worker             Map(0x22),
384*89a0ef05SAndroid Build Coastguard Worker             Map(0x32),
385*89a0ef05SAndroid Build Coastguard Worker         },
386*89a0ef05SAndroid Build Coastguard Worker         {
387*89a0ef05SAndroid Build Coastguard Worker             Map(0x03),
388*89a0ef05SAndroid Build Coastguard Worker             Map(0x13),
389*89a0ef05SAndroid Build Coastguard Worker             Map(0x23),
390*89a0ef05SAndroid Build Coastguard Worker             Map(0x33),
391*89a0ef05SAndroid Build Coastguard Worker         },
392*89a0ef05SAndroid Build Coastguard Worker     };
393*89a0ef05SAndroid Build Coastguard Worker     return values;
394*89a0ef05SAndroid Build Coastguard Worker   }
395*89a0ef05SAndroid Build Coastguard Worker 
396*89a0ef05SAndroid Build Coastguard Worker  protected:
397*89a0ef05SAndroid Build Coastguard Worker   virtual void SetUp();
398*89a0ef05SAndroid Build Coastguard Worker   virtual void TearDown();
399*89a0ef05SAndroid Build Coastguard Worker };
400*89a0ef05SAndroid Build Coastguard Worker 
GainMapMathTest()401*89a0ef05SAndroid Build Coastguard Worker GainMapMathTest::GainMapMathTest() {}
~GainMapMathTest()402*89a0ef05SAndroid Build Coastguard Worker GainMapMathTest::~GainMapMathTest() {}
403*89a0ef05SAndroid Build Coastguard Worker 
SetUp()404*89a0ef05SAndroid Build Coastguard Worker void GainMapMathTest::SetUp() {}
TearDown()405*89a0ef05SAndroid Build Coastguard Worker void GainMapMathTest::TearDown() {}
406*89a0ef05SAndroid Build Coastguard Worker 
407*89a0ef05SAndroid Build Coastguard Worker #define EXPECT_RGB_EQ(e1, e2)      \
408*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ((e1).r, (e2).r); \
409*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ((e1).g, (e2).g); \
410*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ((e1).b, (e2).b)
411*89a0ef05SAndroid Build Coastguard Worker 
412*89a0ef05SAndroid Build Coastguard Worker #define EXPECT_RGB_NEAR(e1, e2)                     \
413*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR((e1).r, (e2).r, ComparisonEpsilon()); \
414*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR((e1).g, (e2).g, ComparisonEpsilon()); \
415*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR((e1).b, (e2).b, ComparisonEpsilon())
416*89a0ef05SAndroid Build Coastguard Worker 
417*89a0ef05SAndroid Build Coastguard Worker #define EXPECT_RGB_CLOSE(e1, e2)                            \
418*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR((e1).r, (e2).r, ComparisonEpsilon() * 10.0f); \
419*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR((e1).g, (e2).g, ComparisonEpsilon() * 10.0f); \
420*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR((e1).b, (e2).b, ComparisonEpsilon() * 10.0f)
421*89a0ef05SAndroid Build Coastguard Worker 
422*89a0ef05SAndroid Build Coastguard Worker #define EXPECT_YUV_EQ(e1, e2)      \
423*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ((e1).y, (e2).y); \
424*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ((e1).u, (e2).u); \
425*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ((e1).v, (e2).v)
426*89a0ef05SAndroid Build Coastguard Worker 
427*89a0ef05SAndroid Build Coastguard Worker #define EXPECT_YUV_NEAR(e1, e2)                     \
428*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR((e1).y, (e2).y, ComparisonEpsilon()); \
429*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR((e1).u, (e2).u, ComparisonEpsilon()); \
430*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR((e1).v, (e2).v, ComparisonEpsilon())
431*89a0ef05SAndroid Build Coastguard Worker 
432*89a0ef05SAndroid Build Coastguard Worker // Due to -ffp-contract=fast being enabled by default with GCC, allow some
433*89a0ef05SAndroid Build Coastguard Worker // margin when comparing fused and unfused floating-point operations.
434*89a0ef05SAndroid Build Coastguard Worker #define EXPECT_YUV_BETWEEN(e, min, max)                                           \
435*89a0ef05SAndroid Build Coastguard Worker   EXPECT_THAT((e).y, testing::AllOf(testing::Ge((min).y - ComparisonEpsilon()),   \
436*89a0ef05SAndroid Build Coastguard Worker                                     testing::Le((max).y + ComparisonEpsilon()))); \
437*89a0ef05SAndroid Build Coastguard Worker   EXPECT_THAT((e).u, testing::AllOf(testing::Ge((min).u - ComparisonEpsilon()),   \
438*89a0ef05SAndroid Build Coastguard Worker                                     testing::Le((max).u + ComparisonEpsilon()))); \
439*89a0ef05SAndroid Build Coastguard Worker   EXPECT_THAT((e).v, testing::AllOf(testing::Ge((min).v - ComparisonEpsilon()),   \
440*89a0ef05SAndroid Build Coastguard Worker                                     testing::Le((max).v + ComparisonEpsilon())))
441*89a0ef05SAndroid Build Coastguard Worker 
442*89a0ef05SAndroid Build Coastguard Worker // TODO: a bunch of these tests can be parameterized.
443*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ColorConstruct)444*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ColorConstruct) {
445*89a0ef05SAndroid Build Coastguard Worker   Color e1 = {{{0.1f, 0.2f, 0.3f}}};
446*89a0ef05SAndroid Build Coastguard Worker 
447*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e1.r, 0.1f);
448*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e1.g, 0.2f);
449*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e1.b, 0.3f);
450*89a0ef05SAndroid Build Coastguard Worker 
451*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e1.y, 0.1f);
452*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e1.u, 0.2f);
453*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e1.v, 0.3f);
454*89a0ef05SAndroid Build Coastguard Worker }
455*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ColorAddColor)456*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ColorAddColor) {
457*89a0ef05SAndroid Build Coastguard Worker   Color e1 = {{{0.1f, 0.2f, 0.3f}}};
458*89a0ef05SAndroid Build Coastguard Worker 
459*89a0ef05SAndroid Build Coastguard Worker   Color e2 = e1 + e1;
460*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, e1.r * 2.0f);
461*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, e1.g * 2.0f);
462*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, e1.b * 2.0f);
463*89a0ef05SAndroid Build Coastguard Worker 
464*89a0ef05SAndroid Build Coastguard Worker   e2 += e1;
465*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, e1.r * 3.0f);
466*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, e1.g * 3.0f);
467*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, e1.b * 3.0f);
468*89a0ef05SAndroid Build Coastguard Worker }
469*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ColorAddFloat)470*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ColorAddFloat) {
471*89a0ef05SAndroid Build Coastguard Worker   Color e1 = {{{0.1f, 0.2f, 0.3f}}};
472*89a0ef05SAndroid Build Coastguard Worker 
473*89a0ef05SAndroid Build Coastguard Worker   Color e2 = e1 + 0.1f;
474*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, e1.r + 0.1f);
475*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, e1.g + 0.1f);
476*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, e1.b + 0.1f);
477*89a0ef05SAndroid Build Coastguard Worker 
478*89a0ef05SAndroid Build Coastguard Worker   e2 += 0.1f;
479*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, e1.r + 0.2f);
480*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, e1.g + 0.2f);
481*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, e1.b + 0.2f);
482*89a0ef05SAndroid Build Coastguard Worker }
483*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ColorSubtractColor)484*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ColorSubtractColor) {
485*89a0ef05SAndroid Build Coastguard Worker   Color e1 = {{{0.1f, 0.2f, 0.3f}}};
486*89a0ef05SAndroid Build Coastguard Worker 
487*89a0ef05SAndroid Build Coastguard Worker   Color e2 = e1 - e1;
488*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, 0.0f);
489*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, 0.0f);
490*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, 0.0f);
491*89a0ef05SAndroid Build Coastguard Worker 
492*89a0ef05SAndroid Build Coastguard Worker   e2 -= e1;
493*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, -e1.r);
494*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, -e1.g);
495*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, -e1.b);
496*89a0ef05SAndroid Build Coastguard Worker }
497*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ColorSubtractFloat)498*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ColorSubtractFloat) {
499*89a0ef05SAndroid Build Coastguard Worker   Color e1 = {{{0.1f, 0.2f, 0.3f}}};
500*89a0ef05SAndroid Build Coastguard Worker 
501*89a0ef05SAndroid Build Coastguard Worker   Color e2 = e1 - 0.1f;
502*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, e1.r - 0.1f);
503*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, e1.g - 0.1f);
504*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, e1.b - 0.1f);
505*89a0ef05SAndroid Build Coastguard Worker 
506*89a0ef05SAndroid Build Coastguard Worker   e2 -= 0.1f;
507*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, e1.r - 0.2f);
508*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, e1.g - 0.2f);
509*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, e1.b - 0.2f);
510*89a0ef05SAndroid Build Coastguard Worker }
511*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ColorMultiplyFloat)512*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ColorMultiplyFloat) {
513*89a0ef05SAndroid Build Coastguard Worker   Color e1 = {{{0.1f, 0.2f, 0.3f}}};
514*89a0ef05SAndroid Build Coastguard Worker 
515*89a0ef05SAndroid Build Coastguard Worker   Color e2 = e1 * 2.0f;
516*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, e1.r * 2.0f);
517*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, e1.g * 2.0f);
518*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, e1.b * 2.0f);
519*89a0ef05SAndroid Build Coastguard Worker 
520*89a0ef05SAndroid Build Coastguard Worker   e2 *= 2.0f;
521*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, e1.r * 4.0f);
522*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, e1.g * 4.0f);
523*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, e1.b * 4.0f);
524*89a0ef05SAndroid Build Coastguard Worker }
525*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ColorDivideFloat)526*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ColorDivideFloat) {
527*89a0ef05SAndroid Build Coastguard Worker   Color e1 = {{{0.1f, 0.2f, 0.3f}}};
528*89a0ef05SAndroid Build Coastguard Worker 
529*89a0ef05SAndroid Build Coastguard Worker   Color e2 = e1 / 2.0f;
530*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, e1.r / 2.0f);
531*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, e1.g / 2.0f);
532*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, e1.b / 2.0f);
533*89a0ef05SAndroid Build Coastguard Worker 
534*89a0ef05SAndroid Build Coastguard Worker   e2 /= 2.0f;
535*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.r, e1.r / 4.0f);
536*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.g, e1.g / 4.0f);
537*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(e2.b, e1.b / 4.0f);
538*89a0ef05SAndroid Build Coastguard Worker }
539*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,SrgbLuminance)540*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, SrgbLuminance) {
541*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(srgbLuminance(RgbBlack()), 0.0f);
542*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(srgbLuminance(RgbWhite()), 1.0f);
543*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(srgbLuminance(RgbRed()), 0.2126f);
544*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(srgbLuminance(RgbGreen()), 0.7152f);
545*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(srgbLuminance(RgbBlue()), 0.0722f);
546*89a0ef05SAndroid Build Coastguard Worker }
547*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,SrgbYuvToRgb)548*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, SrgbYuvToRgb) {
549*89a0ef05SAndroid Build Coastguard Worker   Color rgb_black = srgbYuvToRgb(YuvBlack());
550*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_black, RgbBlack());
551*89a0ef05SAndroid Build Coastguard Worker 
552*89a0ef05SAndroid Build Coastguard Worker   Color rgb_white = srgbYuvToRgb(YuvWhite());
553*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_white, RgbWhite());
554*89a0ef05SAndroid Build Coastguard Worker 
555*89a0ef05SAndroid Build Coastguard Worker   Color rgb_r = srgbYuvToRgb(SrgbYuvRed());
556*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_r, RgbRed());
557*89a0ef05SAndroid Build Coastguard Worker 
558*89a0ef05SAndroid Build Coastguard Worker   Color rgb_g = srgbYuvToRgb(SrgbYuvGreen());
559*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_g, RgbGreen());
560*89a0ef05SAndroid Build Coastguard Worker 
561*89a0ef05SAndroid Build Coastguard Worker   Color rgb_b = srgbYuvToRgb(SrgbYuvBlue());
562*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_b, RgbBlue());
563*89a0ef05SAndroid Build Coastguard Worker }
564*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,SrgbRgbToYuv)565*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, SrgbRgbToYuv) {
566*89a0ef05SAndroid Build Coastguard Worker   Color yuv_black = srgbRgbToYuv(RgbBlack());
567*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_black, YuvBlack());
568*89a0ef05SAndroid Build Coastguard Worker 
569*89a0ef05SAndroid Build Coastguard Worker   Color yuv_white = srgbRgbToYuv(RgbWhite());
570*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_white, YuvWhite());
571*89a0ef05SAndroid Build Coastguard Worker 
572*89a0ef05SAndroid Build Coastguard Worker   Color yuv_r = srgbRgbToYuv(RgbRed());
573*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_r, SrgbYuvRed());
574*89a0ef05SAndroid Build Coastguard Worker 
575*89a0ef05SAndroid Build Coastguard Worker   Color yuv_g = srgbRgbToYuv(RgbGreen());
576*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_g, SrgbYuvGreen());
577*89a0ef05SAndroid Build Coastguard Worker 
578*89a0ef05SAndroid Build Coastguard Worker   Color yuv_b = srgbRgbToYuv(RgbBlue());
579*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_b, SrgbYuvBlue());
580*89a0ef05SAndroid Build Coastguard Worker }
581*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,SrgbRgbYuvRoundtrip)582*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, SrgbRgbYuvRoundtrip) {
583*89a0ef05SAndroid Build Coastguard Worker   Color rgb_black = srgbYuvToRgb(srgbRgbToYuv(RgbBlack()));
584*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_black, RgbBlack());
585*89a0ef05SAndroid Build Coastguard Worker 
586*89a0ef05SAndroid Build Coastguard Worker   Color rgb_white = srgbYuvToRgb(srgbRgbToYuv(RgbWhite()));
587*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_white, RgbWhite());
588*89a0ef05SAndroid Build Coastguard Worker 
589*89a0ef05SAndroid Build Coastguard Worker   Color rgb_r = srgbYuvToRgb(srgbRgbToYuv(RgbRed()));
590*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_r, RgbRed());
591*89a0ef05SAndroid Build Coastguard Worker 
592*89a0ef05SAndroid Build Coastguard Worker   Color rgb_g = srgbYuvToRgb(srgbRgbToYuv(RgbGreen()));
593*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_g, RgbGreen());
594*89a0ef05SAndroid Build Coastguard Worker 
595*89a0ef05SAndroid Build Coastguard Worker   Color rgb_b = srgbYuvToRgb(srgbRgbToYuv(RgbBlue()));
596*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_b, RgbBlue());
597*89a0ef05SAndroid Build Coastguard Worker }
598*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,SrgbTransferFunction)599*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, SrgbTransferFunction) {
600*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(srgbInvOetf(0.0f), 0.0f);
601*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(srgbInvOetf(0.02f), 0.00154f, ComparisonEpsilon());
602*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(srgbInvOetf(0.04045f), 0.00313f, ComparisonEpsilon());
603*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(srgbInvOetf(0.5f), 0.21404f, ComparisonEpsilon());
604*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(srgbInvOetf(1.0f), 1.0f);
605*89a0ef05SAndroid Build Coastguard Worker }
606*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,P3Luminance)607*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, P3Luminance) {
608*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(p3Luminance(RgbBlack()), 0.0f);
609*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(p3Luminance(RgbWhite()), 1.0f);
610*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(p3Luminance(RgbRed()), 0.20949f);
611*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(p3Luminance(RgbGreen()), 0.72160f);
612*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(p3Luminance(RgbBlue()), 0.06891f);
613*89a0ef05SAndroid Build Coastguard Worker }
614*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,P3YuvToRgb)615*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, P3YuvToRgb) {
616*89a0ef05SAndroid Build Coastguard Worker   Color rgb_black = p3YuvToRgb(YuvBlack());
617*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_black, RgbBlack());
618*89a0ef05SAndroid Build Coastguard Worker 
619*89a0ef05SAndroid Build Coastguard Worker   Color rgb_white = p3YuvToRgb(YuvWhite());
620*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_white, RgbWhite());
621*89a0ef05SAndroid Build Coastguard Worker 
622*89a0ef05SAndroid Build Coastguard Worker   Color rgb_r = p3YuvToRgb(P3YuvRed());
623*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_r, RgbRed());
624*89a0ef05SAndroid Build Coastguard Worker 
625*89a0ef05SAndroid Build Coastguard Worker   Color rgb_g = p3YuvToRgb(P3YuvGreen());
626*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_g, RgbGreen());
627*89a0ef05SAndroid Build Coastguard Worker 
628*89a0ef05SAndroid Build Coastguard Worker   Color rgb_b = p3YuvToRgb(P3YuvBlue());
629*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_b, RgbBlue());
630*89a0ef05SAndroid Build Coastguard Worker }
631*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,P3RgbToYuv)632*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, P3RgbToYuv) {
633*89a0ef05SAndroid Build Coastguard Worker   Color yuv_black = p3RgbToYuv(RgbBlack());
634*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_black, YuvBlack());
635*89a0ef05SAndroid Build Coastguard Worker 
636*89a0ef05SAndroid Build Coastguard Worker   Color yuv_white = p3RgbToYuv(RgbWhite());
637*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_white, YuvWhite());
638*89a0ef05SAndroid Build Coastguard Worker 
639*89a0ef05SAndroid Build Coastguard Worker   Color yuv_r = p3RgbToYuv(RgbRed());
640*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_r, P3YuvRed());
641*89a0ef05SAndroid Build Coastguard Worker 
642*89a0ef05SAndroid Build Coastguard Worker   Color yuv_g = p3RgbToYuv(RgbGreen());
643*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_g, P3YuvGreen());
644*89a0ef05SAndroid Build Coastguard Worker 
645*89a0ef05SAndroid Build Coastguard Worker   Color yuv_b = p3RgbToYuv(RgbBlue());
646*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_b, P3YuvBlue());
647*89a0ef05SAndroid Build Coastguard Worker }
648*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,P3RgbYuvRoundtrip)649*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, P3RgbYuvRoundtrip) {
650*89a0ef05SAndroid Build Coastguard Worker   Color rgb_black = p3YuvToRgb(p3RgbToYuv(RgbBlack()));
651*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_black, RgbBlack());
652*89a0ef05SAndroid Build Coastguard Worker 
653*89a0ef05SAndroid Build Coastguard Worker   Color rgb_white = p3YuvToRgb(p3RgbToYuv(RgbWhite()));
654*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_white, RgbWhite());
655*89a0ef05SAndroid Build Coastguard Worker 
656*89a0ef05SAndroid Build Coastguard Worker   Color rgb_r = p3YuvToRgb(p3RgbToYuv(RgbRed()));
657*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_r, RgbRed());
658*89a0ef05SAndroid Build Coastguard Worker 
659*89a0ef05SAndroid Build Coastguard Worker   Color rgb_g = p3YuvToRgb(p3RgbToYuv(RgbGreen()));
660*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_g, RgbGreen());
661*89a0ef05SAndroid Build Coastguard Worker 
662*89a0ef05SAndroid Build Coastguard Worker   Color rgb_b = p3YuvToRgb(p3RgbToYuv(RgbBlue()));
663*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_b, RgbBlue());
664*89a0ef05SAndroid Build Coastguard Worker }
TEST_F(GainMapMathTest,Bt2100Luminance)665*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, Bt2100Luminance) {
666*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(bt2100Luminance(RgbBlack()), 0.0f);
667*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(bt2100Luminance(RgbWhite()), 1.0f);
668*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(bt2100Luminance(RgbRed()), 0.2627f);
669*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(bt2100Luminance(RgbGreen()), 0.6780f);
670*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(bt2100Luminance(RgbBlue()), 0.0593f);
671*89a0ef05SAndroid Build Coastguard Worker }
672*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,Bt2100YuvToRgb)673*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, Bt2100YuvToRgb) {
674*89a0ef05SAndroid Build Coastguard Worker   Color rgb_black = bt2100YuvToRgb(YuvBlack());
675*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_black, RgbBlack());
676*89a0ef05SAndroid Build Coastguard Worker 
677*89a0ef05SAndroid Build Coastguard Worker   Color rgb_white = bt2100YuvToRgb(YuvWhite());
678*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_white, RgbWhite());
679*89a0ef05SAndroid Build Coastguard Worker 
680*89a0ef05SAndroid Build Coastguard Worker   Color rgb_r = bt2100YuvToRgb(Bt2100YuvRed());
681*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_r, RgbRed());
682*89a0ef05SAndroid Build Coastguard Worker 
683*89a0ef05SAndroid Build Coastguard Worker   Color rgb_g = bt2100YuvToRgb(Bt2100YuvGreen());
684*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_g, RgbGreen());
685*89a0ef05SAndroid Build Coastguard Worker 
686*89a0ef05SAndroid Build Coastguard Worker   Color rgb_b = bt2100YuvToRgb(Bt2100YuvBlue());
687*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_b, RgbBlue());
688*89a0ef05SAndroid Build Coastguard Worker }
689*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,Bt2100RgbToYuv)690*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, Bt2100RgbToYuv) {
691*89a0ef05SAndroid Build Coastguard Worker   Color yuv_black = bt2100RgbToYuv(RgbBlack());
692*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_black, YuvBlack());
693*89a0ef05SAndroid Build Coastguard Worker 
694*89a0ef05SAndroid Build Coastguard Worker   Color yuv_white = bt2100RgbToYuv(RgbWhite());
695*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_white, YuvWhite());
696*89a0ef05SAndroid Build Coastguard Worker 
697*89a0ef05SAndroid Build Coastguard Worker   Color yuv_r = bt2100RgbToYuv(RgbRed());
698*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_r, Bt2100YuvRed());
699*89a0ef05SAndroid Build Coastguard Worker 
700*89a0ef05SAndroid Build Coastguard Worker   Color yuv_g = bt2100RgbToYuv(RgbGreen());
701*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_g, Bt2100YuvGreen());
702*89a0ef05SAndroid Build Coastguard Worker 
703*89a0ef05SAndroid Build Coastguard Worker   Color yuv_b = bt2100RgbToYuv(RgbBlue());
704*89a0ef05SAndroid Build Coastguard Worker   EXPECT_YUV_NEAR(yuv_b, Bt2100YuvBlue());
705*89a0ef05SAndroid Build Coastguard Worker }
706*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,Bt2100RgbYuvRoundtrip)707*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, Bt2100RgbYuvRoundtrip) {
708*89a0ef05SAndroid Build Coastguard Worker   Color rgb_black = bt2100YuvToRgb(bt2100RgbToYuv(RgbBlack()));
709*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_black, RgbBlack());
710*89a0ef05SAndroid Build Coastguard Worker 
711*89a0ef05SAndroid Build Coastguard Worker   Color rgb_white = bt2100YuvToRgb(bt2100RgbToYuv(RgbWhite()));
712*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_white, RgbWhite());
713*89a0ef05SAndroid Build Coastguard Worker 
714*89a0ef05SAndroid Build Coastguard Worker   Color rgb_r = bt2100YuvToRgb(bt2100RgbToYuv(RgbRed()));
715*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_r, RgbRed());
716*89a0ef05SAndroid Build Coastguard Worker 
717*89a0ef05SAndroid Build Coastguard Worker   Color rgb_g = bt2100YuvToRgb(bt2100RgbToYuv(RgbGreen()));
718*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_g, RgbGreen());
719*89a0ef05SAndroid Build Coastguard Worker 
720*89a0ef05SAndroid Build Coastguard Worker   Color rgb_b = bt2100YuvToRgb(bt2100RgbToYuv(RgbBlue()));
721*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(rgb_b, RgbBlue());
722*89a0ef05SAndroid Build Coastguard Worker }
723*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,YuvColorGamutConversion)724*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, YuvColorGamutConversion) {
725*89a0ef05SAndroid Build Coastguard Worker   const std::array<Color, 5> SrgbYuvColors{YuvBlack(), YuvWhite(), SrgbYuvRed(), SrgbYuvGreen(),
726*89a0ef05SAndroid Build Coastguard Worker                                            SrgbYuvBlue()};
727*89a0ef05SAndroid Build Coastguard Worker 
728*89a0ef05SAndroid Build Coastguard Worker   const std::array<Color, 5> P3YuvColors{YuvBlack(), YuvWhite(), P3YuvRed(), P3YuvGreen(),
729*89a0ef05SAndroid Build Coastguard Worker                                          P3YuvBlue()};
730*89a0ef05SAndroid Build Coastguard Worker 
731*89a0ef05SAndroid Build Coastguard Worker   const std::array<Color, 5> Bt2100YuvColors{YuvBlack(), YuvWhite(), Bt2100YuvRed(),
732*89a0ef05SAndroid Build Coastguard Worker                                              Bt2100YuvGreen(), Bt2100YuvBlue()};
733*89a0ef05SAndroid Build Coastguard Worker   /*
734*89a0ef05SAndroid Build Coastguard Worker    * Each tuple contains three elements.
735*89a0ef05SAndroid Build Coastguard Worker    * 0. An array containing 9 coefficients needed to perform the color gamut conversion
736*89a0ef05SAndroid Build Coastguard Worker    * 1. Array of colors to be used as test input
737*89a0ef05SAndroid Build Coastguard Worker    * 2. Array of colors to used as reference output
738*89a0ef05SAndroid Build Coastguard Worker    */
739*89a0ef05SAndroid Build Coastguard Worker   const std::array<std::tuple<const std::array<float, 9>&, const std::array<Color, 5>,
740*89a0ef05SAndroid Build Coastguard Worker                               const std::array<Color, 5>>,
741*89a0ef05SAndroid Build Coastguard Worker                    6>
742*89a0ef05SAndroid Build Coastguard Worker       coeffs_setup_expected{{
743*89a0ef05SAndroid Build Coastguard Worker           {kYuvBt709ToBt601, SrgbYuvColors, P3YuvColors},
744*89a0ef05SAndroid Build Coastguard Worker           {kYuvBt709ToBt2100, SrgbYuvColors, Bt2100YuvColors},
745*89a0ef05SAndroid Build Coastguard Worker           {kYuvBt601ToBt709, P3YuvColors, SrgbYuvColors},
746*89a0ef05SAndroid Build Coastguard Worker           {kYuvBt601ToBt2100, P3YuvColors, Bt2100YuvColors},
747*89a0ef05SAndroid Build Coastguard Worker           {kYuvBt2100ToBt709, Bt2100YuvColors, SrgbYuvColors},
748*89a0ef05SAndroid Build Coastguard Worker           {kYuvBt2100ToBt601, Bt2100YuvColors, P3YuvColors},
749*89a0ef05SAndroid Build Coastguard Worker       }};
750*89a0ef05SAndroid Build Coastguard Worker 
751*89a0ef05SAndroid Build Coastguard Worker   for (const auto& [coeffs, input, expected] : coeffs_setup_expected) {
752*89a0ef05SAndroid Build Coastguard Worker     for (size_t color_idx = 0; color_idx < SrgbYuvColors.size(); ++color_idx) {
753*89a0ef05SAndroid Build Coastguard Worker       const Color input_color = input.at(color_idx);
754*89a0ef05SAndroid Build Coastguard Worker       const Color output_color = yuvColorGamutConversion(input_color, coeffs);
755*89a0ef05SAndroid Build Coastguard Worker 
756*89a0ef05SAndroid Build Coastguard Worker       EXPECT_YUV_NEAR(expected.at(color_idx), output_color);
757*89a0ef05SAndroid Build Coastguard Worker     }
758*89a0ef05SAndroid Build Coastguard Worker   }
759*89a0ef05SAndroid Build Coastguard Worker }
760*89a0ef05SAndroid Build Coastguard Worker 
761*89a0ef05SAndroid Build Coastguard Worker #if (defined(UHDR_ENABLE_INTRINSICS) && (defined(__ARM_NEON__) || defined(__ARM_NEON)))
TEST_F(GainMapMathTest,YuvConversionNeon)762*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, YuvConversionNeon) {
763*89a0ef05SAndroid Build Coastguard Worker   const std::array<Pixel, 5> SrgbYuvColors{YuvBlackPixel(), YuvWhitePixel(), SrgbYuvRedPixel(),
764*89a0ef05SAndroid Build Coastguard Worker                                            SrgbYuvGreenPixel(), SrgbYuvBluePixel()};
765*89a0ef05SAndroid Build Coastguard Worker 
766*89a0ef05SAndroid Build Coastguard Worker   const std::array<Pixel, 5> P3YuvColors{YuvBlackPixel(), YuvWhitePixel(), P3YuvRedPixel(),
767*89a0ef05SAndroid Build Coastguard Worker                                          P3YuvGreenPixel(), P3YuvBluePixel()};
768*89a0ef05SAndroid Build Coastguard Worker 
769*89a0ef05SAndroid Build Coastguard Worker   const std::array<Pixel, 5> Bt2100YuvColors{YuvBlackPixel(), YuvWhitePixel(), Bt2100YuvRedPixel(),
770*89a0ef05SAndroid Build Coastguard Worker                                              Bt2100YuvGreenPixel(), Bt2100YuvBluePixel()};
771*89a0ef05SAndroid Build Coastguard Worker 
772*89a0ef05SAndroid Build Coastguard Worker   struct InputSamples {
773*89a0ef05SAndroid Build Coastguard Worker     std::array<uint8_t, 8> y;
774*89a0ef05SAndroid Build Coastguard Worker     std::array<int16_t, 8> u;
775*89a0ef05SAndroid Build Coastguard Worker     std::array<int16_t, 8> v;
776*89a0ef05SAndroid Build Coastguard Worker   };
777*89a0ef05SAndroid Build Coastguard Worker 
778*89a0ef05SAndroid Build Coastguard Worker   struct ExpectedSamples {
779*89a0ef05SAndroid Build Coastguard Worker     std::array<int16_t, 8> y;
780*89a0ef05SAndroid Build Coastguard Worker     std::array<int16_t, 8> u;
781*89a0ef05SAndroid Build Coastguard Worker     std::array<int16_t, 8> v;
782*89a0ef05SAndroid Build Coastguard Worker   };
783*89a0ef05SAndroid Build Coastguard Worker 
784*89a0ef05SAndroid Build Coastguard Worker   // Each tuple contains three elements.
785*89a0ef05SAndroid Build Coastguard Worker   // 0. A pointer to the coefficients that will be passed to the Neon implementation
786*89a0ef05SAndroid Build Coastguard Worker   // 1. Input pixel/color array
787*89a0ef05SAndroid Build Coastguard Worker   // 2. The expected results
788*89a0ef05SAndroid Build Coastguard Worker   const std::array<
789*89a0ef05SAndroid Build Coastguard Worker       std::tuple<const int16_t*, const std::array<Pixel, 5>, const std::array<Pixel, 5>>, 6>
790*89a0ef05SAndroid Build Coastguard Worker       coeffs_setup_correct{{
791*89a0ef05SAndroid Build Coastguard Worker           {kYuv709To601_coeffs_neon, SrgbYuvColors, P3YuvColors},
792*89a0ef05SAndroid Build Coastguard Worker           {kYuv709To2100_coeffs_neon, SrgbYuvColors, Bt2100YuvColors},
793*89a0ef05SAndroid Build Coastguard Worker           {kYuv601To709_coeffs_neon, P3YuvColors, SrgbYuvColors},
794*89a0ef05SAndroid Build Coastguard Worker           {kYuv601To2100_coeffs_neon, P3YuvColors, Bt2100YuvColors},
795*89a0ef05SAndroid Build Coastguard Worker           {kYuv2100To709_coeffs_neon, Bt2100YuvColors, SrgbYuvColors},
796*89a0ef05SAndroid Build Coastguard Worker           {kYuv2100To601_coeffs_neon, Bt2100YuvColors, P3YuvColors},
797*89a0ef05SAndroid Build Coastguard Worker       }};
798*89a0ef05SAndroid Build Coastguard Worker 
799*89a0ef05SAndroid Build Coastguard Worker   for (const auto& [coeff_ptr, input, expected] : coeffs_setup_correct) {
800*89a0ef05SAndroid Build Coastguard Worker     const int16x8_t coeffs = vld1q_s16(coeff_ptr);
801*89a0ef05SAndroid Build Coastguard Worker     InputSamples input_values;
802*89a0ef05SAndroid Build Coastguard Worker     ExpectedSamples expected_values;
803*89a0ef05SAndroid Build Coastguard Worker     for (size_t sample_idx = 0; sample_idx < 8; ++sample_idx) {
804*89a0ef05SAndroid Build Coastguard Worker       size_t ring_idx = sample_idx % input.size();
805*89a0ef05SAndroid Build Coastguard Worker       input_values.y.at(sample_idx) = static_cast<uint8_t>(input.at(ring_idx).y);
806*89a0ef05SAndroid Build Coastguard Worker       input_values.u.at(sample_idx) = input.at(ring_idx).u;
807*89a0ef05SAndroid Build Coastguard Worker       input_values.v.at(sample_idx) = input.at(ring_idx).v;
808*89a0ef05SAndroid Build Coastguard Worker 
809*89a0ef05SAndroid Build Coastguard Worker       expected_values.y.at(sample_idx) = expected.at(ring_idx).y;
810*89a0ef05SAndroid Build Coastguard Worker       expected_values.u.at(sample_idx) = expected.at(ring_idx).u;
811*89a0ef05SAndroid Build Coastguard Worker       expected_values.v.at(sample_idx) = expected.at(ring_idx).v;
812*89a0ef05SAndroid Build Coastguard Worker     }
813*89a0ef05SAndroid Build Coastguard Worker 
814*89a0ef05SAndroid Build Coastguard Worker     const uint8x8_t y_neon = vld1_u8(input_values.y.data());
815*89a0ef05SAndroid Build Coastguard Worker     const int16x8_t u_neon = vld1q_s16(input_values.u.data());
816*89a0ef05SAndroid Build Coastguard Worker     const int16x8_t v_neon = vld1q_s16(input_values.v.data());
817*89a0ef05SAndroid Build Coastguard Worker 
818*89a0ef05SAndroid Build Coastguard Worker     const int16x8x3_t neon_result = yuvConversion_neon(y_neon, u_neon, v_neon, coeffs);
819*89a0ef05SAndroid Build Coastguard Worker 
820*89a0ef05SAndroid Build Coastguard Worker     const int16x8_t y_neon_result = neon_result.val[0];
821*89a0ef05SAndroid Build Coastguard Worker     const int16x8_t u_neon_result = neon_result.val[1];
822*89a0ef05SAndroid Build Coastguard Worker     const int16x8_t v_neon_result = neon_result.val[2];
823*89a0ef05SAndroid Build Coastguard Worker 
824*89a0ef05SAndroid Build Coastguard Worker     const Pixel result0 = {vgetq_lane_s16(y_neon_result, 0), vgetq_lane_s16(u_neon_result, 0),
825*89a0ef05SAndroid Build Coastguard Worker                            vgetq_lane_s16(v_neon_result, 0)};
826*89a0ef05SAndroid Build Coastguard Worker 
827*89a0ef05SAndroid Build Coastguard Worker     const Pixel result1 = {vgetq_lane_s16(y_neon_result, 1), vgetq_lane_s16(u_neon_result, 1),
828*89a0ef05SAndroid Build Coastguard Worker                            vgetq_lane_s16(v_neon_result, 1)};
829*89a0ef05SAndroid Build Coastguard Worker 
830*89a0ef05SAndroid Build Coastguard Worker     const Pixel result2 = {vgetq_lane_s16(y_neon_result, 2), vgetq_lane_s16(u_neon_result, 2),
831*89a0ef05SAndroid Build Coastguard Worker                            vgetq_lane_s16(v_neon_result, 2)};
832*89a0ef05SAndroid Build Coastguard Worker 
833*89a0ef05SAndroid Build Coastguard Worker     const Pixel result3 = {vgetq_lane_s16(y_neon_result, 3), vgetq_lane_s16(u_neon_result, 3),
834*89a0ef05SAndroid Build Coastguard Worker                            vgetq_lane_s16(v_neon_result, 3)};
835*89a0ef05SAndroid Build Coastguard Worker 
836*89a0ef05SAndroid Build Coastguard Worker     const Pixel result4 = {vgetq_lane_s16(y_neon_result, 4), vgetq_lane_s16(u_neon_result, 4),
837*89a0ef05SAndroid Build Coastguard Worker                            vgetq_lane_s16(v_neon_result, 4)};
838*89a0ef05SAndroid Build Coastguard Worker 
839*89a0ef05SAndroid Build Coastguard Worker     const Pixel result5 = {vgetq_lane_s16(y_neon_result, 5), vgetq_lane_s16(u_neon_result, 5),
840*89a0ef05SAndroid Build Coastguard Worker                            vgetq_lane_s16(v_neon_result, 5)};
841*89a0ef05SAndroid Build Coastguard Worker 
842*89a0ef05SAndroid Build Coastguard Worker     const Pixel result6 = {vgetq_lane_s16(y_neon_result, 6), vgetq_lane_s16(u_neon_result, 6),
843*89a0ef05SAndroid Build Coastguard Worker                            vgetq_lane_s16(v_neon_result, 6)};
844*89a0ef05SAndroid Build Coastguard Worker 
845*89a0ef05SAndroid Build Coastguard Worker     const Pixel result7 = {vgetq_lane_s16(y_neon_result, 7), vgetq_lane_s16(u_neon_result, 7),
846*89a0ef05SAndroid Build Coastguard Worker                            vgetq_lane_s16(v_neon_result, 7)};
847*89a0ef05SAndroid Build Coastguard Worker 
848*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result0.y, expected_values.y.at(0), 1);
849*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result0.u, expected_values.u.at(0), 1);
850*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result0.v, expected_values.v.at(0), 1);
851*89a0ef05SAndroid Build Coastguard Worker 
852*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result1.y, expected_values.y.at(1), 1);
853*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result1.u, expected_values.u.at(1), 1);
854*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result1.v, expected_values.v.at(1), 1);
855*89a0ef05SAndroid Build Coastguard Worker 
856*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result2.y, expected_values.y.at(2), 1);
857*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result2.u, expected_values.u.at(2), 1);
858*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result2.v, expected_values.v.at(2), 1);
859*89a0ef05SAndroid Build Coastguard Worker 
860*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result3.y, expected_values.y.at(3), 1);
861*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result3.u, expected_values.u.at(3), 1);
862*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result3.v, expected_values.v.at(3), 1);
863*89a0ef05SAndroid Build Coastguard Worker 
864*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result4.y, expected_values.y.at(4), 1);
865*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result4.u, expected_values.u.at(4), 1);
866*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result4.v, expected_values.v.at(4), 1);
867*89a0ef05SAndroid Build Coastguard Worker 
868*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result5.y, expected_values.y.at(5), 1);
869*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result5.u, expected_values.u.at(5), 1);
870*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result5.v, expected_values.v.at(5), 1);
871*89a0ef05SAndroid Build Coastguard Worker 
872*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result6.y, expected_values.y.at(6), 1);
873*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result6.u, expected_values.u.at(6), 1);
874*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result6.v, expected_values.v.at(6), 1);
875*89a0ef05SAndroid Build Coastguard Worker 
876*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result7.y, expected_values.y.at(7), 1);
877*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result7.u, expected_values.u.at(7), 1);
878*89a0ef05SAndroid Build Coastguard Worker     EXPECT_NEAR(result7.v, expected_values.v.at(7), 1);
879*89a0ef05SAndroid Build Coastguard Worker   }
880*89a0ef05SAndroid Build Coastguard Worker }
881*89a0ef05SAndroid Build Coastguard Worker #endif
882*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,TransformYuv420)883*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, TransformYuv420) {
884*89a0ef05SAndroid Build Coastguard Worker   auto input = Yuv420Image();
885*89a0ef05SAndroid Build Coastguard Worker   const size_t buf_size = input.w * input.h * 3 / 2;
886*89a0ef05SAndroid Build Coastguard Worker   std::unique_ptr<uint8_t[]> out_buf = std::make_unique<uint8_t[]>(buf_size);
887*89a0ef05SAndroid Build Coastguard Worker   uint8_t* luma = out_buf.get();
888*89a0ef05SAndroid Build Coastguard Worker   uint8_t* cb = luma + input.w * input.h;
889*89a0ef05SAndroid Build Coastguard Worker   uint8_t* cr = cb + input.w * input.h / 4;
890*89a0ef05SAndroid Build Coastguard Worker 
891*89a0ef05SAndroid Build Coastguard Worker   const std::array<std::array<float, 9>, 6> conversion_coeffs = {
892*89a0ef05SAndroid Build Coastguard Worker       kYuvBt709ToBt601,  kYuvBt709ToBt2100, kYuvBt601ToBt709,
893*89a0ef05SAndroid Build Coastguard Worker       kYuvBt601ToBt2100, kYuvBt2100ToBt709, kYuvBt2100ToBt601};
894*89a0ef05SAndroid Build Coastguard Worker 
895*89a0ef05SAndroid Build Coastguard Worker   for (size_t coeffs_idx = 0; coeffs_idx < conversion_coeffs.size(); ++coeffs_idx) {
896*89a0ef05SAndroid Build Coastguard Worker     auto output = Yuv420Image();
897*89a0ef05SAndroid Build Coastguard Worker     memcpy(luma, input.planes[UHDR_PLANE_Y], input.w * input.h);
898*89a0ef05SAndroid Build Coastguard Worker     memcpy(cb, input.planes[UHDR_PLANE_U], input.w * input.h / 4);
899*89a0ef05SAndroid Build Coastguard Worker     memcpy(cr, input.planes[UHDR_PLANE_V], input.w * input.h / 4);
900*89a0ef05SAndroid Build Coastguard Worker     output.planes[UHDR_PLANE_Y] = luma;
901*89a0ef05SAndroid Build Coastguard Worker     output.planes[UHDR_PLANE_U] = cb;
902*89a0ef05SAndroid Build Coastguard Worker     output.planes[UHDR_PLANE_V] = cr;
903*89a0ef05SAndroid Build Coastguard Worker 
904*89a0ef05SAndroid Build Coastguard Worker     // Perform a color gamut conversion to the entire 4:2:0 image.
905*89a0ef05SAndroid Build Coastguard Worker     transformYuv420(&output, conversion_coeffs.at(coeffs_idx));
906*89a0ef05SAndroid Build Coastguard Worker 
907*89a0ef05SAndroid Build Coastguard Worker     for (size_t y = 0; y < input.h; y += 2) {
908*89a0ef05SAndroid Build Coastguard Worker       for (size_t x = 0; x < input.w; x += 2) {
909*89a0ef05SAndroid Build Coastguard Worker         Pixel out1 = getYuv420Pixel_uint(&output, x, y);
910*89a0ef05SAndroid Build Coastguard Worker         Pixel out2 = getYuv420Pixel_uint(&output, x + 1, y);
911*89a0ef05SAndroid Build Coastguard Worker         Pixel out3 = getYuv420Pixel_uint(&output, x, y + 1);
912*89a0ef05SAndroid Build Coastguard Worker         Pixel out4 = getYuv420Pixel_uint(&output, x + 1, y + 1);
913*89a0ef05SAndroid Build Coastguard Worker 
914*89a0ef05SAndroid Build Coastguard Worker         Color in1 = getYuv420Pixel(&input, x, y);
915*89a0ef05SAndroid Build Coastguard Worker         Color in2 = getYuv420Pixel(&input, x + 1, y);
916*89a0ef05SAndroid Build Coastguard Worker         Color in3 = getYuv420Pixel(&input, x, y + 1);
917*89a0ef05SAndroid Build Coastguard Worker         Color in4 = getYuv420Pixel(&input, x + 1, y + 1);
918*89a0ef05SAndroid Build Coastguard Worker 
919*89a0ef05SAndroid Build Coastguard Worker         in1 = yuvColorGamutConversion(in1, conversion_coeffs.at(coeffs_idx));
920*89a0ef05SAndroid Build Coastguard Worker         in2 = yuvColorGamutConversion(in2, conversion_coeffs.at(coeffs_idx));
921*89a0ef05SAndroid Build Coastguard Worker         in3 = yuvColorGamutConversion(in3, conversion_coeffs.at(coeffs_idx));
922*89a0ef05SAndroid Build Coastguard Worker         in4 = yuvColorGamutConversion(in4, conversion_coeffs.at(coeffs_idx));
923*89a0ef05SAndroid Build Coastguard Worker 
924*89a0ef05SAndroid Build Coastguard Worker         // Clamp and reduce to uint8_t from float.
925*89a0ef05SAndroid Build Coastguard Worker         uint8_t expect_y1 = static_cast<uint8_t>(CLIP3((in1.y * 255.0f + 0.5f), 0, 255));
926*89a0ef05SAndroid Build Coastguard Worker         uint8_t expect_y2 = static_cast<uint8_t>(CLIP3((in2.y * 255.0f + 0.5f), 0, 255));
927*89a0ef05SAndroid Build Coastguard Worker         uint8_t expect_y3 = static_cast<uint8_t>(CLIP3((in3.y * 255.0f + 0.5f), 0, 255));
928*89a0ef05SAndroid Build Coastguard Worker         uint8_t expect_y4 = static_cast<uint8_t>(CLIP3((in4.y * 255.0f + 0.5f), 0, 255));
929*89a0ef05SAndroid Build Coastguard Worker 
930*89a0ef05SAndroid Build Coastguard Worker         // Allow an absolute difference of 1 to allow for implmentations using a fixed-point
931*89a0ef05SAndroid Build Coastguard Worker         // approximation.
932*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_y1, out1.y, 1);
933*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_y2, out2.y, 1);
934*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_y3, out3.y, 1);
935*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_y4, out4.y, 1);
936*89a0ef05SAndroid Build Coastguard Worker 
937*89a0ef05SAndroid Build Coastguard Worker         Color expect_uv = (in1 + in2 + in3 + in4) / 4.0f;
938*89a0ef05SAndroid Build Coastguard Worker 
939*89a0ef05SAndroid Build Coastguard Worker         uint8_t expect_u =
940*89a0ef05SAndroid Build Coastguard Worker             static_cast<uint8_t>(CLIP3((expect_uv.u * 255.0f + 128.0f + 0.5f), 0, 255));
941*89a0ef05SAndroid Build Coastguard Worker         uint8_t expect_v =
942*89a0ef05SAndroid Build Coastguard Worker             static_cast<uint8_t>(CLIP3((expect_uv.v * 255.0f + 128.0f + 0.5f), 0, 255));
943*89a0ef05SAndroid Build Coastguard Worker 
944*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_u, out1.u, 1);
945*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_u, out2.u, 1);
946*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_u, out3.u, 1);
947*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_u, out4.u, 1);
948*89a0ef05SAndroid Build Coastguard Worker 
949*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_v, out1.v, 1);
950*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_v, out2.v, 1);
951*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_v, out3.v, 1);
952*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_v, out4.v, 1);
953*89a0ef05SAndroid Build Coastguard Worker       }
954*89a0ef05SAndroid Build Coastguard Worker     }
955*89a0ef05SAndroid Build Coastguard Worker   }
956*89a0ef05SAndroid Build Coastguard Worker }
957*89a0ef05SAndroid Build Coastguard Worker 
958*89a0ef05SAndroid Build Coastguard Worker #if (defined(UHDR_ENABLE_INTRINSICS) && (defined(__ARM_NEON__) || defined(__ARM_NEON)))
TEST_F(GainMapMathTest,TransformYuv420Neon)959*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, TransformYuv420Neon) {
960*89a0ef05SAndroid Build Coastguard Worker   const std::array<std::pair<const int16_t*, const std::array<float, 9>>, 6> fixed_floating_coeffs{
961*89a0ef05SAndroid Build Coastguard Worker       {{kYuv709To601_coeffs_neon, kYuvBt709ToBt601},
962*89a0ef05SAndroid Build Coastguard Worker        {kYuv709To2100_coeffs_neon, kYuvBt709ToBt2100},
963*89a0ef05SAndroid Build Coastguard Worker        {kYuv601To709_coeffs_neon, kYuvBt601ToBt709},
964*89a0ef05SAndroid Build Coastguard Worker        {kYuv601To2100_coeffs_neon, kYuvBt601ToBt2100},
965*89a0ef05SAndroid Build Coastguard Worker        {kYuv2100To709_coeffs_neon, kYuvBt2100ToBt709},
966*89a0ef05SAndroid Build Coastguard Worker        {kYuv2100To601_coeffs_neon, kYuvBt2100ToBt601}}};
967*89a0ef05SAndroid Build Coastguard Worker 
968*89a0ef05SAndroid Build Coastguard Worker   for (const auto& [neon_coeffs_ptr, floating_point_coeffs] : fixed_floating_coeffs) {
969*89a0ef05SAndroid Build Coastguard Worker     uhdr_raw_image_t input = Yuv420Image32x4();
970*89a0ef05SAndroid Build Coastguard Worker     const size_t buf_size = input.w * input.h * 3 / 2;
971*89a0ef05SAndroid Build Coastguard Worker     std::unique_ptr<uint8_t[]> out_buf = std::make_unique<uint8_t[]>(buf_size);
972*89a0ef05SAndroid Build Coastguard Worker     uint8_t* luma = out_buf.get();
973*89a0ef05SAndroid Build Coastguard Worker     uint8_t* cb = luma + input.w * input.h;
974*89a0ef05SAndroid Build Coastguard Worker     uint8_t* cr = cb + input.w * input.h / 4;
975*89a0ef05SAndroid Build Coastguard Worker 
976*89a0ef05SAndroid Build Coastguard Worker     uhdr_raw_image_t output = Yuv420Image32x4();
977*89a0ef05SAndroid Build Coastguard Worker     memcpy(luma, input.planes[UHDR_PLANE_Y], input.w * input.h);
978*89a0ef05SAndroid Build Coastguard Worker     memcpy(cb, input.planes[UHDR_PLANE_U], input.w * input.h / 4);
979*89a0ef05SAndroid Build Coastguard Worker     memcpy(cr, input.planes[UHDR_PLANE_V], input.w * input.h / 4);
980*89a0ef05SAndroid Build Coastguard Worker     output.planes[UHDR_PLANE_Y] = luma;
981*89a0ef05SAndroid Build Coastguard Worker     output.planes[UHDR_PLANE_U] = cb;
982*89a0ef05SAndroid Build Coastguard Worker     output.planes[UHDR_PLANE_V] = cr;
983*89a0ef05SAndroid Build Coastguard Worker 
984*89a0ef05SAndroid Build Coastguard Worker     transformYuv420_neon(&output, neon_coeffs_ptr);
985*89a0ef05SAndroid Build Coastguard Worker 
986*89a0ef05SAndroid Build Coastguard Worker     for (size_t y = 0; y < input.h / 2; ++y) {
987*89a0ef05SAndroid Build Coastguard Worker       for (size_t x = 0; x < input.w / 2; ++x) {
988*89a0ef05SAndroid Build Coastguard Worker         const Pixel out1 = getYuv420Pixel_uint(&output, x * 2, y * 2);
989*89a0ef05SAndroid Build Coastguard Worker         const Pixel out2 = getYuv420Pixel_uint(&output, x * 2 + 1, y * 2);
990*89a0ef05SAndroid Build Coastguard Worker         const Pixel out3 = getYuv420Pixel_uint(&output, x * 2, y * 2 + 1);
991*89a0ef05SAndroid Build Coastguard Worker         const Pixel out4 = getYuv420Pixel_uint(&output, x * 2 + 1, y * 2 + 1);
992*89a0ef05SAndroid Build Coastguard Worker 
993*89a0ef05SAndroid Build Coastguard Worker         Color in1 = getYuv420Pixel(&input, x * 2, y * 2);
994*89a0ef05SAndroid Build Coastguard Worker         Color in2 = getYuv420Pixel(&input, x * 2 + 1, y * 2);
995*89a0ef05SAndroid Build Coastguard Worker         Color in3 = getYuv420Pixel(&input, x * 2, y * 2 + 1);
996*89a0ef05SAndroid Build Coastguard Worker         Color in4 = getYuv420Pixel(&input, x * 2 + 1, y * 2 + 1);
997*89a0ef05SAndroid Build Coastguard Worker 
998*89a0ef05SAndroid Build Coastguard Worker         in1 = yuvColorGamutConversion(in1, floating_point_coeffs);
999*89a0ef05SAndroid Build Coastguard Worker         in2 = yuvColorGamutConversion(in2, floating_point_coeffs);
1000*89a0ef05SAndroid Build Coastguard Worker         in3 = yuvColorGamutConversion(in3, floating_point_coeffs);
1001*89a0ef05SAndroid Build Coastguard Worker         in4 = yuvColorGamutConversion(in4, floating_point_coeffs);
1002*89a0ef05SAndroid Build Coastguard Worker 
1003*89a0ef05SAndroid Build Coastguard Worker         const Color expect_uv = (in1 + in2 + in3 + in4) / 4.0f;
1004*89a0ef05SAndroid Build Coastguard Worker 
1005*89a0ef05SAndroid Build Coastguard Worker         const uint8_t expect_y1 = static_cast<uint8_t>(CLIP3(in1.y * 255.0f + 0.5f, 0, 255));
1006*89a0ef05SAndroid Build Coastguard Worker         const uint8_t expect_y2 = static_cast<uint8_t>(CLIP3(in2.y * 255.0f + 0.5f, 0, 255));
1007*89a0ef05SAndroid Build Coastguard Worker         const uint8_t expect_y3 = static_cast<uint8_t>(CLIP3(in3.y * 255.0f + 0.5f, 0, 255));
1008*89a0ef05SAndroid Build Coastguard Worker         const uint8_t expect_y4 = static_cast<uint8_t>(CLIP3(in4.y * 255.0f + 0.5f, 0, 255));
1009*89a0ef05SAndroid Build Coastguard Worker 
1010*89a0ef05SAndroid Build Coastguard Worker         const uint8_t expect_u =
1011*89a0ef05SAndroid Build Coastguard Worker             static_cast<uint8_t>(CLIP3(expect_uv.u * 255.0f + 128.0f + 0.5f, 0, 255));
1012*89a0ef05SAndroid Build Coastguard Worker         const uint8_t expect_v =
1013*89a0ef05SAndroid Build Coastguard Worker             static_cast<uint8_t>(CLIP3(expect_uv.v * 255.0f + 128.0f + 0.5f, 0, 255));
1014*89a0ef05SAndroid Build Coastguard Worker 
1015*89a0ef05SAndroid Build Coastguard Worker         // Due to the Neon version using a fixed-point approximation, this can result in an off by
1016*89a0ef05SAndroid Build Coastguard Worker         // one error compared with the standard floating-point version.
1017*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_y1, out1.y, 1);
1018*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_y2, out2.y, 1);
1019*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_y3, out3.y, 1);
1020*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_y4, out4.y, 1);
1021*89a0ef05SAndroid Build Coastguard Worker 
1022*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_u, out1.u, 1);
1023*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_u, out2.u, 1);
1024*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_u, out3.u, 1);
1025*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_u, out4.u, 1);
1026*89a0ef05SAndroid Build Coastguard Worker 
1027*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_v, out1.v, 1);
1028*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_v, out2.v, 1);
1029*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_v, out3.v, 1);
1030*89a0ef05SAndroid Build Coastguard Worker         EXPECT_NEAR(expect_v, out4.v, 1);
1031*89a0ef05SAndroid Build Coastguard Worker       }
1032*89a0ef05SAndroid Build Coastguard Worker     }
1033*89a0ef05SAndroid Build Coastguard Worker   }
1034*89a0ef05SAndroid Build Coastguard Worker }
1035*89a0ef05SAndroid Build Coastguard Worker #endif
1036*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,HlgOetf)1037*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, HlgOetf) {
1038*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(hlgOetf(0.0f), 0.0f);
1039*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(hlgOetf(0.04167f), 0.35357f, ComparisonEpsilon());
1040*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(hlgOetf(0.08333f), 0.5f, ComparisonEpsilon());
1041*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(hlgOetf(0.5f), 0.87164f, ComparisonEpsilon());
1042*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(hlgOetf(1.0f), 1.0f);
1043*89a0ef05SAndroid Build Coastguard Worker 
1044*89a0ef05SAndroid Build Coastguard Worker   Color e = {{{0.04167f, 0.08333f, 0.5f}}};
1045*89a0ef05SAndroid Build Coastguard Worker   Color e_gamma = {{{0.35357f, 0.5f, 0.87164f}}};
1046*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(hlgOetf(e), e_gamma);
1047*89a0ef05SAndroid Build Coastguard Worker }
1048*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,HlgInvOetf)1049*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, HlgInvOetf) {
1050*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(hlgInvOetf(0.0f), 0.0f);
1051*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(hlgInvOetf(0.25f), 0.02083f, ComparisonEpsilon());
1052*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(hlgInvOetf(0.5f), 0.08333f, ComparisonEpsilon());
1053*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(hlgInvOetf(0.75f), 0.26496f, ComparisonEpsilon());
1054*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(hlgInvOetf(1.0f), 1.0f);
1055*89a0ef05SAndroid Build Coastguard Worker 
1056*89a0ef05SAndroid Build Coastguard Worker   Color e_gamma = {{{0.25f, 0.5f, 0.75f}}};
1057*89a0ef05SAndroid Build Coastguard Worker   Color e = {{{0.02083f, 0.08333f, 0.26496f}}};
1058*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(hlgInvOetf(e_gamma), e);
1059*89a0ef05SAndroid Build Coastguard Worker }
1060*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,HlgTransferFunctionRoundtrip)1061*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, HlgTransferFunctionRoundtrip) {
1062*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(0.0f)), 0.0f);
1063*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(hlgInvOetf(hlgOetf(0.04167f)), 0.04167f, ComparisonEpsilon());
1064*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(hlgInvOetf(hlgOetf(0.08333f)), 0.08333f, ComparisonEpsilon());
1065*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(hlgInvOetf(hlgOetf(0.5f)), 0.5f, ComparisonEpsilon());
1066*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(1.0f)), 1.0f);
1067*89a0ef05SAndroid Build Coastguard Worker }
1068*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,PqOetf)1069*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, PqOetf) {
1070*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(pqOetf(0.0f), 0.0f);
1071*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(pqOetf(0.01f), 0.50808f, ComparisonEpsilon());
1072*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(pqOetf(0.5f), 0.92655f, ComparisonEpsilon());
1073*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(pqOetf(0.99f), 0.99895f, ComparisonEpsilon());
1074*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(pqOetf(1.0f), 1.0f);
1075*89a0ef05SAndroid Build Coastguard Worker 
1076*89a0ef05SAndroid Build Coastguard Worker   Color e = {{{0.01f, 0.5f, 0.99f}}};
1077*89a0ef05SAndroid Build Coastguard Worker   Color e_gamma = {{{0.50808f, 0.92655f, 0.99895f}}};
1078*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(pqOetf(e), e_gamma);
1079*89a0ef05SAndroid Build Coastguard Worker }
1080*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,PqInvOetf)1081*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, PqInvOetf) {
1082*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(pqInvOetf(0.0f), 0.0f);
1083*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(pqInvOetf(0.01f), 2.31017e-7f, ComparisonEpsilon());
1084*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(pqInvOetf(0.5f), 0.00922f, ComparisonEpsilon());
1085*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(pqInvOetf(0.99f), 0.90903f, ComparisonEpsilon());
1086*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(pqInvOetf(1.0f), 1.0f);
1087*89a0ef05SAndroid Build Coastguard Worker 
1088*89a0ef05SAndroid Build Coastguard Worker   Color e_gamma = {{{0.01f, 0.5f, 0.99f}}};
1089*89a0ef05SAndroid Build Coastguard Worker   Color e = {{{2.31017e-7f, 0.00922f, 0.90903f}}};
1090*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(pqInvOetf(e_gamma), e);
1091*89a0ef05SAndroid Build Coastguard Worker }
1092*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,PqInvOetfLUT)1093*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, PqInvOetfLUT) {
1094*89a0ef05SAndroid Build Coastguard Worker   for (size_t idx = 0; idx < kPqInvOETFNumEntries; idx++) {
1095*89a0ef05SAndroid Build Coastguard Worker     float value = static_cast<float>(idx) / static_cast<float>(kPqInvOETFNumEntries - 1);
1096*89a0ef05SAndroid Build Coastguard Worker     EXPECT_FLOAT_EQ(pqInvOetf(value), pqInvOetfLUT(value));
1097*89a0ef05SAndroid Build Coastguard Worker   }
1098*89a0ef05SAndroid Build Coastguard Worker }
1099*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,HlgInvOetfLUT)1100*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, HlgInvOetfLUT) {
1101*89a0ef05SAndroid Build Coastguard Worker   for (size_t idx = 0; idx < kHlgInvOETFNumEntries; idx++) {
1102*89a0ef05SAndroid Build Coastguard Worker     float value = static_cast<float>(idx) / static_cast<float>(kHlgInvOETFNumEntries - 1);
1103*89a0ef05SAndroid Build Coastguard Worker     EXPECT_FLOAT_EQ(hlgInvOetf(value), hlgInvOetfLUT(value));
1104*89a0ef05SAndroid Build Coastguard Worker   }
1105*89a0ef05SAndroid Build Coastguard Worker }
1106*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,pqOetfLUT)1107*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, pqOetfLUT) {
1108*89a0ef05SAndroid Build Coastguard Worker   for (size_t idx = 0; idx < kPqOETFNumEntries; idx++) {
1109*89a0ef05SAndroid Build Coastguard Worker     float value = static_cast<float>(idx) / static_cast<float>(kPqOETFNumEntries - 1);
1110*89a0ef05SAndroid Build Coastguard Worker     EXPECT_FLOAT_EQ(pqOetf(value), pqOetfLUT(value));
1111*89a0ef05SAndroid Build Coastguard Worker   }
1112*89a0ef05SAndroid Build Coastguard Worker }
1113*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,hlgOetfLUT)1114*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, hlgOetfLUT) {
1115*89a0ef05SAndroid Build Coastguard Worker   for (size_t idx = 0; idx < kHlgOETFNumEntries; idx++) {
1116*89a0ef05SAndroid Build Coastguard Worker     float value = static_cast<float>(idx) / static_cast<float>(kHlgOETFNumEntries - 1);
1117*89a0ef05SAndroid Build Coastguard Worker     EXPECT_FLOAT_EQ(hlgOetf(value), hlgOetfLUT(value));
1118*89a0ef05SAndroid Build Coastguard Worker   }
1119*89a0ef05SAndroid Build Coastguard Worker }
1120*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,srgbInvOetfLUT)1121*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, srgbInvOetfLUT) {
1122*89a0ef05SAndroid Build Coastguard Worker   for (size_t idx = 0; idx < kSrgbInvOETFNumEntries; idx++) {
1123*89a0ef05SAndroid Build Coastguard Worker     float value = static_cast<float>(idx) / static_cast<float>(kSrgbInvOETFNumEntries - 1);
1124*89a0ef05SAndroid Build Coastguard Worker     EXPECT_FLOAT_EQ(srgbInvOetf(value), srgbInvOetfLUT(value));
1125*89a0ef05SAndroid Build Coastguard Worker   }
1126*89a0ef05SAndroid Build Coastguard Worker }
1127*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,applyGainLUT)1128*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, applyGainLUT) {
1129*89a0ef05SAndroid Build Coastguard Worker   for (float boost = 1.5; boost <= 12; boost++) {
1130*89a0ef05SAndroid Build Coastguard Worker     uhdr_gainmap_metadata_ext_t metadata;
1131*89a0ef05SAndroid Build Coastguard Worker 
1132*89a0ef05SAndroid Build Coastguard Worker     metadata.min_content_boost = 1.0f / boost;
1133*89a0ef05SAndroid Build Coastguard Worker     metadata.max_content_boost = boost;
1134*89a0ef05SAndroid Build Coastguard Worker     metadata.gamma = 1.0f;
1135*89a0ef05SAndroid Build Coastguard Worker     metadata.hdr_capacity_max = metadata.max_content_boost;
1136*89a0ef05SAndroid Build Coastguard Worker     metadata.hdr_capacity_min = metadata.min_content_boost;
1137*89a0ef05SAndroid Build Coastguard Worker     GainLUT gainLUT(&metadata);
1138*89a0ef05SAndroid Build Coastguard Worker     float weight = (log2(boost) - log2(metadata.hdr_capacity_min)) /
1139*89a0ef05SAndroid Build Coastguard Worker                    (log2(metadata.hdr_capacity_max) - log2(metadata.hdr_capacity_min));
1140*89a0ef05SAndroid Build Coastguard Worker     weight = CLIP3(weight, 0.0f, 1.0f);
1141*89a0ef05SAndroid Build Coastguard Worker     GainLUT gainLUTWithBoost(&metadata, weight);
1142*89a0ef05SAndroid Build Coastguard Worker     for (size_t idx = 0; idx < kGainFactorNumEntries; idx++) {
1143*89a0ef05SAndroid Build Coastguard Worker       float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
1144*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
1145*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlack(), value, gainLUT, &metadata));
1146*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
1147*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbWhite(), value, gainLUT, &metadata));
1148*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
1149*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbRed(), value, gainLUT, &metadata));
1150*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
1151*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbGreen(), value, gainLUT, &metadata));
1152*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
1153*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlue(), value, gainLUT, &metadata));
1154*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata, weight),
1155*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlack(), value, gainLUTWithBoost, &metadata));
1156*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata, weight),
1157*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbWhite(), value, gainLUTWithBoost, &metadata));
1158*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata, weight),
1159*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbRed(), value, gainLUTWithBoost, &metadata));
1160*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata, weight),
1161*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbGreen(), value, gainLUTWithBoost, &metadata));
1162*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata, weight),
1163*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlue(), value, gainLUTWithBoost, &metadata));
1164*89a0ef05SAndroid Build Coastguard Worker     }
1165*89a0ef05SAndroid Build Coastguard Worker   }
1166*89a0ef05SAndroid Build Coastguard Worker 
1167*89a0ef05SAndroid Build Coastguard Worker   for (float boost = 1.5; boost <= 12; boost++) {
1168*89a0ef05SAndroid Build Coastguard Worker     uhdr_gainmap_metadata_ext_t metadata;
1169*89a0ef05SAndroid Build Coastguard Worker 
1170*89a0ef05SAndroid Build Coastguard Worker     metadata.min_content_boost = 1.0f;
1171*89a0ef05SAndroid Build Coastguard Worker     metadata.max_content_boost = boost;
1172*89a0ef05SAndroid Build Coastguard Worker     metadata.gamma = 1.0f;
1173*89a0ef05SAndroid Build Coastguard Worker     metadata.hdr_capacity_max = metadata.max_content_boost;
1174*89a0ef05SAndroid Build Coastguard Worker     metadata.hdr_capacity_min = metadata.min_content_boost;
1175*89a0ef05SAndroid Build Coastguard Worker     GainLUT gainLUT(&metadata);
1176*89a0ef05SAndroid Build Coastguard Worker     float weight = (log2(boost) - log2(metadata.hdr_capacity_min)) /
1177*89a0ef05SAndroid Build Coastguard Worker                    (log2(metadata.hdr_capacity_max) - log2(metadata.hdr_capacity_min));
1178*89a0ef05SAndroid Build Coastguard Worker     weight = CLIP3(weight, 0.0f, 1.0f);
1179*89a0ef05SAndroid Build Coastguard Worker     GainLUT gainLUTWithBoost(&metadata, weight);
1180*89a0ef05SAndroid Build Coastguard Worker     for (size_t idx = 0; idx < kGainFactorNumEntries; idx++) {
1181*89a0ef05SAndroid Build Coastguard Worker       float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
1182*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
1183*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlack(), value, gainLUT, &metadata));
1184*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
1185*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbWhite(), value, gainLUT, &metadata));
1186*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
1187*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbRed(), value, gainLUT, &metadata));
1188*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
1189*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbGreen(), value, gainLUT, &metadata));
1190*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
1191*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlue(), value, gainLUT, &metadata));
1192*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata, weight),
1193*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlack(), value, gainLUTWithBoost, &metadata));
1194*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata, weight),
1195*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbWhite(), value, gainLUTWithBoost, &metadata));
1196*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata, weight),
1197*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbRed(), value, gainLUTWithBoost, &metadata));
1198*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata, weight),
1199*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbGreen(), value, gainLUTWithBoost, &metadata));
1200*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata, weight),
1201*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlue(), value, gainLUTWithBoost, &metadata));
1202*89a0ef05SAndroid Build Coastguard Worker     }
1203*89a0ef05SAndroid Build Coastguard Worker   }
1204*89a0ef05SAndroid Build Coastguard Worker 
1205*89a0ef05SAndroid Build Coastguard Worker   for (float boost = 1.5; boost <= 12; boost++) {
1206*89a0ef05SAndroid Build Coastguard Worker     uhdr_gainmap_metadata_ext_t metadata;
1207*89a0ef05SAndroid Build Coastguard Worker 
1208*89a0ef05SAndroid Build Coastguard Worker     metadata.min_content_boost = 1.0f / powf(boost, 1.0f / 3.0f);
1209*89a0ef05SAndroid Build Coastguard Worker     metadata.max_content_boost = boost;
1210*89a0ef05SAndroid Build Coastguard Worker     metadata.gamma = 1.0f;
1211*89a0ef05SAndroid Build Coastguard Worker     metadata.hdr_capacity_max = metadata.max_content_boost;
1212*89a0ef05SAndroid Build Coastguard Worker     metadata.hdr_capacity_min = metadata.min_content_boost;
1213*89a0ef05SAndroid Build Coastguard Worker     GainLUT gainLUT(&metadata);
1214*89a0ef05SAndroid Build Coastguard Worker     float weight = (log2(boost) - log2(metadata.hdr_capacity_min)) /
1215*89a0ef05SAndroid Build Coastguard Worker                    (log2(metadata.hdr_capacity_max) - log2(metadata.hdr_capacity_min));
1216*89a0ef05SAndroid Build Coastguard Worker     weight = CLIP3(weight, 0.0f, 1.0f);
1217*89a0ef05SAndroid Build Coastguard Worker     GainLUT gainLUTWithBoost(&metadata, weight);
1218*89a0ef05SAndroid Build Coastguard Worker     for (size_t idx = 0; idx < kGainFactorNumEntries; idx++) {
1219*89a0ef05SAndroid Build Coastguard Worker       float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
1220*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
1221*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlack(), value, gainLUT, &metadata));
1222*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
1223*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbWhite(), value, gainLUT, &metadata));
1224*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
1225*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbRed(), value, gainLUT, &metadata));
1226*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
1227*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbGreen(), value, gainLUT, &metadata));
1228*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
1229*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlue(), value, gainLUT, &metadata));
1230*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata, weight),
1231*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlack(), value, gainLUTWithBoost, &metadata));
1232*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata, weight),
1233*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbWhite(), value, gainLUTWithBoost, &metadata));
1234*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata, weight),
1235*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbRed(), value, gainLUTWithBoost, &metadata));
1236*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata, weight),
1237*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbGreen(), value, gainLUTWithBoost, &metadata));
1238*89a0ef05SAndroid Build Coastguard Worker       EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata, weight),
1239*89a0ef05SAndroid Build Coastguard Worker                       applyGainLUT(RgbBlue(), value, gainLUTWithBoost, &metadata));
1240*89a0ef05SAndroid Build Coastguard Worker     }
1241*89a0ef05SAndroid Build Coastguard Worker   }
1242*89a0ef05SAndroid Build Coastguard Worker }
1243*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,PqTransferFunctionRoundtrip)1244*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, PqTransferFunctionRoundtrip) {
1245*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(0.0f)), 0.0f);
1246*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(pqInvOetf(pqOetf(0.01f)), 0.01f, ComparisonEpsilon());
1247*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(pqInvOetf(pqOetf(0.5f)), 0.5f, ComparisonEpsilon());
1248*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(pqInvOetf(pqOetf(0.99f)), 0.99f, ComparisonEpsilon());
1249*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(1.0f)), 1.0f);
1250*89a0ef05SAndroid Build Coastguard Worker }
1251*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ColorConversionLookup)1252*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ColorConversionLookup) {
1253*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_BT_709, UHDR_CG_UNSPECIFIED), nullptr);
1254*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_BT_709, UHDR_CG_BT_709), identityConversion);
1255*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_BT_709, UHDR_CG_DISPLAY_P3), p3ToBt709);
1256*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_BT_709, UHDR_CG_BT_2100), bt2100ToBt709);
1257*89a0ef05SAndroid Build Coastguard Worker 
1258*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_DISPLAY_P3, UHDR_CG_UNSPECIFIED), nullptr);
1259*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_DISPLAY_P3, UHDR_CG_BT_709), bt709ToP3);
1260*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_DISPLAY_P3, UHDR_CG_DISPLAY_P3), identityConversion);
1261*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_DISPLAY_P3, UHDR_CG_BT_2100), bt2100ToP3);
1262*89a0ef05SAndroid Build Coastguard Worker 
1263*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_BT_2100, UHDR_CG_UNSPECIFIED), nullptr);
1264*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_BT_2100, UHDR_CG_BT_709), bt709ToBt2100);
1265*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_BT_2100, UHDR_CG_DISPLAY_P3), p3ToBt2100);
1266*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_BT_2100, UHDR_CG_BT_2100), identityConversion);
1267*89a0ef05SAndroid Build Coastguard Worker 
1268*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_UNSPECIFIED, UHDR_CG_UNSPECIFIED), nullptr);
1269*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_UNSPECIFIED, UHDR_CG_BT_709), nullptr);
1270*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_UNSPECIFIED, UHDR_CG_DISPLAY_P3), nullptr);
1271*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(getGamutConversionFn(UHDR_CG_UNSPECIFIED, UHDR_CG_BT_2100), nullptr);
1272*89a0ef05SAndroid Build Coastguard Worker }
1273*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,EncodeGain)1274*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, EncodeGain) {
1275*89a0ef05SAndroid Build Coastguard Worker   float min_boost = log2(1.0f / 4.0f);
1276*89a0ef05SAndroid Build Coastguard Worker   float max_boost = log2(4.0f);
1277*89a0ef05SAndroid Build Coastguard Worker   float gamma = 1.0f;
1278*89a0ef05SAndroid Build Coastguard Worker 
1279*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(0.0f, 1.0f), min_boost, max_boost, 1.0f), 128);
1280*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 0.0f), min_boost, max_boost, 1.0f), 0);
1281*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(0.5f, 0.0f), min_boost, max_boost, 1.0f), 0);
1282*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 1.0), min_boost, max_boost, 1.0f), 128);
1283*89a0ef05SAndroid Build Coastguard Worker 
1284*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 4.0f), min_boost, max_boost, 1.0f), 255);
1285*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 5.0f), min_boost, max_boost, 1.0f), 255);
1286*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(4.0f, 1.0f), min_boost, max_boost, 1.0f), 0);
1287*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(4.0f, 0.5f), min_boost, max_boost, 1.0f), 0);
1288*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 2.0f), min_boost, max_boost, 1.0f), 191);
1289*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(2.0f, 1.0f), min_boost, max_boost, 1.0f), 64);
1290*89a0ef05SAndroid Build Coastguard Worker 
1291*89a0ef05SAndroid Build Coastguard Worker   min_boost = log2(1.0f / 2.0f);
1292*89a0ef05SAndroid Build Coastguard Worker   max_boost = log2(2.0f);
1293*89a0ef05SAndroid Build Coastguard Worker 
1294*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 2.0f), min_boost, max_boost, 1.0f), 255);
1295*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(2.0f, 1.0f), min_boost, max_boost, 1.0f), 0);
1296*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 1.41421f), min_boost, max_boost, 1.0f), 191);
1297*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.41421f, 1.0f), min_boost, max_boost, 1.0f), 64);
1298*89a0ef05SAndroid Build Coastguard Worker 
1299*89a0ef05SAndroid Build Coastguard Worker   min_boost = log2(1.0f / 8.0f);
1300*89a0ef05SAndroid Build Coastguard Worker   max_boost = log2(8.0f);
1301*89a0ef05SAndroid Build Coastguard Worker 
1302*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 8.0f), min_boost, max_boost, 1.0f), 255);
1303*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(8.0f, 1.0f), min_boost, max_boost, 1.0f), 0);
1304*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 2.82843f), min_boost, max_boost, 1.0f), 191);
1305*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(2.82843f, 1.0f), min_boost, max_boost, 1.0f), 64);
1306*89a0ef05SAndroid Build Coastguard Worker 
1307*89a0ef05SAndroid Build Coastguard Worker   min_boost = log2(1.0f);
1308*89a0ef05SAndroid Build Coastguard Worker   max_boost = log2(8.0f);
1309*89a0ef05SAndroid Build Coastguard Worker 
1310*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(0.0f, 0.0f), min_boost, max_boost, 1.0f), 0);
1311*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 0.0f), min_boost, max_boost, 1.0f), 0);
1312*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 1.0f), min_boost, max_boost, 1.0f), 0);
1313*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 8.0f), min_boost, max_boost, 1.0f), 255);
1314*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 4.0f), min_boost, max_boost, 1.0f), 170);
1315*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 2.0f), min_boost, max_boost, 1.0f), 85);
1316*89a0ef05SAndroid Build Coastguard Worker 
1317*89a0ef05SAndroid Build Coastguard Worker   min_boost = log2(1.0f / 2.0f);
1318*89a0ef05SAndroid Build Coastguard Worker   max_boost = log2(8.0f);
1319*89a0ef05SAndroid Build Coastguard Worker 
1320*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(0.0f, 0.0f), min_boost, max_boost, 1.0f), 64);
1321*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 0.0f), min_boost, max_boost, 1.0f), 0);
1322*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 1.0f), min_boost, max_boost, 1.0f), 64);
1323*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 8.0f), min_boost, max_boost, 1.0f), 255);
1324*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 4.0f), min_boost, max_boost, 1.0f), 191);
1325*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 2.0f), min_boost, max_boost, 1.0f), 128);
1326*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 0.7071f), min_boost, max_boost, 1.0f), 32);
1327*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(affineMapGain(computeGain(1.0f, 0.5f), min_boost, max_boost, 1.0f), 0);
1328*89a0ef05SAndroid Build Coastguard Worker }
1329*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ApplyGain)1330*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ApplyGain) {
1331*89a0ef05SAndroid Build Coastguard Worker   uhdr_gainmap_metadata_ext_t metadata;
1332*89a0ef05SAndroid Build Coastguard Worker 
1333*89a0ef05SAndroid Build Coastguard Worker   metadata.min_content_boost = 1.0f / 4.0f;
1334*89a0ef05SAndroid Build Coastguard Worker   metadata.max_content_boost = 4.0f;
1335*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_max = metadata.max_content_boost;
1336*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_min = metadata.min_content_boost;
1337*89a0ef05SAndroid Build Coastguard Worker   metadata.offset_sdr = 0.0f;
1338*89a0ef05SAndroid Build Coastguard Worker   metadata.offset_hdr = 0.0f;
1339*89a0ef05SAndroid Build Coastguard Worker   metadata.gamma = 1.0f;
1340*89a0ef05SAndroid Build Coastguard Worker 
1341*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.0f, &metadata), RgbBlack());
1342*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.5f, &metadata), RgbBlack());
1343*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbBlack(), 1.0f, &metadata), RgbBlack());
1344*89a0ef05SAndroid Build Coastguard Worker 
1345*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 4.0f);
1346*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.0f);
1347*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
1348*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.0f);
1349*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 4.0f);
1350*89a0ef05SAndroid Build Coastguard Worker 
1351*89a0ef05SAndroid Build Coastguard Worker   metadata.max_content_boost = 2.0f;
1352*89a0ef05SAndroid Build Coastguard Worker   metadata.min_content_boost = 1.0f / 2.0f;
1353*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_max = metadata.max_content_boost;
1354*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_min = metadata.min_content_boost;
1355*89a0ef05SAndroid Build Coastguard Worker 
1356*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
1357*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 1.41421f);
1358*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
1359*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 1.41421f);
1360*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 2.0f);
1361*89a0ef05SAndroid Build Coastguard Worker 
1362*89a0ef05SAndroid Build Coastguard Worker   metadata.max_content_boost = 8.0f;
1363*89a0ef05SAndroid Build Coastguard Worker   metadata.min_content_boost = 1.0f / 8.0f;
1364*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_max = metadata.max_content_boost;
1365*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_min = metadata.min_content_boost;
1366*89a0ef05SAndroid Build Coastguard Worker 
1367*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 8.0f);
1368*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.82843f);
1369*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
1370*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.82843f);
1371*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
1372*89a0ef05SAndroid Build Coastguard Worker 
1373*89a0ef05SAndroid Build Coastguard Worker   metadata.max_content_boost = 8.0f;
1374*89a0ef05SAndroid Build Coastguard Worker   metadata.min_content_boost = 1.0f;
1375*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_max = metadata.max_content_boost;
1376*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_min = metadata.min_content_boost;
1377*89a0ef05SAndroid Build Coastguard Worker 
1378*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite());
1379*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f / 3.0f, &metadata), RgbWhite() * 2.0f);
1380*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 2.0f / 3.0f, &metadata), RgbWhite() * 4.0f);
1381*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
1382*89a0ef05SAndroid Build Coastguard Worker 
1383*89a0ef05SAndroid Build Coastguard Worker   metadata.max_content_boost = 8.0f;
1384*89a0ef05SAndroid Build Coastguard Worker   metadata.min_content_boost = 0.5f;
1385*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_max = metadata.max_content_boost;
1386*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_min = metadata.min_content_boost;
1387*89a0ef05SAndroid Build Coastguard Worker 
1388*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
1389*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite());
1390*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite() * 2.0f);
1391*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 4.0f);
1392*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
1393*89a0ef05SAndroid Build Coastguard Worker 
1394*89a0ef05SAndroid Build Coastguard Worker   Color e = {{{0.0f, 0.5f, 1.0f}}};
1395*89a0ef05SAndroid Build Coastguard Worker   metadata.max_content_boost = 4.0f;
1396*89a0ef05SAndroid Build Coastguard Worker   metadata.min_content_boost = 1.0f / 4.0f;
1397*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_max = metadata.max_content_boost;
1398*89a0ef05SAndroid Build Coastguard Worker   metadata.hdr_capacity_min = metadata.min_content_boost;
1399*89a0ef05SAndroid Build Coastguard Worker 
1400*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(e, 0.0f, &metadata), e / 4.0f);
1401*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(e, 0.25f, &metadata), e / 2.0f);
1402*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(e, 0.5f, &metadata), e);
1403*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(e, 0.75f, &metadata), e * 2.0f);
1404*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_NEAR(applyGain(e, 1.0f, &metadata), e * 4.0f);
1405*89a0ef05SAndroid Build Coastguard Worker }
1406*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,GetYuv420Pixel)1407*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, GetYuv420Pixel) {
1408*89a0ef05SAndroid Build Coastguard Worker   auto image = Yuv420Image();
1409*89a0ef05SAndroid Build Coastguard Worker   Color(*colors)[4] = Yuv420Colors();
1410*89a0ef05SAndroid Build Coastguard Worker 
1411*89a0ef05SAndroid Build Coastguard Worker   for (size_t y = 0; y < 4; ++y) {
1412*89a0ef05SAndroid Build Coastguard Worker     for (size_t x = 0; x < 4; ++x) {
1413*89a0ef05SAndroid Build Coastguard Worker       EXPECT_YUV_NEAR(getYuv420Pixel(&image, x, y), colors[y][x]);
1414*89a0ef05SAndroid Build Coastguard Worker     }
1415*89a0ef05SAndroid Build Coastguard Worker   }
1416*89a0ef05SAndroid Build Coastguard Worker }
1417*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,GetP010Pixel)1418*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, GetP010Pixel) {
1419*89a0ef05SAndroid Build Coastguard Worker   auto image = P010Image();
1420*89a0ef05SAndroid Build Coastguard Worker   Color(*colors)[4] = P010Colors();
1421*89a0ef05SAndroid Build Coastguard Worker 
1422*89a0ef05SAndroid Build Coastguard Worker   for (size_t y = 0; y < 4; ++y) {
1423*89a0ef05SAndroid Build Coastguard Worker     for (size_t x = 0; x < 4; ++x) {
1424*89a0ef05SAndroid Build Coastguard Worker       EXPECT_YUV_NEAR(getP010Pixel(&image, x, y), colors[y][x]);
1425*89a0ef05SAndroid Build Coastguard Worker     }
1426*89a0ef05SAndroid Build Coastguard Worker   }
1427*89a0ef05SAndroid Build Coastguard Worker }
1428*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,SampleYuv420)1429*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, SampleYuv420) {
1430*89a0ef05SAndroid Build Coastguard Worker   auto image = Yuv420Image();
1431*89a0ef05SAndroid Build Coastguard Worker   Color(*colors)[4] = Yuv420Colors();
1432*89a0ef05SAndroid Build Coastguard Worker 
1433*89a0ef05SAndroid Build Coastguard Worker   static const size_t kMapScaleFactor = 2;
1434*89a0ef05SAndroid Build Coastguard Worker   for (size_t y = 0; y < 4 / kMapScaleFactor; ++y) {
1435*89a0ef05SAndroid Build Coastguard Worker     for (size_t x = 0; x < 4 / kMapScaleFactor; ++x) {
1436*89a0ef05SAndroid Build Coastguard Worker       Color min = {{{1.0f, 1.0f, 1.0f}}};
1437*89a0ef05SAndroid Build Coastguard Worker       Color max = {{{-1.0f, -1.0f, -1.0f}}};
1438*89a0ef05SAndroid Build Coastguard Worker 
1439*89a0ef05SAndroid Build Coastguard Worker       for (size_t dy = 0; dy < kMapScaleFactor; ++dy) {
1440*89a0ef05SAndroid Build Coastguard Worker         for (size_t dx = 0; dx < kMapScaleFactor; ++dx) {
1441*89a0ef05SAndroid Build Coastguard Worker           Color e = colors[y * kMapScaleFactor + dy][x * kMapScaleFactor + dx];
1442*89a0ef05SAndroid Build Coastguard Worker           min = ColorMin(min, e);
1443*89a0ef05SAndroid Build Coastguard Worker           max = ColorMax(max, e);
1444*89a0ef05SAndroid Build Coastguard Worker         }
1445*89a0ef05SAndroid Build Coastguard Worker       }
1446*89a0ef05SAndroid Build Coastguard Worker 
1447*89a0ef05SAndroid Build Coastguard Worker       // Instead of reimplementing the sampling algorithm, confirm that the
1448*89a0ef05SAndroid Build Coastguard Worker       // sample output is within the range of the min and max of the nearest
1449*89a0ef05SAndroid Build Coastguard Worker       // points.
1450*89a0ef05SAndroid Build Coastguard Worker       EXPECT_YUV_BETWEEN(sampleYuv420(&image, kMapScaleFactor, x, y), min, max);
1451*89a0ef05SAndroid Build Coastguard Worker     }
1452*89a0ef05SAndroid Build Coastguard Worker   }
1453*89a0ef05SAndroid Build Coastguard Worker }
1454*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,SampleP010)1455*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, SampleP010) {
1456*89a0ef05SAndroid Build Coastguard Worker   auto image = P010Image();
1457*89a0ef05SAndroid Build Coastguard Worker   Color(*colors)[4] = P010Colors();
1458*89a0ef05SAndroid Build Coastguard Worker 
1459*89a0ef05SAndroid Build Coastguard Worker   static const size_t kMapScaleFactor = 2;
1460*89a0ef05SAndroid Build Coastguard Worker   for (size_t y = 0; y < 4 / kMapScaleFactor; ++y) {
1461*89a0ef05SAndroid Build Coastguard Worker     for (size_t x = 0; x < 4 / kMapScaleFactor; ++x) {
1462*89a0ef05SAndroid Build Coastguard Worker       Color min = {{{1.0f, 1.0f, 1.0f}}};
1463*89a0ef05SAndroid Build Coastguard Worker       Color max = {{{-1.0f, -1.0f, -1.0f}}};
1464*89a0ef05SAndroid Build Coastguard Worker 
1465*89a0ef05SAndroid Build Coastguard Worker       for (size_t dy = 0; dy < kMapScaleFactor; ++dy) {
1466*89a0ef05SAndroid Build Coastguard Worker         for (size_t dx = 0; dx < kMapScaleFactor; ++dx) {
1467*89a0ef05SAndroid Build Coastguard Worker           Color e = colors[y * kMapScaleFactor + dy][x * kMapScaleFactor + dx];
1468*89a0ef05SAndroid Build Coastguard Worker           min = ColorMin(min, e);
1469*89a0ef05SAndroid Build Coastguard Worker           max = ColorMax(max, e);
1470*89a0ef05SAndroid Build Coastguard Worker         }
1471*89a0ef05SAndroid Build Coastguard Worker       }
1472*89a0ef05SAndroid Build Coastguard Worker 
1473*89a0ef05SAndroid Build Coastguard Worker       // Instead of reimplementing the sampling algorithm, confirm that the
1474*89a0ef05SAndroid Build Coastguard Worker       // sample output is within the range of the min and max of the nearest
1475*89a0ef05SAndroid Build Coastguard Worker       // points.
1476*89a0ef05SAndroid Build Coastguard Worker       EXPECT_YUV_BETWEEN(sampleP010(&image, kMapScaleFactor, x, y), min, max);
1477*89a0ef05SAndroid Build Coastguard Worker     }
1478*89a0ef05SAndroid Build Coastguard Worker   }
1479*89a0ef05SAndroid Build Coastguard Worker }
1480*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,SampleMap)1481*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, SampleMap) {
1482*89a0ef05SAndroid Build Coastguard Worker   auto image = MapImage();
1483*89a0ef05SAndroid Build Coastguard Worker   float(*values)[4] = MapValues();
1484*89a0ef05SAndroid Build Coastguard Worker 
1485*89a0ef05SAndroid Build Coastguard Worker   static const size_t kMapScaleFactor = 2;
1486*89a0ef05SAndroid Build Coastguard Worker   ShepardsIDW idwTable(kMapScaleFactor);
1487*89a0ef05SAndroid Build Coastguard Worker   for (size_t y = 0; y < 4 * kMapScaleFactor; ++y) {
1488*89a0ef05SAndroid Build Coastguard Worker     for (size_t x = 0; x < 4 * kMapScaleFactor; ++x) {
1489*89a0ef05SAndroid Build Coastguard Worker       size_t x_base = x / kMapScaleFactor;
1490*89a0ef05SAndroid Build Coastguard Worker       size_t y_base = y / kMapScaleFactor;
1491*89a0ef05SAndroid Build Coastguard Worker 
1492*89a0ef05SAndroid Build Coastguard Worker       float min = 1.0f;
1493*89a0ef05SAndroid Build Coastguard Worker       float max = -1.0f;
1494*89a0ef05SAndroid Build Coastguard Worker 
1495*89a0ef05SAndroid Build Coastguard Worker       min = fmin(min, values[y_base][x_base]);
1496*89a0ef05SAndroid Build Coastguard Worker       max = fmax(max, values[y_base][x_base]);
1497*89a0ef05SAndroid Build Coastguard Worker       if (y_base + 1 < 4) {
1498*89a0ef05SAndroid Build Coastguard Worker         min = fmin(min, values[y_base + 1][x_base]);
1499*89a0ef05SAndroid Build Coastguard Worker         max = fmax(max, values[y_base + 1][x_base]);
1500*89a0ef05SAndroid Build Coastguard Worker       }
1501*89a0ef05SAndroid Build Coastguard Worker       if (x_base + 1 < 4) {
1502*89a0ef05SAndroid Build Coastguard Worker         min = fmin(min, values[y_base][x_base + 1]);
1503*89a0ef05SAndroid Build Coastguard Worker         max = fmax(max, values[y_base][x_base + 1]);
1504*89a0ef05SAndroid Build Coastguard Worker       }
1505*89a0ef05SAndroid Build Coastguard Worker       if (y_base + 1 < 4 && x_base + 1 < 4) {
1506*89a0ef05SAndroid Build Coastguard Worker         min = fmin(min, values[y_base + 1][x_base + 1]);
1507*89a0ef05SAndroid Build Coastguard Worker         max = fmax(max, values[y_base + 1][x_base + 1]);
1508*89a0ef05SAndroid Build Coastguard Worker       }
1509*89a0ef05SAndroid Build Coastguard Worker 
1510*89a0ef05SAndroid Build Coastguard Worker       // Instead of reimplementing the sampling algorithm, confirm that the
1511*89a0ef05SAndroid Build Coastguard Worker       // sample output is within the range of the min and max of the nearest
1512*89a0ef05SAndroid Build Coastguard Worker       // points.
1513*89a0ef05SAndroid Build Coastguard Worker       EXPECT_THAT(sampleMap(&image, kMapScaleFactor, x, y),
1514*89a0ef05SAndroid Build Coastguard Worker                   testing::AllOf(testing::Ge(min), testing::Le(max)));
1515*89a0ef05SAndroid Build Coastguard Worker       EXPECT_EQ(sampleMap(&image, kMapScaleFactor, x, y, idwTable),
1516*89a0ef05SAndroid Build Coastguard Worker                 sampleMap(&image, kMapScaleFactor, x, y));
1517*89a0ef05SAndroid Build Coastguard Worker     }
1518*89a0ef05SAndroid Build Coastguard Worker   }
1519*89a0ef05SAndroid Build Coastguard Worker }
1520*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ColorToRgba1010102)1521*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ColorToRgba1010102) {
1522*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgba1010102(RgbBlack()), 0x3 << 30);
1523*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgba1010102(RgbWhite()), 0xFFFFFFFF);
1524*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgba1010102(RgbRed()), 0x3 << 30 | 0x3ff);
1525*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgba1010102(RgbGreen()), 0x3 << 30 | 0x3ff << 10);
1526*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgba1010102(RgbBlue()), 0x3 << 30 | 0x3ff << 20);
1527*89a0ef05SAndroid Build Coastguard Worker 
1528*89a0ef05SAndroid Build Coastguard Worker   Color e_gamma = {{{0.1f, 0.2f, 0.3f}}};
1529*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgba1010102(e_gamma),
1530*89a0ef05SAndroid Build Coastguard Worker             0x3 << 30 | static_cast<uint32_t>(0.1f * static_cast<float>(0x3ff) + 0.5) |
1531*89a0ef05SAndroid Build Coastguard Worker                 static_cast<uint32_t>(0.2f * static_cast<float>(0x3ff) + 0.5) << 10 |
1532*89a0ef05SAndroid Build Coastguard Worker                 static_cast<uint32_t>(0.3f * static_cast<float>(0x3ff) + 0.5) << 20);
1533*89a0ef05SAndroid Build Coastguard Worker }
1534*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ColorToRgbaF16)1535*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ColorToRgbaF16) {
1536*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgbaF16(RgbBlack()), ((uint64_t)0x3C00) << 48);
1537*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgbaF16(RgbWhite()), 0x3C003C003C003C00);
1538*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgbaF16(RgbRed()), (((uint64_t)0x3C00) << 48) | ((uint64_t)0x3C00));
1539*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgbaF16(RgbGreen()), (((uint64_t)0x3C00) << 48) | (((uint64_t)0x3C00) << 16));
1540*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgbaF16(RgbBlue()), (((uint64_t)0x3C00) << 48) | (((uint64_t)0x3C00) << 32));
1541*89a0ef05SAndroid Build Coastguard Worker 
1542*89a0ef05SAndroid Build Coastguard Worker   Color e_gamma = {{{0.1f, 0.2f, 0.3f}}};
1543*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(colorToRgbaF16(e_gamma), 0x3C0034CD32662E66);
1544*89a0ef05SAndroid Build Coastguard Worker }
1545*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,Float32ToFloat16)1546*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, Float32ToFloat16) {
1547*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(floatToHalf(0.1f), 0x2E66);
1548*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(floatToHalf(0.0f), 0x0);
1549*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(floatToHalf(1.0f), 0x3C00);
1550*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(floatToHalf(-1.0f), 0xBC00);
1551*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(floatToHalf(0x1.fffffep127f), 0x7FFF);   // float max
1552*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(floatToHalf(-0x1.fffffep127f), 0xFFFF);  // float min
1553*89a0ef05SAndroid Build Coastguard Worker   EXPECT_EQ(floatToHalf(0x1.0p-126f), 0x0);          // float zero
1554*89a0ef05SAndroid Build Coastguard Worker }
1555*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,GenerateMapLuminanceSrgb)1556*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, GenerateMapLuminanceSrgb) {
1557*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), srgbLuminance), 0.0f);
1558*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), srgbLuminance), kSdrWhiteNits);
1559*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), srgbLuminance),
1560*89a0ef05SAndroid Build Coastguard Worker               srgbLuminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
1561*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), srgbLuminance),
1562*89a0ef05SAndroid Build Coastguard Worker               srgbLuminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
1563*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), srgbLuminance),
1564*89a0ef05SAndroid Build Coastguard Worker               srgbLuminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1565*89a0ef05SAndroid Build Coastguard Worker }
1566*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,GenerateMapLuminanceSrgbP3)1567*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbP3) {
1568*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), p3Luminance), 0.0f);
1569*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), p3Luminance), kSdrWhiteNits);
1570*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), p3Luminance), p3Luminance(RgbRed()) * kSdrWhiteNits,
1571*89a0ef05SAndroid Build Coastguard Worker               LuminanceEpsilon());
1572*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), p3Luminance),
1573*89a0ef05SAndroid Build Coastguard Worker               p3Luminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
1574*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), p3Luminance),
1575*89a0ef05SAndroid Build Coastguard Worker               p3Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1576*89a0ef05SAndroid Build Coastguard Worker }
1577*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,GenerateMapLuminanceSrgbBt2100)1578*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbBt2100) {
1579*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), bt2100Luminance), 0.0f);
1580*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), bt2100Luminance), kSdrWhiteNits);
1581*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvRed(), bt2100Luminance),
1582*89a0ef05SAndroid Build Coastguard Worker               bt2100Luminance(RgbRed()) * kSdrWhiteNits, LuminanceEpsilon());
1583*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvGreen(), bt2100Luminance),
1584*89a0ef05SAndroid Build Coastguard Worker               bt2100Luminance(RgbGreen()) * kSdrWhiteNits, LuminanceEpsilon());
1585*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(SrgbYuvToLuminance(SrgbYuvBlue(), bt2100Luminance),
1586*89a0ef05SAndroid Build Coastguard Worker               bt2100Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
1587*89a0ef05SAndroid Build Coastguard Worker }
1588*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,GenerateMapLuminanceHlg)1589*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, GenerateMapLuminanceHlg) {
1590*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), hlgInvOetf, identityConversion, bt2100Luminance,
1591*89a0ef05SAndroid Build Coastguard Worker                                        kHlgMaxNits),
1592*89a0ef05SAndroid Build Coastguard Worker                   0.0f);
1593*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvWhite(), hlgInvOetf, identityConversion, bt2100Luminance,
1594*89a0ef05SAndroid Build Coastguard Worker                                        kHlgMaxNits),
1595*89a0ef05SAndroid Build Coastguard Worker                   kHlgMaxNits);
1596*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvRed(), hlgInvOetf, identityConversion, bt2100Luminance,
1597*89a0ef05SAndroid Build Coastguard Worker                                    kHlgMaxNits),
1598*89a0ef05SAndroid Build Coastguard Worker               bt2100Luminance(RgbRed()) * kHlgMaxNits, LuminanceEpsilon());
1599*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvGreen(), hlgInvOetf, identityConversion,
1600*89a0ef05SAndroid Build Coastguard Worker                                    bt2100Luminance, kHlgMaxNits),
1601*89a0ef05SAndroid Build Coastguard Worker               bt2100Luminance(RgbGreen()) * kHlgMaxNits, LuminanceEpsilon());
1602*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvBlue(), hlgInvOetf, identityConversion, bt2100Luminance,
1603*89a0ef05SAndroid Build Coastguard Worker                                    kHlgMaxNits),
1604*89a0ef05SAndroid Build Coastguard Worker               bt2100Luminance(RgbBlue()) * kHlgMaxNits, LuminanceEpsilon());
1605*89a0ef05SAndroid Build Coastguard Worker }
1606*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,GenerateMapLuminancePq)1607*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, GenerateMapLuminancePq) {
1608*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(
1609*89a0ef05SAndroid Build Coastguard Worker       Bt2100YuvToLuminance(YuvBlack(), pqInvOetf, identityConversion, bt2100Luminance, kPqMaxNits),
1610*89a0ef05SAndroid Build Coastguard Worker       0.0f);
1611*89a0ef05SAndroid Build Coastguard Worker   EXPECT_FLOAT_EQ(
1612*89a0ef05SAndroid Build Coastguard Worker       Bt2100YuvToLuminance(YuvWhite(), pqInvOetf, identityConversion, bt2100Luminance, kPqMaxNits),
1613*89a0ef05SAndroid Build Coastguard Worker       kPqMaxNits);
1614*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvRed(), pqInvOetf, identityConversion, bt2100Luminance,
1615*89a0ef05SAndroid Build Coastguard Worker                                    kPqMaxNits),
1616*89a0ef05SAndroid Build Coastguard Worker               bt2100Luminance(RgbRed()) * kPqMaxNits, LuminanceEpsilon());
1617*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvGreen(), pqInvOetf, identityConversion, bt2100Luminance,
1618*89a0ef05SAndroid Build Coastguard Worker                                    kPqMaxNits),
1619*89a0ef05SAndroid Build Coastguard Worker               bt2100Luminance(RgbGreen()) * kPqMaxNits, LuminanceEpsilon());
1620*89a0ef05SAndroid Build Coastguard Worker   EXPECT_NEAR(Bt2100YuvToLuminance(Bt2100YuvBlue(), pqInvOetf, identityConversion, bt2100Luminance,
1621*89a0ef05SAndroid Build Coastguard Worker                                    kPqMaxNits),
1622*89a0ef05SAndroid Build Coastguard Worker               bt2100Luminance(RgbBlue()) * kPqMaxNits, LuminanceEpsilon());
1623*89a0ef05SAndroid Build Coastguard Worker }
1624*89a0ef05SAndroid Build Coastguard Worker 
TEST_F(GainMapMathTest,ApplyMap)1625*89a0ef05SAndroid Build Coastguard Worker TEST_F(GainMapMathTest, ApplyMap) {
1626*89a0ef05SAndroid Build Coastguard Worker   uhdr_gainmap_metadata_ext_t metadata;
1627*89a0ef05SAndroid Build Coastguard Worker 
1628*89a0ef05SAndroid Build Coastguard Worker   metadata.min_content_boost = 1.0f / 8.0f;
1629*89a0ef05SAndroid Build Coastguard Worker   metadata.max_content_boost = 8.0f;
1630*89a0ef05SAndroid Build Coastguard Worker   metadata.offset_sdr = 0.0f;
1631*89a0ef05SAndroid Build Coastguard Worker   metadata.offset_hdr = 0.0f;
1632*89a0ef05SAndroid Build Coastguard Worker   metadata.gamma = 1.0f;
1633*89a0ef05SAndroid Build Coastguard Worker 
1634*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
1635*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvBlack(), 1.0f, &metadata), RgbBlack());
1636*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 1.0f, &metadata), RgbRed() * 8.0f);
1637*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 1.0f, &metadata), RgbGreen() * 8.0f);
1638*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 1.0f, &metadata), RgbBlue() * 8.0f);
1639*89a0ef05SAndroid Build Coastguard Worker 
1640*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 0.75f, &metadata), RgbWhite() * sqrt(8.0f));
1641*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvBlack(), 0.75f, &metadata), RgbBlack());
1642*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.75f, &metadata), RgbRed() * sqrt(8.0f));
1643*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.75f, &metadata), RgbGreen() * sqrt(8.0f));
1644*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.75f, &metadata), RgbBlue() * sqrt(8.0f));
1645*89a0ef05SAndroid Build Coastguard Worker 
1646*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 0.5f, &metadata), RgbWhite());
1647*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvBlack(), 0.5f, &metadata), RgbBlack());
1648*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.5f, &metadata), RgbRed());
1649*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.5f, &metadata), RgbGreen());
1650*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.5f, &metadata), RgbBlue());
1651*89a0ef05SAndroid Build Coastguard Worker 
1652*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 0.25f, &metadata), RgbWhite() / sqrt(8.0f));
1653*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvBlack(), 0.25f, &metadata), RgbBlack());
1654*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.25f, &metadata), RgbRed() / sqrt(8.0f));
1655*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.25f, &metadata), RgbGreen() / sqrt(8.0f));
1656*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.25f, &metadata), RgbBlue() / sqrt(8.0f));
1657*89a0ef05SAndroid Build Coastguard Worker 
1658*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata), RgbWhite() / 8.0f);
1659*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvBlack(), 0.0f, &metadata), RgbBlack());
1660*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvRed(), 0.0f, &metadata), RgbRed() / 8.0f);
1661*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvGreen(), 0.0f, &metadata), RgbGreen() / 8.0f);
1662*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_CLOSE(Recover(SrgbYuvBlue(), 0.0f, &metadata), RgbBlue() / 8.0f);
1663*89a0ef05SAndroid Build Coastguard Worker 
1664*89a0ef05SAndroid Build Coastguard Worker   metadata.max_content_boost = 8.0f;
1665*89a0ef05SAndroid Build Coastguard Worker   metadata.min_content_boost = 1.0f;
1666*89a0ef05SAndroid Build Coastguard Worker 
1667*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
1668*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 2.0f / 3.0f, &metadata), RgbWhite() * 4.0f);
1669*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f / 3.0f, &metadata), RgbWhite() * 2.0f);
1670*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata), RgbWhite());
1671*89a0ef05SAndroid Build Coastguard Worker 
1672*89a0ef05SAndroid Build Coastguard Worker   metadata.max_content_boost = 8.0f;
1673*89a0ef05SAndroid Build Coastguard Worker   metadata.min_content_boost = 0.5f;
1674*89a0ef05SAndroid Build Coastguard Worker 
1675*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
1676*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 0.75, &metadata), RgbWhite() * 4.0f);
1677*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 0.5f, &metadata), RgbWhite() * 2.0f);
1678*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 0.25f, &metadata), RgbWhite());
1679*89a0ef05SAndroid Build Coastguard Worker   EXPECT_RGB_EQ(Recover(YuvWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
1680*89a0ef05SAndroid Build Coastguard Worker }
1681*89a0ef05SAndroid Build Coastguard Worker 
1682*89a0ef05SAndroid Build Coastguard Worker }  // namespace ultrahdr
1683