23 plan.json 规范
✅ 已验证 · 产出 code/trace_prepare.py · 消费 code/job_trace.py
读画一步的产物有两个:plan.json(曲线)和 strokes.jsonl(笔画计划——注意和第 22 章的作画日志同名不同物)。坐标全部是 1x,job_trace.py 乘 scale。
plan.json
{
"w": 1024, "h": 1536, "scale": 8,
"expand": 0.6, "smooth": 0.8, "eps": 0.30,
"silhouette": [ {"pts": [[x,y], …], "closed": true}, … ],
"parts": [
{
"id": 1, "name": "Hair_Back", "px": 65416,
"bbox": [x, y, w, h],
"flat": [r, g, b],
"tiers": [
{"role": "Flat", "rgb": [r,g,b], "rings": [ {"pts": […], "closed": true}, … ]},
{"role": "Shadow1", "rgb": [r,g,b], "rings": […]},
…
]
},
…
]
}
| 字段 | 说明 |
|---|---|
w, h | 1x 尺寸 |
scale | 建议倍数(ART_SCALE),job 可覆盖 |
expand / smooth / eps | 矢量化参数,记下来方便复现 |
silhouette | 主体剪影的环,Subject_Silhouette 矢量层 |
parts[].id | 部件编号,cells = id × 100 + tier |
parts[].tiers | 底→顶,第 0 项永远是 Flat |
rings[].pts | Catmull-Rom 的控制点(不是贝塞尔控制点),job_trace 用 contour.to_path_d() 转 |
rings[].closed | 闭合环 vs 开口曲线(贴着画布边的部件) |
一个环变成 SVG:contour._catmull_closed(pts, scale) → M … C … Z。一个 tier 的所有环拼进一条 <path fill-rule="evenodd">,洞自动挖掉。
笔画计划 strokes.jsonl
一行一笔:
{"kind": "soft", "pts": [[36.5, 0.0], [73.1, 0.0], [109.6, 0.0]],
"R": 34.0, "rgb": [0, 0, 0], "op": 0.9, "taper": false, "part": "BG", "tier": 0}
| 字段 | 说明 |
|---|---|
kind | wash(记为 soft)/ soft / hatch / strand / detail / line |
pts | 1x 坐标,已 RDP 简化 |
R | 1x 半径。落笔时 size = 2·R·scale / 系数 |
rgb | 颜色 |
op | opacity,0..1 |
taper | 规划器模拟时的形状标记,job 不用它(第 20 章的回归) |
part | 部件名,或 BG / Line |
tier | 色阶序号,决定落在哪个 Soft / Marks 层 |
顺序就是落笔顺序。job_trace.py 按 (part, tier) 路由到图层,按 kind 查 KIND 表选 preset 和系数,soft 落 Soft 层,其余落 Marks。
预算信息
trace_prepare.py 落盘时打印:
落笔 API 调用 99755 次 (taper 的逐段 paintLine, 其余一次 paintPath)
预计 336 秒 / 撤销栈约 23.2 GB (实测树内 297 次/秒, 每次 233 KB)
调用数 = Σ(收尖的笔的段数) + (不收尖的笔数)。超过 11 万打警告(第 19 章)。
附带的图
同目录下 parts.png / cells.png / preview_cel.png / preview.png,见第 2 章。