Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "ColorSpaceTest"
     18 
     19 #include <math.h>
     20 #include <stdlib.h>
     21 
     22 #include <ui/ColorSpace.h>
     23 
     24 #include <gtest/gtest.h>
     25 
     26 namespace android {
     27 
     28 class ColorSpaceTest : public testing::Test {
     29 protected:
     30 };
     31 
     32 TEST_F(ColorSpaceTest, XYZ) {
     33     mat3 sRGBToXYZ(transpose(mat3{
     34         0.412391f, 0.357584f, 0.180481f,
     35         0.212639f, 0.715169f, 0.072192f,
     36         0.019331f, 0.119195f, 0.950532f
     37     }));
     38 
     39     mat3 XYZtoSRGB(inverse(sRGBToXYZ));
     40 
     41     ColorSpace sRGB("sRGB", sRGBToXYZ);
     42 
     43     EXPECT_EQ(sRGBToXYZ, sRGB.getRGBtoXYZ());
     44     EXPECT_EQ(XYZtoSRGB, sRGB.getXYZtoRGB());
     45 }
     46 
     47 TEST_F(ColorSpaceTest, XYZPrimaries) {
     48     mat3 sRGBToXYZ(transpose(mat3{
     49         0.412391f, 0.357584f, 0.180481f,
     50         0.212639f, 0.715169f, 0.072192f,
     51         0.019331f, 0.119195f, 0.950532f
     52     }));
     53 
     54     ColorSpace sRGB("sRGB", sRGBToXYZ);
     55 
     56     EXPECT_NEAR(0.640f, sRGB.getPrimaries()[0].x, 1e-5f);
     57     EXPECT_NEAR(0.330f, sRGB.getPrimaries()[0].y, 1e-5f);
     58 
     59     EXPECT_NEAR(0.300f, sRGB.getPrimaries()[1].x, 1e-5f);
     60     EXPECT_NEAR(0.600f, sRGB.getPrimaries()[1].y, 1e-5f);
     61 
     62     EXPECT_NEAR(0.150f, sRGB.getPrimaries()[2].x, 1e-5f);
     63     EXPECT_NEAR(0.060f, sRGB.getPrimaries()[2].y, 1e-5f);
     64 }
     65 
     66 TEST_F(ColorSpaceTest, XYZWhitePoint) {
     67     mat3 sRGBToXYZ(transpose(mat3{
     68         0.412391f, 0.357584f, 0.180481f,
     69         0.212639f, 0.715169f, 0.072192f,
     70         0.019331f, 0.119195f, 0.950532f
     71     }));
     72 
     73     ColorSpace sRGB("sRGB", sRGBToXYZ);
     74 
     75     EXPECT_NEAR(0.3127f, sRGB.getWhitePoint().x, 1e-5f);
     76     EXPECT_NEAR(0.3290f, sRGB.getWhitePoint().y, 1e-5f);
     77 }
     78 
     79 TEST_F(ColorSpaceTest, XYZFromPrimaries) {
     80     mat3 sRGBToXYZ(transpose(mat3{
     81         0.412391f, 0.357584f, 0.180481f,
     82         0.212639f, 0.715169f, 0.072192f,
     83         0.019331f, 0.119195f, 0.950532f
     84     }));
     85 
     86     ColorSpace sRGB1("sRGB", sRGBToXYZ);
     87     ColorSpace sRGB2(
     88           "sRGB",
     89           {{float2{0.640f, 0.330f}, {0.300f, 0.600f}, {0.150f, 0.060f}}},
     90           {0.3127f, 0.3290f}
     91     );
     92 
     93     for (size_t i = 0; i < 3; i++) {
     94         for (size_t j= 0; j < 3; j++) {
     95             ASSERT_NEAR(sRGB1.getRGBtoXYZ()[i][j], sRGB2.getRGBtoXYZ()[i][j], 1e-5f);
     96         }
     97     }
     98 
     99     for (size_t i = 0; i < 3; i++) {
    100         for (size_t j= 0; j < 3; j++) {
    101             ASSERT_NEAR(sRGB2.getXYZtoRGB()[i][j], sRGB2.getXYZtoRGB()[i][j], 1e-5f);
    102         }
    103     }
    104 }
    105 
    106 TEST_F(ColorSpaceTest, TransferFunctions) {
    107     ColorSpace sRGB = ColorSpace::sRGB();
    108 
    109     EXPECT_NEAR(0.0f, sRGB.getEOTF()(0.0f), 1e-6f);
    110     EXPECT_NEAR(0.0f, sRGB.getOETF()(0.0f), 1e-6f);
    111     EXPECT_NEAR(1.0f, sRGB.getEOTF()(1.0f), 1e-6f);
    112     EXPECT_NEAR(1.0f, sRGB.getOETF()(1.0f), 1e-6f);
    113 
    114     for (float v = 0.0f; v <= 0.5f; v += 1e-3f) {
    115         ASSERT_TRUE(v >= sRGB.getEOTF()(v));
    116         ASSERT_TRUE(v <= sRGB.getOETF()(v));
    117     }
    118 
    119     float previousEOTF = std::numeric_limits<float>::lowest();
    120     float previousOETF = std::numeric_limits<float>::lowest();
    121     for (float v = 0.0f; v <= 1.0f; v += 1e-3f) {
    122         ASSERT_TRUE(previousEOTF < sRGB.getEOTF()(v));
    123         previousEOTF = sRGB.getEOTF()(v);
    124         ASSERT_TRUE(previousOETF < sRGB.getOETF()(v));
    125         previousOETF = sRGB.getOETF()(v);
    126     }
    127 
    128     ColorSpace sRGB2(
    129           "sRGB",
    130           {{float2{0.640f, 0.330f}, {0.300f, 0.600f}, {0.150f, 0.060f}}},
    131           {0.3127f, 0.3290f}
    132           // linear transfer functions
    133     );
    134     for (float v = 0.0f; v <= 1.0f; v += 1e-3f) {
    135         ASSERT_EQ(v, sRGB2.getEOTF()(v));
    136         ASSERT_EQ(v, sRGB2.getOETF()(v));
    137     }
    138 }
    139 
    140 TEST_F(ColorSpaceTest, Clamping) {
    141     // Pick a color outside of sRGB
    142     float3 c(ColorSpace::BT2020().rgbToXYZ(float3{0, 1, 0}));
    143 
    144     // The color will be clamped
    145     float3 sRGB(ColorSpace::sRGB().xyzToRGB(c));
    146     EXPECT_TRUE(sRGB > float3{0.0} && sRGB < float3{1.0});
    147 
    148     // The color will not be clamped
    149     float3 extendedSRGB(ColorSpace::linearExtendedSRGB().xyzToRGB(c));
    150     EXPECT_TRUE(extendedSRGB.g > 1.0f);
    151 }
    152 
    153 TEST_F(ColorSpaceTest, Connect) {
    154     // No chromatic adaptation
    155     auto r = ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::AdobeRGB())
    156             .transform({1.0f, 0.5f, 0.0f});
    157     EXPECT_TRUE(all(lessThan(abs(r - float3{0.8912f, 0.4962f, 0.1164f}), float3{1e-4f})));
    158 
    159     // Test with chromatic adaptation
    160     r = ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::ProPhotoRGB())
    161             .transform({1.0f, 0.0f, 0.0f});
    162     EXPECT_TRUE(all(lessThan(abs(r - float3{0.70226f, 0.2757f, 0.1036f}), float3{1e-4f})));
    163 }
    164 
    165 TEST_F(ColorSpaceTest, LUT) {
    166     auto lut = ColorSpace::createLUT(17, ColorSpace::sRGB(), ColorSpace::AdobeRGB());
    167     EXPECT_TRUE(lut != nullptr);
    168 
    169     // {1.0f, 0.5f, 0.0f}
    170     auto r = lut.get()[0 * 17 * 17 + 8 * 17 + 16];
    171     EXPECT_TRUE(all(lessThan(abs(r - float3{0.8912f, 0.4962f, 0.1164f}), float3{1e-4f})));
    172 
    173     // {1.0f, 1.0f, 0.5f}
    174     r = lut.get()[8 * 17 * 17 + 0 * 17 + 16]; // y (G) is flipped
    175     EXPECT_TRUE(all(lessThan(abs(r - float3{1.0f, 1.0f, 0.5290f}), float3{1e-4f})));
    176 
    177     // {1.0f, 1.0f, 1.0f}
    178     r = lut.get()[16 * 17 * 17 + 0 * 17 + 16]; // y (G) is flipped
    179     EXPECT_TRUE(all(lessThan(abs(r - float3{1.0f, 1.0f, 1.0f}), float3{1e-4f})));
    180 
    181 }
    182 
    183 }; // namespace android
    184