Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2017 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 SkImageInfoPriv_DEFINED
      9 #define SkImageInfoPriv_DEFINED
     10 
     11 #include "SkImageInfo.h"
     12 
     13 /**
     14  *  This contains shared checks on SkImageInfo.  Depending on the desired color space behavior,
     15  *  the caller should choose one of the two versions below.
     16  */
     17 static inline bool SkImageInfoIsValidCommon(const SkImageInfo& info) {
     18     if (info.width() <= 0 || info.height() <= 0) {
     19         return false;
     20     }
     21 
     22     const int kMaxDimension = SK_MaxS32 >> 2;
     23     if (info.width() > kMaxDimension || info.height() > kMaxDimension) {
     24         return false;
     25     }
     26 
     27     if (kUnknown_SkColorType == info.colorType() || kUnknown_SkAlphaType == info.alphaType()) {
     28         return false;
     29     }
     30 
     31     if (kOpaque_SkAlphaType != info.alphaType() &&
     32        (kRGB_565_SkColorType == info.colorType() || kGray_8_SkColorType == info.colorType())) {
     33         return false;
     34     }
     35 
     36     if (kRGBA_F16_SkColorType == info.colorType() &&
     37        (info.colorSpace() && (!info.colorSpace()->gammaIsLinear()))) {
     38         return false;
     39     }
     40 
     41     return true;
     42 }
     43 
     44 /**
     45  *  Returns true if |info| contains a valid combination of width, height, colorType, alphaType,
     46  *  colorSpace.  Allows numerical color spaces.  Returns false otherwise.
     47  */
     48 static inline bool SkImageInfoIsValidAllowNumericalCS(const SkImageInfo& info) {
     49     if (!SkImageInfoIsValidCommon(info)) {
     50         return false;
     51     }
     52 
     53     SkColorSpaceTransferFn fn;
     54     if (info.colorSpace() && !info.colorSpace()->isNumericalTransferFn(&fn)) {
     55         return false;
     56     }
     57 
     58     return true;
     59 }
     60 
     61 /**
     62  *  Returns true if |info| contains a valid combination of width, height, colorType, alphaType,
     63  *  colorSpace.  Only supports rendering color spaces.  Returns false otherwise.
     64  */
     65 static inline bool SkImageInfoIsValidRenderingCS(const SkImageInfo& info) {
     66     if (!SkImageInfoIsValidCommon(info)) {
     67         return false;
     68     }
     69 
     70     if (info.colorSpace() &&
     71        (!info.colorSpace()->gammaCloseToSRGB() && !info.colorSpace()->gammaIsLinear())) {
     72         return false;
     73     }
     74 
     75     return true;
     76 }
     77 
     78 /**
     79  *  Returns true if |info| contains a valid combination of width, height, colorType, alphaType,
     80  *  colorSpace.  Uses |colorMode| to decide how to treat color spaces.
     81  */
     82 static inline bool SkImageInfoIsValid(const SkImageInfo& info,
     83                                       SkDestinationSurfaceColorMode colorMode) {
     84     if (SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware == colorMode) {
     85         return SkImageInfoIsValidRenderingCS(info);
     86     }
     87 
     88     return SkImageInfoIsValidAllowNumericalCS(info);
     89 }
     90 
     91 /**
     92  *  Returns true if Skia has defined a pixel conversion from the |src| to the |dst|.
     93  *  Returns false otherwise.  Some discussion of false cases:
     94  *      We will not convert to kIndex8 unless it exactly matches the src, since color tables
     95  *      are immutable.
     96  *      We do not convert to kGray8 when the |src| is not kGray8 in the same color space.
     97  *      We may add this feature - it just requires some work to convert to luminance while
     98  *      handling color spaces correctly.  Currently no one is asking for this.
     99  *      We will not convert from kAlpha8 when the |dst| is not kAlpha8.  This would require
    100  *      inventing color information.
    101  *      We will not convert to kOpaque when the |src| is not kOpaque.  This could be
    102  *      implemented to set all the alpha values to 1, but there is still some ambiguity -
    103  *      should we use kPremul or kUnpremul color values with the opaque alphas?  Or should
    104  *      we just use whatever the |src| alpha is?  In the future, we could choose to clearly
    105  *      define this, but currently no one is asking for this feature.
    106  *      We will not convert to a particular color space if |src| is nullptr.  The color space
    107  *      conversion is not well-defined.
    108  */
    109 static inline bool SkImageInfoValidConversion(const SkImageInfo& dst, const SkImageInfo& src) {
    110     if (!SkImageInfoIsValidAllowNumericalCS(dst) || !SkImageInfoIsValidAllowNumericalCS(src)) {
    111         return false;
    112     }
    113 
    114     if (kGray_8_SkColorType == dst.colorType()) {
    115         if (kGray_8_SkColorType != src.colorType()) {
    116             return false;
    117         }
    118 
    119         if (dst.colorSpace() && !SkColorSpace::Equals(dst.colorSpace(), src.colorSpace())) {
    120             return false;
    121         }
    122     }
    123 
    124     if (kAlpha_8_SkColorType != dst.colorType() && kAlpha_8_SkColorType == src.colorType()) {
    125         return false;
    126     }
    127 
    128     if (kOpaque_SkAlphaType == dst.alphaType() && kOpaque_SkAlphaType != src.alphaType()) {
    129         return false;
    130     }
    131 
    132     if (dst.colorSpace() && !src.colorSpace()) {
    133         return false;
    134     }
    135 
    136     return true;
    137 }
    138 #endif  // SkImageInfoPriv_DEFINED
    139