FastLED 3.9.15
Loading...
Searching...
No Matches
rgbw_colorimetric.h File Reference

Detailed Description

Chromaticity-aware RGBW solvers — strict sub-gamut + wx_lp_legacy white extraction + boosted overdrive + LUT + RGBCCT (issue #2545).

This header carries the public/internal declarations and the small inline math helpers used by the implementation. The heavier solver, LUT, and RGBCCT code lives in rgbw_colorimetric.cpp.hpp behind the FASTLED_RGBW_COLORIMETRIC compile gate.

Solver model in one paragraph:

  • Input RGB is treated as linear-light source-gamut coordinates.
  • A DiodeProfile supplies measured emitter xy + peak Y values.
  • The source matrix maps input RGB to target CIE XYZ in the measured device's absolute XYZ frame.
  • Strict mode routes that target into a legal RGBW topology and solves a small linear system.
  • wx_lp_legacy solves a chromaticity-preserving maximum-W endpoint.
  • boosted/overdrive intentionally trades chromaticity for more W/luminance.

Native-gamut invariants:

  • Single-channel R/G/B inputs are exact identity.
  • Native outer edges RG/RB/GB are topology-locked: no W and no inactive third RGB primary may appear.
  • Dual edges are still colorimetric solves, not raw 1:1 passthrough; the measured emitter XYZ/Y values determine the active-channel ratio.
  • Three-channel/interior inputs use chroma/value separation: solve the full-chroma endpoint, then apply the original source value.

Definition in file rgbw_colorimetric.h.

#include "fl/gfx/rgbw.h"
#include "fl/math/math.h"
#include "fl/stl/stdint.h"
#include "fl/stl/unique_ptr.h"
+ Include dependency graph for rgbw_colorimetric.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  fl::colorimetric_detail::LutTable
 
struct  fl::colorimetric_detail::ProfileCache
 
struct  fl::colorimetric_detail::RgbcctProfile
 

Namespaces

namespace  fl
 Base definition for an LED controller.
 
namespace  fl::colorimetric_detail
 

Enumerations

enum class  fl::colorimetric_detail::LutInterp : u8 { fl::colorimetric_detail::Bilinear = 0 , fl::colorimetric_detail::Hermite = 1 }
 

Functions

bool fl::colorimetric_detail::barycentric_xy (const float t[2], const float A[2], const float B[2], const float C[2], float bary[3]) FL_NOEXCEPT
 
LutTable fl::colorimetric_detail::build_lut (const ProfileCache &cache, int grid_n) FL_NOEXCEPT
 
LutTable fl::colorimetric_detail::build_lut (const ProfileCache &cache, int grid_n, LutInterp interp) FL_NOEXCEPT
 
void fl::colorimetric_detail::build_profile_cache (const DiodeProfile *p, int cct_override, ProfileCache *cache) FL_NOEXCEPT
 
void fl::colorimetric_detail::build_profile_cache (const DiodeProfile *p, ProfileCache *cache) FL_NOEXCEPT
 
bool fl::colorimetric_detail::build_source_matrix (const float xy_r[2], const float xy_g[2], const float xy_b[2], const float xy_w[2], float M_out[3][3]) FL_NOEXCEPT
 
void fl::colorimetric_detail::cct_to_xy (int cct, float out[2]) FL_NOEXCEPT
 
int fl::colorimetric_detail::count_active_channels (float s_r, float s_g, float s_b) FL_NOEXCEPT
 
void fl::colorimetric_detail::hermite_basis (float t, float out[4]) FL_NOEXCEPT
 
bool fl::colorimetric_detail::invert3x3 (const float in[3][3], float out[3][3]) FL_NOEXCEPT
 
bool fl::colorimetric_detail::is_native_input_gamut (const DiodeProfile &p) FL_NOEXCEPT
 
void fl::colorimetric_detail::lookup_lut (const LutTable &lut, const float xy_t[2], float Y_t, float out_rgbw[4]) FL_NOEXCEPT
 
void fl::colorimetric_detail::matvec3 (const float M[3][3], const float v[3], float out[3]) FL_NOEXCEPT
 
void fl::colorimetric_detail::nnls3 (const float M[3][3], const float b[3], float t_out[3], float *residual_out) FL_NOEXCEPT
 
i16 fl::colorimetric_detail::quantize_lut_cell (float v) FL_NOEXCEPT
 
u8 fl::colorimetric_detail::quantize_u8 (float v) FL_NOEXCEPT
 
float fl::colorimetric_detail::rgbcct_eta_for_cct (int target_cct, int warm_cct, int cool_cct) FL_NOEXCEPT
 
void fl::colorimetric_detail::solve_rgbcct (const RgbcctProfile &profile, float s_r, float s_g, float s_b, float eta, float out[5]) FL_NOEXCEPT
 
bool fl::colorimetric_detail::solve_strict_subgamut (const ProfileCache &cache, float s_r, float s_g, float s_b, float out_rgbw[4]) FL_NOEXCEPT
 
bool fl::colorimetric_detail::solve_strict_subgamut_xy (const ProfileCache &cache, const float xy_t[2], float Y_t, float out_rgbw[4]) FL_NOEXCEPT
 
bool fl::colorimetric_detail::solve_wx_lp_legacy (const ProfileCache &cache, float s_r, float s_g, float s_b, float out_rgbw[4]) FL_NOEXCEPT
 
void fl::colorimetric_detail::solve_wx_overdrive (const ProfileCache &cache, float s_r, float s_g, float s_b, float overdrive_ratio, float out_rgbw[4]) FL_NOEXCEPT
 
void fl::colorimetric_detail::xyY_to_XYZ (float x, float y, float Y, float out[3]) FL_NOEXCEPT
 

Variables

constexpr float fl::colorimetric_detail::kDefaultOverdriveRatio = 0.5f
 
constexpr i16 fl::colorimetric_detail::kLutQ = 4096
 
constexpr int fl::colorimetric_detail::kLutStrideBilinear = 4
 
constexpr int fl::colorimetric_detail::kLutStrideHermite = 12
 

Class Documentation

◆ fl::colorimetric_detail::LutTable

struct fl::colorimetric_detail::LutTable
+ Collaboration diagram for fl::colorimetric_detail::LutTable:
Class Members
unique_ptr< i16[]> cells
LutInterp interp = LutInterp::Bilinear
int N = 0
float xy_max[2] = {0.0f, 0.0f}
float xy_min[2] = {0.0f, 0.0f}

◆ fl::colorimetric_detail::ProfileCache

struct fl::colorimetric_detail::ProfileCache
+ Collaboration diagram for fl::colorimetric_detail::ProfileCache:
Class Members
float d_W[3]
bool has_source_space
float M_src[3][3]
float P_B[3]
float P_BGW_inv[3][3]
float P_G[3]
float P_R[3]
float P_RBW_inv[3][3]
float P_RGB_inv[3][3]
float P_RGW_inv[3][3]
float P_W[3]
const DiodeProfile * profile
float xy_w[2]

◆ fl::colorimetric_detail::RgbcctProfile

struct fl::colorimetric_detail::RgbcctProfile
+ Collaboration diagram for fl::colorimetric_detail::RgbcctProfile:
Class Members
DiodeProfile cool_path
DiodeProfile warm_path