FastLED 3.10.6
Loading...
Searching...
No Matches
white_allocation.h
Go to the documentation of this file.
1#pragma once
2
3// White-preferred allocation for a device with a white emitter (C3, #4041).
4//
5// A white emitter makes the emitter matrix wide: a target's preimage is no
6// longer unique, and C3 asks for the white-preferred one -- as much light
7// from the white emitter as the target allows.
8//
9// The P5 reference finds it by enumerating vertices, which A3/B11 forbid per
10// pixel. It does not need to be. With the white emitter at drive w, the RGB
11// drives making up the difference are
12//
13// d(w) = M^-1 . target - w * (M^-1 . white)
14//
15// which is affine in w. Each of the six bounds on the three RGB drives is
16// therefore one inequality in w, the feasible set is a single interval, and
17// white-preferred is its upper end.
18//
19// `docs/color-gamut-algorithm-selection.md` records the measurement: over
20// the corpus's `rgbw` and `non_d65_white` devices this reproduces the
21// reference's drives to 1.1e-15 and 7.8e-16 respectively -- float64
22// rounding. The derivation never assumed the white sat on the neutral axis,
23// which is what the second device checks.
24//
25// Two whites are a different problem, solved by
26// `allocateTwoWhiteDrivesQ16` further down: maximizing w1 + w2 is a linear
27// program over a polygon, and the obvious reduction -- run this twice and
28// keep the better answer -- agrees with the reference on every corpus vector
29// while being wrong on 85% of random reachable targets, because a single
30// emitter's drive is capped at 1. See the same document.
31
32#include "fl/gfx/device_solve.h"
33#include "fl/stl/int.h"
34#include "fl/stl/noexcept.h"
35
36namespace fl {
37
59
85
94 const i32 (&white_xyz)[3],
97
103 const EmitterSolveMatrixQ16& solve, const i32 (&white_xyz)[3],
105
121bool allocateEmitterDrivesQ16(const WhiteAllocationQ16& allocation,
122 const i32 (&xyz)[3],
123 i32 (&drives)[4]) FL_NO_EXCEPT;
124
145
156 const i32 (&white1_xyz)[3],
157 const i32 (&white2_xyz)[3],
160
163 const EmitterSolveMatrixQ16& solve, const i32 (&white1_xyz)[3],
164 const i32 (&white2_xyz)[3], WhiteAllocationPolicy policy,
166
214 const i32 (&xyz)[3],
215 i32 (&drives)[5]) FL_NO_EXCEPT;
216
217} // namespace fl
bool buildTwoWhiteAllocationFromSolveQ16(const EmitterSolveMatrixQ16 &solve, const i32(&white1_xyz)[3], const i32(&white2_xyz)[3], WhiteAllocationPolicy policy, TwoWhiteAllocationQ16 *out) FL_NO_EXCEPT
Bind two adapted white columns with an RGB solve in the same XYZ domain.
bool allocateTwoWhiteDrivesQ16(const TwoWhiteAllocationQ16 &allocation, const i32(&xyz)[3], i32(&drives)[5]) FL_NO_EXCEPT
One pixel: XYZ in s16.16 to five drives – red, green, blue, white1, white2 – at whichever end of the ...
bool allocateEmitterDrivesQ16(const WhiteAllocationQ16 &allocation, const i32(&xyz)[3], i32(&drives)[4]) FL_NO_EXCEPT
One pixel: XYZ in s16.16 to four drives, in the order red, green, blue, white, at whichever end of th...
WhiteAllocationPolicy
Which end of the feasible white interval to take (C3).
@ WhitePreferred
As much white as the target allows.
@ RgbPreferred
As little as the target allows, which for most targets is none.
bool buildWhiteAllocationQ16(const colorimetric_response::EmitterProfile &profile, const i32(&white_xyz)[3], WhiteAllocationPolicy policy, WhiteAllocationQ16 *out) FL_NO_EXCEPT
Derive the allocation for a three-primary profile plus one white emitter.
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
bool buildWhiteAllocationFromSolveQ16(const colorimetric_response::EmitterProfile &profile, const EmitterSolveMatrixQ16 &solve, const i32(&white_xyz)[3], WhiteAllocationPolicy policy, WhiteAllocationQ16 *out) FL_NO_EXCEPT
Bind from an RGB solve already adapted to the D65 working domain.
bool buildTwoWhiteAllocationQ16(const colorimetric_response::EmitterProfile &profile, const i32(&white1_xyz)[3], const i32(&white2_xyz)[3], WhiteAllocationPolicy policy, TwoWhiteAllocationQ16 *out) FL_NO_EXCEPT
Derive the allocation for three primaries plus two white emitters.
Base definition for an LED controller.
Definition crgb.hpp:179
i32 per_white2[3]
M^-1 . w2: the RGB drives one unit of the second white replaces.
WhiteAllocationPolicy policy
Which end of the feasible total this profile takes.
EmitterSolveMatrixQ16 rgb_solve
Inverse RGB emitter matrix.
EmitterSolveMatrixQ16 rgb_solve
Inverse RGB emitter matrix.
i32 slack[3]
Per-channel drive slack, in s16.16 raw units.
WhiteAllocationPolicy policy
Which end of the interval this profile takes.
Inverse emitter matrix in s16.16, mapping XYZ to three emitter drives.
Everything the per-pixel allocation needs, derived once when a profile binds.
Everything the two-white allocation needs, derived once when a profile binds (C3, #4198).