| 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> |
| 11 | 11 |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/stringprintf.h" |
| 14 #include "third_party/qcms/src/qcms.h" | 15 #include "third_party/qcms/src/qcms.h" |
| 15 #include "ui/gfx/color_space.h" | 16 #include "ui/gfx/color_space.h" |
| 16 #include "ui/gfx/icc_profile.h" | 17 #include "ui/gfx/icc_profile.h" |
| 17 #include "ui/gfx/skia_color_space_util.h" | 18 #include "ui/gfx/skia_color_space_util.h" |
| 18 #include "ui/gfx/transform.h" | 19 #include "ui/gfx/transform.h" |
| 19 | 20 |
| 20 #ifndef THIS_MUST_BE_INCLUDED_AFTER_QCMS_H | 21 #ifndef THIS_MUST_BE_INCLUDED_AFTER_QCMS_H |
| 21 extern "C" { | 22 extern "C" { |
| 22 #include "third_party/qcms/src/chain.h" | 23 #include "third_party/qcms/src/chain.h" |
| 23 }; | 24 }; |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 virtual ColorTransformNull* GetNull() { return nullptr; } | 244 virtual ColorTransformNull* GetNull() { return nullptr; } |
| 244 virtual QCMSColorTransform* GetQCMS() { return nullptr; } | 245 virtual QCMSColorTransform* GetQCMS() { return nullptr; } |
| 245 | 246 |
| 246 // Join methods, returns true if the |next| transform was successfully | 247 // Join methods, returns true if the |next| transform was successfully |
| 247 // assimilated into |this|. | 248 // assimilated into |this|. |
| 248 // If Join() returns true, |next| is no longer needed and can be deleted. | 249 // If Join() returns true, |next| is no longer needed and can be deleted. |
| 249 virtual bool Join(ColorTransformStep* next) { return false; } | 250 virtual bool Join(ColorTransformStep* next) { return false; } |
| 250 | 251 |
| 251 // Return true if this is a null transform. | 252 // Return true if this is a null transform. |
| 252 virtual bool IsNull() { return false; } | 253 virtual bool IsNull() { return false; } |
| 253 | |
| 254 virtual void Transform(ColorTransform::TriStim* color, size_t num) = 0; | 254 virtual void Transform(ColorTransform::TriStim* color, size_t num) = 0; |
| 255 virtual bool CanAppendShaderSource() { return false; } |
| 256 virtual void AppendShaderSource(std::string* result) { NOTREACHED(); } |
| 255 | 257 |
| 256 private: | 258 private: |
| 257 DISALLOW_COPY_AND_ASSIGN(ColorTransformStep); | 259 DISALLOW_COPY_AND_ASSIGN(ColorTransformStep); |
| 258 }; | 260 }; |
| 259 | 261 |
| 260 class ColorTransformInternal : public ColorTransform { | 262 class ColorTransformInternal : public ColorTransform { |
| 261 public: | 263 public: |
| 262 ColorTransformInternal(const ColorSpace& from, | 264 ColorTransformInternal(const ColorSpace& from, |
| 263 const ColorSpace& to, | 265 const ColorSpace& to, |
| 264 Intent intent); | 266 Intent intent); |
| 265 ~ColorTransformInternal() override; | 267 ~ColorTransformInternal() override; |
| 266 | 268 |
| 267 // Perform transformation of colors, |colors| is both input and output. | |
| 268 void Transform(TriStim* colors, size_t num) override { | 269 void Transform(TriStim* colors, size_t num) override { |
| 269 for (const auto& step : steps_) | 270 for (const auto& step : steps_) |
| 270 step->Transform(colors, num); | 271 step->Transform(colors, num); |
| 271 } | 272 } |
| 273 bool CanGetShaderSource() const override; |
| 274 std::string GetShaderSource() const override; |
| 275 bool IsIdentity() const override { return steps_.empty(); } |
| 272 size_t NumberOfStepsForTesting() const override { return steps_.size(); } | 276 size_t NumberOfStepsForTesting() const override { return steps_.size(); } |
| 273 | 277 |
| 274 private: | 278 private: |
| 275 void AppendColorSpaceToColorSpaceTransform(ColorSpace from, | 279 void AppendColorSpaceToColorSpaceTransform(ColorSpace from, |
| 276 const ColorSpace& to, | 280 const ColorSpace& to, |
| 277 ColorTransform::Intent intent); | 281 ColorTransform::Intent intent); |
| 278 void Simplify(); | 282 void Simplify(); |
| 279 | 283 |
| 280 // Retrieve the ICC profile from which |color_space| was created, only if that | 284 // Retrieve the ICC profile from which |color_space| was created, only if that |
| 281 // is a more precise representation of the color space than the primaries and | 285 // is a more precise representation of the color space than the primaries and |
| 282 // transfer function in |color_space|. | 286 // transfer function in |color_space|. |
| 283 ScopedQcmsProfile GetQCMSProfileIfNecessary(const ColorSpace& color_space); | 287 ScopedQcmsProfile GetQCMSProfileIfNecessary(const ColorSpace& color_space); |
| 284 | 288 |
| 285 std::list<std::unique_ptr<ColorTransformStep>> steps_; | 289 std::list<std::unique_ptr<ColorTransformStep>> steps_; |
| 286 }; | 290 }; |
| 287 | 291 |
| 292 #define SRC(...) \ |
| 293 do { \ |
| 294 *result += std::string(" ") + base::StringPrintf(__VA_ARGS__) + \ |
| 295 std::string("\n"); \ |
| 296 } while (0) |
| 297 |
| 288 class ColorTransformNull : public ColorTransformStep { | 298 class ColorTransformNull : public ColorTransformStep { |
| 289 public: | 299 public: |
| 290 ColorTransformNull* GetNull() override { return this; } | 300 ColorTransformNull* GetNull() override { return this; } |
| 291 bool IsNull() override { return true; } | 301 bool IsNull() override { return true; } |
| 292 void Transform(ColorTransform::TriStim* color, size_t num) override {} | 302 void Transform(ColorTransform::TriStim* color, size_t num) override {} |
| 303 bool CanAppendShaderSource() override { return true; } |
| 304 void AppendShaderSource(std::string* result) override {} |
| 293 }; | 305 }; |
| 294 | 306 |
| 295 class ColorTransformMatrix : public ColorTransformStep { | 307 class ColorTransformMatrix : public ColorTransformStep { |
| 296 public: | 308 public: |
| 297 explicit ColorTransformMatrix(const class Transform& matrix) | 309 explicit ColorTransformMatrix(const class Transform& matrix) |
| 298 : matrix_(matrix) {} | 310 : matrix_(matrix) {} |
| 299 ColorTransformMatrix* GetMatrix() override { return this; } | 311 ColorTransformMatrix* GetMatrix() override { return this; } |
| 300 bool Join(ColorTransformStep* next_untyped) override { | 312 bool Join(ColorTransformStep* next_untyped) override { |
| 301 ColorTransformMatrix* next = next_untyped->GetMatrix(); | 313 ColorTransformMatrix* next = next_untyped->GetMatrix(); |
| 302 if (!next) | 314 if (!next) |
| 303 return false; | 315 return false; |
| 304 class Transform tmp = next->matrix_; | 316 class Transform tmp = next->matrix_; |
| 305 tmp *= matrix_; | 317 tmp *= matrix_; |
| 306 matrix_ = tmp; | 318 matrix_ = tmp; |
| 307 return true; | 319 return true; |
| 308 } | 320 } |
| 309 | 321 |
| 310 bool IsNull() override { | 322 bool IsNull() override { |
| 311 return SkMatrixIsApproximatelyIdentity(matrix_.matrix()); | 323 return SkMatrixIsApproximatelyIdentity(matrix_.matrix()); |
| 312 } | 324 } |
| 313 | 325 |
| 314 void Transform(ColorTransform::TriStim* colors, size_t num) override { | 326 void Transform(ColorTransform::TriStim* colors, size_t num) override { |
| 315 for (size_t i = 0; i < num; i++) | 327 for (size_t i = 0; i < num; i++) |
| 316 matrix_.TransformPoint(colors + i); | 328 matrix_.TransformPoint(colors + i); |
| 317 } | 329 } |
| 318 | 330 |
| 331 bool CanAppendShaderSource() override { return true; } |
| 332 |
| 333 void AppendShaderSource(std::string* result) override { |
| 334 const SkMatrix44& m = matrix_.matrix(); |
| 335 SRC("color = mat3(%f, %f, %f, %f, %f, %f, %f, %f, %f) * color;", |
| 336 m.get(0, 0), m.get(1, 0), m.get(2, 0), // column 1 |
| 337 m.get(0, 1), m.get(1, 1), m.get(2, 1), // column 2 |
| 338 m.get(0, 2), m.get(1, 2), m.get(2, 2)); // column 3 |
| 339 SRC("color += vec3(%f, %f, %f);", m.get(0, 3), m.get(1, 3), m.get(2, 3)); |
| 340 } |
| 341 |
| 319 private: | 342 private: |
| 320 class Transform matrix_; | 343 class Transform matrix_; |
| 321 }; | 344 }; |
| 322 | 345 |
| 323 class ColorTransformFromLinear : public ColorTransformStep { | 346 class ColorTransformFromLinear : public ColorTransformStep { |
| 324 public: | 347 public: |
| 325 explicit ColorTransformFromLinear(ColorSpace::TransferID transfer, | 348 explicit ColorTransformFromLinear(ColorSpace::TransferID transfer, |
| 326 const SkColorSpaceTransferFn& fn, | 349 const SkColorSpaceTransferFn& fn, |
| 327 bool fn_valid) | 350 bool fn_valid) |
| 328 : transfer_(transfer), fn_(fn), fn_valid_(fn_valid) { | 351 : transfer_(transfer), fn_(fn), fn_valid_(fn_valid) { |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 | 607 |
| 585 // TODO(hubbe): shrink gamuts here (never stretch gamuts) | 608 // TODO(hubbe): shrink gamuts here (never stretch gamuts) |
| 586 } | 609 } |
| 587 | 610 |
| 588 steps_.push_back( | 611 steps_.push_back( |
| 589 base::MakeUnique<ColorTransformMatrix>(GetRangeAdjustMatrix(from))); | 612 base::MakeUnique<ColorTransformMatrix>(GetRangeAdjustMatrix(from))); |
| 590 | 613 |
| 591 steps_.push_back( | 614 steps_.push_back( |
| 592 base::MakeUnique<ColorTransformMatrix>(Invert(GetTransferMatrix(from)))); | 615 base::MakeUnique<ColorTransformMatrix>(Invert(GetTransferMatrix(from)))); |
| 593 | 616 |
| 617 // If the target color space is not defined, just apply the adjust and |
| 618 // tranfer matrices. |
| 619 if (!to.IsValid()) |
| 620 return; |
| 621 |
| 594 SkColorSpaceTransferFn to_linear_fn; | 622 SkColorSpaceTransferFn to_linear_fn; |
| 595 bool to_linear_fn_valid = from.GetTransferFunction(&to_linear_fn); | 623 bool to_linear_fn_valid = from.GetTransferFunction(&to_linear_fn); |
| 596 steps_.push_back(base::MakeUnique<ColorTransformToLinear>( | 624 steps_.push_back(base::MakeUnique<ColorTransformToLinear>( |
| 597 from.transfer_, to_linear_fn, to_linear_fn_valid)); | 625 from.transfer_, to_linear_fn, to_linear_fn_valid)); |
| 598 | 626 |
| 599 if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) { | 627 if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) { |
| 600 // BT2020 CL is a special case. | 628 // BT2020 CL is a special case. |
| 601 steps_.push_back(base::MakeUnique<ColorTransformFromBT2020CL>()); | 629 steps_.push_back(base::MakeUnique<ColorTransformFromBT2020CL>()); |
| 602 } | 630 } |
| 603 steps_.push_back( | 631 steps_.push_back( |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 | 744 |
| 717 if (to_profile) { | 745 if (to_profile) { |
| 718 steps_.push_back(base::MakeUnique<QCMSColorTransform>( | 746 steps_.push_back(base::MakeUnique<QCMSColorTransform>( |
| 719 GetXYZD50Profile(), std::move(to_profile))); | 747 GetXYZD50Profile(), std::move(to_profile))); |
| 720 } | 748 } |
| 721 | 749 |
| 722 if (intent != Intent::TEST_NO_OPT) | 750 if (intent != Intent::TEST_NO_OPT) |
| 723 Simplify(); | 751 Simplify(); |
| 724 } | 752 } |
| 725 | 753 |
| 754 std::string ColorTransformInternal::GetShaderSource() const { |
| 755 std::string result; |
| 756 result += "vec3 DoColorConversion(vec3 color) {\n"; |
| 757 for (const auto& step : steps_) |
| 758 step->AppendShaderSource(&result); |
| 759 result += " return color;\n"; |
| 760 result += "}\n"; |
| 761 return result; |
| 762 } |
| 763 |
| 764 bool ColorTransformInternal::CanGetShaderSource() const { |
| 765 for (const auto& step : steps_) { |
| 766 if (!step->CanAppendShaderSource()) |
| 767 return false; |
| 768 } |
| 769 return true; |
| 770 } |
| 771 |
| 726 ColorTransformInternal::~ColorTransformInternal() {} | 772 ColorTransformInternal::~ColorTransformInternal() {} |
| 727 | 773 |
| 728 void ColorTransformInternal::Simplify() { | 774 void ColorTransformInternal::Simplify() { |
| 729 for (auto iter = steps_.begin(); iter != steps_.end();) { | 775 for (auto iter = steps_.begin(); iter != steps_.end();) { |
| 730 std::unique_ptr<ColorTransformStep>& this_step = *iter; | 776 std::unique_ptr<ColorTransformStep>& this_step = *iter; |
| 731 | 777 |
| 732 // Try to Join |next_step| into |this_step|. If successful, re-visit the | 778 // Try to Join |next_step| into |this_step|. If successful, re-visit the |
| 733 // step before |this_step|. | 779 // step before |this_step|. |
| 734 auto iter_next = iter; | 780 auto iter_next = iter; |
| 735 iter_next++; | 781 iter_next++; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 762 const ColorSpace& to, | 808 const ColorSpace& to, |
| 763 Intent intent) { | 809 Intent intent) { |
| 764 return std::unique_ptr<ColorTransform>( | 810 return std::unique_ptr<ColorTransform>( |
| 765 new ColorTransformInternal(from, to, intent)); | 811 new ColorTransformInternal(from, to, intent)); |
| 766 } | 812 } |
| 767 | 813 |
| 768 ColorTransform::ColorTransform() {} | 814 ColorTransform::ColorTransform() {} |
| 769 ColorTransform::~ColorTransform() {} | 815 ColorTransform::~ColorTransform() {} |
| 770 | 816 |
| 771 } // namespace gfx | 817 } // namespace gfx |
| OLD | NEW |