feat(metadata): XM-2 图片元数据——四个落盘点顺手记下宽高与 seed - #226
Merged
Conversation
XM-1 把视频的时长/宽高打通了,图片这半边一直空着:batch_results 的 width/height/seed 三列建了却没人写,画廊只能按默认比例排版。 - core/media/png_dimensions.dart:纯函数读 PNG 文件头(签名 + IHDR), 不引图片解码库。判定刻意严格——签名、chunk 类型、IHDR 长度、非零边长 全对才认。认错了会把垃圾尺寸写进库再一路带到排版;返回 null 只是让前端 退回默认比例。两害相权,宁可不猜。 - 四个落盘点(inline 单/批、remote 单/批)解析后写 node.type_config (主图那一张,与 XM-1 视频侧同键)与 batch_results 三列(逐 slot 各记各的)。 - inline 路径 bytes 在手,零额外 IO;remote 路径回读文件头 33 字节 (完整 IHDR 含 CRC),不把整张图读进内存。 - 拿不到就不写键。写 0 会被下游当成真实尺寸;列停在 NULL 才是「没拿到」。 - 探针任何失败一律吞掉——元数据是锦上添花,不能把一次成功的生成拖成失败。 视频侧不动:宽高仍归 XM-1 的抽帧探针,本卡只补图片。 测试 +22(1923 → 1945):解析器 12 例(合法/JPEG/坏签名/非 IHDR/长度不符/ 零边长/截断/空输入),落盘 10 例(四路径正向 + 非 PNG 时键缺席的反向断言 + 探针失败不影响成功终态)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这张卡解决什么
XM-1 把视频的 duration_ms/width/height 打通了,图片这半边一直空着:
batch_results的width/height/seed三列在 001_init.sql 里建了却从没人写,画廊排版只能按默认比例猜。XM-2 补上图片侧:产物落盘时顺手解析一次尺寸,连同
task.seed一并记下来。做了什么
lib/core/media/png_dimensions.dart— 纯函数读 PNG 文件头(8 字节签名 + IHDR),不引图片解码库。判定刻意严格:签名、chunk 类型必须是 IHDR、IHDR 声明长度必须是 13、宽高必须非零,全对才认,否则一律
null。理由:认错了会把垃圾尺寸写进库,而库里的 width/height 后续要拿去排版和算比例;返回 null 的代价只是前端退回默认比例。两害相权,宁可不猜。四个落盘点(
job_media_persister.dart):node.type_config(与 XM-1 视频侧同键)node.type_config33 = 8 签名 + 4 长度 + 4 类型 + 13 IHDR + 4 CRC,正好一个完整 IHDR chunk,不必把整张图读进内存。
两条不变量
拿不到就不写键。
patchTypeConfig是合并语义,省略键即保持原样;slot 列停在 NULL。写 0 或 -1 会被下游当成真实尺寸拿去算比例,那比没有更糟。测试里每条正向断言都配了一条「非 PNG 时这些键根本不出现」的反向断言。元数据不能把成功的生成拖成失败。 探针的任何 IO 失败一律吞掉并 warn。有一条专门用例:下载器什么都不写(文件不存在)→ 回读必然失败 → 生成仍返回 success,只是没有尺寸键。
边界
视频侧一行没动——width/height 仍归 XM-1 的抽帧探针。有一条用例把这条钉死了:即使下载到的视频文件字节碰巧是合法 PNG 头,视频路径也不去解析。
seed目前只落图片路径(卡面口径是「图片元数据」)。视频的 seed 若要落,是另一张卡的事。测试
+22(1923 → 1945),0 失败:png_dimensions_test.dart(12):合法 PNG / >16 位边长 / 带尾巴 / 1x1;JPEG 头 / 坏签名 / 非 IHDR / 长度不符 / 零边长 / 截断 / 空输入job_media_persister_metadata_test.dart(10):四条落盘路径正向、非 PNG 时键缺席、无 seed 时键缺席、首张解析不出不去借别张的尺寸、视频路径不碰 PNG 解析、探针失败不影响成功终态本地闸:
flutter analyze lib test→ No issues;flutter test --exclude-tags golden→ +1945 / 0 失败 / 66 skip。顺带
BOARD 里 SB-1 那行的「本 PR」补成
#224(合入时漏改),并补上 SB-2#225的落地行。披露
按会话约定,本 PR 未跑双轨对抗式评审(
/code-review由用户触发,我无法自行发起)。未改动任何 golden 覆盖的界面。🤖 Generated with Claude Code