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