Build a mapper from a bind-time solve already transformed into D65 working coordinates.
The neutral cap must be derived from this same solve.
301 {
302 if (out == nullptr) return false;
304
305
306
307
308 i32 neutral_drives[3];
310 i32 largest = neutral_drives[0];
311 for (int i = 0; i < 3; ++i) {
312
313
314
315
316
317
318 if (neutral_drives[i] <= 0) {
319 return false;
320 }
321 if (neutral_drives[i] > largest) {
322 largest = neutral_drives[i];
323 }
324 }
325
326
327
328
329
330
331
332
333
334
335
336
337
339 static_cast<i64>(largest);
342 }
343 const i32
scale =
static_cast<i32
>(scale_wide);
344 const i32 brightest_neutral[3] = {
348 };
349 i32 lab[3];
352 return true;
353}
fl::UISlider scale("Scale", 4,.1, 4,.1)
i32 scaleGamutQ16(i32 value, i32 factor) FL_NO_EXCEPT
Scale an s16.16 value by an s16.16 factor, rounding to nearest.
constexpr i32 kGamutFullDrive
Full drive, as an s16.16 raw value.
constexpr i32 kOklabQ16MaxMagnitude
Largest magnitude either direction accepts, as an s16.16 raw value (64.0).
void xyzToOklabQ16(const i32(&xyz)[3], i32(&out_lab)[3]) FL_NO_EXCEPT
XYZ (s16.16, D65-relative) -> OKLab (s16.16), L then a then b.
void solveRgbDrivesQ16(const EmitterSolveMatrixQ16 &matrix, const i32(&xyz)[3], i32(&drives)[3]) FL_NO_EXCEPT
One pixel: XYZ in s16.16 to three emitter drives in s16.16.
i32 max_neutral_lightness
OKLab lightness of the brightest D65 neutral this device can reach.
EmitterSolveMatrixQ16 solve