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 SkICC_DEFINED 9 #define SkICC_DEFINED 10 11 #include "SkData.h" 12 #include "SkRefCnt.h" 13 14 struct SkColorSpaceTransferFn; 15 class SkColorSpace; 16 class SkData; 17 class SkMatrix44; 18 19 class SK_API SkICC : public SkRefCnt { 20 public: 21 22 /** 23 * Parse an ICC profile. 24 * 25 * Returns nullptr if the data is not a valid ICC profile or if the profile 26 * input space is not RGB. 27 */ 28 static sk_sp<SkICC> Make(const void*, size_t); 29 30 /** 31 * If the gamut can be represented as transformation into XYZ D50, returns 32 * true and sets the proper values in |toXYZD50|. 33 * 34 * If not, returns false. This indicates that the ICC data is too complex 35 * to isolate a simple gamut transformation. 36 */ 37 bool toXYZD50(SkMatrix44* toXYZD50) const; 38 39 /** 40 * If the transfer function can be represented as coefficients to the standard 41 * equation, returns true and sets |fn| to the proper values. 42 * 43 * If not, returns false. This indicates one of the following: 44 * (1) The R, G, and B transfer functions are not the same. 45 * (2) The transfer function is represented as a table that we have not managed 46 * to match to a standard curve. 47 * (3) The ICC data is too complex to isolate a single transfer function. 48 */ 49 bool isNumericalTransferFn(SkColorSpaceTransferFn* fn) const; 50 51 /** 52 * Please do not call this unless isNumericalTransferFn() has been called and it 53 * fails. SkColorSpaceTransferFn is the preferred representation. 54 * 55 * If it is not possible to represent the R, G, and B transfer functions numerically 56 * and it is still necessary to get the transfer function, this will return the 57 * transfer functions as three tables (R, G, and B). 58 * 59 * If possible, this will return tables of the same length as they were specified in 60 * the ICC profile. This means that the lengths of the three tables are not 61 * guaranteed to be the same. If the ICC representation was not a table, the length 62 * will be chosen arbitrarily. 63 * 64 * The lengths of the tables are all guaranteed to be at least 2. Entries in the 65 * tables are guaranteed to be in [0, 1]. 66 * 67 * This API may be deleted in favor of a numerical approximation of the raw data. 68 * 69 * This function may fail, indicating that the ICC profile does not have transfer 70 * functions. 71 */ 72 struct Channel { 73 // Byte offset of the start of the table in |fStorage| 74 size_t fOffset; 75 int fCount; 76 }; 77 struct Tables { 78 Channel fRed; 79 Channel fGreen; 80 Channel fBlue; 81 redTables82 const float* red() { 83 return (const float*) (fStorage->bytes() + fRed.fOffset); 84 } greenTables85 const float* green() { 86 return (const float*) (fStorage->bytes() + fGreen.fOffset); 87 } blueTables88 const float* blue() { 89 return (const float*) (fStorage->bytes() + fBlue.fOffset); 90 } 91 92 sk_sp<SkData> fStorage; 93 }; 94 bool rawTransferFnData(Tables* tables) const; 95 96 /** 97 * Write an ICC profile with transfer function |fn| and gamut |toXYZD50|. 98 */ 99 static sk_sp<SkData> WriteToICC(const SkColorSpaceTransferFn& fn, const SkMatrix44& toXYZD50); 100 101 private: 102 SkICC(sk_sp<SkColorSpace> colorSpace); 103 104 sk_sp<SkColorSpace> fColorSpace; 105 106 friend class ICCTest; 107 }; 108 109 #endif 110