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

◆ resolveVideoColor() [1/2]

ColorStatus fl::fled::resolveVideoColor ( const fl::json & envelope,
fl::u8 pixelFormat,
VideoColor * out )

Definition at line 137 of file color.cpp.hpp.

138 {
139 if (!out) return ColorStatus::NullOutput;
140
141 const bool hasTuple = pixelFormatHasDefaultTuple(pixelFormat);
142
143 // Locate video.color without requiring either level to exist.
144 const fl::string kVideo("video");
145 const fl::string kColor("color");
146 bool present = false;
147 fl::json colorNode;
148 if (envelope.is_object() && envelope.contains(kVideo)) {
149 const fl::json videoNode = envelope[kVideo];
150 if (videoNode.is_object() && videoNode.contains(kColor)) {
151 colorNode = videoNode[kColor];
152 // An explicit JSON null means "not set" for most serializers.
153 // Treat it as absent rather than rejecting the file - omitting
154 // the key and nulling it should not have opposite outcomes.
155 present = !colorNode.is_null();
156 }
157 }
158
159 if (!present) {
160 // Absent metadata: the format's default tuple is the historical
161 // interpretation. Formats without one are simply unresolvable.
162 VideoColor resolved;
163 if (!defaultVideoColor(pixelFormat, &resolved)) {
165 }
166 *out = resolved;
167 return ColorStatus::Ok;
168 }
169
170 if (!colorNode.is_object()) {
172 }
173
174 const fl::string kPrimaries("primaries");
175 const fl::string kTransfer("transfer");
176 const fl::string kMatrix("matrix");
177 const fl::string kRange("range");
178
179 const bool hasP = colorNode.contains(kPrimaries);
180 const bool hasT = colorNode.contains(kTransfer);
181 const bool hasM = colorNode.contains(kMatrix);
182 const bool hasR = colorNode.contains(kRange);
183
184 // Key inheritance is scoped to formats that define a default tuple.
185 // Everything else is all-or-nothing, so a future YCbCr format can never
186 // silently inherit `matrix: rgb`.
187 if (!hasTuple && !(hasP && hasT && hasM && hasR)) {
189 }
190
191 VideoColor resolved;
192 if (!defaultVideoColor(pixelFormat, &resolved)) {
193 // No tuple to seed from; every field is explicit here (checked above).
194 resolved.primaries = ColorPrimaries::Bt709;
195 resolved.transfer = ColorTransfer::Srgb;
196 resolved.matrix = ColorMatrix::Rgb;
197 resolved.range = ColorRange::Full;
198 for (fl::size i = 0; i < 8; ++i) resolved.customPrimaries[i] = 0.0f;
199 }
200 resolved.declared = true;
201
202 // ---- primaries ----
203 if (hasP) {
204 const fl::json node = colorNode[kPrimaries];
205 if (node.is_object()) {
206 if (!readCustomPrimaries(node, resolved.customPrimaries)) {
208 }
209 resolved.primaries = ColorPrimaries::Custom;
210 } else if (node.is_string()) {
211 auto s = node.as_string();
212 if (!s) return ColorStatus::UnknownPrimaries;
213 if (nameIs(*s, "bt709")) resolved.primaries = ColorPrimaries::Bt709;
214 else if (nameIs(*s, "display-p3")) resolved.primaries = ColorPrimaries::DisplayP3;
215 else if (nameIs(*s, "bt2020")) resolved.primaries = ColorPrimaries::Bt2020;
217 } else {
219 }
220 }
221
222 // ---- transfer ----
223 if (hasT) {
224 const fl::json node = colorNode[kTransfer];
225 if (!node.is_string()) return ColorStatus::UnknownTransfer;
226 auto s = node.as_string();
227 if (!s) return ColorStatus::UnknownTransfer;
228 switch (parseTransferName(*s)) {
229 case TransferName::Srgb: resolved.transfer = ColorTransfer::Srgb; break;
230 case TransferName::Bt709: resolved.transfer = ColorTransfer::Bt709; break;
231 case TransferName::Linear: resolved.transfer = ColorTransfer::Linear; break;
232 case TransferName::Pq:
233 case TransferName::Hlg:
234 // Reserved names: no v1 payload format can carry them.
236 case TransferName::Unrecognized:
238 }
239 }
240
241 // Transfer must agree with what the pixel format's bytes actually hold.
242 if (isDisplayEncodedRgb(pixelFormat) &&
243 resolved.transfer == ColorTransfer::Linear) {
245 }
246 if (isLinearRgb(pixelFormat) && resolved.transfer != ColorTransfer::Linear) {
248 }
249
250 // ---- matrix ----
251 if (hasM) {
252 const fl::json node = colorNode[kMatrix];
253 if (!node.is_string()) return ColorStatus::UnknownMatrix;
254 auto s = node.as_string();
255 if (!s) return ColorStatus::UnknownMatrix;
256 if (!nameIs(*s, "rgb")) {
257 // "reserved" sends the author to the spec; "unrecognized" tells
258 // them they typoed. Conflating the two wastes their time.
261 }
262 resolved.matrix = ColorMatrix::Rgb;
263 }
264
265 // ---- range ----
266 if (hasR) {
267 const fl::json node = colorNode[kRange];
268 if (!node.is_string()) return ColorStatus::UnknownRange;
269 auto s = node.as_string();
270 if (!s) return ColorStatus::UnknownRange;
271 if (nameIs(*s, "full")) {
272 resolved.range = ColorRange::Full;
273 } else if (nameIs(*s, "limited")) {
275 } else {
277 }
278 }
279
280 *out = resolved;
281 return ColorStatus::Ok;
282}
bool is_object() const FL_NO_EXCEPT
Definition json.h:391
fl::optional< fl::string > as_string() const FL_NO_EXCEPT
Definition json.h:443
bool is_null() const FL_NO_EXCEPT
Definition json.h:381
bool contains(size_t idx) const FL_NO_EXCEPT
Definition json.h:790
bool is_string() const FL_NO_EXCEPT
Definition json.h:388
bool isReservedMatrixName(const fl::string &s) FL_NO_EXCEPT
Definition color.cpp.hpp:38
bool isDisplayEncodedRgb(fl::u8 pf) FL_NO_EXCEPT
Definition color.cpp.hpp:50
bool readCustomPrimaries(const fl::json &node, float *out8) FL_NO_EXCEPT
bool isLinearRgb(fl::u8 pf) FL_NO_EXCEPT
Definition color.cpp.hpp:56
TransferName parseTransferName(const fl::string &s) FL_NO_EXCEPT
Definition color.cpp.hpp:25
bool nameIs(const fl::string &s, const char *lit) FL_NO_EXCEPT
Definition color.cpp.hpp:21
bool defaultVideoColor(fl::u8 pixelFormat, VideoColor *out) FL_NO_EXCEPT
@ TransferConflictsWithFormat
Definition color.h:70
bool pixelFormatHasDefaultTuple(fl::u8 pixelFormat) FL_NO_EXCEPT

References fl::json::as_string(), Bt2020, Bt709, fl::json::contains(), Custom, fl::fled::VideoColor::customPrimaries, fl::fled::VideoColor::declared, defaultVideoColor(), DisplayP3, fl::FL_NO_EXCEPT, Full, IncompleteForFormat, fl::json::is_null(), fl::json::is_object(), fl::json::is_string(), LimitedRangeUnsupported, Linear, MalformedCustomPrimaries, fl::fled::VideoColor::matrix, MatrixUnsupported, NoDefaultTuple, NotAnObject, NullOutput, Ok, pixelFormatHasDefaultTuple(), fl::fled::VideoColor::primaries, fl::fled::VideoColor::range, Rgb, Srgb, fl::fled::VideoColor::transfer, TransferConflictsWithFormat, UnknownMatrix, UnknownPrimaries, UnknownRange, and UnknownTransfer.

Referenced by fl::video::PixelStream::begin(), resolveVideoColor(), and fl::Fled::videoColor().

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