11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
19PROMEKI_NAMESPACE_BEGIN
68 using DataType = Array<double, 2>;
71 static constexpr double MinWavelength = 360;
74 static constexpr double MaxWavelength = 700;
84 static bool isValidWavelength(
double val) {
return val >= MinWavelength && val <= MaxWavelength; }
97 static XYZColor wavelengthToXYZ(
double wavelength);
109 static CIEPoint wavelengthToCIEPoint(
double wavelength);
134 static CIEPoint colorTempToWhitePoint(
double cct) {
139 }
else if (cct <= 7000.0) {
140 x = (-4.6070e9 / std::pow(cct, 3)) + (2.9678e6 / std::pow(cct, 2)) + (0.09911e3 / cct) +
142 }
else if (cct <= 25000) {
143 x = (-2.0064e9 / std::pow(cct, 3)) + (1.9108e6 / std::pow(cct, 2)) + (0.24748e3 / cct) +
148 y = (-3.0 * std::pow(x, 2)) + (2.870 * x) - 0.275;
149 return CIEPoint(x, y);
157 CIEPoint(
double x = -1.0,
double y = -1.0) : d(x, y) {}
163 CIEPoint(
const DataType &other) : d(other) {}
166 double x()
const {
return d[0]; }
169 double y()
const {
return d[1]; }
172 const DataType &data()
const {
return d; }
178 bool isValid()
const {
return d.isBetween(DataType(0.0, 0.0), DataType(0.8, 0.9)); }
186 CIEPoint lerp(
const CIEPoint &other,
double t)
const {
return d.lerp(other.d, t); }
188 XYZ toXYZ(
double Y = 1.0)
const {
189 double X = (x() * Y) / y();
190 double Z = ((1.0 - x() - y()) * Y) / y();
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;
201 double colorTemp()
const {
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) +