Home | History | Annotate | Download | only in core
      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_DEFINED
      9 #define SkColorSpace_DEFINED
     10 
     11 #include "SkMatrix44.h"
     12 #include "SkRefCnt.h"
     13 
     14 class SkData;
     15 
     16 /**
     17  *  Describes a color gamut with primaries and a white point.
     18  */
     19 struct SK_API SkColorSpacePrimaries {
     20     float fRX, fRY;
     21     float fGX, fGY;
     22     float fBX, fBY;
     23     float fWX, fWY;
     24 
     25     /**
     26      *  Convert primaries and a white point to a toXYZD50 matrix, the preferred color gamut
     27      *  representation of SkColorSpace.
     28      */
     29     bool toXYZD50(SkMatrix44* toXYZD50) const;
     30 };
     31 
     32 /**
     33  *  Contains the coefficients for a common transfer function equation, specified as
     34  *  a transformation from a curved space to linear.
     35  *
     36  *  LinearVal = C*InputVal + F        , for 0.0f <= InputVal <  D
     37  *  LinearVal = (A*InputVal + B)^G + E, for D    <= InputVal <= 1.0f
     38  *
     39  *  Function is undefined if InputVal is not in [ 0.0f, 1.0f ].
     40  *  Resulting LinearVals must be in [ 0.0f, 1.0f ].
     41  *  Function must be positive and increasing.
     42  */
     43 struct SK_API SkColorSpaceTransferFn {
     44     float fG;
     45     float fA;
     46     float fB;
     47     float fC;
     48     float fD;
     49     float fE;
     50     float fF;
     51 
     52     /**
     53      * Produces a new parametric transfer function equation that is the mathematical inverse of
     54      * this one.
     55      */
     56     SkColorSpaceTransferFn invert() const;
     57 };
     58 
     59 class SK_API SkColorSpace : public SkRefCnt {
     60 public:
     61 
     62     /**
     63      *  Create the sRGB color space.
     64      */
     65     static sk_sp<SkColorSpace> MakeSRGB();
     66 
     67     /**
     68      *  Colorspace with the sRGB primaries, but a linear (1.0) gamma. Commonly used for
     69      *  half-float surfaces, and high precision individual colors (gradient stops, etc...)
     70      */
     71     static sk_sp<SkColorSpace> MakeSRGBLinear();
     72 
     73     enum RenderTargetGamma : uint8_t {
     74         kLinear_RenderTargetGamma,
     75 
     76         /**
     77          *  Transfer function is the canonical sRGB curve, which has a short linear segment
     78          *  followed by a 2.4f exponential.
     79          */
     80         kSRGB_RenderTargetGamma,
     81     };
     82 
     83     enum Gamut {
     84         kSRGB_Gamut,
     85         kAdobeRGB_Gamut,
     86         kDCIP3_D65_Gamut,
     87         kRec2020_Gamut,
     88     };
     89 
     90     /**
     91      *  Create an SkColorSpace from a transfer function and a color gamut.
     92      *
     93      *  Transfer function can be specified as an enum or as the coefficients to an equation.
     94      *  Gamut can be specified as an enum or as the matrix transformation to XYZ D50.
     95      */
     96     static sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma gamma, Gamut gamut);
     97     static sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma gamma, const SkMatrix44& toXYZD50);
     98     static sk_sp<SkColorSpace> MakeRGB(const SkColorSpaceTransferFn& coeffs, Gamut gamut);
     99     static sk_sp<SkColorSpace> MakeRGB(const SkColorSpaceTransferFn& coeffs,
    100                                        const SkMatrix44& toXYZD50);
    101 
    102     /**
    103      *  Create an SkColorSpace from an ICC profile.
    104      */
    105     static sk_sp<SkColorSpace> MakeICC(const void*, size_t);
    106 
    107     /**
    108      *  Returns true if the color space gamma is near enough to be approximated as sRGB.
    109      *  This includes the canonical sRGB transfer function as well as a 2.2f exponential
    110      *  transfer function.
    111      */
    112     bool gammaCloseToSRGB() const;
    113 
    114     /**
    115      *  Returns true if the color space gamma is linear.
    116      */
    117     bool gammaIsLinear() const;
    118 
    119     /**
    120      *  If the transfer function can be represented as coefficients to the standard
    121      *  equation, returns true and sets |fn| to the proper values.
    122      *
    123      *  If not, returns false.
    124      */
    125     bool isNumericalTransferFn(SkColorSpaceTransferFn* fn) const;
    126 
    127     /**
    128      *  Returns true and sets |toXYZD50| if the color gamut can be described as a matrix.
    129      *  Returns false otherwise.
    130      */
    131     bool toXYZD50(SkMatrix44* toXYZD50) const;
    132 
    133     /**
    134      *  Returns true if the color space is sRGB.
    135      *  Returns false otherwise.
    136      *
    137      *  This allows a little bit of tolerance, given that we might see small numerical error
    138      *  in some cases: converting ICC fixed point to float, converting white point to D50,
    139      *  rounding decisions on transfer function and matrix.
    140      *
    141      *  This does not consider a 2.2f exponential transfer function to be sRGB.  While these
    142      *  functions are similar (and it is sometimes useful to consider them together), this
    143      *  function checks for logical equality.
    144      */
    145     bool isSRGB() const;
    146 
    147     /**
    148      *  Returns nullptr on failure.  Fails when we fallback to serializing ICC data and
    149      *  the data is too large to serialize.
    150      */
    151     sk_sp<SkData> serialize() const;
    152 
    153     /**
    154      *  If |memory| is nullptr, returns the size required to serialize.
    155      *  Otherwise, serializes into |memory| and returns the size.
    156      */
    157     size_t writeToMemory(void* memory) const;
    158 
    159     static sk_sp<SkColorSpace> Deserialize(const void* data, size_t length);
    160 
    161     /**
    162      *  If both are null, we return true.  If one is null and the other is not, we return false.
    163      *  If both are non-null, we do a deeper compare.
    164      */
    165     static bool Equals(const SkColorSpace* src, const SkColorSpace* dst);
    166 
    167 protected:
    168     SkColorSpace() {}
    169 };
    170 
    171 enum class SkTransferFunctionBehavior {
    172     /**
    173      *  Converts to a linear space before premultiplying, unpremultiplying, or blending.
    174      */
    175     kRespect,
    176 
    177     /**
    178      *  Premultiplies, unpremultiplies, and blends ignoring the transfer function.  Pixels are
    179      *  treated as if they are linear, regardless of their transfer function encoding.
    180      */
    181     kIgnore,
    182 };
    183 
    184 #endif
    185