• 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 #ifndef SkColorSpacePriv_DEFINED
8 #define SkColorSpacePriv_DEFINED
9 
10 #include <math.h>
11 
12 #include "include/core/SkColorSpace.h"
13 #include "include/private/SkFixed.h"
14 
15 #define SkColorSpacePrintf(...)
16 
17 // A gamut narrower than sRGB, useful for testing.
18 static constexpr skcms_Matrix3x3 gNarrow_toXYZD50 = {{
19     { 0.190974f,  0.404865f,  0.368380f },
20     { 0.114746f,  0.582937f,  0.302318f },
21     { 0.032925f,  0.153615f,  0.638669f },
22 }};
23 
color_space_almost_equal(float a,float b)24 static inline bool color_space_almost_equal(float a, float b) {
25     return SkTAbs(a - b) < 0.01f;
26 }
27 
28 // Let's use a stricter version for transfer functions.  Worst case, these are encoded
29 // in ICC format, which offers 16-bits of fractional precision.
transfer_fn_almost_equal(float a,float b)30 static inline bool transfer_fn_almost_equal(float a, float b) {
31     return SkTAbs(a - b) < 0.001f;
32 }
33 
is_valid_transfer_fn(const skcms_TransferFunction & coeffs)34 static inline bool is_valid_transfer_fn(const skcms_TransferFunction& coeffs) {
35     if (SkScalarIsNaN(coeffs.a) || SkScalarIsNaN(coeffs.b) ||
36         SkScalarIsNaN(coeffs.c) || SkScalarIsNaN(coeffs.d) ||
37         SkScalarIsNaN(coeffs.e) || SkScalarIsNaN(coeffs.f) ||
38         SkScalarIsNaN(coeffs.g))
39     {
40         return false;
41     }
42 
43     if (coeffs.d < 0.0f) {
44         return false;
45     }
46 
47     if (coeffs.d == 0.0f) {
48         // Y = (aX + b)^g + e  for always
49         if (0.0f == coeffs.a || 0.0f == coeffs.g) {
50             SkColorSpacePrintf("A or G is zero, constant transfer function "
51                                "is nonsense");
52             return false;
53         }
54     }
55 
56     if (coeffs.d >= 1.0f) {
57         // Y = cX + f          for always
58         if (0.0f == coeffs.c) {
59             SkColorSpacePrintf("C is zero, constant transfer function is "
60                                "nonsense");
61             return false;
62         }
63     }
64 
65     if ((0.0f == coeffs.a || 0.0f == coeffs.g) && 0.0f == coeffs.c) {
66         SkColorSpacePrintf("A or G, and C are zero, constant transfer function "
67                            "is nonsense");
68         return false;
69     }
70 
71     if (coeffs.c < 0.0f) {
72         SkColorSpacePrintf("Transfer function must be increasing");
73         return false;
74     }
75 
76     if (coeffs.a < 0.0f || coeffs.g < 0.0f) {
77         SkColorSpacePrintf("Transfer function must be positive or increasing");
78         return false;
79     }
80 
81     return true;
82 }
83 
is_almost_srgb(const skcms_TransferFunction & coeffs)84 static inline bool is_almost_srgb(const skcms_TransferFunction& coeffs) {
85     return transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.a, coeffs.a) &&
86            transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.b, coeffs.b) &&
87            transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.c, coeffs.c) &&
88            transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.d, coeffs.d) &&
89            transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.e, coeffs.e) &&
90            transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.f, coeffs.f) &&
91            transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.g, coeffs.g);
92 }
93 
is_almost_2dot2(const skcms_TransferFunction & coeffs)94 static inline bool is_almost_2dot2(const skcms_TransferFunction& coeffs) {
95     return transfer_fn_almost_equal(1.0f, coeffs.a) &&
96            transfer_fn_almost_equal(0.0f, coeffs.b) &&
97            transfer_fn_almost_equal(0.0f, coeffs.e) &&
98            transfer_fn_almost_equal(2.2f, coeffs.g) &&
99            coeffs.d <= 0.0f;
100 }
101 
is_almost_linear(const skcms_TransferFunction & coeffs)102 static inline bool is_almost_linear(const skcms_TransferFunction& coeffs) {
103     // OutputVal = InputVal ^ 1.0f
104     const bool linearExp =
105             transfer_fn_almost_equal(1.0f, coeffs.a) &&
106             transfer_fn_almost_equal(0.0f, coeffs.b) &&
107             transfer_fn_almost_equal(0.0f, coeffs.e) &&
108             transfer_fn_almost_equal(1.0f, coeffs.g) &&
109             coeffs.d <= 0.0f;
110 
111     // OutputVal = 1.0f * InputVal
112     const bool linearFn =
113             transfer_fn_almost_equal(1.0f, coeffs.c) &&
114             transfer_fn_almost_equal(0.0f, coeffs.f) &&
115             coeffs.d >= 1.0f;
116 
117     return linearExp || linearFn;
118 }
119 
120 // Return raw pointers to commonly used SkColorSpaces.
121 // No need to ref/unref these, but if you do, do it in pairs.
122 SkColorSpace* sk_srgb_singleton();
123 SkColorSpace* sk_srgb_linear_singleton();
124 
125 #endif  // SkColorSpacePriv_DEFINED
126