OLD | NEW |
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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/color_transform.h" | 5 #include "ui/gfx/color_transform.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <list> | 9 #include <list> |
10 #include <memory> | 10 #include <memory> |
(...skipping 17 matching lines...) Expand all Loading... |
28 using std::log; | 28 using std::log; |
29 using std::max; | 29 using std::max; |
30 using std::min; | 30 using std::min; |
31 using std::pow; | 31 using std::pow; |
32 using std::sqrt; | 32 using std::sqrt; |
33 | 33 |
34 namespace gfx { | 34 namespace gfx { |
35 | 35 |
36 namespace { | 36 namespace { |
37 | 37 |
| 38 std::string Str(float f) { |
| 39 return base::StringPrintf("%+1.8e", f); |
| 40 } |
| 41 |
38 // Helper for scoped QCMS profiles. | 42 // Helper for scoped QCMS profiles. |
39 struct QcmsProfileDeleter { | 43 struct QcmsProfileDeleter { |
40 void operator()(qcms_profile* p) { | 44 void operator()(qcms_profile* p) { |
41 if (p) { | 45 if (p) { |
42 qcms_profile_release(p); | 46 qcms_profile_release(p); |
43 } | 47 } |
44 } | 48 } |
45 }; | 49 }; |
46 using ScopedQcmsProfile = std::unique_ptr<qcms_profile, QcmsProfileDeleter>; | 50 using ScopedQcmsProfile = std::unique_ptr<qcms_profile, QcmsProfileDeleter>; |
47 | 51 |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 | 224 |
221 Transform GetPrimaryTransform(const gfx::ColorSpace& color_space) { | 225 Transform GetPrimaryTransform(const gfx::ColorSpace& color_space) { |
222 SkMatrix44 primary_matrix; | 226 SkMatrix44 primary_matrix; |
223 color_space.GetPrimaryMatrix(&primary_matrix); | 227 color_space.GetPrimaryMatrix(&primary_matrix); |
224 return Transform(primary_matrix); | 228 return Transform(primary_matrix); |
225 } | 229 } |
226 | 230 |
227 } // namespace | 231 } // namespace |
228 | 232 |
229 class ColorTransformMatrix; | 233 class ColorTransformMatrix; |
| 234 class ColorTransformSkTransferFn; |
230 class ColorTransformFromLinear; | 235 class ColorTransformFromLinear; |
231 class ColorTransformToBT2020CL; | 236 class ColorTransformToBT2020CL; |
232 class ColorTransformFromBT2020CL; | 237 class ColorTransformFromBT2020CL; |
233 class ColorTransformNull; | 238 class ColorTransformNull; |
234 class QCMSColorTransform; | 239 class QCMSColorTransform; |
235 | 240 |
236 class ColorTransformStep { | 241 class ColorTransformStep { |
237 public: | 242 public: |
238 ColorTransformStep() {} | 243 ColorTransformStep() {} |
239 virtual ~ColorTransformStep() {} | 244 virtual ~ColorTransformStep() {} |
240 virtual ColorTransformFromLinear* GetFromLinear() { return nullptr; } | 245 virtual ColorTransformFromLinear* GetFromLinear() { return nullptr; } |
241 virtual ColorTransformToBT2020CL* GetToBT2020CL() { return nullptr; } | 246 virtual ColorTransformToBT2020CL* GetToBT2020CL() { return nullptr; } |
242 virtual ColorTransformFromBT2020CL* GetFromBT2020CL() { return nullptr; } | 247 virtual ColorTransformFromBT2020CL* GetFromBT2020CL() { return nullptr; } |
| 248 virtual ColorTransformSkTransferFn* GetSkTransferFn() { return nullptr; } |
243 virtual ColorTransformMatrix* GetMatrix() { return nullptr; } | 249 virtual ColorTransformMatrix* GetMatrix() { return nullptr; } |
244 virtual ColorTransformNull* GetNull() { return nullptr; } | 250 virtual ColorTransformNull* GetNull() { return nullptr; } |
245 virtual QCMSColorTransform* GetQCMS() { return nullptr; } | 251 virtual QCMSColorTransform* GetQCMS() { return nullptr; } |
246 | 252 |
247 // Join methods, returns true if the |next| transform was successfully | 253 // Join methods, returns true if the |next| transform was successfully |
248 // assimilated into |this|. | 254 // assimilated into |this|. |
249 // If Join() returns true, |next| is no longer needed and can be deleted. | 255 // If Join() returns true, |next| is no longer needed and can be deleted. |
250 virtual bool Join(ColorTransformStep* next) { return false; } | 256 virtual bool Join(ColorTransformStep* next) { return false; } |
251 | 257 |
252 // Return true if this is a null transform. | 258 // Return true if this is a null transform. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 | 336 |
331 void Transform(ColorTransform::TriStim* colors, size_t num) const override { | 337 void Transform(ColorTransform::TriStim* colors, size_t num) const override { |
332 for (size_t i = 0; i < num; i++) | 338 for (size_t i = 0; i < num; i++) |
333 matrix_.TransformPoint(colors + i); | 339 matrix_.TransformPoint(colors + i); |
334 } | 340 } |
335 | 341 |
336 bool CanAppendShaderSource() override { return true; } | 342 bool CanAppendShaderSource() override { return true; } |
337 | 343 |
338 void AppendShaderSource(std::string* result) override { | 344 void AppendShaderSource(std::string* result) override { |
339 const SkMatrix44& m = matrix_.matrix(); | 345 const SkMatrix44& m = matrix_.matrix(); |
340 SRC("color = mat3(%1.8e, %1.8e, %1.8e, %1.8e, %1.8e, %1.8e, %1.8e, %1.8e, " | 346 SRC("color = mat3(%+1.8e, %+1.8e, %+1.8e,", // column 1 |
341 "%1.8e) * color;", | 347 m.get(0, 0), m.get(1, 0), m.get(2, 0)); |
342 m.get(0, 0), m.get(1, 0), m.get(2, 0), // column 1 | 348 SRC(" %+1.8e, %+1.8e, %+1.8e,", // column 2 |
343 m.get(0, 1), m.get(1, 1), m.get(2, 1), // column 2 | 349 m.get(0, 1), m.get(1, 1), m.get(2, 1)); |
344 m.get(0, 2), m.get(1, 2), m.get(2, 2)); // column 3 | 350 SRC(" %+1.8e, %+1.8e, %+1.8e) * color;", // column 3 |
345 SRC("color += vec3(%1.8e, %1.8e, %1.8e);", m.get(0, 3), m.get(1, 3), | 351 m.get(0, 2), m.get(1, 2), m.get(2, 2)); |
346 m.get(2, 3)); | 352 SRC("color = vec3(%+1.8e, %+1.8e, %+1.8e) + color;", // column 4 |
| 353 m.get(0, 3), m.get(1, 3), m.get(2, 3)); |
347 } | 354 } |
348 | 355 |
349 private: | 356 private: |
350 class Transform matrix_; | 357 class Transform matrix_; |
351 }; | 358 }; |
352 | 359 |
| 360 class ColorTransformSkTransferFn : public ColorTransformStep { |
| 361 public: |
| 362 explicit ColorTransformSkTransferFn(const SkColorSpaceTransferFn& fn) |
| 363 : fn_(fn) {} |
| 364 ColorTransformSkTransferFn* GetSkTransferFn() override { return this; } |
| 365 |
| 366 bool Join(ColorTransformStep* next_untyped) override { |
| 367 ColorTransformSkTransferFn* next = next_untyped->GetSkTransferFn(); |
| 368 if (!next) |
| 369 return false; |
| 370 if (SkTransferFnsApproximatelyCancel(fn_, next->fn_)) { |
| 371 // Set to be the identity. |
| 372 fn_.fA = 1; |
| 373 fn_.fB = 0; |
| 374 fn_.fC = 1; |
| 375 fn_.fD = 0; |
| 376 fn_.fE = 0; |
| 377 fn_.fF = 0; |
| 378 fn_.fG = 1; |
| 379 return true; |
| 380 } |
| 381 return false; |
| 382 } |
| 383 |
| 384 bool IsNull() override { return SkTransferFnIsApproximatelyIdentity(fn_); } |
| 385 |
| 386 void Transform(ColorTransform::TriStim* colors, size_t num) const override { |
| 387 for (size_t i = 0; i < num; i++) { |
| 388 colors[i].set_x(SkTransferFnEval(fn_, colors[i].x())); |
| 389 colors[i].set_y(SkTransferFnEval(fn_, colors[i].y())); |
| 390 colors[i].set_z(SkTransferFnEval(fn_, colors[i].z())); |
| 391 } |
| 392 } |
| 393 |
| 394 bool CanAppendShaderSource() override { return true; } |
| 395 |
| 396 void AppendShaderSourceChannel(std::string* result, const char* value) { |
| 397 const float kEpsilon = 1.f / 1024.f; |
| 398 |
| 399 // Construct the linear segment |
| 400 // linear = C * x + F |
| 401 // Elide operations that will be close to the identity. |
| 402 std::string linear = value; |
| 403 if (std::abs(fn_.fC - 1.f) > kEpsilon) |
| 404 linear = Str(fn_.fC) + " * " + linear; |
| 405 if (std::abs(fn_.fF) > kEpsilon) |
| 406 linear = linear + " + " + Str(fn_.fF); |
| 407 |
| 408 // Construct the nonlinear segment. |
| 409 // nonlinear = pow(A * x + B, G) + E |
| 410 // Elide operations (especially the pow) that will be close to the |
| 411 // identity. |
| 412 std::string nonlinear = value; |
| 413 if (std::abs(fn_.fA - 1.f) > kEpsilon) |
| 414 nonlinear = Str(fn_.fA) + " * " + nonlinear; |
| 415 if (std::abs(fn_.fB) > kEpsilon) |
| 416 nonlinear = nonlinear + " + " + Str(fn_.fB); |
| 417 if (std::abs(fn_.fG - 1.f) > kEpsilon) |
| 418 nonlinear = "pow(" + nonlinear + ", " + Str(fn_.fG) + ")"; |
| 419 if (std::abs(fn_.fE) > kEpsilon) |
| 420 nonlinear = nonlinear + " + " + Str(fn_.fE); |
| 421 |
| 422 // Add both parts, skpping the if clause if possible. |
| 423 if (fn_.fD > kEpsilon) { |
| 424 SRC("if (%s < %f)", value, fn_.fD); |
| 425 SRC(" %s = %s;", value, linear.c_str()); |
| 426 SRC("else"); |
| 427 SRC(" %s = %s;", value, nonlinear.c_str()); |
| 428 } else { |
| 429 SRC("%s = %s;", value, nonlinear.c_str()); |
| 430 } |
| 431 } |
| 432 |
| 433 void AppendShaderSource(std::string* result) override { |
| 434 // Append the transfer function for each channel. |
| 435 AppendShaderSourceChannel(result, "color.r"); |
| 436 AppendShaderSourceChannel(result, "color.g"); |
| 437 AppendShaderSourceChannel(result, "color.b"); |
| 438 } |
| 439 |
| 440 private: |
| 441 SkColorSpaceTransferFn fn_; |
| 442 }; |
| 443 |
353 class ColorTransformFromLinear : public ColorTransformStep { | 444 class ColorTransformFromLinear : public ColorTransformStep { |
354 public: | 445 public: |
355 explicit ColorTransformFromLinear(ColorSpace::TransferID transfer, | 446 explicit ColorTransformFromLinear(ColorSpace::TransferID transfer) |
356 const SkColorSpaceTransferFn& fn, | 447 : transfer_(transfer) {} |
357 bool fn_valid) | |
358 : transfer_(transfer), fn_(fn), fn_valid_(fn_valid) { | |
359 if (transfer_ == ColorSpace::TransferID::LINEAR_HDR) | |
360 transfer_ = ColorSpace::TransferID::LINEAR; | |
361 } | |
362 ColorTransformFromLinear* GetFromLinear() override { return this; } | 448 ColorTransformFromLinear* GetFromLinear() override { return this; } |
363 bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; } | 449 bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; } |
364 void Transform(ColorTransform::TriStim* colors, size_t num) const override { | 450 void Transform(ColorTransform::TriStim* colors, size_t num) const override { |
365 if (fn_valid_) { | 451 for (size_t i = 0; i < num; i++) { |
366 for (size_t i = 0; i < num; i++) { | 452 colors[i].set_x(FromLinear(transfer_, colors[i].x())); |
367 colors[i].set_x(EvalSkTransferFn(fn_, colors[i].x())); | 453 colors[i].set_y(FromLinear(transfer_, colors[i].y())); |
368 colors[i].set_y(EvalSkTransferFn(fn_, colors[i].y())); | 454 colors[i].set_z(FromLinear(transfer_, colors[i].z())); |
369 colors[i].set_z(EvalSkTransferFn(fn_, colors[i].z())); | |
370 } | |
371 } else { | |
372 for (size_t i = 0; i < num; i++) { | |
373 colors[i].set_x(FromLinear(transfer_, colors[i].x())); | |
374 colors[i].set_y(FromLinear(transfer_, colors[i].y())); | |
375 colors[i].set_z(FromLinear(transfer_, colors[i].z())); | |
376 } | |
377 } | 455 } |
378 } | 456 } |
379 | 457 |
380 private: | 458 private: |
381 friend class ColorTransformToLinear; | 459 friend class ColorTransformToLinear; |
382 ColorSpace::TransferID transfer_; | 460 ColorSpace::TransferID transfer_; |
383 SkColorSpaceTransferFn fn_; | |
384 bool fn_valid_ = false; | |
385 }; | 461 }; |
386 | 462 |
387 class ColorTransformToLinear : public ColorTransformStep { | 463 class ColorTransformToLinear : public ColorTransformStep { |
388 public: | 464 public: |
389 explicit ColorTransformToLinear(ColorSpace::TransferID transfer, | 465 explicit ColorTransformToLinear(ColorSpace::TransferID transfer) |
390 const SkColorSpaceTransferFn& fn, | 466 : transfer_(transfer) {} |
391 bool fn_valid) | |
392 : transfer_(transfer), fn_(fn), fn_valid_(fn_valid) { | |
393 if (transfer_ == ColorSpace::TransferID::LINEAR_HDR) | |
394 transfer_ = ColorSpace::TransferID::LINEAR; | |
395 } | |
396 | |
397 static bool IsGamma22(ColorSpace::TransferID transfer) { | |
398 switch (transfer) { | |
399 // We don't need to check BT709 here because it's been translated into | |
400 // SRGB in ColorSpaceToColorSpaceTransform::ColorSpaceToLinear below. | |
401 case ColorSpace::TransferID::GAMMA22: | |
402 case ColorSpace::TransferID::IEC61966_2_1: // SRGB | |
403 return true; | |
404 | |
405 default: | |
406 return false; | |
407 } | |
408 } | |
409 | 467 |
410 bool Join(ColorTransformStep* next_untyped) override { | 468 bool Join(ColorTransformStep* next_untyped) override { |
411 ColorTransformFromLinear* next = next_untyped->GetFromLinear(); | 469 ColorTransformFromLinear* next = next_untyped->GetFromLinear(); |
412 if (!next) | 470 if (!next) |
413 return false; | 471 return false; |
414 // TODO(ccameron): Use SkTransferFnsApproximatelyCancel and | 472 if (transfer_ == next->transfer_) { |
415 // SkTransferFnIsApproximatelyIdentity to merge parametric transfer | |
416 // functions. | |
417 if (transfer_ == next->transfer_ || | |
418 (IsGamma22(transfer_) && IsGamma22(next->transfer_))) { | |
419 transfer_ = ColorSpace::TransferID::LINEAR; | 473 transfer_ = ColorSpace::TransferID::LINEAR; |
420 return true; | 474 return true; |
421 } | 475 } |
422 return false; | 476 return false; |
423 } | 477 } |
424 | 478 |
425 bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; } | 479 bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; } |
426 | 480 |
427 // Assumes BT2020 primaries. | 481 // Assumes BT2020 primaries. |
428 static float Luma(const ColorTransform::TriStim& c) { | 482 static float Luma(const ColorTransform::TriStim& c) { |
429 return c.x() * 0.2627f + c.y() * 0.6780f + c.z() * 0.0593f; | 483 return c.x() * 0.2627f + c.y() * 0.6780f + c.z() * 0.0593f; |
430 } | 484 } |
431 | 485 |
432 static ColorTransform::TriStim ClipToWhite(ColorTransform::TriStim& c) { | 486 static ColorTransform::TriStim ClipToWhite(ColorTransform::TriStim& c) { |
433 float maximum = max(max(c.x(), c.y()), c.z()); | 487 float maximum = max(max(c.x(), c.y()), c.z()); |
434 if (maximum > 1.0f) { | 488 if (maximum > 1.0f) { |
435 float l = Luma(c); | 489 float l = Luma(c); |
436 c.Scale(1.0f / maximum); | 490 c.Scale(1.0f / maximum); |
437 ColorTransform::TriStim white(1.0f, 1.0f, 1.0f); | 491 ColorTransform::TriStim white(1.0f, 1.0f, 1.0f); |
438 white.Scale((1.0f - 1.0f / maximum) * l / Luma(white)); | 492 white.Scale((1.0f - 1.0f / maximum) * l / Luma(white)); |
439 ColorTransform::TriStim black(0.0f, 0.0f, 0.0f); | 493 ColorTransform::TriStim black(0.0f, 0.0f, 0.0f); |
440 c += white - black; | 494 c += white - black; |
441 } | 495 } |
442 return c; | 496 return c; |
443 } | 497 } |
444 | 498 |
445 void Transform(ColorTransform::TriStim* colors, size_t num) const override { | 499 void Transform(ColorTransform::TriStim* colors, size_t num) const override { |
446 if (fn_valid_) { | 500 if (transfer_ == ColorSpace::TransferID::SMPTEST2084_NON_HDR) { |
447 for (size_t i = 0; i < num; i++) { | |
448 colors[i].set_x(EvalSkTransferFn(fn_, colors[i].x())); | |
449 colors[i].set_y(EvalSkTransferFn(fn_, colors[i].y())); | |
450 colors[i].set_z(EvalSkTransferFn(fn_, colors[i].z())); | |
451 } | |
452 } else if (transfer_ == ColorSpace::TransferID::SMPTEST2084_NON_HDR) { | |
453 for (size_t i = 0; i < num; i++) { | 501 for (size_t i = 0; i < num; i++) { |
454 ColorTransform::TriStim ret(ToLinear(transfer_, colors[i].x()), | 502 ColorTransform::TriStim ret(ToLinear(transfer_, colors[i].x()), |
455 ToLinear(transfer_, colors[i].y()), | 503 ToLinear(transfer_, colors[i].y()), |
456 ToLinear(transfer_, colors[i].z())); | 504 ToLinear(transfer_, colors[i].z())); |
457 if (Luma(ret) > 0.0) { | 505 if (Luma(ret) > 0.0) { |
458 ColorTransform::TriStim smpte2084( | 506 ColorTransform::TriStim smpte2084( |
459 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].x()), | 507 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].x()), |
460 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].y()), | 508 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].y()), |
461 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].z())); | 509 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].z())); |
462 smpte2084.Scale(Luma(ret) / Luma(smpte2084)); | 510 smpte2084.Scale(Luma(ret) / Luma(smpte2084)); |
463 ret = ClipToWhite(smpte2084); | 511 ret = ClipToWhite(smpte2084); |
464 } | 512 } |
465 colors[i] = ret; | 513 colors[i] = ret; |
466 } | 514 } |
467 } else { | 515 } else { |
468 for (size_t i = 0; i < num; i++) { | 516 for (size_t i = 0; i < num; i++) { |
469 colors[i].set_x(ToLinear(transfer_, colors[i].x())); | 517 colors[i].set_x(ToLinear(transfer_, colors[i].x())); |
470 colors[i].set_y(ToLinear(transfer_, colors[i].y())); | 518 colors[i].set_y(ToLinear(transfer_, colors[i].y())); |
471 colors[i].set_z(ToLinear(transfer_, colors[i].z())); | 519 colors[i].set_z(ToLinear(transfer_, colors[i].z())); |
472 } | 520 } |
473 } | 521 } |
474 } | 522 } |
475 | 523 |
476 private: | 524 private: |
477 ColorSpace::TransferID transfer_; | 525 ColorSpace::TransferID transfer_; |
478 SkColorSpaceTransferFn fn_; | |
479 bool fn_valid_ = false; | |
480 }; | 526 }; |
481 | 527 |
482 // BT2020 Constant Luminance is different than most other | 528 // BT2020 Constant Luminance is different than most other |
483 // ways to encode RGB values as YUV. The basic idea is that | 529 // ways to encode RGB values as YUV. The basic idea is that |
484 // transfer functions are applied on the Y value instead of | 530 // transfer functions are applied on the Y value instead of |
485 // on the RGB values. However, running the transfer function | 531 // on the RGB values. However, running the transfer function |
486 // on the U and V values doesn't make any sense since they | 532 // on the U and V values doesn't make any sense since they |
487 // are centered at 0.5. To work around this, the transfer function | 533 // are centered at 0.5. To work around this, the transfer function |
488 // is applied to the Y, R and B values, and then the U and V | 534 // is applied to the Y, R and B values, and then the U and V |
489 // values are calculated from that. | 535 // values are calculated from that. |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 | 662 |
617 steps_.push_back( | 663 steps_.push_back( |
618 base::MakeUnique<ColorTransformMatrix>(Invert(GetTransferMatrix(from)))); | 664 base::MakeUnique<ColorTransformMatrix>(Invert(GetTransferMatrix(from)))); |
619 | 665 |
620 // If the target color space is not defined, just apply the adjust and | 666 // If the target color space is not defined, just apply the adjust and |
621 // tranfer matrices. | 667 // tranfer matrices. |
622 if (!to.IsValid()) | 668 if (!to.IsValid()) |
623 return; | 669 return; |
624 | 670 |
625 SkColorSpaceTransferFn to_linear_fn; | 671 SkColorSpaceTransferFn to_linear_fn; |
626 bool to_linear_fn_valid = from.GetTransferFunction(&to_linear_fn); | 672 if (from.GetTransferFunction(&to_linear_fn)) { |
627 steps_.push_back(base::MakeUnique<ColorTransformToLinear>( | 673 steps_.push_back( |
628 from.transfer_, to_linear_fn, to_linear_fn_valid)); | 674 base::MakeUnique<ColorTransformSkTransferFn>(to_linear_fn)); |
| 675 } else { |
| 676 steps_.push_back(base::MakeUnique<ColorTransformToLinear>(from.transfer_)); |
| 677 } |
629 | 678 |
630 if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) { | 679 if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) { |
631 // BT2020 CL is a special case. | 680 // BT2020 CL is a special case. |
632 steps_.push_back(base::MakeUnique<ColorTransformFromBT2020CL>()); | 681 steps_.push_back(base::MakeUnique<ColorTransformFromBT2020CL>()); |
633 } | 682 } |
634 steps_.push_back( | 683 steps_.push_back( |
635 base::MakeUnique<ColorTransformMatrix>(GetPrimaryTransform(from))); | 684 base::MakeUnique<ColorTransformMatrix>(GetPrimaryTransform(from))); |
636 | 685 |
637 steps_.push_back( | 686 steps_.push_back( |
638 base::MakeUnique<ColorTransformMatrix>(Invert(GetPrimaryTransform(to)))); | 687 base::MakeUnique<ColorTransformMatrix>(Invert(GetPrimaryTransform(to)))); |
639 if (to.matrix_ == ColorSpace::MatrixID::BT2020_CL) { | 688 if (to.matrix_ == ColorSpace::MatrixID::BT2020_CL) { |
640 // BT2020 CL is a special case. | 689 // BT2020 CL is a special case. |
641 steps_.push_back(base::MakeUnique<ColorTransformToBT2020CL>()); | 690 steps_.push_back(base::MakeUnique<ColorTransformToBT2020CL>()); |
642 } | 691 } |
643 | 692 |
644 SkColorSpaceTransferFn from_linear_fn; | 693 SkColorSpaceTransferFn from_linear_fn; |
645 bool from_linear_fn_valid = to.GetInverseTransferFunction(&from_linear_fn); | 694 if (to.GetInverseTransferFunction(&from_linear_fn)) { |
646 steps_.push_back(base::MakeUnique<ColorTransformFromLinear>( | 695 steps_.push_back( |
647 to.transfer_, from_linear_fn, from_linear_fn_valid)); | 696 base::MakeUnique<ColorTransformSkTransferFn>(from_linear_fn)); |
| 697 } else { |
| 698 steps_.push_back(base::MakeUnique<ColorTransformFromLinear>(to.transfer_)); |
| 699 } |
648 | 700 |
649 steps_.push_back( | 701 steps_.push_back( |
650 base::MakeUnique<ColorTransformMatrix>(GetTransferMatrix(to))); | 702 base::MakeUnique<ColorTransformMatrix>(GetTransferMatrix(to))); |
651 | 703 |
652 steps_.push_back( | 704 steps_.push_back( |
653 base::MakeUnique<ColorTransformMatrix>(Invert(GetRangeAdjustMatrix(to)))); | 705 base::MakeUnique<ColorTransformMatrix>(Invert(GetRangeAdjustMatrix(to)))); |
654 } | 706 } |
655 | 707 |
656 class QCMSColorTransform : public ColorTransformStep { | 708 class QCMSColorTransform : public ColorTransformStep { |
657 public: | 709 public: |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
812 const ColorSpace& to, | 864 const ColorSpace& to, |
813 Intent intent) { | 865 Intent intent) { |
814 return std::unique_ptr<ColorTransform>( | 866 return std::unique_ptr<ColorTransform>( |
815 new ColorTransformInternal(from, to, intent)); | 867 new ColorTransformInternal(from, to, intent)); |
816 } | 868 } |
817 | 869 |
818 ColorTransform::ColorTransform() {} | 870 ColorTransform::ColorTransform() {} |
819 ColorTransform::~ColorTransform() {} | 871 ColorTransform::~ColorTransform() {} |
820 | 872 |
821 } // namespace gfx | 873 } // namespace gfx |
OLD | NEW |