• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
13 #include <vector>
14 
15 // 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
19 // 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).
22 //
23 // 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.
28 class SkColorSpace_A2B : public SkColorSpace_Base {
29 public:
toXYZD50()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 
toXYZD50Hash()39     uint32_t toXYZD50Hash() const override {
40         // See toXYZD50()'s comment.
41         return 0;
42     }
43 
fromXYZD50()44     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     }
49 
50     // There is no single gamma curve in an A2B0 profile
onGammaCloseToSRGB()51     bool onGammaCloseToSRGB() const override { return false; }
onGammaIsLinear()52     bool onGammaIsLinear() const override { return false; }
onIsNumericalTransferFn(SkColorSpaceTransferFn * coeffs)53     bool onIsNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const override { return false; }
54 
onIsCMYK()55     bool onIsCMYK() const override { return kCMYK_ICCTypeFlag == fICCType; }
56 
makeLinearGamma()57     sk_sp<SkColorSpace> makeLinearGamma() const override {
58         // 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.
60         return SkColorSpace::MakeSRGBLinear();
61     }
62 
makeSRGBGamma()63     sk_sp<SkColorSpace> makeSRGBGamma() const override {
64         // See comment in makeLinearGamma
65         return SkColorSpace::MakeSRGB();
66     }
67 
type()68     Type type() const override { return Type::kA2B; }
69 
70     class Element {
71     public:
Element(SkGammaNamed gammaNamed,int channelCount)72         Element(SkGammaNamed gammaNamed, int channelCount)
73             : fType(Type::kGammaNamed)
74             , fGammaNamed(gammaNamed)
75             , fMatrix(SkMatrix44::kUninitialized_Constructor)
76             , fInputChannels(channelCount)
77             , fOutputChannels(channelCount) {
78             SkASSERT(gammaNamed != kNonStandard_SkGammaNamed);
79         }
80 
Element(sk_sp<SkGammas> gammas)81         explicit Element(sk_sp<SkGammas> gammas)
82             : fType(Type::kGammas)
83             , fGammas(std::move(gammas))
84             , fMatrix(SkMatrix44::kUninitialized_Constructor)
85             , fInputChannels(fGammas->channels())
86             , 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         }
93 
Element(sk_sp<SkColorLookUpTable> colorLUT)94         explicit Element(sk_sp<SkColorLookUpTable> colorLUT)
95             : fType(Type::kCLUT)
96             , fCLUT(std::move(colorLUT))
97             , fMatrix(SkMatrix44::kUninitialized_Constructor)
98             , fInputChannels(fCLUT->inputChannels())
99             , fOutputChannels(fCLUT->outputChannels())
100         {}
101 
Element(const SkMatrix44 & matrix)102         explicit Element(const SkMatrix44& matrix)
103             : fType(Type::kMatrix)
104             , fMatrix(matrix)
105             , fInputChannels(3)
106             , fOutputChannels(3)
107         {}
108 
109         enum class Type {
110             kGammaNamed,
111             kGammas,
112             kCLUT,
113             kMatrix
114         };
115 
type()116         Type type() const { return fType; }
117 
gammaNamed()118         SkGammaNamed gammaNamed() const {
119             SkASSERT(Type::kGammaNamed == fType);
120             return fGammaNamed;
121         }
122 
gammas()123         const SkGammas& gammas() const {
124             SkASSERT(Type::kGammas == fType);
125             return *fGammas;
126         }
127 
colorLUT()128         const SkColorLookUpTable& colorLUT() const {
129             SkASSERT(Type::kCLUT == fType);
130             return *fCLUT;
131         }
132 
matrix()133         const SkMatrix44& matrix() const {
134             SkASSERT(Type::kMatrix == fType);
135             return fMatrix;
136         }
137 
inputChannels()138         int inputChannels() const { return fInputChannels; }
139 
outputChannels()140         int outputChannels() const { return fOutputChannels; }
141 
142     private:
143         Type                      fType;
144         SkGammaNamed              fGammaNamed;
145         sk_sp<SkGammas>           fGammas;
146         sk_sp<SkColorLookUpTable> fCLUT;
147         SkMatrix44                fMatrix;
148         int                       fInputChannels;
149         int                       fOutputChannels;
150     };
element(int i)151     const Element& element(int i) const { return fElements[i]; }
152 
count()153     int count() const { return (int)fElements.size(); }
154 
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     };
161 
pcs()162     PCS pcs() const { return fPCS; }
163 
iccType()164     ICCTypeFlag iccType() const { return fICCType; }
165 
166     SkColorSpace_A2B(ICCTypeFlag iccType, std::vector<Element> elements, PCS pcs,
167                      sk_sp<SkData> profileData);
168 
169 private:
170     ICCTypeFlag          fICCType;
171     std::vector<Element> fElements;
172     PCS                  fPCS;
173 
174     friend class SkColorSpace_Base;
175     friend class ColorSpaceXformTest;
176     typedef SkColorSpace_Base INHERITED;
177 };
178 
179 #endif
180