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

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

Issue 2742613002: color: Always use parametric color spaces for raster (Closed)
Patch Set: Incorporate review feedback Created 3 years, 9 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/skia_color_space_util.h ('k') | ui/gfx/test/icc_profiles.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 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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/skia_color_space_util.h" 5 #include "ui/gfx/skia_color_space_util.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <vector>
9 10
10 #include "base/logging.h" 11 #include "base/logging.h"
11 12
12 namespace gfx { 13 namespace gfx {
13 14
14 namespace { 15 namespace {
15 16
16 // Solve for the parameter fC, given the parameter fD, assuming fF is zero. 17 // Solve for the parameter fC, given the parameter fD, assuming fF is zero.
17 void SkTransferFnSolveLinear(SkColorSpaceTransferFn* fn, 18 void SkTransferFnSolveLinear(SkColorSpaceTransferFn* fn,
18 const float* x, 19 const float* x,
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 if (std::abs(fn->fG - 1.f) < kRoundEpsilon) 214 if (std::abs(fn->fG - 1.f) < kRoundEpsilon)
214 fn->fG = 1.f; 215 fn->fG = 1.f;
215 return true; 216 return true;
216 } 217 }
217 218
218 bool SkApproximateTransferFnInternal(const float* x, 219 bool SkApproximateTransferFnInternal(const float* x,
219 const float* t, 220 const float* t,
220 size_t n, 221 size_t n,
221 SkColorSpaceTransferFn* fn) { 222 SkColorSpaceTransferFn* fn) {
222 // First, guess at a value of fD. Assume that the nonlinear segment applies 223 // First, guess at a value of fD. Assume that the nonlinear segment applies
223 // to all x >= 0.1. This is generally a safe assumption (fD is usually less 224 // to all x >= 0.25. This is generally a safe assumption (fD is usually less
224 // than 0.1). 225 // than 0.1).
225 fn->fD = 0.1f; 226 fn->fD = 0.25f;
226 227
227 // Do a nonlinear regression on the nonlinear segment. Use a number of guesses 228 // Do a nonlinear regression on the nonlinear segment. Use a number of guesses
228 // for the initial value of fG, because not all values will converge. 229 // for the initial value of fG, because not all values will converge.
229 bool nonlinear_fit_converged = false; 230 bool nonlinear_fit_converged = false;
230 { 231 {
231 const size_t kNumInitialGammas = 4; 232 const size_t kNumInitialGammas = 4;
232 float initial_gammas[kNumInitialGammas] = {2.f, 1.f, 3.f, 0.5f}; 233 float initial_gammas[kNumInitialGammas] = {2.f, 1.f, 3.f, 0.5f};
233 for (size_t i = 0; i < kNumInitialGammas; ++i) { 234 for (size_t i = 0; i < kNumInitialGammas; ++i) {
234 fn->fG = initial_gammas[i]; 235 fn->fG = initial_gammas[i];
235 fn->fA = 1; 236 fn->fA = 1;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 fn->fA = 1; 356 fn->fA = 1;
356 fn->fB = 0; 357 fn->fB = 0;
357 fn->fC = 1; 358 fn->fC = 1;
358 fn->fD = 0; 359 fn->fD = 0;
359 fn->fE = 0; 360 fn->fE = 0;
360 fn->fF = 0; 361 fn->fF = 0;
361 fn->fG = 1; 362 fn->fG = 1;
362 return false; 363 return false;
363 } 364 }
364 365
366 bool GFX_EXPORT SkApproximateTransferFn(sk_sp<SkICC> sk_icc,
367 float* max_error,
368 SkColorSpaceTransferFn* fn) {
369 SkICC::Tables tables;
370 bool got_tables = sk_icc->rawTransferFnData(&tables);
371 if (!got_tables)
372 return false;
373
374 // Merge all channels' tables into a single array.
375 std::vector<float> x;
376 std::vector<float> t;
377 for (size_t c = 0; c < 3; ++c) {
378 SkICC::Channel* channels[3] = {&tables.fRed, &tables.fGreen, &tables.fBlue};
379 SkICC::Channel* channel = channels[c];
380 const float* data = reinterpret_cast<const float*>(
381 tables.fStorage->bytes() + channel->fOffset);
382 for (int i = 0; i < channel->fCount; ++i) {
383 float xi = i / (channel->fCount - 1.f);
384 float ti = data[i];
385 x.push_back(xi);
386 t.push_back(ti);
387 }
388 }
389
390 // Approximate and evalaute.
391 bool converged =
392 SkApproximateTransferFnInternal(x.data(), t.data(), x.size(), fn);
393 if (!converged)
394 return false;
395 *max_error = 0;
396 for (size_t i = 0; i < x.size(); ++i) {
397 float fn_of_xi = gfx::SkTransferFnEval(*fn, x[i]);
398 float error_at_xi = std::abs(t[i] - fn_of_xi);
399 *max_error = std::max(*max_error, error_at_xi);
400 }
401 return true;
402 }
403
365 bool SkMatrixIsApproximatelyIdentity(const SkMatrix44& m) { 404 bool SkMatrixIsApproximatelyIdentity(const SkMatrix44& m) {
366 const float kEpsilon = 1.f / 256.f; 405 const float kEpsilon = 1.f / 256.f;
367 for (int i = 0; i < 4; ++i) { 406 for (int i = 0; i < 4; ++i) {
368 for (int j = 0; j < 4; ++j) { 407 for (int j = 0; j < 4; ++j) {
369 float identity_value = i == j ? 1 : 0; 408 float identity_value = i == j ? 1 : 0;
370 float value = m.get(i, j); 409 float value = m.get(i, j);
371 if (std::abs(identity_value - value) > kEpsilon) 410 if (std::abs(identity_value - value) > kEpsilon)
372 return false; 411 return false;
373 } 412 }
374 } 413 }
375 return true; 414 return true;
376 } 415 }
377 416
378 } // namespace gfx 417 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/skia_color_space_util.h ('k') | ui/gfx/test/icc_profiles.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698