msarett | 6a73821 | 2016-03-04 13:27:35 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #include "Resources.h" |
| 9 | #include "SkCodec.h" |
| 10 | #include "SkColorSpace.h" |
Matt Sarett | 1e85424 | 2017-01-04 10:53:31 -0500 | [diff] [blame] | 11 | #include "SkColorSpacePriv.h" |
Ben Wagner | eed6128 | 2018-04-17 14:14:51 -0400 | [diff] [blame] | 12 | #include "SkColorSpace_XYZ.h" |
| 13 | #include "SkData.h" |
| 14 | #include "SkImageInfo.h" |
| 15 | #include "SkMatrix44.h" |
| 16 | #include "SkRefCnt.h" |
| 17 | #include "SkStream.h" |
| 18 | #include "SkTypes.h" |
msarett | 6a73821 | 2016-03-04 13:27:35 -0800 | [diff] [blame] | 19 | #include "Test.h" |
msarett | 53add95 | 2016-03-07 17:25:12 -0800 | [diff] [blame] | 20 | #include "png.h" |
Brian Osman | 8dc68c6 | 2018-05-30 12:57:45 -0400 | [diff] [blame] | 21 | #include "../third_party/skcms/skcms.h" |
Brian Osman | 12e4e84 | 2018-04-27 12:03:51 -0400 | [diff] [blame] | 22 | |
Ben Wagner | eed6128 | 2018-04-17 14:14:51 -0400 | [diff] [blame] | 23 | #include <memory> |
| 24 | #include <utility> |
| 25 | |
reed | 50d3b57 | 2016-05-03 12:13:21 -0700 | [diff] [blame] | 26 | static bool almost_equal(float a, float b) { |
| 27 | return SkTAbs(a - b) < 0.001f; |
| 28 | } |
| 29 | |
| 30 | static void test_space(skiatest::Reporter* r, SkColorSpace* space, |
| 31 | const float red[], const float green[], const float blue[], |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 32 | const SkGammaNamed expectedGamma) { |
msarett | bb9f774 | 2016-05-17 09:31:20 -0700 | [diff] [blame] | 33 | |
msarett | 9d15dab | 2016-08-24 07:36:06 -0700 | [diff] [blame] | 34 | REPORTER_ASSERT(r, nullptr != space); |
Brian Osman | 36703d9 | 2017-12-12 14:09:31 -0500 | [diff] [blame] | 35 | REPORTER_ASSERT(r, expectedGamma == space->gammaNamed()); |
msarett | bb9f774 | 2016-05-17 09:31:20 -0700 | [diff] [blame] | 36 | |
Brian Osman | 36703d9 | 2017-12-12 14:09:31 -0500 | [diff] [blame] | 37 | const SkMatrix44& mat = *space->toXYZD50(); |
reed | 50d3b57 | 2016-05-03 12:13:21 -0700 | [diff] [blame] | 38 | const float src[] = { |
| 39 | 1, 0, 0, 1, |
| 40 | 0, 1, 0, 1, |
| 41 | 0, 0, 1, 1, |
| 42 | }; |
brianosman | de68d6c | 2016-09-09 10:36:17 -0700 | [diff] [blame] | 43 | const float* ref[3] = { red, green, blue }; |
reed | 50d3b57 | 2016-05-03 12:13:21 -0700 | [diff] [blame] | 44 | float dst[4]; |
| 45 | for (int i = 0; i < 3; ++i) { |
| 46 | mat.mapScalars(&src[i*4], dst); |
brianosman | de68d6c | 2016-09-09 10:36:17 -0700 | [diff] [blame] | 47 | REPORTER_ASSERT(r, almost_equal(ref[i][0], dst[0])); |
| 48 | REPORTER_ASSERT(r, almost_equal(ref[i][1], dst[1])); |
| 49 | REPORTER_ASSERT(r, almost_equal(ref[i][2], dst[2])); |
reed | 50d3b57 | 2016-05-03 12:13:21 -0700 | [diff] [blame] | 50 | } |
| 51 | } |
| 52 | |
msarett | 9d15dab | 2016-08-24 07:36:06 -0700 | [diff] [blame] | 53 | static void test_path(skiatest::Reporter* r, const char* path, |
| 54 | const float red[], const float green[], const float blue[], |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 55 | const SkGammaNamed expectedGamma) { |
Ben Wagner | 145dbcd | 2016-11-03 14:40:50 -0400 | [diff] [blame] | 56 | std::unique_ptr<SkStream> stream(GetResourceAsStream(path)); |
msarett | 0e6274f | 2016-03-21 08:04:40 -0700 | [diff] [blame] | 57 | REPORTER_ASSERT(r, nullptr != stream); |
Brian Salomon | d2100f2 | 2016-03-25 17:02:20 -0400 | [diff] [blame] | 58 | if (!stream) { |
| 59 | return; |
| 60 | } |
msarett | 0e6274f | 2016-03-21 08:04:40 -0700 | [diff] [blame] | 61 | |
Mike Reed | ede7bac | 2017-07-23 15:30:02 -0400 | [diff] [blame] | 62 | std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream))); |
msarett | 0e6274f | 2016-03-21 08:04:40 -0700 | [diff] [blame] | 63 | REPORTER_ASSERT(r, nullptr != codec); |
Brian Salomon | d2100f2 | 2016-03-25 17:02:20 -0400 | [diff] [blame] | 64 | if (!codec) { |
| 65 | return; |
| 66 | } |
msarett | 0e6274f | 2016-03-21 08:04:40 -0700 | [diff] [blame] | 67 | |
msarett | 530c844 | 2016-07-21 11:57:49 -0700 | [diff] [blame] | 68 | SkColorSpace* colorSpace = codec->getInfo().colorSpace(); |
msarett | 9d15dab | 2016-08-24 07:36:06 -0700 | [diff] [blame] | 69 | test_space(r, colorSpace, red, green, blue, expectedGamma); |
| 70 | } |
| 71 | |
brianosman | de68d6c | 2016-09-09 10:36:17 -0700 | [diff] [blame] | 72 | static constexpr float g_sRGB_XYZ[]{ |
| 73 | 0.4358f, 0.3853f, 0.1430f, // Rx, Gx, Bx |
| 74 | 0.2224f, 0.7170f, 0.0606f, // Ry, Gy, Gz |
| 75 | 0.0139f, 0.0971f, 0.7139f, // Rz, Gz, Bz |
| 76 | }; |
| 77 | |
| 78 | static constexpr float g_sRGB_R[]{ 0.4358f, 0.2224f, 0.0139f }; |
| 79 | static constexpr float g_sRGB_G[]{ 0.3853f, 0.7170f, 0.0971f }; |
| 80 | static constexpr float g_sRGB_B[]{ 0.1430f, 0.0606f, 0.7139f }; |
msarett | 9d15dab | 2016-08-24 07:36:06 -0700 | [diff] [blame] | 81 | |
| 82 | DEF_TEST(ColorSpace_sRGB, r) { |
Matt Sarett | 77a7a1b | 2017-02-07 13:56:11 -0500 | [diff] [blame] | 83 | test_space(r, SkColorSpace::MakeSRGB().get(), |
brianosman | de68d6c | 2016-09-09 10:36:17 -0700 | [diff] [blame] | 84 | g_sRGB_R, g_sRGB_G, g_sRGB_B, kSRGB_SkGammaNamed); |
msarett | 9d15dab | 2016-08-24 07:36:06 -0700 | [diff] [blame] | 85 | |
| 86 | } |
| 87 | |
| 88 | DEF_TEST(ColorSpaceParseICCProfiles, r) { |
| 89 | |
| 90 | #if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 6) |
Hal Canary | c465d13 | 2017-12-08 10:21:31 -0500 | [diff] [blame] | 91 | test_path(r, "images/color_wheel_with_profile.png", g_sRGB_R, g_sRGB_G, g_sRGB_B, |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 92 | kSRGB_SkGammaNamed); |
msarett | 9d15dab | 2016-08-24 07:36:06 -0700 | [diff] [blame] | 93 | #endif |
msarett | 0e6274f | 2016-03-21 08:04:40 -0700 | [diff] [blame] | 94 | |
reed | 50d3b57 | 2016-05-03 12:13:21 -0700 | [diff] [blame] | 95 | const float red[] = { 0.385117f, 0.716904f, 0.0970612f }; |
| 96 | const float green[] = { 0.143051f, 0.0606079f, 0.713913f }; |
| 97 | const float blue[] = { 0.436035f, 0.222488f, 0.013916f }; |
Hal Canary | c465d13 | 2017-12-08 10:21:31 -0500 | [diff] [blame] | 98 | test_path(r, "images/icc-v2-gbr.jpg", red, green, blue, k2Dot2Curve_SkGammaNamed); |
msarett | 9d15dab | 2016-08-24 07:36:06 -0700 | [diff] [blame] | 99 | |
Hal Canary | c465d13 | 2017-12-08 10:21:31 -0500 | [diff] [blame] | 100 | test_path(r, "images/webp-color-profile-crash.webp", |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 101 | red, green, blue, kNonStandard_SkGammaNamed); |
Hal Canary | c465d13 | 2017-12-08 10:21:31 -0500 | [diff] [blame] | 102 | test_path(r, "images/webp-color-profile-lossless.webp", |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 103 | red, green, blue, kNonStandard_SkGammaNamed); |
Hal Canary | c465d13 | 2017-12-08 10:21:31 -0500 | [diff] [blame] | 104 | test_path(r, "images/webp-color-profile-lossy.webp", |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 105 | red, green, blue, kNonStandard_SkGammaNamed); |
Hal Canary | c465d13 | 2017-12-08 10:21:31 -0500 | [diff] [blame] | 106 | test_path(r, "images/webp-color-profile-lossy-alpha.webp", |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 107 | red, green, blue, kNonStandard_SkGammaNamed); |
msarett | 0e6274f | 2016-03-21 08:04:40 -0700 | [diff] [blame] | 108 | } |
msarett | 02125d1 | 2016-05-03 14:24:47 -0700 | [diff] [blame] | 109 | |
| 110 | DEF_TEST(ColorSpaceSRGBCompare, r) { |
| 111 | // Create an sRGB color space by name |
Matt Sarett | 77a7a1b | 2017-02-07 13:56:11 -0500 | [diff] [blame] | 112 | sk_sp<SkColorSpace> namedColorSpace = SkColorSpace::MakeSRGB(); |
msarett | 02125d1 | 2016-05-03 14:24:47 -0700 | [diff] [blame] | 113 | |
| 114 | // Create an sRGB color space by value |
| 115 | SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); |
msarett | c1a3e24 | 2016-06-23 12:42:29 -0700 | [diff] [blame] | 116 | srgbToxyzD50.set3x3RowMajorf(g_sRGB_XYZ); |
msarett | 48ba2b8 | 2016-09-07 18:55:49 -0700 | [diff] [blame] | 117 | sk_sp<SkColorSpace> rgbColorSpace = |
Brian Osman | 526972e | 2016-10-24 09:24:02 -0400 | [diff] [blame] | 118 | SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, srgbToxyzD50); |
msarett | ab926f0 | 2016-05-25 08:53:40 -0700 | [diff] [blame] | 119 | REPORTER_ASSERT(r, rgbColorSpace == namedColorSpace); |
msarett | 02125d1 | 2016-05-03 14:24:47 -0700 | [diff] [blame] | 120 | |
Matt Sarett | 1e85424 | 2017-01-04 10:53:31 -0500 | [diff] [blame] | 121 | SkColorSpaceTransferFn srgbFn; |
| 122 | srgbFn.fA = (1.0f / 1.055f); |
| 123 | srgbFn.fB = (0.055f / 1.055f); |
| 124 | srgbFn.fC = (1.0f / 12.92f); |
| 125 | srgbFn.fD = 0.04045f; |
| 126 | srgbFn.fE = 0.0f; |
| 127 | srgbFn.fF = 0.0f; |
| 128 | srgbFn.fG = 2.4f; |
| 129 | sk_sp<SkColorSpace> rgbColorSpace2 = SkColorSpace::MakeRGB(srgbFn, srgbToxyzD50); |
| 130 | REPORTER_ASSERT(r, rgbColorSpace2 == namedColorSpace); |
| 131 | |
msarett | 02125d1 | 2016-05-03 14:24:47 -0700 | [diff] [blame] | 132 | // Change a single value from the sRGB matrix |
| 133 | srgbToxyzD50.set(2, 2, 0.5f); |
msarett | 48ba2b8 | 2016-09-07 18:55:49 -0700 | [diff] [blame] | 134 | sk_sp<SkColorSpace> strangeColorSpace = |
Brian Osman | 526972e | 2016-10-24 09:24:02 -0400 | [diff] [blame] | 135 | SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, srgbToxyzD50); |
msarett | 02125d1 | 2016-05-03 14:24:47 -0700 | [diff] [blame] | 136 | REPORTER_ASSERT(r, strangeColorSpace != namedColorSpace); |
| 137 | } |
msarett | ab926f0 | 2016-05-25 08:53:40 -0700 | [diff] [blame] | 138 | |
brianosman | eec8304 | 2016-09-27 15:11:47 -0700 | [diff] [blame] | 139 | DEF_TEST(ColorSpaceSRGBLinearCompare, r) { |
| 140 | // Create the linear sRGB color space by name |
Matt Sarett | 77a7a1b | 2017-02-07 13:56:11 -0500 | [diff] [blame] | 141 | sk_sp<SkColorSpace> namedColorSpace = SkColorSpace::MakeSRGBLinear(); |
brianosman | eec8304 | 2016-09-27 15:11:47 -0700 | [diff] [blame] | 142 | |
| 143 | // Create the linear sRGB color space via the sRGB color space's makeLinearGamma() |
Matt Sarett | 77a7a1b | 2017-02-07 13:56:11 -0500 | [diff] [blame] | 144 | auto srgb = SkColorSpace::MakeSRGB(); |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 145 | auto srgbXYZ = static_cast<SkColorSpace_XYZ*>(srgb.get()); |
| 146 | sk_sp<SkColorSpace> viaSrgbColorSpace = srgbXYZ->makeLinearGamma(); |
brianosman | eec8304 | 2016-09-27 15:11:47 -0700 | [diff] [blame] | 147 | REPORTER_ASSERT(r, namedColorSpace == viaSrgbColorSpace); |
| 148 | |
| 149 | // Create a linear sRGB color space by value |
| 150 | SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); |
| 151 | srgbToxyzD50.set3x3RowMajorf(g_sRGB_XYZ); |
| 152 | sk_sp<SkColorSpace> rgbColorSpace = |
Brian Osman | 526972e | 2016-10-24 09:24:02 -0400 | [diff] [blame] | 153 | SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, srgbToxyzD50); |
brianosman | eec8304 | 2016-09-27 15:11:47 -0700 | [diff] [blame] | 154 | REPORTER_ASSERT(r, rgbColorSpace == namedColorSpace); |
| 155 | |
Matt Sarett | 1e85424 | 2017-01-04 10:53:31 -0500 | [diff] [blame] | 156 | SkColorSpaceTransferFn linearExpFn; |
| 157 | linearExpFn.fA = 1.0f; |
| 158 | linearExpFn.fB = 0.0f; |
| 159 | linearExpFn.fC = 0.0f; |
| 160 | linearExpFn.fD = 0.0f; |
| 161 | linearExpFn.fE = 0.0f; |
| 162 | linearExpFn.fF = 0.0f; |
| 163 | linearExpFn.fG = 1.0f; |
| 164 | sk_sp<SkColorSpace> rgbColorSpace2 = SkColorSpace::MakeRGB(linearExpFn, srgbToxyzD50); |
| 165 | REPORTER_ASSERT(r, rgbColorSpace2 == namedColorSpace); |
| 166 | |
| 167 | SkColorSpaceTransferFn linearFn; |
| 168 | linearFn.fA = 0.0f; |
| 169 | linearFn.fB = 0.0f; |
| 170 | linearFn.fC = 1.0f; |
| 171 | linearFn.fD = 1.0f; |
| 172 | linearFn.fE = 0.0f; |
| 173 | linearFn.fF = 0.0f; |
| 174 | linearFn.fG = 0.0f; |
| 175 | sk_sp<SkColorSpace> rgbColorSpace3 = SkColorSpace::MakeRGB(linearFn, srgbToxyzD50); |
| 176 | REPORTER_ASSERT(r, rgbColorSpace3 == namedColorSpace); |
| 177 | |
brianosman | eec8304 | 2016-09-27 15:11:47 -0700 | [diff] [blame] | 178 | // Change a single value from the sRGB matrix |
| 179 | srgbToxyzD50.set(2, 2, 0.5f); |
| 180 | sk_sp<SkColorSpace> strangeColorSpace = |
Brian Osman | 526972e | 2016-10-24 09:24:02 -0400 | [diff] [blame] | 181 | SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, srgbToxyzD50); |
brianosman | eec8304 | 2016-09-27 15:11:47 -0700 | [diff] [blame] | 182 | REPORTER_ASSERT(r, strangeColorSpace != namedColorSpace); |
| 183 | } |
| 184 | |
Mike Klein | 8fcfcc5 | 2018-05-23 12:43:42 -0400 | [diff] [blame] | 185 | static void test_serialize(skiatest::Reporter* r, sk_sp<SkColorSpace> space, bool isNamed) { |
msarett | a0605bf | 2016-07-28 10:47:50 -0700 | [diff] [blame] | 186 | sk_sp<SkData> data1 = space->serialize(); |
| 187 | |
| 188 | size_t bytes = space->writeToMemory(nullptr); |
| 189 | sk_sp<SkData> data2 = SkData::MakeUninitialized(bytes); |
| 190 | space->writeToMemory(data2->writable_data()); |
| 191 | |
| 192 | sk_sp<SkColorSpace> newSpace1 = SkColorSpace::Deserialize(data1->data(), data1->size()); |
| 193 | sk_sp<SkColorSpace> newSpace2 = SkColorSpace::Deserialize(data2->data(), data2->size()); |
msarett | 111a42d | 2016-06-22 08:18:54 -0700 | [diff] [blame] | 194 | |
| 195 | if (isNamed) { |
Mike Klein | 8fcfcc5 | 2018-05-23 12:43:42 -0400 | [diff] [blame] | 196 | REPORTER_ASSERT(r, space.get() == newSpace1.get()); |
| 197 | REPORTER_ASSERT(r, space.get() == newSpace2.get()); |
msarett | 111a42d | 2016-06-22 08:18:54 -0700 | [diff] [blame] | 198 | } else { |
Mike Klein | 8fcfcc5 | 2018-05-23 12:43:42 -0400 | [diff] [blame] | 199 | REPORTER_ASSERT(r, SkColorSpace::Equals(space.get(), newSpace1.get())); |
| 200 | REPORTER_ASSERT(r, SkColorSpace::Equals(space.get(), newSpace2.get())); |
msarett | 111a42d | 2016-06-22 08:18:54 -0700 | [diff] [blame] | 201 | } |
| 202 | } |
| 203 | |
| 204 | DEF_TEST(ColorSpace_Serialize, r) { |
Mike Klein | 8fcfcc5 | 2018-05-23 12:43:42 -0400 | [diff] [blame] | 205 | test_serialize(r, SkColorSpace::MakeSRGB(), true); |
| 206 | test_serialize(r, SkColorSpace::MakeSRGBLinear(), true); |
msarett | 111a42d | 2016-06-22 08:18:54 -0700 | [diff] [blame] | 207 | |
Mike Klein | 8fcfcc5 | 2018-05-23 12:43:42 -0400 | [diff] [blame] | 208 | auto test = [&](const char* path) { |
| 209 | sk_sp<SkData> data = GetResourceAsData(path); |
| 210 | |
| 211 | skcms_ICCProfile profile; |
| 212 | REPORTER_ASSERT(r, skcms_Parse(data->data(), data->size(), &profile)); |
| 213 | |
| 214 | sk_sp<SkColorSpace> space = SkColorSpace::Make(profile); |
| 215 | REPORTER_ASSERT(r, space); |
| 216 | |
| 217 | test_serialize(r, space, false); |
| 218 | }; |
| 219 | test("icc_profiles/HP_ZR30w.icc"); |
| 220 | test("icc_profiles/HP_Z32x.icc"); |
msarett | d9015a4 | 2016-08-22 12:29:31 -0700 | [diff] [blame] | 221 | |
Matt Sarett | df44fc5 | 2016-10-11 16:57:50 -0400 | [diff] [blame] | 222 | SkColorSpaceTransferFn fn; |
| 223 | fn.fA = 1.0f; |
| 224 | fn.fB = 0.0f; |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 225 | fn.fC = 1.0f; |
Matt Sarett | df44fc5 | 2016-10-11 16:57:50 -0400 | [diff] [blame] | 226 | fn.fD = 0.5f; |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 227 | fn.fE = 0.0f; |
Matt Sarett | df44fc5 | 2016-10-11 16:57:50 -0400 | [diff] [blame] | 228 | fn.fF = 0.0f; |
| 229 | fn.fG = 1.0f; |
Matt Sarett | 99e3f7d | 2016-10-28 12:51:08 -0400 | [diff] [blame] | 230 | SkMatrix44 toXYZ(SkMatrix44::kIdentity_Constructor); |
Mike Klein | 8fcfcc5 | 2018-05-23 12:43:42 -0400 | [diff] [blame] | 231 | test_serialize(r, SkColorSpace::MakeRGB(fn, toXYZ), false); |
msarett | 111a42d | 2016-06-22 08:18:54 -0700 | [diff] [blame] | 232 | } |
| 233 | |
msarett | abbd6d5 | 2016-08-01 09:43:08 -0700 | [diff] [blame] | 234 | DEF_TEST(ColorSpace_Equals, r) { |
Matt Sarett | 77a7a1b | 2017-02-07 13:56:11 -0500 | [diff] [blame] | 235 | sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB(); |
Mike Klein | 8fcfcc5 | 2018-05-23 12:43:42 -0400 | [diff] [blame] | 236 | |
Mike Klein | 8fcfcc5 | 2018-05-23 12:43:42 -0400 | [diff] [blame] | 237 | auto parse = [&](const char* path) { |
| 238 | sk_sp<SkData> data = GetResourceAsData(path); |
| 239 | |
| 240 | skcms_ICCProfile profile; |
| 241 | REPORTER_ASSERT(r, skcms_Parse(data->data(), data->size(), &profile)); |
| 242 | |
| 243 | sk_sp<SkColorSpace> space = SkColorSpace::Make(profile); |
| 244 | REPORTER_ASSERT(r, space); |
| 245 | |
| 246 | return space; |
| 247 | }; |
| 248 | sk_sp<SkColorSpace> z30 = parse("icc_profiles/HP_ZR30w.icc"); |
| 249 | sk_sp<SkColorSpace> z32 = parse("icc_profiles/HP_Z32x.icc"); |
msarett | abbd6d5 | 2016-08-01 09:43:08 -0700 | [diff] [blame] | 250 | |
Matt Sarett | df44fc5 | 2016-10-11 16:57:50 -0400 | [diff] [blame] | 251 | SkColorSpaceTransferFn fn; |
| 252 | fn.fA = 1.0f; |
| 253 | fn.fB = 0.0f; |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 254 | fn.fC = 1.0f; |
Matt Sarett | df44fc5 | 2016-10-11 16:57:50 -0400 | [diff] [blame] | 255 | fn.fD = 0.5f; |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 256 | fn.fE = 0.0f; |
Matt Sarett | df44fc5 | 2016-10-11 16:57:50 -0400 | [diff] [blame] | 257 | fn.fF = 0.0f; |
| 258 | fn.fG = 1.0f; |
Matt Sarett | 99e3f7d | 2016-10-28 12:51:08 -0400 | [diff] [blame] | 259 | SkMatrix44 toXYZ(SkMatrix44::kIdentity_Constructor); |
Brian Osman | 526972e | 2016-10-24 09:24:02 -0400 | [diff] [blame] | 260 | sk_sp<SkColorSpace> rgb4 = SkColorSpace::MakeRGB(fn, toXYZ); |
Matt Sarett | df44fc5 | 2016-10-11 16:57:50 -0400 | [diff] [blame] | 261 | |
msarett | abbd6d5 | 2016-08-01 09:43:08 -0700 | [diff] [blame] | 262 | REPORTER_ASSERT(r, SkColorSpace::Equals(nullptr, nullptr)); |
| 263 | REPORTER_ASSERT(r, SkColorSpace::Equals(srgb.get(), srgb.get())); |
msarett | abbd6d5 | 2016-08-01 09:43:08 -0700 | [diff] [blame] | 264 | REPORTER_ASSERT(r, SkColorSpace::Equals(z30.get(), z30.get())); |
| 265 | REPORTER_ASSERT(r, SkColorSpace::Equals(z32.get(), z32.get())); |
Matt Sarett | df44fc5 | 2016-10-11 16:57:50 -0400 | [diff] [blame] | 266 | REPORTER_ASSERT(r, SkColorSpace::Equals(rgb4.get(), rgb4.get())); |
msarett | abbd6d5 | 2016-08-01 09:43:08 -0700 | [diff] [blame] | 267 | |
| 268 | REPORTER_ASSERT(r, !SkColorSpace::Equals(nullptr, srgb.get())); |
| 269 | REPORTER_ASSERT(r, !SkColorSpace::Equals(srgb.get(), nullptr)); |
msarett | abbd6d5 | 2016-08-01 09:43:08 -0700 | [diff] [blame] | 270 | REPORTER_ASSERT(r, !SkColorSpace::Equals(z30.get(), srgb.get())); |
| 271 | REPORTER_ASSERT(r, !SkColorSpace::Equals(z32.get(), z30.get())); |
Matt Sarett | 99e3f7d | 2016-10-28 12:51:08 -0400 | [diff] [blame] | 272 | REPORTER_ASSERT(r, !SkColorSpace::Equals(z30.get(), rgb4.get())); |
| 273 | REPORTER_ASSERT(r, !SkColorSpace::Equals(srgb.get(), rgb4.get())); |
msarett | abbd6d5 | 2016-08-01 09:43:08 -0700 | [diff] [blame] | 274 | } |
msarett | a5a31dd | 2016-10-11 09:41:16 -0700 | [diff] [blame] | 275 | |
Matt Sarett | 8c05b45 | 2016-10-28 14:45:03 -0400 | [diff] [blame] | 276 | static inline bool matrix_almost_equal(const SkMatrix44& a, const SkMatrix44& b) { |
| 277 | return almost_equal(a.get(0, 0), b.get(0, 0)) && |
| 278 | almost_equal(a.get(0, 1), b.get(0, 1)) && |
| 279 | almost_equal(a.get(0, 2), b.get(0, 2)) && |
| 280 | almost_equal(a.get(0, 3), b.get(0, 3)) && |
| 281 | almost_equal(a.get(1, 0), b.get(1, 0)) && |
| 282 | almost_equal(a.get(1, 1), b.get(1, 1)) && |
| 283 | almost_equal(a.get(1, 2), b.get(1, 2)) && |
| 284 | almost_equal(a.get(1, 3), b.get(1, 3)) && |
| 285 | almost_equal(a.get(2, 0), b.get(2, 0)) && |
| 286 | almost_equal(a.get(2, 1), b.get(2, 1)) && |
| 287 | almost_equal(a.get(2, 2), b.get(2, 2)) && |
| 288 | almost_equal(a.get(2, 3), b.get(2, 3)) && |
| 289 | almost_equal(a.get(3, 0), b.get(3, 0)) && |
| 290 | almost_equal(a.get(3, 1), b.get(3, 1)) && |
| 291 | almost_equal(a.get(3, 2), b.get(3, 2)) && |
| 292 | almost_equal(a.get(3, 3), b.get(3, 3)); |
| 293 | } |
msarett | a5a31dd | 2016-10-11 09:41:16 -0700 | [diff] [blame] | 294 | |
Matt Sarett | 8c05b45 | 2016-10-28 14:45:03 -0400 | [diff] [blame] | 295 | static inline void check_primaries(skiatest::Reporter* r, const SkColorSpacePrimaries& primaries, |
| 296 | const SkMatrix44& reference) { |
msarett | a5a31dd | 2016-10-11 09:41:16 -0700 | [diff] [blame] | 297 | SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); |
| 298 | bool result = primaries.toXYZD50(&toXYZ); |
| 299 | REPORTER_ASSERT(r, result); |
Matt Sarett | 8c05b45 | 2016-10-28 14:45:03 -0400 | [diff] [blame] | 300 | REPORTER_ASSERT(r, matrix_almost_equal(toXYZ, reference)); |
| 301 | } |
msarett | a5a31dd | 2016-10-11 09:41:16 -0700 | [diff] [blame] | 302 | |
Matt Sarett | 8c05b45 | 2016-10-28 14:45:03 -0400 | [diff] [blame] | 303 | DEF_TEST(ColorSpace_Primaries, r) { |
| 304 | // sRGB primaries (D65) |
| 305 | SkColorSpacePrimaries srgb; |
| 306 | srgb.fRX = 0.64f; |
| 307 | srgb.fRY = 0.33f; |
| 308 | srgb.fGX = 0.30f; |
| 309 | srgb.fGY = 0.60f; |
| 310 | srgb.fBX = 0.15f; |
| 311 | srgb.fBY = 0.06f; |
| 312 | srgb.fWX = 0.3127f; |
| 313 | srgb.fWY = 0.3290f; |
| 314 | SkMatrix44 srgbToXYZ(SkMatrix44::kUninitialized_Constructor); |
| 315 | bool result = srgb.toXYZD50(&srgbToXYZ); |
| 316 | REPORTER_ASSERT(r, result); |
| 317 | |
| 318 | sk_sp<SkColorSpace> space = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, |
| 319 | srgbToXYZ); |
Matt Sarett | 77a7a1b | 2017-02-07 13:56:11 -0500 | [diff] [blame] | 320 | REPORTER_ASSERT(r, SkColorSpace::MakeSRGB() == space); |
Matt Sarett | 8c05b45 | 2016-10-28 14:45:03 -0400 | [diff] [blame] | 321 | |
Matt Sarett | 8c05b45 | 2016-10-28 14:45:03 -0400 | [diff] [blame] | 322 | // ProPhoto (D50) |
| 323 | SkColorSpacePrimaries proPhoto; |
| 324 | proPhoto.fRX = 0.7347f; |
| 325 | proPhoto.fRY = 0.2653f; |
| 326 | proPhoto.fGX = 0.1596f; |
| 327 | proPhoto.fGY = 0.8404f; |
| 328 | proPhoto.fBX = 0.0366f; |
| 329 | proPhoto.fBY = 0.0001f; |
| 330 | proPhoto.fWX = 0.34567f; |
| 331 | proPhoto.fWY = 0.35850f; |
| 332 | SkMatrix44 proToXYZ(SkMatrix44::kUninitialized_Constructor); |
| 333 | proToXYZ.set3x3(0.7976749f, 0.2880402f, 0.0000000f, |
| 334 | 0.1351917f, 0.7118741f, 0.0000000f, |
| 335 | 0.0313534f, 0.0000857f, 0.8252100f); |
| 336 | check_primaries(r, proPhoto, proToXYZ); |
| 337 | |
| 338 | // NTSC (C) |
| 339 | SkColorSpacePrimaries ntsc; |
| 340 | ntsc.fRX = 0.67f; |
| 341 | ntsc.fRY = 0.33f; |
| 342 | ntsc.fGX = 0.21f; |
| 343 | ntsc.fGY = 0.71f; |
| 344 | ntsc.fBX = 0.14f; |
| 345 | ntsc.fBY = 0.08f; |
| 346 | ntsc.fWX = 0.31006f; |
| 347 | ntsc.fWY = 0.31616f; |
| 348 | SkMatrix44 ntscToXYZ(SkMatrix44::kUninitialized_Constructor); |
| 349 | ntscToXYZ.set3x3(0.6343706f, 0.3109496f, -0.0011817f, |
| 350 | 0.1852204f, 0.5915984f, 0.0555518f, |
| 351 | 0.1446290f, 0.0974520f, 0.7708399f); |
| 352 | check_primaries(r, ntsc, ntscToXYZ); |
Matt Sarett | 77a7a1b | 2017-02-07 13:56:11 -0500 | [diff] [blame] | 353 | |
| 354 | // DCI P3 (D65) |
| 355 | SkColorSpacePrimaries p3; |
| 356 | p3.fRX = 0.680f; |
| 357 | p3.fRY = 0.320f; |
| 358 | p3.fGX = 0.265f; |
| 359 | p3.fGY = 0.690f; |
| 360 | p3.fBX = 0.150f; |
| 361 | p3.fBY = 0.060f; |
| 362 | p3.fWX = 0.3127f; |
| 363 | p3.fWY = 0.3290f; |
| 364 | space = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, |
| 365 | SkColorSpace::kDCIP3_D65_Gamut); |
| 366 | SkMatrix44 reference(SkMatrix44::kUninitialized_Constructor); |
| 367 | SkAssertResult(space->toXYZD50(&reference)); |
| 368 | check_primaries(r, p3, reference); |
| 369 | |
| 370 | // Rec 2020 (D65) |
| 371 | SkColorSpacePrimaries rec2020; |
| 372 | rec2020.fRX = 0.708f; |
| 373 | rec2020.fRY = 0.292f; |
| 374 | rec2020.fGX = 0.170f; |
| 375 | rec2020.fGY = 0.797f; |
| 376 | rec2020.fBX = 0.131f; |
| 377 | rec2020.fBY = 0.046f; |
| 378 | rec2020.fWX = 0.3127f; |
| 379 | rec2020.fWY = 0.3290f; |
| 380 | space = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, |
| 381 | SkColorSpace::kRec2020_Gamut); |
| 382 | SkAssertResult(space->toXYZD50(&reference)); |
| 383 | check_primaries(r, rec2020, reference); |
msarett | a5a31dd | 2016-10-11 09:41:16 -0700 | [diff] [blame] | 384 | } |
Matt Sarett | 0186661 | 2016-10-31 13:41:57 -0400 | [diff] [blame] | 385 | |
Matt Sarett | e151bdb | 2017-01-04 11:05:05 -0500 | [diff] [blame] | 386 | DEF_TEST(ColorSpace_MatrixHash, r) { |
Matt Sarett | 77a7a1b | 2017-02-07 13:56:11 -0500 | [diff] [blame] | 387 | sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB(); |
Matt Sarett | e151bdb | 2017-01-04 11:05:05 -0500 | [diff] [blame] | 388 | |
| 389 | SkColorSpaceTransferFn fn; |
| 390 | fn.fA = 1.0f; |
| 391 | fn.fB = 0.0f; |
| 392 | fn.fC = 0.0f; |
| 393 | fn.fD = 0.0f; |
| 394 | fn.fE = 0.0f; |
| 395 | fn.fF = 0.0f; |
| 396 | fn.fG = 3.0f; |
| 397 | |
| 398 | SkMatrix44 srgbMat(SkMatrix44::kUninitialized_Constructor); |
| 399 | srgbMat.set3x3RowMajorf(gSRGB_toXYZD50); |
| 400 | sk_sp<SkColorSpace> strange = SkColorSpace::MakeRGB(fn, srgbMat); |
| 401 | |
Brian Osman | 36703d9 | 2017-12-12 14:09:31 -0500 | [diff] [blame] | 402 | REPORTER_ASSERT(r, *srgb->toXYZD50() == *strange->toXYZD50()); |
| 403 | REPORTER_ASSERT(r, srgb->toXYZD50Hash() == strange->toXYZD50Hash()); |
Matt Sarett | e151bdb | 2017-01-04 11:05:05 -0500 | [diff] [blame] | 404 | } |
Matt Sarett | d83545e | 2017-03-06 11:11:23 -0500 | [diff] [blame] | 405 | |
| 406 | DEF_TEST(ColorSpace_IsSRGB, r) { |
| 407 | sk_sp<SkColorSpace> srgb0 = SkColorSpace::MakeSRGB(); |
Matt Sarett | d83545e | 2017-03-06 11:11:23 -0500 | [diff] [blame] | 408 | |
| 409 | SkColorSpaceTransferFn fn; |
| 410 | fn.fA = 1.0f; |
| 411 | fn.fB = 0.0f; |
| 412 | fn.fC = 0.0f; |
| 413 | fn.fD = 0.0f; |
| 414 | fn.fE = 0.0f; |
| 415 | fn.fF = 0.0f; |
| 416 | fn.fG = 2.2f; |
| 417 | sk_sp<SkColorSpace> twoDotTwo = SkColorSpace::MakeRGB(fn, SkColorSpace::kSRGB_Gamut); |
| 418 | |
| 419 | REPORTER_ASSERT(r, srgb0->isSRGB()); |
Matt Sarett | d83545e | 2017-03-06 11:11:23 -0500 | [diff] [blame] | 420 | REPORTER_ASSERT(r, !twoDotTwo->isSRGB()); |
| 421 | } |
Brian Osman | 12e4e84 | 2018-04-27 12:03:51 -0400 | [diff] [blame] | 422 | |
Brian Osman | 12e4e84 | 2018-04-27 12:03:51 -0400 | [diff] [blame] | 423 | DEF_TEST(ColorSpace_skcms_IsSRGB, r) { |
Mike Klein | e61b969 | 2018-05-09 15:00:25 -0400 | [diff] [blame] | 424 | sk_sp<SkColorSpace> srgb = SkColorSpace::Make(*skcms_sRGB_profile()); |
Brian Osman | 12e4e84 | 2018-04-27 12:03:51 -0400 | [diff] [blame] | 425 | REPORTER_ASSERT(r, srgb->isSRGB()); |
| 426 | } |