Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Side by Side Diff: ui/gfx/icc_profile.cc

Issue 2663453002: Revert of Use SkICC in gfx::ICCProfile and gfx::ColorSpace (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/gfx/icc_profile.h ('k') | ui/gfx/ipc/color/gfx_param_traits.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/icc_profile.h" 5 #include "ui/gfx/icc_profile.h"
6 6
7 #include <list> 7 #include <list>
8 8
9 #include "base/containers/mru_cache.h" 9 #include "base/containers/mru_cache.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/synchronization/lock.h" 11 #include "base/synchronization/lock.h"
12 #include "third_party/skia/include/core/SkData.h"
13 #include "third_party/skia/include/core/SkICC.h"
14 #include "ui/gfx/color_transform.h" 12 #include "ui/gfx/color_transform.h"
15 13
16 namespace gfx { 14 namespace gfx {
17 15
18 namespace { 16 namespace {
19 const size_t kMinProfileLength = 128; 17 const size_t kMinProfileLength = 128;
20 const size_t kMaxProfileLength = 4 * 1024 * 1024; 18 const size_t kMaxProfileLength = 4 * 1024 * 1024;
21 19
22 // Allow keeping around a maximum of 8 cached ICC profiles. Beware that 20 // Allow keeping around a maximum of 8 cached ICC profiles. Beware that
23 // we will do a linear search thorugh currently-cached ICC profiles, 21 // we will do a linear search thorugh currently-cached ICC profiles,
(...skipping 14 matching lines...) Expand all
38 } // namespace 36 } // namespace
39 37
40 ICCProfile::ICCProfile() = default; 38 ICCProfile::ICCProfile() = default;
41 ICCProfile::ICCProfile(ICCProfile&& other) = default; 39 ICCProfile::ICCProfile(ICCProfile&& other) = default;
42 ICCProfile::ICCProfile(const ICCProfile& other) = default; 40 ICCProfile::ICCProfile(const ICCProfile& other) = default;
43 ICCProfile& ICCProfile::operator=(ICCProfile&& other) = default; 41 ICCProfile& ICCProfile::operator=(ICCProfile&& other) = default;
44 ICCProfile& ICCProfile::operator=(const ICCProfile& other) = default; 42 ICCProfile& ICCProfile::operator=(const ICCProfile& other) = default;
45 ICCProfile::~ICCProfile() = default; 43 ICCProfile::~ICCProfile() = default;
46 44
47 bool ICCProfile::operator==(const ICCProfile& other) const { 45 bool ICCProfile::operator==(const ICCProfile& other) const {
48 return data_ == data_; 46 if (type_ != other.type_)
47 return false;
48 switch (type_) {
49 case Type::INVALID:
50 return true;
51 case Type::FROM_COLOR_SPACE:
52 return color_space_ == other.color_space_;
53 case Type::FROM_DATA:
54 return data_ == other.data_;
55 }
56 return false;
49 } 57 }
50 58
51 bool ICCProfile::operator!=(const ICCProfile& other) const { 59 bool ICCProfile::operator!=(const ICCProfile& other) const {
52 return !(*this == other); 60 return !(*this == other);
53 } 61 }
54 62
55 // static 63 // static
56 ICCProfile ICCProfile::FromData(const void* data, size_t size) { 64 ICCProfile ICCProfile::FromData(const char* data, size_t size) {
57 if (!IsValidProfileLength(size)) { 65 ICCProfile icc_profile;
58 if (size != 0) 66 if (IsValidProfileLength(size)) {
59 DLOG(ERROR) << "Invalid ICC profile length: " << size << "."; 67 icc_profile.type_ = Type::FROM_DATA;
68 icc_profile.data_.insert(icc_profile.data_.begin(), data, data + size);
69 } else {
60 return ICCProfile(); 70 return ICCProfile();
61 } 71 }
62 72
63 uint64_t new_profile_id = 0; 73 Cache& cache = g_cache.Get();
64 const char* data_as_char = reinterpret_cast<const char*>(data); 74 base::AutoLock lock(cache.lock);
65 { 75
66 // Linearly search the cached ICC profiles to find one with the same data. 76 // Linearly search the cached ICC profiles to find one with the same data.
67 // If it exists, re-use its id and touch it in the cache. 77 // If it exists, re-use its id and touch it in the cache.
68 Cache& cache = g_cache.Get(); 78 for (auto iter = cache.id_to_icc_profile_mru.begin();
69 base::AutoLock lock(cache.lock); 79 iter != cache.id_to_icc_profile_mru.end(); ++iter) {
70 for (auto iter = cache.id_to_icc_profile_mru.begin(); 80 if (icc_profile.data_ == iter->second.data_) {
71 iter != cache.id_to_icc_profile_mru.end(); ++iter) { 81 icc_profile = iter->second;
72 const std::vector<char>& iter_data = iter->second.data_; 82 cache.id_to_icc_profile_mru.Get(icc_profile.id_);
73 if (iter_data.size() != size || memcmp(data, iter_data.data(), size)) 83 return icc_profile;
74 continue;
75 auto found = cache.id_to_icc_profile_mru.Get(iter->second.id_);
76 return found->second;
77 } 84 }
78 new_profile_id = cache.next_unused_id++;
79 } 85 }
80 86
81 // Create a new cached id and add it to the cache. 87 // Create a new cached id and add it to the cache.
82 ICCProfile icc_profile; 88 icc_profile.id_ = cache.next_unused_id++;
83 icc_profile.id_ = new_profile_id; 89 icc_profile.color_space_ =
84 icc_profile.data_.insert(icc_profile.data_.begin(), data_as_char, 90 ColorSpace(ColorSpace::PrimaryID::CUSTOM, ColorSpace::TransferID::CUSTOM,
85 data_as_char + size); 91 ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL);
86 icc_profile.ComputeColorSpaceAndCache(); 92 icc_profile.color_space_.icc_profile_id_ = icc_profile.id_;
93 icc_profile.color_space_.sk_color_space_ = SkColorSpace::MakeICC(data, size);
94 cache.id_to_icc_profile_mru.Put(icc_profile.id_, icc_profile);
87 return icc_profile; 95 return icc_profile;
88 } 96 }
89 97
90 #if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(USE_X11) 98 #if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(USE_X11)
91 // static 99 // static
92 ICCProfile ICCProfile::FromBestMonitor() { 100 ICCProfile ICCProfile::FromBestMonitor() {
93 return ICCProfile(); 101 return ICCProfile();
94 } 102 }
95 #endif 103 #endif
96 104
97 // static 105 // static
98 ICCProfile ICCProfile::FromColorSpace(const gfx::ColorSpace& color_space) { 106 ICCProfile ICCProfile::FromColorSpace(const gfx::ColorSpace& color_space) {
99 if (color_space == gfx::ColorSpace()) 107 if (color_space == gfx::ColorSpace())
100 return ICCProfile(); 108 return ICCProfile();
101 109
102 // If |color_space| was created from an ICC profile, retrieve that exact 110 // If |color_space| was created from an ICC profile, retrieve that exact
103 // profile. 111 // profile.
104 if (color_space.icc_profile_id_) { 112 if (color_space.icc_profile_id_) {
105 Cache& cache = g_cache.Get(); 113 Cache& cache = g_cache.Get();
106 base::AutoLock lock(cache.lock); 114 base::AutoLock lock(cache.lock);
115
107 auto found = cache.id_to_icc_profile_mru.Get(color_space.icc_profile_id_); 116 auto found = cache.id_to_icc_profile_mru.Get(color_space.icc_profile_id_);
108 if (found != cache.id_to_icc_profile_mru.end()) 117 if (found != cache.id_to_icc_profile_mru.end()) {
109 return found->second; 118 return found->second;
119 }
110 } 120 }
111 121
112 // Otherwise, construct an ICC profile based on the best approximated 122 // TODO(ccameron): Support constructing ICC profiles from arbitrary ColorSpace
113 // primaries and matrix. 123 // objects.
114 SkMatrix44 to_XYZD50_matrix; 124 ICCProfile icc_profile;
115 color_space.GetPrimaryMatrix(&to_XYZD50_matrix); 125 icc_profile.type_ = gfx::ICCProfile::Type::FROM_COLOR_SPACE;
116 SkColorSpaceTransferFn fn; 126 icc_profile.color_space_ = color_space;
117 if (!color_space.GetTransferFunction(&fn)) { 127 return icc_profile;
118 DLOG(ERROR) << "Failed to get ColorSpace transfer function for ICCProfile.";
119 return ICCProfile();
120 }
121
122 sk_sp<SkData> data = SkICC::WriteToICC(fn, to_XYZD50_matrix);
123 if (!data) {
124 DLOG(ERROR) << "Failed to create SkICC.";
125 return ICCProfile();
126 }
127
128 // gfx::ColorTransform assumes that this will return an empty profile for any
129 // color space that was not constructed from an ICC profile.
130 // TODO(ccameron): Fix this assumption.
131 // return FromData(data->data(), data->size());
132 return ICCProfile();
133 } 128 }
134 129
135 ICCProfile ICCProfile::FromSkColorSpace(sk_sp<SkColorSpace> color_space) { 130 ICCProfile ICCProfile::FromSkColorSpace(sk_sp<SkColorSpace> color_space) {
136 ICCProfile icc_profile; 131 ICCProfile icc_profile;
137 132
138 Cache& cache = g_cache.Get(); 133 Cache& cache = g_cache.Get();
139 base::AutoLock lock(cache.lock); 134 base::AutoLock lock(cache.lock);
140 135
141 // Linearly search the cached ICC profiles to find one with the same data. 136 // Linearly search the cached ICC profiles to find one with the same data.
142 // If it exists, re-use its id and touch it in the cache. 137 // If it exists, re-use its id and touch it in the cache.
143 for (auto iter = cache.id_to_icc_profile_mru.begin(); 138 for (auto iter = cache.id_to_icc_profile_mru.begin();
144 iter != cache.id_to_icc_profile_mru.end(); ++iter) { 139 iter != cache.id_to_icc_profile_mru.end(); ++iter) {
145 sk_sp<SkColorSpace> iter_color_space = 140 sk_sp<SkColorSpace> iter_color_space =
146 iter->second.color_space_.ToSkColorSpace(); 141 iter->second.color_space_.ToSkColorSpace();
147 if (SkColorSpace::Equals(color_space.get(), iter_color_space.get())) { 142 if (SkColorSpace::Equals(color_space.get(), iter_color_space.get())) {
148 icc_profile = iter->second; 143 icc_profile = iter->second;
149 cache.id_to_icc_profile_mru.Get(icc_profile.id_); 144 cache.id_to_icc_profile_mru.Get(icc_profile.id_);
150 return icc_profile; 145 return icc_profile;
151 } 146 }
152 } 147 }
153 148
154 // TODO(ccameron): Support constructing ICC profiles from arbitrary 149 // TODO(ccameron): Support constructing ICC profiles from arbitrary
155 // SkColorSpace objects. 150 // SkColorSpace objects.
156 DLOG(ERROR) << "Failed to find ICC profile matching SkColorSpace.";
157 return icc_profile; 151 return icc_profile;
158 } 152 }
159 153
160 const std::vector<char>& ICCProfile::GetData() const { 154 const std::vector<char>& ICCProfile::GetData() const {
161 return data_; 155 return data_;
162 } 156 }
163 157
164 const ColorSpace& ICCProfile::GetColorSpace() const { 158 ColorSpace ICCProfile::GetColorSpace() const {
165 // Move this ICC profile to the most recently used end of the cache, 159 if (type_ == Type::INVALID)
166 // inserting if needed. 160 return gfx::ColorSpace();
167 if (id_) { 161 if (type_ == Type::FROM_COLOR_SPACE)
168 Cache& cache = g_cache.Get(); 162 return color_space_;
169 base::AutoLock lock(cache.lock);
170 auto found = cache.id_to_icc_profile_mru.Get(id_);
171 if (found == cache.id_to_icc_profile_mru.end())
172 found = cache.id_to_icc_profile_mru.Put(id_, *this);
173 }
174 return color_space_;
175 }
176 163
177 void ICCProfile::ComputeColorSpaceAndCache() { 164 ColorSpace color_space = color_space_;
178 if (!id_)
179 return;
180 165
181 // If this already exists in the cache, just update its |color_space_|. 166 // Move this ICC profile to the most recently used end of the cache.
182 { 167 {
183 Cache& cache = g_cache.Get(); 168 Cache& cache = g_cache.Get();
184 base::AutoLock lock(cache.lock); 169 base::AutoLock lock(cache.lock);
170
185 auto found = cache.id_to_icc_profile_mru.Get(id_); 171 auto found = cache.id_to_icc_profile_mru.Get(id_);
186 if (found != cache.id_to_icc_profile_mru.end()) { 172 if (found == cache.id_to_icc_profile_mru.end())
187 color_space_ = found->second.color_space_; 173 cache.id_to_icc_profile_mru.Put(id_, *this);
188 return;
189 }
190 } 174 }
191 175
192 // Compute the color space. 176 ColorSpace unity_colorspace(
193 color_space_ = gfx::ColorSpace( 177 ColorSpace::PrimaryID::CUSTOM, ColorSpace::TransferID::LINEAR,
194 ColorSpace::PrimaryID::CUSTOM, ColorSpace::TransferID::CUSTOM,
195 ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL); 178 ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL);
196 color_space_.icc_profile_id_ = id_; 179 unity_colorspace.custom_primary_matrix_[0] = 1.0f;
197 color_space_.sk_color_space_ = 180 unity_colorspace.custom_primary_matrix_[1] = 0.0f;
198 SkColorSpace::MakeICC(data_.data(), data_.size()); 181 unity_colorspace.custom_primary_matrix_[2] = 0.0f;
182 unity_colorspace.custom_primary_matrix_[3] = 0.0f;
199 183
200 sk_sp<SkICC> sk_icc = SkICC::Make(data_.data(), data_.size()); 184 unity_colorspace.custom_primary_matrix_[4] = 0.0f;
201 if (sk_icc) { 185 unity_colorspace.custom_primary_matrix_[5] = 1.0f;
202 bool result; 186 unity_colorspace.custom_primary_matrix_[6] = 0.0f;
203 SkMatrix44 to_XYZD50_matrix; 187 unity_colorspace.custom_primary_matrix_[7] = 0.0f;
204 result = sk_icc->toXYZD50(&to_XYZD50_matrix);
205 if (result) {
206 for (int row = 0; row < 3; ++row) {
207 for (int col = 0; col < 3; ++col) {
208 color_space_.custom_primary_matrix_[3 * row + col] =
209 to_XYZD50_matrix.get(row, col);
210 }
211 }
212 } else {
213 // Just say that the primaries were the sRGB primaries if we can't
214 // extract them.
215 color_space_.primaries_ = ColorSpace::PrimaryID::BT709;
216 DLOG(ERROR) << "Unable to handle ICCProfile primaries.";
217 }
218 SkColorSpaceTransferFn fn;
219 result = sk_icc->isNumericalTransferFn(&fn);
220 if (result) {
221 color_space_.custom_transfer_params_[0] = fn.fA;
222 color_space_.custom_transfer_params_[1] = fn.fB;
223 color_space_.custom_transfer_params_[2] = fn.fC;
224 color_space_.custom_transfer_params_[3] = fn.fD;
225 color_space_.custom_transfer_params_[4] = fn.fE;
226 color_space_.custom_transfer_params_[5] = fn.fF;
227 color_space_.custom_transfer_params_[6] = fn.fG;
228 } else {
229 // Just say that the transfer function was sRGB if we cannot read it.
230 // TODO(ccameron): Use a least squares approximation of the transfer
231 // function when it is not numerical.
232 color_space_.transfer_ = ColorSpace::TransferID::IEC61966_2_1;
233 DLOG(ERROR) << "Unable to handle ICCProfile transfer function.";
234 }
235 }
236 188
237 // Add to the cache. 189 unity_colorspace.custom_primary_matrix_[8] = 0.0f;
238 { 190 unity_colorspace.custom_primary_matrix_[9] = 0.0f;
239 Cache& cache = g_cache.Get(); 191 unity_colorspace.custom_primary_matrix_[10] = 1.0f;
240 base::AutoLock lock(cache.lock); 192 unity_colorspace.custom_primary_matrix_[11] = 0.0f;
241 cache.id_to_icc_profile_mru.Put(id_, *this); 193
242 } 194 // This will look up and use the ICC profile.
195 std::unique_ptr<ColorTransform> transform(ColorTransform::NewColorTransform(
196 color_space, unity_colorspace, ColorTransform::Intent::INTENT_ABSOLUTE));
197
198 ColorTransform::TriStim tmp[4];
199 tmp[0].set_x(1.0f);
200 tmp[1].set_y(1.0f);
201 tmp[2].set_z(1.0f);
202 transform->transform(tmp, arraysize(tmp));
203
204 color_space.custom_primary_matrix_[0] = tmp[0].x() - tmp[3].x();
205 color_space.custom_primary_matrix_[1] = tmp[1].x() - tmp[3].x();
206 color_space.custom_primary_matrix_[2] = tmp[2].x() - tmp[3].x();
207 color_space.custom_primary_matrix_[3] = tmp[3].x();
208
209 color_space.custom_primary_matrix_[4] = tmp[0].y() - tmp[3].y();
210 color_space.custom_primary_matrix_[5] = tmp[1].y() - tmp[3].y();
211 color_space.custom_primary_matrix_[6] = tmp[2].y() - tmp[3].y();
212 color_space.custom_primary_matrix_[7] = tmp[3].y();
213
214 color_space.custom_primary_matrix_[8] = tmp[0].z() - tmp[3].z();
215 color_space.custom_primary_matrix_[9] = tmp[1].z() - tmp[3].z();
216 color_space.custom_primary_matrix_[10] = tmp[2].z() - tmp[3].z();
217 color_space.custom_primary_matrix_[11] = tmp[3].z();
218
219 return color_space;
243 } 220 }
244 221
245 // static 222 // static
246 bool ICCProfile::IsValidProfileLength(size_t length) { 223 bool ICCProfile::IsValidProfileLength(size_t length) {
247 return length >= kMinProfileLength && length <= kMaxProfileLength; 224 return length >= kMinProfileLength && length <= kMaxProfileLength;
248 } 225 }
249 226
250 } // namespace gfx 227 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/icc_profile.h ('k') | ui/gfx/ipc/color/gfx_param_traits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698