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

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

Issue 2697863003: color: Clarify default behaviors (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
« ui/gfx/color_space.cc ('K') | « ui/gfx/icc_profile.h ('k') | no next file » | 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"
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 101
102 #if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(USE_X11) 102 #if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(USE_X11)
103 // static 103 // static
104 ICCProfile ICCProfile::FromBestMonitor() { 104 ICCProfile ICCProfile::FromBestMonitor() {
105 return ICCProfile(); 105 return ICCProfile();
106 } 106 }
107 #endif 107 #endif
108 108
109 // static 109 // static
110 ICCProfile ICCProfile::FromColorSpace(const gfx::ColorSpace& color_space) { 110 ICCProfile ICCProfile::FromColorSpace(const gfx::ColorSpace& color_space) {
111 if (color_space == gfx::ColorSpace()) 111 if (!color_space.IsValid())
112 return ICCProfile(); 112 return ICCProfile();
113 113
114 // If |color_space| was created from an ICC profile, retrieve that exact 114 // If |color_space| was created from an ICC profile, retrieve that exact
115 // profile. 115 // profile.
116 if (color_space.icc_profile_id_) { 116 ICCProfile result;
117 Cache& cache = g_cache.Get(); 117 if (FromId(color_space.icc_profile_id_, false, &result)) {
118 base::AutoLock lock(cache.lock); 118 return result;
119 auto found = cache.id_to_icc_profile_mru.Get(color_space.icc_profile_id_);
120 if (found != cache.id_to_icc_profile_mru.end())
121 return found->second;
122 } 119 }
123 120
124 // Otherwise, construct an ICC profile based on the best approximated 121 // Otherwise, construct an ICC profile based on the best approximated
125 // primaries and matrix. 122 // primaries and matrix.
126 SkMatrix44 to_XYZD50_matrix; 123 SkMatrix44 to_XYZD50_matrix;
127 color_space.GetPrimaryMatrix(&to_XYZD50_matrix); 124 color_space.GetPrimaryMatrix(&to_XYZD50_matrix);
128 SkColorSpaceTransferFn fn; 125 SkColorSpaceTransferFn fn;
129 if (!color_space.GetTransferFunction(&fn)) { 126 if (!color_space.GetTransferFunction(&fn)) {
130 DLOG(ERROR) << "Failed to get ColorSpace transfer function for ICCProfile."; 127 DLOG(ERROR) << "Failed to get ColorSpace transfer function for ICCProfile.";
131 return ICCProfile(); 128 return ICCProfile();
132 } 129 }
133
134 sk_sp<SkData> data = SkICC::WriteToICC(fn, to_XYZD50_matrix); 130 sk_sp<SkData> data = SkICC::WriteToICC(fn, to_XYZD50_matrix);
135 if (!data) { 131 if (!data) {
136 DLOG(ERROR) << "Failed to create SkICC."; 132 DLOG(ERROR) << "Failed to create SkICC.";
137 return ICCProfile(); 133 return ICCProfile();
138 } 134 }
139 135 return FromData(data->data(), data->size());
140 // gfx::ColorTransform assumes that this will return an empty profile for any
141 // color space that was not constructed from an ICC profile.
142 // TODO(ccameron): Fix this assumption.
143 // return FromData(data->data(), data->size());
144 return ICCProfile();
145 } 136 }
146 137
147 const std::vector<char>& ICCProfile::GetData() const { 138 const std::vector<char>& ICCProfile::GetData() const {
148 return data_; 139 return data_;
149 } 140 }
150 141
151 const ColorSpace& ICCProfile::GetColorSpace() const { 142 const ColorSpace& ICCProfile::GetColorSpace() const {
152 // Move this ICC profile to the most recently used end of the cache, 143 // Move this ICC profile to the most recently used end of the cache,
153 // inserting if needed. 144 // inserting if needed.
154 if (id_) { 145 if (id_) {
155 Cache& cache = g_cache.Get(); 146 Cache& cache = g_cache.Get();
156 base::AutoLock lock(cache.lock); 147 base::AutoLock lock(cache.lock);
157 auto found = cache.id_to_icc_profile_mru.Get(id_); 148 auto found = cache.id_to_icc_profile_mru.Get(id_);
158 if (found == cache.id_to_icc_profile_mru.end()) 149 if (found == cache.id_to_icc_profile_mru.end())
159 found = cache.id_to_icc_profile_mru.Put(id_, *this); 150 found = cache.id_to_icc_profile_mru.Put(id_, *this);
160 } 151 }
161 return color_space_; 152 return color_space_;
162 } 153 }
163 154
155 // static
156 bool ICCProfile::FromId(uint64_t id,
157 bool only_if_needed,
158 ICCProfile* icc_profile) {
159 if (!id)
160 return false;
161
162 Cache& cache = g_cache.Get();
163 base::AutoLock lock(cache.lock);
164
165 auto found = cache.id_to_icc_profile_mru.Get(id);
166 if (found == cache.id_to_icc_profile_mru.end())
167 return false;
168
169 const ICCProfile& found_icc_profile = found->second;
170 if (found_icc_profile.color_space_is_accurate_ && only_if_needed)
171 return false;
172
173 *icc_profile = found_icc_profile;
174 return true;
175 }
176
164 void ICCProfile::ComputeColorSpaceAndCache() { 177 void ICCProfile::ComputeColorSpaceAndCache() {
165 if (!id_) 178 if (!id_)
166 return; 179 return;
167 180
168 // If this already exists in the cache, just update its |color_space_|. 181 // If this already exists in the cache, just update its |color_space_|.
169 { 182 {
170 Cache& cache = g_cache.Get(); 183 Cache& cache = g_cache.Get();
171 base::AutoLock lock(cache.lock); 184 base::AutoLock lock(cache.lock);
172 auto found = cache.id_to_icc_profile_mru.Get(id_); 185 auto found = cache.id_to_icc_profile_mru.Get(id_);
173 if (found != cache.id_to_icc_profile_mru.end()) { 186 if (found != cache.id_to_icc_profile_mru.end()) {
174 color_space_ = found->second.color_space_; 187 color_space_ = found->second.color_space_;
175 return; 188 return;
176 } 189 }
177 } 190 }
178 191
192 color_space_is_accurate_ = true;
193 SkMatrix44 to_XYZD50_matrix;
194 SkColorSpaceTransferFn fn;
195 sk_sp<SkICC> sk_icc = SkICC::Make(data_.data(), data_.size());
196 if (sk_icc) {
197 if (!sk_icc->toXYZD50(&to_XYZD50_matrix)) {
198 // Just say that the primaries were the sRGB primaries if we can't
199 // extract them.
200 gfx::ColorSpace::CreateSRGB().GetPrimaryMatrix(&to_XYZD50_matrix);
201 color_space_is_accurate_ = false;
202 DLOG(ERROR) << "Unable to handle ICCProfile primaries.";
203 }
204 if (!sk_icc->isNumericalTransferFn(&fn)) {
205 // Just say that the transfer function was sRGB if we cannot read it.
206 // TODO(ccameron): Use a least squares approximation of the transfer
207 // function when it is not numerical.
208 gfx::ColorSpace::CreateSRGB().GetTransferFunction(&fn);
209 color_space_is_accurate_ = false;
210 DLOG(ERROR) << "Unable to handle ICCProfile transfer function.";
211 }
212 } else {
213 gfx::ColorSpace::CreateSRGB().GetPrimaryMatrix(&to_XYZD50_matrix);
214 gfx::ColorSpace::CreateSRGB().GetTransferFunction(&fn);
215 color_space_is_accurate_ = false;
216 DLOG(ERROR) << "Unable parse ICCProfile.";
217 }
218
179 // Compute the color space. 219 // Compute the color space.
180 color_space_ = gfx::ColorSpace( 220 color_space_ = gfx::ColorSpace::CreateCustom(to_XYZD50_matrix, fn);
181 ColorSpace::PrimaryID::CUSTOM, ColorSpace::TransferID::CUSTOM,
182 ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL);
183 color_space_.icc_profile_id_ = id_; 221 color_space_.icc_profile_id_ = id_;
184 color_space_.icc_profile_sk_color_space_ = 222 color_space_.icc_profile_sk_color_space_ =
185 SkColorSpace::MakeICC(data_.data(), data_.size()); 223 SkColorSpace::MakeICC(data_.data(), data_.size());
186 224
187 sk_sp<SkICC> sk_icc = SkICC::Make(data_.data(), data_.size());
188 if (sk_icc) {
189 bool result;
190 SkMatrix44 to_XYZD50_matrix;
191 result = sk_icc->toXYZD50(&to_XYZD50_matrix);
192 if (result) {
193 for (int row = 0; row < 3; ++row) {
194 for (int col = 0; col < 3; ++col) {
195 color_space_.custom_primary_matrix_[3 * row + col] =
196 to_XYZD50_matrix.get(row, col);
197 }
198 }
199 } else {
200 // Just say that the primaries were the sRGB primaries if we can't
201 // extract them.
202 color_space_.primaries_ = ColorSpace::PrimaryID::BT709;
203 DLOG(ERROR) << "Unable to handle ICCProfile primaries.";
204 }
205 SkColorSpaceTransferFn fn;
206 result = sk_icc->isNumericalTransferFn(&fn);
207 if (result) {
208 color_space_.custom_transfer_params_[0] = fn.fA;
209 color_space_.custom_transfer_params_[1] = fn.fB;
210 color_space_.custom_transfer_params_[2] = fn.fC;
211 color_space_.custom_transfer_params_[3] = fn.fD;
212 color_space_.custom_transfer_params_[4] = fn.fE;
213 color_space_.custom_transfer_params_[5] = fn.fF;
214 color_space_.custom_transfer_params_[6] = fn.fG;
215 } else {
216 // Just say that the transfer function was sRGB if we cannot read it.
217 // TODO(ccameron): Use a least squares approximation of the transfer
218 // function when it is not numerical.
219 color_space_.transfer_ = ColorSpace::TransferID::IEC61966_2_1;
220 DLOG(ERROR) << "Unable to handle ICCProfile transfer function.";
221 }
222 }
223
224 // Add to the cache. 225 // Add to the cache.
225 { 226 {
226 Cache& cache = g_cache.Get(); 227 Cache& cache = g_cache.Get();
227 base::AutoLock lock(cache.lock); 228 base::AutoLock lock(cache.lock);
228 cache.id_to_icc_profile_mru.Put(id_, *this); 229 cache.id_to_icc_profile_mru.Put(id_, *this);
229 } 230 }
230 } 231 }
231 232
232 // static 233 // static
233 bool ICCProfile::IsValidProfileLength(size_t length) { 234 bool ICCProfile::IsValidProfileLength(size_t length) {
234 return length >= kMinProfileLength && length <= kMaxProfileLength; 235 return length >= kMinProfileLength && length <= kMaxProfileLength;
235 } 236 }
236 237
237 } // namespace gfx 238 } // namespace gfx
OLDNEW
« ui/gfx/color_space.cc ('K') | « ui/gfx/icc_profile.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698