深度解析:从二进制头到 JSON 信封与色彩元数据`)
嵌入式物联网硬件开发驱动开发【免费下载链接】FastLEDThe FastLED library for colored LED animation on Arduino. Please direct questions/requests for help to the FastLED Reddit community: http://fastled.io/r Wed like to use github issues just for tracking library bugs / enhancements.项目地址https://gitcode.com/gh_mirrors/fa/FastLED点击查看免费下载.fled是 FastLED 原生的自包含 LED 图案数据容器格式由fl::Fled模块提供读取、校验与构建能力。本指南以 src/fl/fled/README.md 及其镜像的格式规范 FLED_FORMAT.md 为主体结合 src/fl/fled/ 下的解析器、构建器与色彩校验源码完整讲解 FLED v1 的文件布局、像素格式枚举、JSON 信封、video.color源色彩元数据及其校验规则并给出读取、播放与生成的实战用法。读完本文你将能读懂任意.fled文件的字节结构知道如何在 FastLED 中加载、查询与播放它也能依据规范自行编写兼容的 writer 或 validator。一、格式定位为什么需要.fledFastLED 传统上以无头headerless的.rgb流直接喂给 LED 控制器像素数据与这些数据应该摆在哪颗 LED 上screenmap彼此分离。.fledFLED v1的出发点是把播放所需的所有字节放在一起视频数据逐帧的原始像素载荷frame payload屏幕映射screenmap把载荷中每个采样放到物理 LED 上的几何信息未来的扩展段如通道channels配置、脚本scripts等。这一目标在 FLED_FORMAT.md 的引言中有明确表述让一个文件成为视频 screenmap 可选 bundle 段的自包含单元。在代码层面fl::Fled是解析后的.fledv1 容器的值类型句柄PIMPL 实现、拷贝廉价、默认构造为空态且operator bool为假其完整接口见 fled.h。权威性说明.fled格式的权威规范在 ledmapper.fled文件的产方维护仓库内的 FLED_FORMAT.md 与 agents/docs/fled-format.md 是本地镜像。若本地镜像与 ledmapper 规范不一致以 ledmapper 为准。诊断工具header dump、JSON 信封解析、载荷尺寸校验同样随产方提供。二、文件布局12 字节二进制头 JSON 信封 帧载荷FLED v1 的文件是小而紧凑的二进制头 UTF-8 JSON 信封 原始帧字节的三段式结构。规范规定所有整数均为无符号多字节整数一律小端序little-endian二进制头恰好 12 字节。完整布局如下出自 FLED_FORMAT.md 的 File Layout 表偏移大小字段类型说明04magicASCII必须为FLED41versionu8本版本必须为151pixel_formatu8帧载荷的像素格式枚举62reservedu8[2]必须为零84json_lengthu32leUTF-8 JSON 信封的字节数12json_lengthjson_bytesUTF-8JSON 信封无 NUL 结束符、无 BOM12 json_length剩余字节frame_payloadbytes按pixel_format拼接的帧数据帧载荷从12 json_length开始。对于视频内容帧数由文件剩余大小推导frame_count payload_bytes / (led_count * bytes_per_led)其中led_count来自内嵌的 screenmapbytes_per_led来自下述像素格式表。writer 应保证payload_bytes恰好是led_count * bytes_per_led的整数倍reader 应将余数视为畸形或截断输入。源码中的头解析解析入口在 detail/parser.h 的parseHeaderAndEnvelope()它负责校验 12 字节头 JSON 信封失败条件包括长度小于 12、magic 非FLED、version 非 1、jsonLen超过上限kMaxJsonBytes、jsonLen大于len - 12截断、JSON 解析失败。三个加载工厂见 fled.cpp.hpp都委托这一函数Fled::load(FileSystem fs, const char *path)从文件系统打开、读入并解析任何失败打开失败、截断、坏 magic/version、JSON 解析错误都返回 null FledFled::loadFromStatic(fl::spanconst fl::u8)零拷贝加载span 必须比 Fled 及其所有副本活得更久该构造不复制字节Fled::loadFromVector(fl::vectorfl::u8 )移动加载调用方持有的 vector 存储无额外拷贝。加载成功后可通过version()v1 返回 1、pixelFormat()偏移 5 处的字节0x00为 rgb8、bytesPerLed()、payloadBytes()、frameCount(ledCount)等访问器查询头部信息frameCount的实现正是规范公式payloadLen() / (ledCount * bytesPerLed)当led_count为 0、每 LED 字节数为 0 或 bundle 为空时返回 0。三、像素格式枚举Pixel Format EnumFLED v1 定义了0x000x05六种像素格式0x060xff保留给未来格式。规范明确只支持部分像素格式的消费端应在读取任何帧字节之前拒绝不支持的pixel_format值bytesPerLed()对未知/保留格式返回 0即触发拒绝路径。值名称每 LED 字节数载荷字节序说明0x00rgb83R, G, BFastLED 传统 CRGB 播放与类型化输入支持0x01gray81Y8 位亮度消费端按需扩展为 RGB0x02rgba84R, G, B, A8 位 RGB 加 alphaalpha 语义由消费端定义0x03rgbw84R, G, B, W8 位 RGB 加白通道0x04rgb565le2小端 RGB565红 5 位、绿 6 位、蓝 5 位0x05rgb16_linear6R, G, B各u16le线性光 16 位 RGB要求transfer: linear0x06–0xff保留可变TBD由 ledmapper 保留给未来的像素编码源码中这一枚举定义在 pixel_format.henum class PixelFormat : fl::u8 { Rgb8 0x00, // 3 bpp - R, G, B Gray8 0x01, // 1 bpp - Y Rgba8 0x02, // 4 bpp - R, G, B, A Rgbw8 0x03, // 4 bpp - R, G, B, W Rgb565Le 0x04, // 2 bpp - little-endian RGB565 Rgb16Linear 0x05, // 6 bpp - R, G, B as u16le, linear light };该文件还定义了ComponentByteOrder区分LittleEndian与Native——Rgb16 本身绝不授权把 FLED 的 u16le 载荷当作本机字直接重解释以及PixelStorage结构。转换函数toPixelStorage()目前只映射直接 RGB 存储toFledPixelFormat()则要求像素格式与源色彩声明配对使用见第四节。值得注意的实现细节VideoFrameView::component16()fled.h在读取rgb16_linear帧时按led * 6 component * 2计算偏移并从两个小端字节手工拼出u16从不把载荷当作本机字节序的字读取——这是小端序约定的代码级落实。四、JSON 信封screenmap 与视频元数据JSON 信封是 UTF-8 文本长度由json_length精确计数。它被刻意设计为可扩展reader 应消费自己理解的段并按自身角色保留或忽略未知段。原始帧载荷紧跟在 JSON 信封之后不经过 base64、也不嵌入 JSON 文本。必需的 screenmap 内容信封携带解释载荷所需的 LED 几何map下的标准ScreenMapschemascreenmap 中的 LED 顺序就是帧载荷使用的顺序led_count是 screenmap 各 segment 描述的总 LED 数。在 fled.cpp.hpp 中screenMap()访问器把整个信封文本交给ScreenMap::ParseJson信封的顶层map对象与解析器期望的形状一致单条 strip 路径返回第一个 segment。视频元数据video.fps可选声明播放帧率缺失时消费端可用应用默认值、sketch 参数或外部播放设置。Fled::videoFps(defaultFps)的默认参数正是 30.0f且仅在video是对象且fps能转为浮点数时生效video.color可选声明载荷的源色彩编码详见第五节。信封示例取自规范{ map: { strip0: { x: [0, 1, 2], y: [0, 0, 0], diameter: 0.25 } }, video: { fps: 30, color: { primaries: bt709, transfer: srgb, matrix: rgb, range: full } } }代码层面Fled::json()返回解析后的信封null Fled 返回静态空 json可安全链式调用sectionCount()返回顶层键数量blob(frame_payload, len)则返回指向帧载荷原始字节的别名共享指针frame_payload与payload均为合法名称。五、源色彩元数据video.color编码语义的精确契约video.color描述载荷数值如何编码颜色——它只描述已编码的载荷本身与 LED 布局、输出芯片组、以及将显示它的灯带物理发射器特性无关。规范特别强调四个字段相互独立绝不允许多合并成一个含糊的单一标签如BT.709。字段v1 取值含义primariesbt709、display-p3、bt2020或自定义对象色度 白点。bt709指 BT.709/sRGB 基色 D65 白transfersrgb、bt709、linear传递函数。srgb是分段 sRGB 函数——不是BT.709 摄像机 OETF不得用未命名的幂律近似matrixrgb载荷携带直接 RGB 分量即恒等/无矩阵情形YCbCr 系数值保留rangefull所有码值都是图像值8 位下0为黑、255为满通道limited保留自定义primaries对象携带 CIE xy 对primaries: { red: [0.640, 0.330], green: [0.300, 0.600], blue: [0.150, 0.060], white: [0.3127, 0.3290] }none不是合法的transfer值——它语义含糊。真正携带线性光样本的产方应声明transfer: linear并使用允许线性数据的像素格式rgb16_linear。默认元组与按格式的色彩类别规范定义的权威默认元组为{ primaries: bt709, transfer: srgb, matrix: rgb, range: full }当video.color缺失时定义了默认元组的像素格式按该元组解释对显示编码 RGB 格式这保留了.fledRGB8 数据的历史解释。缺失的单个键从同一元组继承——但仅限定义了默认元组的像素格式。不得把该默认描述为就是 BT.709否则传递函数悬而未决。pixel_format色彩类别默认元组约束rgb8,rgba8,rgb565le显示编码 RGB{bt709, srgb, rgb, full}transfer必须为srgb或bt709rgb16_linear线性光 RGB{bt709, linear, rgb, full}transfer必须为lineargray8,rgbw8无定义元组无video.color必须声明全部四个键缺失或部分即不可解析gray8不携带色度rgbw8的白通道是 RGB 基色无法描述的器件基色因此两者都不继承默认元组其色彩元数据是全有或全无的。两种失败被明确区分见 color.h 的ColorStatus枚举缺失声明解析为NoDefaultTuple部分声明解析为IncompleteForFormat。两者都不算畸形文件——由调用方决定是否在意而非把文件当作损坏。源码中resolveVideoColor()含PixelFormat类型化重载负责把信封中的video.color与头部像素格式对照解析对定义了默认元组的格式为缺失键套用默认元组并执行规范的全部校验规则返回ColorStatus::Ok时VideoColor被填充含区分文件声明与默认元组套用的declared布尔位以及自定义基色时的customPrimaries[8]数组布局为{red.x, red.y, green.x, green.y, blue.x, blue.y, white.x, white.y}。colorStatusMessage()为每种状态提供稳定的人类可读诊断文本。Fled::videoColor()在 null Fled 上按空信封 rgb8解析使调用方仍能得到历史默认元组。有无色彩管理colour management下的播放B6无色彩管理默认路径.fled文件的播放行为与以往完全一致——RGB8 值到达灯带就是字节本身应用颜色顺序、亮度缩放与传统校正不做其他处理。video.color被携带与校验但不改变任何输出。既有文件在既有 sketch 上看起来不变tests/fl/channels/channel.cpp 在 clockless 与 SPI 芯片上把未绑定的输出逐字节钉死。有色彩管理通过setColorProfile配置的通道每个像素经由通道的源 profile解释——解码为线性光、映射进灯带色域、按发射器逐个求解。同一文件因此看起来不同且理应如此。为什么LED 的光大致正比于驱动而显示编码的.fled存的是 sRGB 编码值。传统播放把 sRGB 值 128 当作约一半驱动发送实际只有约 22% 全亮度——中间调过亮且欠饱和。色彩管理播放解码传递函数按数值所请求的光渲染。怎么设色彩管理通道通过其源 profile 解码即FastLED.defaultSourceProfile()未改时是线性 sRGB或传入setColorProfile的 profile。文件的声明经由Video::sourceProfile()或fled::toSourceProfile()针对已解析的VideoColor成为该 profile它覆盖命名基色、自定义 xy 基色以及 sRGB、BT.709、linear 三种传递函数。缺失声明得到像素格式的默认元组因此传统 rgb8 文件映射到 sRGBfl::SourceProfile source; if (video.sourceProfile(source)) { FastLED.setDefaultSourceProfile(source); // 或经 setColorProfile 按通道设置 }绑定是显式而非自动的这是有意设计Video把画面画进像素缓冲而非特定通道一个 sketch 可能播放多个文件或把视频与生成内容混排B8此时静默地把每个通道的解码切到最后打开的文件是错误的。在 sketch 显式绑定之前一切不变传统播放保持逐字节一致。toSourceProfile()color.h仅对 null 输出指针返回 false——每个可解析的VideoColor都有对应的SourceProfile。声明判定 vs 消费端策略拒绝一个声明不等于拒绝一个文件显示编码 RGB 格式上声明是**建议性advisory**的。无法解析如来自未来 minor 版本的未知名的消费端可以回退到默认元组并给出诊断——更新的 reader 在同一文件上永远不会严格劣于更老的 reader色彩语义**强制mandatory**的格式rgb16_linear上无法解析的声明意味着载荷无法被解释消费端必须拒绝而非猜测。产方与校验工具总是采用严格解读。resolveVideoColor()报告每一条违规。FastLED 播放默认严格应用可仅为建议性的rgb8色彩元数据显式选择 best-effort该路径会发出警告。畸形或截断的容器、以及所有强制的rgb16_linear色彩失败始终是硬错误。校验规则Validation Rules合规产方不得写出、合规校验器必须拒绝四个字段中任一出现无法识别的值——拒绝并给出指明字段与值的清晰诊断绝不静默回退显示编码 RGB 格式上出现transfer为linear、pq或hlg——rgb8是显示编码数据绝不能携带线性光样本rgb16_linear的任何transfer非linear任何 v1 格式上出现range: limited——保留给明确标注的未来/导入载荷任何matrix非rgb——YCbCr 载荷需要一个尚不存在的像素格式届时必须显式声明其系数无默认元组的格式gray8、rgbw8上出现部分video.color——必须完整或缺失video.color存在但不是 JSON 对象或自定义primaries对象缺少red/green/blue/white任一键或 xy 对畸形。显式 JSONnull的video.color按缺失处理而非畸形对象许多序列化器对未设置的 optional 会输出null省略键与置 null 不应产生不同结果。pq与hlg是保留的传递函数名v1 中一律拒绝16 位线性整数载荷无法忠实承载 PQ 解码内容因此 HDR 传递函数要等待能承载它们的载荷格式与工作域。前向兼容为什么加video.color不需要升版本video.color对显示编码 RGB 格式是建议性的。早于本节出现的 reader 会忽略该键并恰好落在默认元组上——旧 reader 退化为降低保真度而绝不退化为错误数据。这就是为什么添加video.color不是版本 bump。而色彩语义强制的载荷改由新的pixel_format值来门槛化。强制性是载荷格式的属性不是版本标志。但该门槛只对真正校验格式字段的 reader 成立。规范明确指出 FastLED 自己的旧 reader 是反例FastLED #4156 R1PixelStream::begin()只识别带rgb8的 FLED v1对任何其他格式或版本旧版曾回卷到字节零并当作无头.rgb流成功播放。于是一个可寻址的rgb16_linear文件只要有足够字节就会被当原始数据播放其第一次readPixel()返回 ASCII magicFLE——RGB(70, 76, 69)一种近中性暗灰——而非拒绝文件。头部字节到达 LED 正是规范断言不可能发生的失败。修复后的 reader 区分无 magic与识别出但不支持的 FLED无 magic 仍回退到原始 RGB一旦匹配到FLED任何无效性——不支持的格式、未来版本、保留字节被置位、头截断、信封畸形——都关闭流并失败。不可寻址输入本身不算无效首字节不是FLED的流仍按原始 RGB 播放probeStreamingMagic()会缓冲部分前缀直到字节足够判定。它不能做的是承认已识别的 FLED 容器因为头无法重读这种情况会被拒绝而不是当像素重放。所以该门槛从现在起成立但对截至 3.10.5含的所有 FastLED 发行版不成立——修复比该 tag 更新。新增格式枚举无法修复已经在现场运行的二进制。对产方而言这是部署约束而非格式问题向可能仍在运行旧版 FastLED 的受众发布rgb16_linear意味着旧播放器显示灰色噪点而非拒绝文件。要对播放器做门槛检查而非对容器。最后澄清一个易混点强制针对的是不可解析的声明而非缺失的声明。rgb16_linear与显示编码格式一样携带默认元组因此缺失的video.color仍可解析——格式值已钉死线性光样本BT.709 基色 full range 是历史解读的其余部分。此时declared为 false消费端仍能区分继承的元组与作者的声明。rgb16_linear不允许的是回退rgb8上未知名可以带诊断回退到默认元组同样的名字在rgb16_linear上就是拒绝对应 FastLED #4156 R10 对早期措辞的修正。六、帧载荷Frame Payload帧载荷是扁平字节流frame 0 LED 0, frame 0 LED 1, ... frame 0 LED N-1, frame 1 LED 0, frame 1 LED 1, ... frame 1 LED N-1, ...每个 LED 记录使用头部声明的pixel_format。对rgb8跳过 FLED 头与 JSON 信封后载荷与传统的无头.rgb布局完全相同。Fled::videoFrame(frameIndex, ledCount, view)提供类型化的零拷贝帧视图VideoFrameViewfled.h它保留存储精度、分量布局与解析后的 FLED 源色彩元组。仅在存储不支持、色彩元数据无效、帧不完整或帧索引越界时返回 false。调用链见 fled.cpp.hpp依次执行toPixelStorage检查格式可映射、videoColor必须为ColorStatus::Ok、bytesPerLed非零且ledCount不超过payloadBytes / bytesPerLed、payloadBytes必须被stride整除且frameIndex在范围内最后通过blob(frame_payload, ...)取别名指针定位到该帧的字节范围。rgb16_linear的 16 位分量总是从小端字节解码绝不以本机字节序重解释CRGB 绘制路径在受管变换阶段落地前对 RGB16 表现为暗fails dark。七、生成.fledFledBuilder读写对称是格式契约的一部分。fl::fled::FledBuilderbuilder.h是命令式构建器从头部字节 可选 JSON 段 可选帧载荷组装 v1.fled字节缓冲然后经规范路径Fled::loadFromVector()重新解析返回的 Fled 与从磁盘加载的逐字节等价。要点头部必填version默认 1v1 唯一发行版本pixelFormat默认 0rgb8setScreenMapJson()/setChannelsJson()各自合并到信封的规范顶层键map、channels下需传 JSON 对象字符串非原始值builder 会拷贝字节setVideoColor()以 FLED_FORMAT.md 规定的拼写发出video.color。元组总是完整写出全部四个键、绝不写部分对象——因为缺键继承仅适用于定义了默认元组的像素格式产方不该为此推理declared位被忽略调用即声明setPayload()追加在信封之后的原始帧字节build()序列化信封、前置 12 字节头、追加载荷再经loadFromVector解析。辅助的sectionNameIsPayload()detail/parser.h集中管理blob()认识的段名别名保证 builder 与公共访问器对规范名称frame_payload/payload意见一致。八、测试与验证仓库为.fled提供了成组的测试以锁定读写两侧的行为tests/fl/fled/fled.cppFled加载、头部访问器、帧视图等核心行为tests/fl/fled/fled_builder.cppFledBuilder组装与往返等价性tests/fl/fled/fled_color.cppvideo.color解析、默认元组套用与各类校验规则的拒绝路径tests/fl/fled/fled_filesystem.cppload()文件系统路径tests/fl/fled/fled_format.cpp字节级格式头、信封、载荷边界tests/fl/channels/channel.cpp未绑定色彩管理时输出逐字节钉死legacy 播放保真tests/test_fled_format_docs.py文档与实现一致性的守护测试。九、增长方向Growth NotesFLED v1 保留了像素格式枚举的大半空间并保持元数据信封开放使一个文件能从视频 screenmap成长为完整的图案 bundle像素格式增长压缩或替代编码如 BC1/BC3 压缩帧、索引调色板、更高位深色彩或其他产方定义格式。新值必须先在权威 ledmapper 规范中分配JSON 信封增长channelsfl::MultiChannelConfigJSON让文件能描述输出通道接线与播放路由Fled::channels()的 typed 访问器已预留待fl/channels/的 JSON 反序列化器落地script.micropython随图案携带行为的 MicroPython 字节码或源码元数据script.wasm随图案携带可移植行为的 WASM 模块元数据或载荷引用。路线图方向是单个.fled文件同时携带视频、screenmap、通道与行为成为 FastLED 自包含的部署单元。channels段是 v1 的下一个新增受fl::Fled统辖MicroPython 与 WASM 脚本段在 ledmapper 与 FastLED 同时落地之前保持为路线图项目。十、快速上手读取与播放要点加载fl::Fled fled Fled::load(fs, pattern.fled);用if (!fled)判空任何解析失败都得到 null Fled内存中已有字节时优先loadFromStatic注意生命周期约定或loadFromVector移动语义、零拷贝。查头部version()、pixelFormat()、bytesPerLed()、payloadBytes()、frameCount(ledCount)。取信封json()/sectionCount()videoFps()读取帧率默认 30。取载荷blob(frame_payload, len)得到原始帧字节videoFrame(i, ledCount, view)得到类型化帧视图对rgb16_linear用component16()逐分量读取小端 16 位样本。色彩语义videoColor(vc)解析video.color并执行全部校验需要精确渲染时经toSourceProfile()绑定到FastLED.setDefaultSourceProfile()或通道的setColorProfile。记住绑定是显式的——不绑定时传统播放逐字节不变。生成用FledBuilder组装头、信封段与载荷build()后得到的 Fled 与磁盘加载等价。规范的完整权威文本请直接阅读 src/fl/fled/FLED_FORMAT.md接口级契约见 src/fl/fled/fled.h 与 src/fl/fled/color.h。赞分享嵌入式物联网硬件开发驱动开发【免费下载链接】FastLEDThe FastLED library for colored LED animation on Arduino. Please direct questions/requests for help to the FastLED Reddit community: http://fastled.io/r Wed like to use github issues just for tracking library bugs / enhancements.项目地址https://gitcode.com/gh_mirrors/fa/FastLED点击查看免费下载相关推荐FastLED .fled 容器格式深度解析自描述 LED 视频打包、源色彩元数据与播放管线FastLED .fled 容器格式深度解析自描述 LED 视频打包、源色彩元数据与播放管线 .fled 是 FastLED 面向可独立分发 LED 图案数嵌入式物联网硬件开发驱动开发HVE Core Tech Lead 指南架构审查与提示词工程的 5 个领导者视角HVE Core Tech Lead 指南架构审查与提示词工程的 5 个领导者视角 HVE Core 是微软推出的 GitHub Copilot 提示词工程组嵌入式物联网硬件开发驱动开发Spine Runtimes数据格式解析JSON与二进制文件的深度对比Spine Runtimes数据格式解析JSON与二进制文件的深度对比 Spine Runtimes是业界领先的2D骨骼动画运行时库为游戏开发者和动画师提供游戏开发图形学上一篇React-admin CRUD 页面开发全指南List / Show / Edit / Create 页面组件、路由与无头变体深度解析下一篇xi-editor 注解Annotations机制解析RFC 设计、协议实现与插件开发实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。