11constexpr float CCT_MIN_K = 1000.0f;
12constexpr float CCT_MAX_K = 25000.0f;
16float gamma_correct(
float channel) {
17 if (channel <= 0.0031308f) {
18 return 12.92f * channel;
20 return 1.055f * std::pow(channel, 1.0f / 2.4f) - 0.055f;
23uint8_t to_byte(
float channel) {
return static_cast<uint8_t
>(std::clamp(channel, 0.0f, 1.0f) * 255.0f); }
29 const float sum =
x +
y +
z;
36 const float chroma_x =
x / sum;
37 const float chroma_y =
y / sum;
42 const float denominator = 0.1858f - chroma_y;
43 if (std::abs(denominator) < 1e-4f) {
46 const float n = (chroma_x - 0.3320f) / denominator;
47 const float cct = ((437.0f * n + 3601.0f) * n + 6861.0f) * n + 5517.0f;
48 return (cct >= CCT_MIN_K && cct <= CCT_MAX_K) ? cct : NAN;
53 const float r_linear = 3.2406f *
x - 1.5372f *
y - 0.4986f *
z;
54 const float g_linear = -0.9689f *
x + 1.8758f *
y + 0.0415f *
z;
55 const float b_linear = 0.0557f *
x - 0.2040f *
y + 1.0570f *
z;
57 r = to_byte(gamma_correct(r_linear));
58 g = to_byte(gamma_correct(g_linear));
59 b = to_byte(gamma_correct(b_linear));
void tristimulus_to_rgb(float x, float y, float z, uint8_t &r, uint8_t &g, uint8_t &b)
float tristimulus_to_cct(float x, float y, float z)
constexpr float MIN_TRISTIMULUS_SUM