libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
ciepoint.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
13#include <cmath>
14#include <array>
15#include <promeki/namespace.h>
16#include <promeki/point.h>
17#include <promeki/xyzcolor.h>
18
19PROMEKI_NAMESPACE_BEGIN
20
65class CIEPoint {
66 public:
68 using DataType = Array<double, 2>;
69
71 static constexpr double MinWavelength = 360;
72
74 static constexpr double MaxWavelength = 700;
75
76 //static const CIEPoint D50;
77 //static const CIEPoint D55;
78
84 static bool isValidWavelength(double val) { return val >= MinWavelength && val <= MaxWavelength; }
85
97 static XYZColor wavelengthToXYZ(double wavelength);
98
109 static CIEPoint wavelengthToCIEPoint(double wavelength);
110
134 static CIEPoint colorTempToWhitePoint(double cct) {
135 // from http://www.brucelindbloom.com/index.html?Eqn_T_to_xy.html
136 double x, y;
137 if (cct < 4000) {
138 return CIEPoint(); // Invalid.
139 } else if (cct <= 7000.0) {
140 x = (-4.6070e9 / std::pow(cct, 3)) + (2.9678e6 / std::pow(cct, 2)) + (0.09911e3 / cct) +
141 0.244063;
142 } else if (cct <= 25000) {
143 x = (-2.0064e9 / std::pow(cct, 3)) + (1.9108e6 / std::pow(cct, 2)) + (0.24748e3 / cct) +
144 0.237040;
145 } else {
146 return CIEPoint(); // Invalid
147 }
148 y = (-3.0 * std::pow(x, 2)) + (2.870 * x) - 0.275;
149 return CIEPoint(x, y);
150 }
151
157 CIEPoint(double x = -1.0, double y = -1.0) : d(x, y) {}
158
163 CIEPoint(const DataType &other) : d(other) {}
164
166 double x() const { return d[0]; }
167
169 double y() const { return d[1]; }
170
172 const DataType &data() const { return d; }
173
178 bool isValid() const { return d.isBetween(DataType(0.0, 0.0), DataType(0.8, 0.9)); }
179
186 CIEPoint lerp(const CIEPoint &other, double t) const { return d.lerp(other.d, t); }
187#if 0
188 XYZ toXYZ(double Y = 1.0) const {
189 double X = (x() * Y) / y();
190 double Z = ((1.0 - x() - y()) * Y) / y();
191 return {X, Y, Z};
192 }
193
194 bool isInGamut() const {
195 auto [X, Y, Z] = toXYZ();
196 double u = (4.0 * X) / (-2.0 * X + 12.0 * Y + 3.0 * Z);
197 double v = (9.0 * Y) / (-2.0 * X + 12.0 * Y + 3.0 * Z);
198 return u >= 0 && u <= 0.6 && v >= 0 && v <= 0.6 && u + v <= 0.6;
199 }
200
201 double colorTemp() const {
202 // McCamy's approximation
203 double n = (x() - 0.3320) / (0.1858 - y());
204 return 437.0 * std::pow(n, 3.0) +
205 3601.0 * std::pow(n, 2.0) +
206 6861.0 * n + 5517;
207 }
208#endif
209 private:
210 DataType d;
211};
212
213PROMEKI_NAMESPACE_END
214
215#endif // PROMEKI_ENABLE_CORE