19488833428e83c93a7e6002f4d056084fb57112fraftias/* 29488833428e83c93a7e6002f4d056084fb57112fraftias * Copyright 2016 Google Inc. 39488833428e83c93a7e6002f4d056084fb57112fraftias * 49488833428e83c93a7e6002f4d056084fb57112fraftias * Use of this source code is governed by a BSD-style license that can be 59488833428e83c93a7e6002f4d056084fb57112fraftias * found in the LICENSE file. 69488833428e83c93a7e6002f4d056084fb57112fraftias */ 79488833428e83c93a7e6002f4d056084fb57112fraftias 89488833428e83c93a7e6002f4d056084fb57112fraftias#ifndef SkColorSpace_A2B_DEFINED 99488833428e83c93a7e6002f4d056084fb57112fraftias#define SkColorSpace_A2B_DEFINED 109488833428e83c93a7e6002f4d056084fb57112fraftias 11333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein#include "SkColorLookUpTable.h" 12333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein#include "SkColorSpace.h" 13333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein#include "SkGammas.h" 14026f223d8641beeae19ed0bdbeca738be62256f5raftias#include <vector> 15026f223d8641beeae19ed0bdbeca738be62256f5raftias 169488833428e83c93a7e6002f4d056084fb57112fraftias// An alternative SkColorSpace that represents all the color space data that 179488833428e83c93a7e6002f4d056084fb57112fraftias// is stored in an A2B0 ICC tag. This allows us to use alternative profile 189488833428e83c93a7e6002f4d056084fb57112fraftias// connection spaces (CIELAB instead of just CIEXYZ), use color-lookup-tables 199488833428e83c93a7e6002f4d056084fb57112fraftias// to do color space transformations not representable as TRC functions or 205476128f0a88217414f05e6a7ee518cdb411d026raftias// matrix operations, as well as have multiple TRC functions. The CLUT also 215476128f0a88217414f05e6a7ee518cdb411d026raftias// allows conversion between non-3-channel input color spaces ie CMYK(4) to 225476128f0a88217414f05e6a7ee518cdb411d026raftias// a workable PCS (ie XYZ). 239488833428e83c93a7e6002f4d056084fb57112fraftias// 245476128f0a88217414f05e6a7ee518cdb411d026raftias// AtoBType, lut8Type and lut16Type A2B0 tag types are supported. There are 255476128f0a88217414f05e6a7ee518cdb411d026raftias// also MPET (multi-processing-elements) A2B0 tags in the standard which allow 265476128f0a88217414f05e6a7ee518cdb411d026raftias// you to combine these 3 primitives (TRC, CLUT, matrix) in any order/quantity. 275476128f0a88217414f05e6a7ee518cdb411d026raftias// MPET tags are currently unsupported by the MakeICC parser, could be supported 285476128f0a88217414f05e6a7ee518cdb411d026raftias// here by the nature of the design. 29333848272c4d023199e44ff38f2e6fc6876388e8Mike Kleinclass SkColorSpace_A2B : public SkColorSpace { 309488833428e83c93a7e6002f4d056084fb57112fraftiaspublic: 3136703d9d368050a20764b5336534bd718fd00a6eBrian Osman const SkMatrix44* onToXYZD50() const override { 329488833428e83c93a7e6002f4d056084fb57112fraftias // the matrix specified in A2B0 profiles is not necessarily 339488833428e83c93a7e6002f4d056084fb57112fraftias // a to-XYZ matrix, as to-Lab is supported as well so returning 349488833428e83c93a7e6002f4d056084fb57112fraftias // that could be misleading. Additionally, B-curves are applied 359488833428e83c93a7e6002f4d056084fb57112fraftias // after the matrix is, but a toXYZD50 matrix is the last thing 369488833428e83c93a7e6002f4d056084fb57112fraftias // applied in order to get into the (XYZ) profile connection space. 379488833428e83c93a7e6002f4d056084fb57112fraftias return nullptr; 389488833428e83c93a7e6002f4d056084fb57112fraftias } 399488833428e83c93a7e6002f4d056084fb57112fraftias 4036703d9d368050a20764b5336534bd718fd00a6eBrian Osman uint32_t onToXYZD50Hash() const override { 4136703d9d368050a20764b5336534bd718fd00a6eBrian Osman // See onToXYZD50()'s comment. 42bbf251bf225489a0939fff6df938035a290f4d16Brian Osman return 0; 43bbf251bf225489a0939fff6df938035a290f4d16Brian Osman } 44bbf251bf225489a0939fff6df938035a290f4d16Brian Osman 4536703d9d368050a20764b5336534bd718fd00a6eBrian Osman const SkMatrix44* onFromXYZD50() const override { 4636703d9d368050a20764b5336534bd718fd00a6eBrian Osman // See onToXYZD50()'s comment. Also, A2B0 profiles are not supported 479488833428e83c93a7e6002f4d056084fb57112fraftias // as destination color spaces, so an inverse matrix is never wanted. 489488833428e83c93a7e6002f4d056084fb57112fraftias return nullptr; 499488833428e83c93a7e6002f4d056084fb57112fraftias } 505476128f0a88217414f05e6a7ee518cdb411d026raftias 51113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry // There is no single gamma curve in an A2B0 profile 5236703d9d368050a20764b5336534bd718fd00a6eBrian Osman SkGammaNamed onGammaNamed() const override { return kNonStandard_SkGammaNamed; } 53113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry bool onGammaCloseToSRGB() const override { return false; } 54113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry bool onGammaIsLinear() const override { return false; } 55113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry bool onIsNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const override { return false; } 569488833428e83c93a7e6002f4d056084fb57112fraftias 57f78b55cb94f4ac89b76a26d5a56d6380aa8fea6bLeon Scroggins III bool onIsCMYK() const override { return SkColorSpace::kCMYK_Type == fICCType; } 587f15b682f4e3e0f61a56d3bbdb8163d3a54b997cMatt Sarett 59e9edf8cc50e50998f7074023f974ec034cfcec4cBrian Osman const SkData* onProfileData() const override { return fProfileData.get(); } 60e9edf8cc50e50998f7074023f974ec034cfcec4cBrian Osman 61b1e6cfdb28b7a3db9ab64f90a709df725c1a9c43Mike Klein sk_sp<SkColorSpace> makeLinearGamma() const override { 6212313f072b3563d652a789e28140f70b48e57e03Brian Osman // TODO: Analyze the extrema of our projection into XYZ and use suitable primaries? 6312313f072b3563d652a789e28140f70b48e57e03Brian Osman // For now, just fall back to a default, because we don't have a good answer. 6477a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett return SkColorSpace::MakeSRGBLinear(); 6512313f072b3563d652a789e28140f70b48e57e03Brian Osman } 6612313f072b3563d652a789e28140f70b48e57e03Brian Osman 67b1e6cfdb28b7a3db9ab64f90a709df725c1a9c43Mike Klein sk_sp<SkColorSpace> makeSRGBGamma() const override { 6812313f072b3563d652a789e28140f70b48e57e03Brian Osman // See comment in makeLinearGamma 6977a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett return SkColorSpace::MakeSRGB(); 7012313f072b3563d652a789e28140f70b48e57e03Brian Osman } 7112313f072b3563d652a789e28140f70b48e57e03Brian Osman 72026f223d8641beeae19ed0bdbeca738be62256f5raftias class Element { 73026f223d8641beeae19ed0bdbeca738be62256f5raftias public: 745476128f0a88217414f05e6a7ee518cdb411d026raftias Element(SkGammaNamed gammaNamed, int channelCount) 75026f223d8641beeae19ed0bdbeca738be62256f5raftias : fType(Type::kGammaNamed) 76026f223d8641beeae19ed0bdbeca738be62256f5raftias , fGammaNamed(gammaNamed) 77026f223d8641beeae19ed0bdbeca738be62256f5raftias , fMatrix(SkMatrix44::kUninitialized_Constructor) 785476128f0a88217414f05e6a7ee518cdb411d026raftias , fInputChannels(channelCount) 79e8ea07a6127971aea8183303b9abfa9856b7a54craftias , fOutputChannels(channelCount) { 80e8ea07a6127971aea8183303b9abfa9856b7a54craftias SkASSERT(gammaNamed != kNonStandard_SkGammaNamed); 81e8ea07a6127971aea8183303b9abfa9856b7a54craftias } 82026f223d8641beeae19ed0bdbeca738be62256f5raftias 83026f223d8641beeae19ed0bdbeca738be62256f5raftias explicit Element(sk_sp<SkGammas> gammas) 84026f223d8641beeae19ed0bdbeca738be62256f5raftias : fType(Type::kGammas) 85026f223d8641beeae19ed0bdbeca738be62256f5raftias , fGammas(std::move(gammas)) 865476128f0a88217414f05e6a7ee518cdb411d026raftias , fMatrix(SkMatrix44::kUninitialized_Constructor) 875476128f0a88217414f05e6a7ee518cdb411d026raftias , fInputChannels(fGammas->channels()) 88197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias , fOutputChannels(fGammas->channels()) { 89197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias for (int i = 0; i < fGammas->channels(); ++i) { 90197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias if (SkGammas::Type::kTable_Type == fGammas->type(i)) { 91197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias SkASSERT(fGammas->data(i).fTable.fSize >= 2); 92197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias } 93197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias } 94197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias } 95026f223d8641beeae19ed0bdbeca738be62256f5raftias 96026f223d8641beeae19ed0bdbeca738be62256f5raftias explicit Element(sk_sp<SkColorLookUpTable> colorLUT) 97026f223d8641beeae19ed0bdbeca738be62256f5raftias : fType(Type::kCLUT) 98026f223d8641beeae19ed0bdbeca738be62256f5raftias , fCLUT(std::move(colorLUT)) 99026f223d8641beeae19ed0bdbeca738be62256f5raftias , fMatrix(SkMatrix44::kUninitialized_Constructor) 1005476128f0a88217414f05e6a7ee518cdb411d026raftias , fInputChannels(fCLUT->inputChannels()) 1015476128f0a88217414f05e6a7ee518cdb411d026raftias , fOutputChannels(fCLUT->outputChannels()) 102026f223d8641beeae19ed0bdbeca738be62256f5raftias {} 103026f223d8641beeae19ed0bdbeca738be62256f5raftias 104026f223d8641beeae19ed0bdbeca738be62256f5raftias explicit Element(const SkMatrix44& matrix) 105026f223d8641beeae19ed0bdbeca738be62256f5raftias : fType(Type::kMatrix) 106026f223d8641beeae19ed0bdbeca738be62256f5raftias , fMatrix(matrix) 1075476128f0a88217414f05e6a7ee518cdb411d026raftias , fInputChannels(3) 1085476128f0a88217414f05e6a7ee518cdb411d026raftias , fOutputChannels(3) 109026f223d8641beeae19ed0bdbeca738be62256f5raftias {} 1105476128f0a88217414f05e6a7ee518cdb411d026raftias 111026f223d8641beeae19ed0bdbeca738be62256f5raftias enum class Type { 112026f223d8641beeae19ed0bdbeca738be62256f5raftias kGammaNamed, 113026f223d8641beeae19ed0bdbeca738be62256f5raftias kGammas, 114026f223d8641beeae19ed0bdbeca738be62256f5raftias kCLUT, 115026f223d8641beeae19ed0bdbeca738be62256f5raftias kMatrix 116026f223d8641beeae19ed0bdbeca738be62256f5raftias }; 117026f223d8641beeae19ed0bdbeca738be62256f5raftias 118026f223d8641beeae19ed0bdbeca738be62256f5raftias Type type() const { return fType; } 119026f223d8641beeae19ed0bdbeca738be62256f5raftias 120026f223d8641beeae19ed0bdbeca738be62256f5raftias SkGammaNamed gammaNamed() const { 121026f223d8641beeae19ed0bdbeca738be62256f5raftias SkASSERT(Type::kGammaNamed == fType); 122026f223d8641beeae19ed0bdbeca738be62256f5raftias return fGammaNamed; 123026f223d8641beeae19ed0bdbeca738be62256f5raftias } 124026f223d8641beeae19ed0bdbeca738be62256f5raftias 125026f223d8641beeae19ed0bdbeca738be62256f5raftias const SkGammas& gammas() const { 126026f223d8641beeae19ed0bdbeca738be62256f5raftias SkASSERT(Type::kGammas == fType); 127026f223d8641beeae19ed0bdbeca738be62256f5raftias return *fGammas; 128026f223d8641beeae19ed0bdbeca738be62256f5raftias } 129026f223d8641beeae19ed0bdbeca738be62256f5raftias 130026f223d8641beeae19ed0bdbeca738be62256f5raftias const SkColorLookUpTable& colorLUT() const { 131026f223d8641beeae19ed0bdbeca738be62256f5raftias SkASSERT(Type::kCLUT == fType); 132026f223d8641beeae19ed0bdbeca738be62256f5raftias return *fCLUT; 133026f223d8641beeae19ed0bdbeca738be62256f5raftias } 134026f223d8641beeae19ed0bdbeca738be62256f5raftias 135026f223d8641beeae19ed0bdbeca738be62256f5raftias const SkMatrix44& matrix() const { 136026f223d8641beeae19ed0bdbeca738be62256f5raftias SkASSERT(Type::kMatrix == fType); 137026f223d8641beeae19ed0bdbeca738be62256f5raftias return fMatrix; 138026f223d8641beeae19ed0bdbeca738be62256f5raftias } 139026f223d8641beeae19ed0bdbeca738be62256f5raftias 1405476128f0a88217414f05e6a7ee518cdb411d026raftias int inputChannels() const { return fInputChannels; } 1415476128f0a88217414f05e6a7ee518cdb411d026raftias 1425476128f0a88217414f05e6a7ee518cdb411d026raftias int outputChannels() const { return fOutputChannels; } 1435476128f0a88217414f05e6a7ee518cdb411d026raftias 144026f223d8641beeae19ed0bdbeca738be62256f5raftias private: 145026f223d8641beeae19ed0bdbeca738be62256f5raftias Type fType; 146026f223d8641beeae19ed0bdbeca738be62256f5raftias SkGammaNamed fGammaNamed; 147026f223d8641beeae19ed0bdbeca738be62256f5raftias sk_sp<SkGammas> fGammas; 148026f223d8641beeae19ed0bdbeca738be62256f5raftias sk_sp<SkColorLookUpTable> fCLUT; 149026f223d8641beeae19ed0bdbeca738be62256f5raftias SkMatrix44 fMatrix; 1505476128f0a88217414f05e6a7ee518cdb411d026raftias int fInputChannels; 1515476128f0a88217414f05e6a7ee518cdb411d026raftias int fOutputChannels; 152026f223d8641beeae19ed0bdbeca738be62256f5raftias }; 1535476128f0a88217414f05e6a7ee518cdb411d026raftias const Element& element(int i) const { return fElements[i]; } 1545476128f0a88217414f05e6a7ee518cdb411d026raftias 1552563601fc2b0505619f905f86bd249ae630197ccraftias int count() const { return (int)fElements.size(); } 1569488833428e83c93a7e6002f4d056084fb57112fraftias 1579488833428e83c93a7e6002f4d056084fb57112fraftias // the intermediate profile connection space that this color space 1589488833428e83c93a7e6002f4d056084fb57112fraftias // represents the transformation to 1599488833428e83c93a7e6002f4d056084fb57112fraftias enum class PCS : uint8_t { 1609488833428e83c93a7e6002f4d056084fb57112fraftias kLAB, // CIELAB 1619488833428e83c93a7e6002f4d056084fb57112fraftias kXYZ // CIEXYZ 1629488833428e83c93a7e6002f4d056084fb57112fraftias }; 1635476128f0a88217414f05e6a7ee518cdb411d026raftias 1649488833428e83c93a7e6002f4d056084fb57112fraftias PCS pcs() const { return fPCS; } 1659488833428e83c93a7e6002f4d056084fb57112fraftias 166f78b55cb94f4ac89b76a26d5a56d6380aa8fea6bLeon Scroggins III SkColorSpace::Type iccType() const { return fICCType; } 1675476128f0a88217414f05e6a7ee518cdb411d026raftias 168f78b55cb94f4ac89b76a26d5a56d6380aa8fea6bLeon Scroggins III SkColorSpace_A2B(SkColorSpace::Type iccType, std::vector<Element> elements, PCS pcs, 1695476128f0a88217414f05e6a7ee518cdb411d026raftias sk_sp<SkData> profileData); 170026f223d8641beeae19ed0bdbeca738be62256f5raftias 171595599f46261225dfc67ab4d91d326e099558239Matt Sarettprivate: 172e9edf8cc50e50998f7074023f974ec034cfcec4cBrian Osman sk_sp<SkData> fProfileData; 173e9edf8cc50e50998f7074023f974ec034cfcec4cBrian Osman 174f78b55cb94f4ac89b76a26d5a56d6380aa8fea6bLeon Scroggins III SkColorSpace::Type fICCType; 17562458a6778bc39eea5360301a67d192b3a263df1Mike Klein std::vector<Element> fElements; 1765476128f0a88217414f05e6a7ee518cdb411d026raftias PCS fPCS; 177026f223d8641beeae19ed0bdbeca738be62256f5raftias 1782563601fc2b0505619f905f86bd249ae630197ccraftias friend class ColorSpaceXformTest; 1799488833428e83c93a7e6002f4d056084fb57112fraftias}; 1809488833428e83c93a7e6002f4d056084fb57112fraftias 1819488833428e83c93a7e6002f4d056084fb57112fraftias#endif 182