blob: 5f2800796a47133cce7d554c913f76e493ab027a [file] [log] [blame]
raftias94888332016-10-18 10:02:51 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkColorSpace_A2B_DEFINED
9#define SkColorSpace_A2B_DEFINED
10
11#include "SkColorSpace_Base.h"
12
raftias026f2232016-10-24 09:52:26 -070013#include <vector>
14
raftias94888332016-10-18 10:02:51 -070015// An alternative SkColorSpace that represents all the color space data that
16// is stored in an A2B0 ICC tag. This allows us to use alternative profile
17// connection spaces (CIELAB instead of just CIEXYZ), use color-lookup-tables
18// to do color space transformations not representable as TRC functions or
raftias54761282016-12-01 13:44:07 -050019// matrix operations, as well as have multiple TRC functions. The CLUT also
20// allows conversion between non-3-channel input color spaces ie CMYK(4) to
21// a workable PCS (ie XYZ).
raftias94888332016-10-18 10:02:51 -070022//
raftias54761282016-12-01 13:44:07 -050023// AtoBType, lut8Type and lut16Type A2B0 tag types are supported. There are
24// also MPET (multi-processing-elements) A2B0 tags in the standard which allow
25// you to combine these 3 primitives (TRC, CLUT, matrix) in any order/quantity.
26// MPET tags are currently unsupported by the MakeICC parser, could be supported
27// here by the nature of the design.
raftias94888332016-10-18 10:02:51 -070028class SkColorSpace_A2B : public SkColorSpace_Base {
29public:
30 const SkMatrix44* toXYZD50() const override {
31 // the matrix specified in A2B0 profiles is not necessarily
32 // a to-XYZ matrix, as to-Lab is supported as well so returning
33 // that could be misleading. Additionally, B-curves are applied
34 // after the matrix is, but a toXYZD50 matrix is the last thing
35 // applied in order to get into the (XYZ) profile connection space.
36 return nullptr;
37 }
38
Brian Osmanbbf251b2016-10-19 14:56:07 -040039 uint32_t toXYZD50Hash() const override {
40 // See toXYZD50()'s comment.
41 return 0;
42 }
43
raftias94888332016-10-18 10:02:51 -070044 const SkMatrix44* fromXYZD50() const override {
45 // See toXYZD50()'s comment. Also, A2B0 profiles are not supported
46 // as destination color spaces, so an inverse matrix is never wanted.
47 return nullptr;
48 }
raftias54761282016-12-01 13:44:07 -050049
Ravi Mistry113d05f2016-12-17 01:31:03 +000050 // There is no single gamma curve in an A2B0 profile
51 bool onGammaCloseToSRGB() const override { return false; }
52 bool onGammaIsLinear() const override { return false; }
53 bool onIsNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const override { return false; }
raftias94888332016-10-18 10:02:51 -070054
Matt Sarett7f15b682017-02-24 17:22:09 -050055 bool onIsCMYK() const override { return kCMYK_ICCTypeFlag == fICCType; }
56
Mike Kleinb1e6cfd2017-06-12 15:20:33 -040057 sk_sp<SkColorSpace> makeLinearGamma() const override {
Brian Osman12313f02016-11-07 09:42:37 -050058 // TODO: Analyze the extrema of our projection into XYZ and use suitable primaries?
59 // For now, just fall back to a default, because we don't have a good answer.
Matt Sarett77a7a1b2017-02-07 13:56:11 -050060 return SkColorSpace::MakeSRGBLinear();
Brian Osman12313f02016-11-07 09:42:37 -050061 }
62
Mike Kleinb1e6cfd2017-06-12 15:20:33 -040063 sk_sp<SkColorSpace> makeSRGBGamma() const override {
Brian Osman12313f02016-11-07 09:42:37 -050064 // See comment in makeLinearGamma
Matt Sarett77a7a1b2017-02-07 13:56:11 -050065 return SkColorSpace::MakeSRGB();
Brian Osman12313f02016-11-07 09:42:37 -050066 }
67
raftias026f2232016-10-24 09:52:26 -070068 Type type() const override { return Type::kA2B; }
raftias94888332016-10-18 10:02:51 -070069
raftias026f2232016-10-24 09:52:26 -070070 class Element {
71 public:
raftias54761282016-12-01 13:44:07 -050072 Element(SkGammaNamed gammaNamed, int channelCount)
raftias026f2232016-10-24 09:52:26 -070073 : fType(Type::kGammaNamed)
74 , fGammaNamed(gammaNamed)
75 , fMatrix(SkMatrix44::kUninitialized_Constructor)
raftias54761282016-12-01 13:44:07 -050076 , fInputChannels(channelCount)
raftiase8ea07a2016-12-05 14:21:45 -050077 , fOutputChannels(channelCount) {
78 SkASSERT(gammaNamed != kNonStandard_SkGammaNamed);
79 }
raftias94888332016-10-18 10:02:51 -070080
raftias026f2232016-10-24 09:52:26 -070081 explicit Element(sk_sp<SkGammas> gammas)
82 : fType(Type::kGammas)
83 , fGammas(std::move(gammas))
raftias54761282016-12-01 13:44:07 -050084 , fMatrix(SkMatrix44::kUninitialized_Constructor)
85 , fInputChannels(fGammas->channels())
raftias197e3112016-12-01 15:31:29 -050086 , fOutputChannels(fGammas->channels()) {
87 for (int i = 0; i < fGammas->channels(); ++i) {
88 if (SkGammas::Type::kTable_Type == fGammas->type(i)) {
89 SkASSERT(fGammas->data(i).fTable.fSize >= 2);
90 }
91 }
92 }
raftias94888332016-10-18 10:02:51 -070093
raftias026f2232016-10-24 09:52:26 -070094 explicit Element(sk_sp<SkColorLookUpTable> colorLUT)
95 : fType(Type::kCLUT)
96 , fCLUT(std::move(colorLUT))
97 , fMatrix(SkMatrix44::kUninitialized_Constructor)
raftias54761282016-12-01 13:44:07 -050098 , fInputChannels(fCLUT->inputChannels())
99 , fOutputChannels(fCLUT->outputChannels())
raftias026f2232016-10-24 09:52:26 -0700100 {}
101
102 explicit Element(const SkMatrix44& matrix)
103 : fType(Type::kMatrix)
104 , fMatrix(matrix)
raftias54761282016-12-01 13:44:07 -0500105 , fInputChannels(3)
106 , fOutputChannels(3)
raftias026f2232016-10-24 09:52:26 -0700107 {}
raftias54761282016-12-01 13:44:07 -0500108
raftias026f2232016-10-24 09:52:26 -0700109 enum class Type {
110 kGammaNamed,
111 kGammas,
112 kCLUT,
113 kMatrix
114 };
raftias94888332016-10-18 10:02:51 -0700115
raftias026f2232016-10-24 09:52:26 -0700116 Type type() const { return fType; }
raftias94888332016-10-18 10:02:51 -0700117
raftias026f2232016-10-24 09:52:26 -0700118 SkGammaNamed gammaNamed() const {
119 SkASSERT(Type::kGammaNamed == fType);
120 return fGammaNamed;
121 }
122
123 const SkGammas& gammas() const {
124 SkASSERT(Type::kGammas == fType);
125 return *fGammas;
126 }
127
128 const SkColorLookUpTable& colorLUT() const {
129 SkASSERT(Type::kCLUT == fType);
130 return *fCLUT;
131 }
132
133 const SkMatrix44& matrix() const {
134 SkASSERT(Type::kMatrix == fType);
135 return fMatrix;
136 }
137
raftias54761282016-12-01 13:44:07 -0500138 int inputChannels() const { return fInputChannels; }
139
140 int outputChannels() const { return fOutputChannels; }
141
raftias026f2232016-10-24 09:52:26 -0700142 private:
143 Type fType;
144 SkGammaNamed fGammaNamed;
145 sk_sp<SkGammas> fGammas;
146 sk_sp<SkColorLookUpTable> fCLUT;
147 SkMatrix44 fMatrix;
raftias54761282016-12-01 13:44:07 -0500148 int fInputChannels;
149 int fOutputChannels;
raftias026f2232016-10-24 09:52:26 -0700150 };
raftias54761282016-12-01 13:44:07 -0500151 const Element& element(int i) const { return fElements[i]; }
152
raftias25636012016-11-11 15:27:39 -0800153 int count() const { return (int)fElements.size(); }
raftias94888332016-10-18 10:02:51 -0700154
155 // the intermediate profile connection space that this color space
156 // represents the transformation to
157 enum class PCS : uint8_t {
158 kLAB, // CIELAB
159 kXYZ // CIEXYZ
160 };
raftias54761282016-12-01 13:44:07 -0500161
raftias94888332016-10-18 10:02:51 -0700162 PCS pcs() const { return fPCS; }
163
Matt Sarett523116d2017-01-12 18:36:38 -0500164 ICCTypeFlag iccType() const { return fICCType; }
raftias54761282016-12-01 13:44:07 -0500165
Matt Sarett523116d2017-01-12 18:36:38 -0500166 SkColorSpace_A2B(ICCTypeFlag iccType, std::vector<Element> elements, PCS pcs,
raftias54761282016-12-01 13:44:07 -0500167 sk_sp<SkData> profileData);
raftias94888332016-10-18 10:02:51 -0700168
Matt Sarett595599f2016-12-15 13:05:53 -0500169private:
Matt Sarett523116d2017-01-12 18:36:38 -0500170 ICCTypeFlag fICCType;
Mike Klein62458a62016-12-01 16:38:16 +0000171 std::vector<Element> fElements;
raftias54761282016-12-01 13:44:07 -0500172 PCS fPCS;
raftias026f2232016-10-24 09:52:26 -0700173
raftias54761282016-12-01 13:44:07 -0500174 friend class SkColorSpace_Base;
raftias25636012016-11-11 15:27:39 -0800175 friend class ColorSpaceXformTest;
raftias94888332016-10-18 10:02:51 -0700176 typedef SkColorSpace_Base INHERITED;
177};
178
179#endif