FastLED 3.10.6
Loading...
Searching...
No Matches

◆ buildSourceMatrixQ16()

bool fl::buildSourceMatrixQ16 ( const RgbPrimaries & primaries,
SourceMatrixQ16 * out )

Quantize the source matrix for primaries.

False if the primaries are collinear, which makes the primary matrix singular.

Definition at line 57 of file source_xyz.cpp.hpp.

58 {
59 if (out == nullptr) {
60 return false;
61 }
62 // In s16.16 throughout (FastLED#4458): the same construction as
63 // `colorimetric_response::build_source_matrix` -- primaries' XYZ at unit
64 // luminance as columns P, scaled per column by k = P^-1 W so that full
65 // RGB lands on the white -- with no float operation on the way.
66 i32 xy_r[2];
67 i32 xy_g[2];
68 i32 xy_b[2];
69 i32 xy_w[2];
70 if (!sourceChromaticityQ16(primaries.red, xy_r) ||
71 !sourceChromaticityQ16(primaries.green, xy_g) ||
72 !sourceChromaticityQ16(primaries.blue, xy_b) ||
73 !sourceChromaticityQ16(primaries.white, xy_w)) {
74 return false;
75 }
76 if (!sourcePrimariesEncloseAreaQ16(xy_r, xy_g, xy_b)) {
77 return false;
78 }
79 i64 red[3];
80 i64 green[3];
81 i64 blue[3];
82 i64 white[3];
83 if (!detail::xyzColumnQ16(xy_r, kSourceQ16One, red) ||
84 !detail::xyzColumnQ16(xy_g, kSourceQ16One, green) ||
85 !detail::xyzColumnQ16(xy_b, kSourceQ16One, blue) ||
86 !detail::xyzColumnQ16(xy_w, kSourceQ16One, white)) {
87 return false;
88 }
89 const i32 primaries_xyz[3][3] = {
90 {static_cast<i32>(red[0]), static_cast<i32>(green[0]), static_cast<i32>(blue[0])},
91 {static_cast<i32>(red[1]), static_cast<i32>(green[1]), static_cast<i32>(blue[1])},
92 {static_cast<i32>(red[2]), static_cast<i32>(green[2]), static_cast<i32>(blue[2])},
93 };
94 i32 inverse[3][3];
95 if (!invert3x3Q16(primaries_xyz, inverse)) {
96 return false;
97 }
98 const i32 white_xyz[3] = {static_cast<i32>(white[0]), static_cast<i32>(white[1]),
99 static_cast<i32>(white[2])};
100 i32 k[3];
101 for (int i = 0; i < 3; ++i) {
102 k[i] = detail::dotRowQ16(inverse[i], white_xyz);
103 }
104 for (int row = 0; row < 3; ++row) {
105 for (int col = 0; col < 3; ++col) {
106 const i64 product = static_cast<i64>(primaries_xyz[row][col]) * k[col];
107 out->m[row][col] = static_cast<i32>(
108 detail::roundedDivideQ16(product, kSourceQ16One));
109 }
110 }
111 return true;
112}
bool sourcePrimariesEncloseAreaQ16(const i32(&r)[2], const i32(&g)[2], const i32(&b)[2]) FL_NO_EXCEPT
True when the three primaries enclose an actual area of chromaticity.
i32 dotRowQ16(const i32(&row)[3], const i32(&v)[3]) FL_NO_EXCEPT
One s16.16 matrix row against a vector, rounded and saturated.
i64 roundedDivideQ16(i64 numerator, i64 denominator) FL_NO_EXCEPT
The s16.16 building blocks the bind-time builders share.
bool xyzColumnQ16(const i32(&xy)[2], i32 luminance, i64(&column)[3]) FL_NO_EXCEPT
XYZ of chromaticity xy at luminance luminance, all s16.16; false for a non-positive or out-of-simplex...
bool invert3x3Q16(const i32(&in)[3][3], i32(&out)[3][3]) FL_NO_EXCEPT
Inverse of an s16.16 3x3 matrix, in s16.16, computed without floats.
fl::i64 i64
Definition stdint.h:221
Chromaticity white
Chromaticity green
Chromaticity blue
Chromaticity red

References fl::detail::dotRowQ16(), FL_NO_EXCEPT, invert3x3Q16(), fl::detail::roundedDivideQ16(), and fl::detail::xyzColumnQ16().

Referenced by buildStreamingPipelineQ16().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: