MCPcopy Create free account
hub / github.com/FastLED/FastLED / strict_subgamut

Function strict_subgamut

tests/fl/gfx/rgbw_colorimetric.cpp:670–720  ·  view source on GitHub ↗

Verbatim copy of solve_strict_subgamut (post-#2708 — includes hull projection, post-#2748 — includes native topology authority guard).

Source from the content-addressed store, hash-verified

668// Verbatim copy of solve_strict_subgamut (post-#2708 — includes hull projection,
669// post-#2748 — includes native topology authority guard).
670inline bool strict_subgamut(const ProfileCache& cache, float s_r, float s_g, float s_b, float out[4]) {
671 out[0] = out[1] = out[2] = out[3] = 0.0f;
672
673 // #2748 native topology authority guard. Mirrors the production check.
674 if (is_native_input_gamut(*cache.profile)) {
675 const int n_active = count_active_channels(s_r, s_g, s_b);
676 if (n_active <= 2) {
677 out[0] = fl::clamp(s_r, 0.0f, 1.0f);
678 out[1] = fl::clamp(s_g, 0.0f, 1.0f);
679 out[2] = fl::clamp(s_b, 0.0f, 1.0f);
680 out[3] = 0.0f;
681 return true;
682 }
683 }
684
685 float X_t[3];
686 if (cache.has_source_space) {
687 const float s[3] = { s_r, s_g, s_b };
688 matvec3(cache.M_src, s, X_t);
689 } else {
690 X_t[0] = cache.P_R[0]*s_r + cache.P_G[0]*s_g + cache.P_B[0]*s_b;
691 X_t[1] = cache.P_R[1]*s_r + cache.P_G[1]*s_g + cache.P_B[1]*s_b;
692 X_t[2] = cache.P_R[2]*s_r + cache.P_G[2]*s_g + cache.P_B[2]*s_b;
693 }
694 const float sum = X_t[0]+X_t[1]+X_t[2];
695 if (sum < 1e-9f) return true;
696 float xy_t[2] = { X_t[0]/sum, X_t[1]/sum };
697 project_to_hull_mirror(cache, X_t, xy_t);
698 struct SG { const float* a; const float* b; const float* c;
699 const float (*Pinv)[3]; int ia,ib,ic; };
700 const SG sgs[3] = {
701 { cache.profile->xy_r, cache.profile->xy_g, cache.xy_w, cache.P_RGW_inv, 0,1,3 },
702 { cache.profile->xy_r, cache.profile->xy_b, cache.xy_w, cache.P_RBW_inv, 0,2,3 },
703 { cache.profile->xy_b, cache.profile->xy_g, cache.xy_w, cache.P_BGW_inv, 2,1,3 },
704 };
705 const float kEps = 1e-4f;
706 for (int k = 0; k < 3; ++k) {
707 const SG& sg = sgs[k];
708 float bary[3];
709 if (!barycentric_xy(xy_t, sg.a, sg.b, sg.c, bary)) continue;
710 if (bary[0] < -kEps || bary[1] < -kEps || bary[2] < -kEps) continue;
711 float t[3]; matvec3(sg.Pinv, X_t, t);
712 if (t[0] < -kEps || t[1] < -kEps || t[2] < -kEps) continue;
713 if (t[0] < 0) t[0] = 0; if (t[1] < 0) t[1] = 0; if (t[2] < 0) t[2] = 0;
714 float m = t[0]; if (t[1] > m) m = t[1]; if (t[2] > m) m = t[2];
715 if (m > 1.0f) { float inv = 1.0f/m; t[0]*=inv; t[1]*=inv; t[2]*=inv; }
716 out[sg.ia] = t[0]; out[sg.ib] = t[1]; out[sg.ic] = t[2];
717 return true;
718 }
719 return false;
720}
721
722} // namespace fastled_mirror
723

Callers 1

Calls 6

is_native_input_gamutFunction · 0.85
count_active_channelsFunction · 0.85
clampFunction · 0.85
matvec3Function · 0.85
project_to_hull_mirrorFunction · 0.85
barycentric_xyFunction · 0.85

Tested by

no test coverage detected