Bind a source declaration and a device profile into a pipeline.
False when either half is degenerate – collinear primaries, a white with no cone response, a device that cannot make a neutral. The individual stages decide that; this reports it.
The flux scalar starts at unity. setPipelineFluxQ16 is how brightness and the power limiter reach it, because they change between frames while everything else here does not. With target_white, D65 working XYZ is adapted to the selected physical neutral at bind time. A white outside the emitter gamut rejects the build; nullptr preserves the historical D65 output byte-for-byte.
144 {
145 if (out == nullptr) {
146 return false;
147 }
150 return false;
151 }
152
153
154
155
156
157
158
159
161 i32 white_x = 0;
162 i32 white_y = 0;
165 return false;
166 }
167 constexpr i32 kD65XQ16 = 20493;
168 constexpr i32 kD65YQ16 = 21561;
169 constexpr i32 kD65ToleranceQ16 = 7;
170 const bool already_d65 = white_x > kD65XQ16 - kD65ToleranceQ16 &&
171 white_x < kD65XQ16 + kD65ToleranceQ16 &&
172 white_y > kD65YQ16 - kD65ToleranceQ16 &&
173 white_y < kD65YQ16 + kD65ToleranceQ16;
174 if (!already_d65) {
177 return false;
178 }
180 }
181
183 const bool is_rgb =
185 if (target_white == nullptr) {
186 if (is_rgb) {
190 return false;
191 }
192 } else {
193
194
195
196
199 return false;
203 for (int row = 0; row < 3; ++row) {
204 for (int col = 0; col < 3; ++col) {
206 constexpr i64 kMax = 9223372036854775807LL;
207 for (int k = 0; k < 3; ++k) {
208
209 const i64 term =
static_cast<i64>(physical_solve.m[row][k]) *
210 to_target.m[k][col];
211 if ((term > 0 && sum > kMax - term) ||
212 (term < 0 && sum < -kMax - term)) return false;
213 sum += term;
214 }
215
216 if (sum > 2147483647LL * 65536 + 32768 ||
217 sum < -2147483648LL * 65536 - 32768) return false;
218 const i64 value = sum >= 0 ? (sum + 32768) >> 16
219 : -((-sum + 32768) >> 16);
221 return false;
222 effective_solve.m[row][col] =
static_cast<i32
>(
value);
223 }
224 }
225 if (is_rgb) {
227 return false;
229 &effective_solve, &out->
wide)) {
230 return false;
231 }
232 }
239 return false;
240 }
242 if (!response) return false;
247 response->blue.size() != size)
return false;
249 }
252 return true;
253}
static FluxScalar unity() FL_NO_EXCEPT
Identity. Drives pass through unchanged.
bool validResponseLut(const u16 *values, u16 size) FL_NO_EXCEPT
bool buildWidePipelineQ16(const colorimetric_response::EmitterProfile &device, const Chromaticity *target_white, const EmitterSolveMatrixQ16 *effective_solve, shared_ptr< const WidePipelineQ16 > *out) FL_NO_EXCEPT
constexpr int type_rank< T >::value
bool buildGamutMapQ16(const colorimetric_response::EmitterProfile &profile, GamutMapQ16 *out) FL_NO_EXCEPT
Derive the mapper for a three-emitter profile.
void foldAdaptationIntoSourceMatrix(const AdaptationMatrixQ16 &adaptation, SourceMatrixQ16 *source) FL_NO_EXCEPT
Pre-multiply the adaptation into a source matrix, in place.
bool buildSourceMatrixQ16(const RgbPrimaries &primaries, SourceMatrixQ16 *out) FL_NO_EXCEPT
Quantize the source matrix for primaries.
shared_ptr< T > make_shared(Args &&... args) FL_NO_EXCEPT
bool buildGamutMapFromSolveQ16(const EmitterSolveMatrixQ16 &solve, GamutMapQ16 *out) FL_NO_EXCEPT
Build a mapper from a bind-time solve already transformed into D65 working coordinates.
bool buildRgbSolveMatrixQ16(const colorimetric_response::EmitterProfile &profile, EmitterSolveMatrixQ16 *out) FL_NO_EXCEPT
Invert the emitter matrix for a three-emitter profile.
bool buildBradfordMatrixQ16(Chromaticity source_white, Chromaticity destination_white, AdaptationMatrixQ16 *out) FL_NO_EXCEPT
Build the Bradford transform from source_white to destination_white.
bool q16FromFloatBits(float value, i32 *out) FL_NO_EXCEPT
s16.16 of a float, rounded to nearest, computed from its IEEE-754 bits with integer arithmetic only –...
TransferFunction transfer
The source's transfer function, applied per code.
GamutPolicy gamut_policy
What to do with a target the device cannot reproduce.
shared_ptr< const ResponseLutsQ16 > response
Absent means linear code-to-light response.
GamutMapQ16 gamut
The device hull, its solve, and the lightness bound.
FluxScalar flux
Brightness times power limiting, as one scalar (C4).
shared_ptr< const WidePipelineQ16 > wide
SourceMatrixQ16 source
Source primaries to XYZ, with adaptation to D65 already folded in.
Inverse emitter matrix in s16.16, mapping XYZ to three emitter drives.
A collapsed adaptation transform in s16.16.
CIE 1931 xy chromaticity, independent of encoded storage and chipset.
TransferFunction transfer
const u16 * response_lut_r
const u16 * response_lut_g
const u16 * response_lut_b