1 | // LAF Gfx Library |
2 | // Copyright (c) 2018-2022 Igara Studio S.A. |
3 | // |
4 | // This file is released under the terms of the MIT license. |
5 | // Read LICENSE.txt for more information. |
6 | |
7 | #ifndef GFX_COLOR_SPACE_H_INCLUDED |
8 | #define GFX_COLOR_SPACE_H_INCLUDED |
9 | #pragma once |
10 | |
11 | #include "base/ref.h" |
12 | |
13 | #include <algorithm> |
14 | #include <cstdint> |
15 | #include <string> |
16 | #include <vector> |
17 | |
18 | #pragma push_macro("None") |
19 | #undef None // Undefine the X11 None macro |
20 | |
21 | namespace gfx { |
22 | |
23 | class ColorSpace; |
24 | using ColorSpaceRef = base::Ref<ColorSpace>; |
25 | |
26 | // Gamut white point and primaries as in Skia's SkColorSpacePrimaries. |
27 | struct ColorSpacePrimaries { |
28 | float rx, ry, gx, gy, bx, by; // Red/Green/Blue XY |
29 | float wx, wy; // White point XY |
30 | }; |
31 | |
32 | // Transfer coefficients as in Skia's skcms_TransferFunction, to |
33 | // transform from a curved space to linear: |
34 | // |
35 | // LinearVal = C*InputVal + F , for 0.0f <= InputVal < D |
36 | // LinearVal = (A*InputVal + B)^G + E, for D <= InputVal <= 1.0f |
37 | // |
38 | struct ColorSpaceTransferFn { |
39 | float g, a, b, c, d, e, f; |
40 | }; |
41 | |
42 | class ColorSpace : public base::RefCountT<ColorSpace> { |
43 | public: |
44 | enum Type { None, |
45 | sRGB, |
46 | RGB, |
47 | ICC }; |
48 | |
49 | enum Flag { NoFlags = 0, |
50 | HasGamma = 1, |
51 | HasTransferFn = 2, |
52 | HasPrimaries = 4, |
53 | HasICC = 8 }; |
54 | |
55 | ColorSpace(const Type type, |
56 | const Flag flags = NoFlags, |
57 | const float gamma = 1.0, |
58 | std::vector<uint8_t>&& rawData = std::vector<uint8_t>()); |
59 | |
60 | static ColorSpaceRef MakeNone(); // Use display color space |
61 | static ColorSpaceRef MakeSRGB(); |
62 | static ColorSpaceRef MakeLinearSRGB(); |
63 | static ColorSpaceRef MakeSRGBWithGamma(float gamma); |
64 | static ColorSpaceRef MakeRGB(const ColorSpaceTransferFn& fn, |
65 | const ColorSpacePrimaries& p); |
66 | static ColorSpaceRef MakeRGBWithSRGBGamut(const ColorSpaceTransferFn& fn); |
67 | static ColorSpaceRef MakeRGBWithSRGBGamma(const ColorSpacePrimaries& p); |
68 | static ColorSpaceRef MakeICC(const void* data, size_t n); |
69 | static ColorSpaceRef MakeICC(std::vector<uint8_t>&& data); |
70 | |
71 | Type type() const { return m_type; } |
72 | Flag flags() const { return m_flags; } |
73 | |
74 | const std::string& name() const { return m_name; } |
75 | void setName(const std::string& name) { m_name = name; } |
76 | |
77 | float gamma() const { return m_gamma; } |
78 | |
79 | bool hasGamma() const { return has(HasGamma); } |
80 | bool hasTransferFn() const { return has(HasTransferFn); } |
81 | bool hasPrimaries() const { return has(HasPrimaries); } |
82 | |
83 | size_t iccSize() const { |
84 | if (has(HasICC)) |
85 | return m_data.size(); |
86 | else |
87 | return 0; |
88 | } |
89 | |
90 | const void* iccData() const { |
91 | if (has(HasICC)) |
92 | return &m_data[0]; |
93 | else |
94 | return nullptr; |
95 | } |
96 | |
97 | const ColorSpaceTransferFn* transferFn() const { |
98 | if (has(HasTransferFn)) |
99 | return (const ColorSpaceTransferFn*)&m_data[0]; |
100 | else |
101 | return nullptr; |
102 | } |
103 | |
104 | const ColorSpacePrimaries* primaries() const { |
105 | if (has(HasPrimaries)) { |
106 | if (has(HasTransferFn)) |
107 | return (const ColorSpacePrimaries*)&m_data[sizeof(ColorSpaceTransferFn)]; |
108 | else |
109 | return (const ColorSpacePrimaries*)&m_data[0]; |
110 | } |
111 | else |
112 | return nullptr; |
113 | } |
114 | |
115 | bool operator==(const ColorSpace& that) const = delete; |
116 | bool operator!=(const ColorSpace& that) const = delete; |
117 | bool nearlyEqual(const ColorSpace& that) const; |
118 | |
119 | // This data can be used |
120 | const std::vector<uint8_t>& rawData() const { return m_data; } |
121 | |
122 | private: |
123 | bool has(const Flag flag) const { return (m_flags & int(flag)) == int(flag); } |
124 | |
125 | Type m_type; |
126 | Flag m_flags; |
127 | std::string m_name; |
128 | float m_gamma = 1.0f; |
129 | // ColorSpacePrimaries + ColorSpaceTransferFn or raw ICC profile data |
130 | std::vector<uint8_t> m_data; |
131 | }; |
132 | |
133 | } // namespace gfx |
134 | |
135 | #pragma pop_macro("None") |
136 | |
137 | #endif |
138 | |