白色背景上,那张像素风显示器精灵图看着毫无问题。换到深色背景,同一张图中间出现了一个黑洞。

打开网易新闻 查看精彩图片

Refmade 是一个桌面应用,读取 Claude Code 和 Codex 的会话日志,把它们画成一个小像素办公室。这是独立项目,与 Anthropic 或 OpenAI 没有关联。Claude Code 和 Codex 的智能体在作者指挥下写了大部分代码——作者写规格,决定什么留下、什么打回。这是系列的第 7 篇,记录 9 月 27 日这一天:办公室精灵图被画了两遍,一遍游戏风格,一遍粉彩风格。

当天作者要求所有办公室资源都用 Codex CLI 内置的图像生成来画。每一批是一个 JSON 规格加一次 codex exec 调用,回来 22 张原始图集。第二个脚本把它们切成 69 个文件:12 个角色各四种姿势(站立、两帧行走、坐姿)、四块地毯、一扇开着的门和一扇关着的门、七件休息区道具、一条带完成看板的墙带,以及桌子、椅子、显示器、地板等零碎部件。原始图集从不直接编辑,脚本负责裁切和缩小,重复运行输出一致。

同一天作者还在重做产品站,连续否掉了五套配色。智能体问到底哪里不对,作者勾了三个框:背景与卡片色、图里的木色和棕色、按钮与强调色。这几乎等于全部,什么也没缩小。最后给出的是一条规则:整体更浅的粉彩、点阵风格字体(Galmuri,SIL 开源字体许可下的像素字体)、主色不用藏青。22 张办公室图集当天下午被重画成粉彩版,文件时间戳落在 16:00 到 16:09 之间,16:30 整站统一为粉彩。透明问题就出在粉彩版上。

作者在写这篇文章时实测了一张图:p-illus-monitor-v1.png,1536 x 1024。

  • alpha 为 255 的像素:0 个。文件里的最大 alpha 是 254。
  • 蓝色屏幕:alpha 约 250,例如 RGBA (146, 186, 227, 241)。
  • 奶油色边框:RGBA (253, 247, 243, 254)。
  • 白色光晕内部:alpha 只有 1 到 4,例如 RGBA (22, 34, 44, 1)。合成到白底上,这些像素显示为 (254, 254, 254)。

最大 254 本身无害。同一批里的游戏风格显示器图集最高也是 254,但它没有接近纯白的像素,所以不会出现洞。粉彩版里,奶油色和粉彩色停在 alpha 252 到 254,而原本是纯白的区域——光晕和背景——回来时 alpha 接近 0。作者的猜测是图像工具把纯白当成背景抠掉了,但这一点没有验证。

修复脚本 unmatte.py 分两步。先在白底上合成,恢复光晕的正确颜色;然后从四条边开始泛洪填充所有 alpha 低于阈值的像素,填充能到达的区域算作"外部",变成透明。像素画本身带的深色描边正好当墙,屏幕内部的光晕因此保留下来。

作者还要求"这个问题不能再回来",智能体把它做成了一个会大声失败的检查:一段简短的 Playwright 脚本,对比渲染比例和文件原始比例,如果图片使用默认的 object-fit: fill 且比例差超过 2%,审计就失败。9 月 27 日最后一次运行打印出 0 张变形图片。

之后是两套主题:粉彩外观和更早的游戏风格点阵,只有主题不同。integrate_p3.py 增加了 --theme game 参数,跳过粉彩图集,把原始美术构建到单独文件夹。到 17:30,办公室页面已经能通过 data-theme 属性在两者间切换。19:20 角色长出了部门服装:21 个角色、24 张话题贴纸、12 个徽章。

作者列了几条下次要检查的事:在接入之前先把生成的精灵图放到深色背景上看一眼,白色页面会藏住这个 bug;用几行 Python 加 PIL 读一下文件的 alpha 通道;原始图集保持不动,让集成脚本可重复运行,两套主题就是这么从同一批图集构建出来的;把"这不能再发生"变成退出码非零的检查。

最后留下的问题:用图像模型生成精灵图或图标时,怎么在它们进入界面之前抓住 alpha 问题?作者还没有建好这个检查。一个想法是在集成脚本里把每张精灵图渲染到深色背景上,只要出现大于几个像素的洞就失败。