blob: 8e2bb4974f4161751203d2be5a9d91e8b3fc7b9f [file] [log] [blame]
ccameron87b65e9b62016-12-27 10:19:071// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
ccameron290a91a2017-05-13 19:22:335#include "ui/gfx/icc_profile.h"
ccameron87b65e9b62016-12-27 10:19:076#include "base/logging.h"
7#include "testing/gtest/include/gtest/gtest.h"
8#include "ui/gfx/color_space.h"
ccameron290a91a2017-05-13 19:22:339#include "ui/gfx/skia_color_space_util.h"
ccameron83e8e9a2017-01-04 01:31:2010#include "ui/gfx/test/icc_profiles.h"
ccameron87b65e9b62016-12-27 10:19:0711
12namespace gfx {
13
ccameron87b65e9b62016-12-27 10:19:0714TEST(ICCProfile, Conversions) {
15 ICCProfile icc_profile = ICCProfileForTestingColorSpin();
16 ColorSpace color_space_from_icc_profile = icc_profile.GetColorSpace();
17
Christopher Cameron3bc3d5e2017-11-23 03:48:1118 ICCProfile icc_profile_from_color_space =
19 ICCProfile::FromParametricColorSpace(color_space_from_icc_profile);
20 EXPECT_TRUE(icc_profile_from_color_space.IsValid());
21 EXPECT_NE(icc_profile, icc_profile_from_color_space);
ccameron87b65e9b62016-12-27 10:19:0722}
23
24TEST(ICCProfile, SRGB) {
ccameronfa21c642017-05-10 19:38:3625 ICCProfile icc_profile = ICCProfileForTestingSRGB();
ccameron87b65e9b62016-12-27 10:19:0726 ColorSpace color_space = ColorSpace::CreateSRGB();
msarett29c85572017-02-10 22:16:5527 sk_sp<SkColorSpace> sk_color_space = SkColorSpace::MakeSRGB();
ccameron87b65e9b62016-12-27 10:19:0728
ccameronfa21c642017-05-10 19:38:3629 // The ICC profile parser should note that this is SRGB.
Christopher Camerona4adb41b2017-07-13 06:44:2530 EXPECT_EQ(icc_profile.GetColorSpace(), ColorSpace::CreateSRGB());
ccameronfa21c642017-05-10 19:38:3631 EXPECT_EQ(icc_profile.GetColorSpace().ToSkColorSpace().get(),
32 sk_color_space.get());
33 // The parametric generating code should recognize that this is SRGB.
ccamerone35e2322017-11-02 23:33:4634 EXPECT_EQ(icc_profile.GetParametricColorSpace(), ColorSpace::CreateSRGB());
35 EXPECT_EQ(icc_profile.GetParametricColorSpace().ToSkColorSpace().get(),
ccameronfa21c642017-05-10 19:38:3636 sk_color_space.get());
37 // The generated color space should recognize that this is SRGB.
ccameron628896ee2017-02-03 09:29:1238 EXPECT_EQ(color_space.ToSkColorSpace().get(), sk_color_space.get());
ccameron87b65e9b62016-12-27 10:19:0739}
40
ccameron549738b2017-01-28 17:39:3241TEST(ICCProfile, Equality) {
42 ICCProfile spin_profile = ICCProfileForTestingColorSpin();
43 ICCProfile adobe_profile = ICCProfileForTestingAdobeRGB();
44 EXPECT_TRUE(spin_profile == spin_profile);
45 EXPECT_FALSE(spin_profile != spin_profile);
46 EXPECT_FALSE(spin_profile == adobe_profile);
47 EXPECT_TRUE(spin_profile != adobe_profile);
48
49 gfx::ColorSpace spin_space = spin_profile.GetColorSpace();
50 gfx::ColorSpace adobe_space = adobe_profile.GetColorSpace();
51 EXPECT_TRUE(spin_space == spin_space);
52 EXPECT_FALSE(spin_space != spin_space);
53 EXPECT_FALSE(spin_space == adobe_space);
54 EXPECT_TRUE(spin_space != adobe_space);
55
Christopher Cameron3bc3d5e2017-11-23 03:48:1156 ICCProfile temp = ICCProfile::FromCacheMac(spin_space);
57 EXPECT_TRUE(temp.IsValid());
ccameron3b6fe6d2017-02-17 06:21:5858 EXPECT_TRUE(spin_profile == temp);
59 EXPECT_FALSE(spin_profile != temp);
60
Christopher Cameron3bc3d5e2017-11-23 03:48:1161 temp = ICCProfile::FromCacheMac(adobe_space);
62 EXPECT_TRUE(temp.IsValid());
ccameron3b6fe6d2017-02-17 06:21:5863 EXPECT_FALSE(spin_profile == temp);
64 EXPECT_TRUE(spin_profile != temp);
ccameron628896ee2017-02-03 09:29:1265
66 EXPECT_TRUE(!!spin_space.ToSkColorSpace());
67 EXPECT_TRUE(!!adobe_space.ToSkColorSpace());
68 EXPECT_FALSE(SkColorSpace::Equals(
69 spin_space.ToSkColorSpace().get(),
70 adobe_space.ToSkColorSpace().get()));
ccameron549738b2017-01-28 17:39:3271}
72
Christopher Cameron3bc3d5e2017-11-23 03:48:1173TEST(ICCProfile, ParametricVersusExactInaccurate) {
ccameron24c87c32017-03-14 21:50:4274 // This ICC profile has three transfer functions that differ enough that the
75 // parametric color space is considered inaccurate.
ccameron95f83c512017-03-31 20:16:1276 ICCProfile multi_tr_fn = ICCProfileForTestingNoAnalyticTrFn();
ccamerone35e2322017-11-02 23:33:4677 EXPECT_NE(multi_tr_fn.GetColorSpace(), multi_tr_fn.GetParametricColorSpace());
ccameron24c87c32017-03-14 21:50:4278
Christopher Cameron3bc3d5e2017-11-23 03:48:1179 // Fails to get parametric color space because the space is not parametric.
80 ICCProfile profile;
81 profile = ICCProfile::FromParametricColorSpace(multi_tr_fn.GetColorSpace());
82 EXPECT_FALSE(profile.IsValid());
ccameron24c87c32017-03-14 21:50:4283
Christopher Cameron3bc3d5e2017-11-23 03:48:1184 // The Mac cache does not find the parametric approximation, because the cache
85 // only has the original.
86 profile = ICCProfile::FromCacheMac(multi_tr_fn.GetParametricColorSpace());
87 EXPECT_FALSE(profile.IsValid());
ccameron95f83c512017-03-31 20:16:1288
Christopher Cameron3bc3d5e2017-11-23 03:48:1189 // The Mac cache does find the original.
90 profile = ICCProfile::FromCacheMac(multi_tr_fn.GetColorSpace());
91 EXPECT_TRUE(profile.IsValid());
92 EXPECT_EQ(profile, multi_tr_fn);
93
94 // We are capable of generating a parametric approximation.
95 profile = ICCProfile::FromParametricColorSpace(
96 multi_tr_fn.GetParametricColorSpace());
97 EXPECT_TRUE(profile.IsValid());
98 EXPECT_NE(profile, multi_tr_fn);
99}
100
101TEST(ICCProfile, ParametricVersusExactOvershoot) {
ccameron95f83c512017-03-31 20:16:12102 // This ICC profile has a transfer function with T(1) that is greater than 1
103 // in the approximation, but is still close enough to be considered accurate.
104 ICCProfile overshoot = ICCProfileForTestingOvershoot();
ccamerone35e2322017-11-02 23:33:46105 EXPECT_EQ(overshoot.GetColorSpace(), overshoot.GetParametricColorSpace());
ccameron95f83c512017-03-31 20:16:12106
Christopher Cameron3bc3d5e2017-11-23 03:48:11107 ICCProfile profile;
108 profile = ICCProfile::FromCacheMac(overshoot.GetColorSpace());
109 EXPECT_TRUE(profile.IsValid());
110 EXPECT_EQ(profile, overshoot);
ccameron95f83c512017-03-31 20:16:12111
Christopher Cameron3bc3d5e2017-11-23 03:48:11112 profile = ICCProfile::FromParametricColorSpace(overshoot.GetColorSpace());
113 EXPECT_TRUE(profile.IsValid());
114 EXPECT_NE(profile, overshoot);
115}
ccameron24c87c32017-03-14 21:50:42116
Christopher Cameron3bc3d5e2017-11-23 03:48:11117TEST(ICCProfile, ParametricVersusExactAdobe) {
ccameron24c87c32017-03-14 21:50:42118 // This ICC profile is precisely represented by the parametric color space.
119 ICCProfile accurate = ICCProfileForTestingAdobeRGB();
ccamerone35e2322017-11-02 23:33:46120 EXPECT_EQ(accurate.GetColorSpace(), accurate.GetParametricColorSpace());
ccameron24c87c32017-03-14 21:50:42121
Christopher Cameron3bc3d5e2017-11-23 03:48:11122 ICCProfile profile;
123 profile = ICCProfile::FromCacheMac(accurate.GetColorSpace());
124 EXPECT_TRUE(profile.IsValid());
125 EXPECT_EQ(profile, accurate);
ccameron24c87c32017-03-14 21:50:42126
Christopher Cameron3bc3d5e2017-11-23 03:48:11127 profile = ICCProfile::FromParametricColorSpace(accurate.GetColorSpace());
128 EXPECT_TRUE(profile.IsValid());
129 EXPECT_NE(profile, accurate);
130}
ccameron24c87c32017-03-14 21:50:42131
Christopher Cameron3bc3d5e2017-11-23 03:48:11132TEST(ICCProfile, ParametricVersusExactA2B) {
ccameronb3206e22017-03-25 02:09:12133 // This ICC profile has only an A2B representation. We cannot create an
134 // SkColorSpaceXform to A2B only ICC profiles, so this should be marked
135 // as invalid.
ccameron24c87c32017-03-14 21:50:42136 ICCProfile a2b = ICCProfileForTestingA2BOnly();
ccameronb3206e22017-03-25 02:09:12137 EXPECT_FALSE(a2b.GetColorSpace().IsValid());
Christopher Cameron64a55ad2017-09-21 05:31:22138
139 // Even though it is invalid, it should not be equal to the empty constructor.
140 EXPECT_NE(a2b, gfx::ICCProfile());
ccameron24c87c32017-03-14 21:50:42141}
142
143TEST(ICCProfile, GarbageData) {
144 std::vector<char> bad_data(10 * 1024);
145 const char* bad_data_string = "deadbeef";
146 for (size_t i = 0; i < bad_data.size(); ++i)
147 bad_data[i] = bad_data_string[i % 8];
148 ICCProfile garbage_profile =
149 ICCProfile::FromData(bad_data.data(), bad_data.size());
150 EXPECT_FALSE(garbage_profile.IsValid());
151 EXPECT_FALSE(garbage_profile.GetColorSpace().IsValid());
ccamerone35e2322017-11-02 23:33:46152 EXPECT_FALSE(garbage_profile.GetParametricColorSpace().IsValid());
ccameron24c87c32017-03-14 21:50:42153
154 ICCProfile default_ctor_profile;
155 EXPECT_FALSE(default_ctor_profile.IsValid());
156 EXPECT_FALSE(default_ctor_profile.GetColorSpace().IsValid());
ccamerone35e2322017-11-02 23:33:46157 EXPECT_FALSE(default_ctor_profile.GetParametricColorSpace().IsValid());
ccameron24c87c32017-03-14 21:50:42158}
159
ccameron290a91a2017-05-13 19:22:33160TEST(ICCProfile, GenericRGB) {
161 ColorSpace icc_profile = ICCProfileForTestingGenericRGB().GetColorSpace();
162 ColorSpace color_space(ColorSpace::PrimaryID::APPLE_GENERIC_RGB,
163 ColorSpace::TransferID::GAMMA18);
164
165 SkMatrix44 icc_profile_matrix;
166 SkMatrix44 color_space_matrix;
167
168 icc_profile.GetPrimaryMatrix(&icc_profile_matrix);
169 color_space.GetPrimaryMatrix(&color_space_matrix);
170
171 SkMatrix44 eye;
172 icc_profile_matrix.invert(&eye);
173 eye.postConcat(color_space_matrix);
174 EXPECT_TRUE(SkMatrixIsApproximatelyIdentity(eye));
175}
176
ccameron87b65e9b62016-12-27 10:19:07177} // namespace gfx