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

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

Issue 2203213002: ICC profile color translations (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@color_correction7
Patch Set: win compile fix Created 4 years, 4 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/DEPS ('k') | ui/gfx/color_transform_unittest.cc » ('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 (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 <vector> 7 #include <vector>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "ui/gfx/color_space.h" 10 #include "ui/gfx/color_space.h"
11 #include "ui/gfx/icc_profile.h"
11 #include "ui/gfx/transform.h" 12 #include "ui/gfx/transform.h"
13 #include "third_party/qcms/src/qcms.h"
14
15 #ifndef THIS_MUST_BE_INCLUDED_AFTER_QCMS_H
16 extern "C" {
17 #include "third_party/qcms/src/chain.h"
18 };
19 #endif
12 20
13 namespace gfx { 21 namespace gfx {
14 22
15 Transform Invert(const Transform& t) { 23 Transform Invert(const Transform& t) {
16 Transform ret = t; 24 Transform ret = t;
17 if (!t.GetInverse(&ret)) { 25 if (!t.GetInverse(&ret)) {
18 LOG(ERROR) << "Inverse should alsways be possible."; 26 LOG(ERROR) << "Inverse should alsways be possible.";
19 } 27 }
20 return ret; 28 return ret;
21 } 29 }
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 179
172 ColorTransform::TriStim D50(0.9642f, 1.0f, 0.8249f); 180 ColorTransform::TriStim D50(0.9642f, 1.0f, 0.8249f);
173 ColorTransform::TriStim source_response = Map(bradford, WXYZ); 181 ColorTransform::TriStim source_response = Map(bradford, WXYZ);
174 ColorTransform::TriStim dest_response = Map(bradford, D50); 182 ColorTransform::TriStim dest_response = Map(bradford, D50);
175 183
176 Transform adapter; 184 Transform adapter;
177 adapter.Scale3d(dest_response.x() / source_response.x(), 185 adapter.Scale3d(dest_response.x() / source_response.x(),
178 dest_response.y() / source_response.y(), 186 dest_response.y() / source_response.y(),
179 dest_response.z() / source_response.z()); 187 dest_response.z() / source_response.z());
180 188
181 return bradford * adapter * Invert(bradford) * ret; 189 return Invert(bradford) * adapter * bradford * ret;
182 } 190 }
183 191
184 GFX_EXPORT float FromLinear(ColorSpace::TransferID id, float v) { 192 GFX_EXPORT float FromLinear(ColorSpace::TransferID id, float v) {
185 switch (id) { 193 switch (id) {
186 default: 194 default:
187 case ColorSpace::TransferID::BT709: 195 case ColorSpace::TransferID::BT709:
188 case ColorSpace::TransferID::SMPTE170M: 196 case ColorSpace::TransferID::SMPTE170M:
189 case ColorSpace::TransferID::BT2020_10: 197 case ColorSpace::TransferID::BT2020_10:
190 case ColorSpace::TransferID::BT2020_12: { 198 case ColorSpace::TransferID::BT2020_12: {
191 v = fmax(0.0f, v); 199 v = fmax(0.0f, v);
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 private: 548 private:
541 ColorSpace from_; 549 ColorSpace from_;
542 ColorSpace to_; 550 ColorSpace to_;
543 551
544 // a_ -> tolinear -> b_ -> fromlinear -> c_; 552 // a_ -> tolinear -> b_ -> fromlinear -> c_;
545 Transform a_; 553 Transform a_;
546 Transform b_; 554 Transform b_;
547 Transform c_; 555 Transform c_;
548 }; 556 };
549 557
558 class QCMSColorTransform : public ColorTransform {
559 public:
560 // Takes ownership of the profiles
561 QCMSColorTransform(qcms_profile* from, qcms_profile* to)
562 : from_(from), to_(to) {}
563 ~QCMSColorTransform() {
564 qcms_profile_release(from_);
565 qcms_profile_release(to_);
566 }
567 void transform(TriStim* colors, size_t num) override {
568 CHECK(sizeof(TriStim) == sizeof(float[3]));
569 // QCMS doesn't like numbers outside 0..1
570 for (size_t i = 0; i < num; i++) {
571 colors[i].set_x(fmin(1.0f, fmax(0.0f, colors[i].x())));
572 colors[i].set_y(fmin(1.0f, fmax(0.0f, colors[i].y())));
573 colors[i].set_z(fmin(1.0f, fmax(0.0f, colors[i].z())));
574 }
575 qcms_chain_transform(from_, to_, reinterpret_cast<float*>(colors),
576 reinterpret_cast<float*>(colors), num * 3);
577 }
578
579 private:
580 qcms_profile *from_, *to_;
581 };
582
583 class ChainColorTransform : public ColorTransform {
584 public:
585 ChainColorTransform(std::unique_ptr<ColorTransform> a,
586 std::unique_ptr<ColorTransform> b)
587 : a_(std::move(a)), b_(std::move(b)) {}
588
589 private:
590 void transform(TriStim* colors, size_t num) override {
591 a_->transform(colors, num);
592 b_->transform(colors, num);
593 }
594 std::unique_ptr<ColorTransform> a_;
595 std::unique_ptr<ColorTransform> b_;
596 };
597
598 qcms_profile* GetQCMSProfileIfAvailable(const ColorSpace& color_space) {
599 ICCProfile icc_profile = ICCProfile::FromColorSpace(color_space);
600 if (icc_profile.GetData().empty())
601 return nullptr;
602 return qcms_profile_from_memory(icc_profile.GetData().data(),
603 icc_profile.GetData().size());
604 }
605
606 qcms_profile* GetXYZD50Profile() {
607 // QCMS is trixy, it has a datatype called qcms_CIE_xyY, but what it expects
608 // is in fact not xyY color coordinates, it just wants the x/y values of the
609 // primaries with Y equal to 1.0.
610 qcms_CIE_xyYTRIPLE xyz;
611 qcms_CIE_xyY w;
612 xyz.red.x = 1.0f;
613 xyz.red.y = 0.0f;
614 xyz.red.Y = 1.0f;
615 xyz.green.x = 0.0f;
616 xyz.green.y = 1.0f;
617 xyz.green.Y = 1.0f;
618 xyz.blue.x = 0.0f;
619 xyz.blue.y = 0.0f;
620 xyz.blue.Y = 1.0f;
621 w.x = 0.34567f;
622 w.y = 0.35850f;
623 w.Y = 1.0f;
624 return qcms_profile_create_rgb_with_gamma(w, xyz, 1.0f);
625 }
626
550 std::unique_ptr<ColorTransform> ColorTransform::NewColorTransform( 627 std::unique_ptr<ColorTransform> ColorTransform::NewColorTransform(
551 const ColorSpace& from, 628 const ColorSpace& from,
552 const ColorSpace& to, 629 const ColorSpace& to,
553 Intent intent) { 630 Intent intent) {
554 // TODO(Hubbe): Check if from and/or to can be mapped to ICC profiles and 631 qcms_profile* from_profile = GetQCMSProfileIfAvailable(from);
555 // provide better transforms in those cases. 632 qcms_profile* to_profile = GetQCMSProfileIfAvailable(to);
556 return std::unique_ptr<ColorTransform>( 633 if (from_profile) {
557 new ColorSpaceToColorSpaceTransform(from, to, intent)); 634 if (to_profile) {
635 return std::unique_ptr<ColorTransform>(
636 new QCMSColorTransform(from_profile, to_profile));
637 } else {
638 return std::unique_ptr<ColorTransform>(new ChainColorTransform(
639 std::unique_ptr<ColorTransform>(
640 new QCMSColorTransform(from_profile, GetXYZD50Profile())),
641 std::unique_ptr<ColorTransform>(new ColorSpaceToColorSpaceTransform(
642 ColorSpace::CreateXYZD50(), to, intent))));
643 }
644 } else {
645 if (to_profile) {
646 return std::unique_ptr<ColorTransform>(new ChainColorTransform(
647 std::unique_ptr<ColorTransform>(new ColorSpaceToColorSpaceTransform(
648 from, ColorSpace::CreateXYZD50(), intent)),
649 std::unique_ptr<ColorTransform>(
650 new QCMSColorTransform(GetXYZD50Profile(), to_profile))));
651 } else {
652 return std::unique_ptr<ColorTransform>(
653 new ColorSpaceToColorSpaceTransform(from, to, intent));
654 }
655 }
558 } 656 }
559 657
560 } // namespace gfx 658 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/DEPS ('k') | ui/gfx/color_transform_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698