Skip to content

feat(metadata): XM-2 图片元数据——四个落盘点顺手记下宽高与 seed - #226

Merged
KerroKapple merged 1 commit into
mainfrom
feat/xm-2-image-metadata
Aug 11, 2026
Merged

feat(metadata): XM-2 图片元数据——四个落盘点顺手记下宽高与 seed#226
KerroKapple merged 1 commit into
mainfrom
feat/xm-2-image-metadata

Conversation

@KerroKapple

Copy link
Copy Markdown
Owner

这张卡解决什么

XM-1 把视频的 duration_ms/width/height 打通了,图片这半边一直空着:batch_resultswidth / 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):

路径 尺寸从哪来 写到哪
inline 单张 bytes 在手,零额外 IO node.type_config(与 XM-1 视频侧同键)
inline 批量 逐张解析 每 slot 各记各的 + 主图那张进 type_config
remote 单张 回读文件头 33 字节 node.type_config
remote 批量 逐张回读 每 slot + 主图

33 = 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

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>
@KerroKapple
KerroKapple merged commit 33757f8 into main Aug 11, 2026
5 checks passed
@KerroKapple
KerroKapple deleted the feat/xm-2-image-metadata branch August 11, 2026 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant