
这是什么
这是给那些已经熟悉 Photoshop、但不想按月租用它的人做的图像编辑器。菜单、快捷键、面板的排布都按 Adobe 的方式来,文档可以打开、分层、加蒙版、修图、排版、挂上实时调整图层,再原样写回分层 PSD。底下没有 webview、没有 Electron、也没有 C++:一套纯数据的文档模型,一个所有界面都按 id 调用的命令注册表,一个充当参照的 CPU 合成器和一个对着它测的 GPU 合成器,以及一个自己解析 ICC 配置文件的色彩引擎。它作为签过名的桌面应用发布在 macOS、Windows、Linux 和 FreeBSD 上,同样的 Rust 也编译成 WebAssembly 跑在浏览器里。项目自称早期 alpha,并且给自己的完成度标了数字。
谁做的一个 2021 年创建的组织账号,56 个公开仓库、25,251 个关注者。它用同一套文风规范发布七个桌面应用:PhotoCraft、VectorCraft、FilmCraft、LightCraft、PdfCraft、EffectCraft、DesignCraft,外加托管式的图像视频工作室 ArtCraft。PhotoCraft 仓库在 1,256 次提交里点名了 184 个账号;最多的是 @echelon,240 次提交、281,036 行新增,另外 228 条提交尾注把这个账号写成共同作者。contributors/people.toml 存着十几位贡献者自己选择的署名,文件里要求每个人只添加自己那一条。
它是怎么搭起来的
组成 · 6组织方式是:引擎是产品,界面只是它的一个客户端。文档是纯数据——图层是一个枚举,成员包括像素、调整、填充、文字、形状和智能对象,像素放在 Arc 指向的 256 像素瓦片里,于是给文档拍一张快照的代价是每层一个指针,撤销、自动保存和后台任务都能不加锁地读它。所有对用户可见的东西都只存在于一个命令注册表里:菜单项、快捷键、命令面板、录制下来的动作、命令行工具、只监听回环地址的 JSON 控制通道,以及一个 MCP 服务器,解析到的是同一个命令 id 和同一份带类型的参数——这也是 agent 能在没有屏幕的情况下驱动它的原因。位深和色彩模式在每一个表面上都是运行时数据,所以 8 位 RGB 文档和 32 位浮点 CMYK 文档走的是同一套代码。两个合成器并行维护:CPU 那个是参照,wgpu 那个对着它测。外壳刻意做薄,是 eframe 上的 egui,没有 webview,整个项目里没有一行 JavaScript;同一批 crate 还编译成 WebAssembly,这一点由构建强制而不是靠自觉。
- crates/geom、color、cms、raster
- 地基:几何、像素格式以及作用在其上的混合数学、一个自己解析配置文件并构建变换与 LUT 的 ICC 色彩引擎,以及所有 crate 都经由它分配内存的写时复制瓦片存储。
- crates/psd 与 crates/codecs
- 不依赖工作区里任何东西的格式 crate,因此每个都能单独发布和单独阅读。PSD 那个就是整个 Photoshop 文件:文件头、图层记录与蒙版、色彩模式数据、描述符与标记块读取器,以及笔刷(
.abr)、色板(.aco)、渐变(.grd)、图案和 TIFF 的解析器。 - crates/doc
- 只装数据、不装别的文档模型:图层、组、剪贴、像素与矢量蒙版、调整图层、图层样式、带智能滤镜的智能对象、alpha 与专色通道、参考线和切片。不做渲染,不带工具箱,不碰 I/O。
- crates/ops、paint、algo、text、vector
- 历史记录与日志、带动态参数且笔画可确定性重放的笔刷引擎、图像算法、文字引擎,以及路径与形状及其布尔运算。
- crates/compose、gpu、format
- 充当参照的 CPU 合成器、在 Metal/Vulkan/DX12/WebGPU 上绘制画布并对着 CPU 版测试的 wgpu 合成器,以及原生格式
.pcraft——文档结构新增字段却没有映射时会编译失败,因此保存不可能悄悄丢掉一个字段。 - crates/engine 与 crates/ui-egui
- 会话与命令注册表:约 700 条命令,每条都声明了 id、名称、菜单路径、默认快捷键、参数说明、启用条件和执行闭包;以及只持有视图状态、其余一律转发的 egui 外壳。
crates/automation提供 MCP 服务器,apps/photocraft、apps/photocraft-cli和apps/photocraft-web是同一个引擎的三扇门。
取舍,以及另一种做法
让每一个用户可见的操作都是注册表里的一条命令 替代 先在界面里实现功能,之后再考虑暴露
这是
AGENTS.md的第 1 条规则,理由也一并写着:UI、CLI、控制通道和 MCP 都按 id 分发,所以写成命令的功能在上线当天就能被 agent 和脚本驱动;而直接用 Photoshop 菜单目录里的 id,菜单项不需要写任何界面代码就会亮起来。让位深和色彩模式在每一个表面上都是运行时数据 替代 以 8 位 RGB 为核心,高位数路径事后补
架构文档开篇就是一节「Avoiding GIMP's hole」,逐条算给 GIMP 看:把 8 位瓦片写死在核心里,代价是另起一套引擎 GEGL,2000 年前后开始,到 2018 年的 2.10 才真正完成。PhotoCraft 因此把
PixelFormat { depth, model, alpha }放在每个表面上,禁止公开引擎 API 里出现u8,并从第一天起就在 8、16、32 位上跑同一套黄金测试。把 CPU 合成器留作 GPU 合成器的参照 替代 只做 GPU 路径并相信它
两个合成器互相对测,由 CPU 那个裁定 GPU 那个对不对。项目对外声称两者一致到 1/255,而必须一直维持这句话的是
crates/gpu/tests/parity.rs。照 Adobe 公布的规范写 PSD crate 替代 读另一份该格式的实现
贡献指南写明了来源,也写明了随之而来的规则:可以研究行为,不可以复制代码,实现来自公开规范。也正因为如此,没被建模的块在往返保存时会被原样带过去,而不是丢掉。
在非测试代码里禁止 panic 与
unsafe替代 把崩溃当成报一个修一个的 bug工作区在干净的 crate 里禁止整个 panic 家族(
unwrap、expect、panic!、unimplemented!及其同类),除隔离出来的手写笔输入 crate 外一律禁止unsafe,另有一个集成测试拿对抗性参数去轰每一条命令。给的理由是:用户把无法重做的工作交给了这个程序。把引擎和外壳一起编译成 WebAssembly 替代 只做原生应用
外壳以下的 crate 不许用工具箱,碰文件系统的代码放在
cfg(not(target_arch = "wasm32"))后面,构建会拿 wasm 目标检查整个下层。浏览器版就是同一个应用,体积约束直接写进 Cargo profile:fat LTO、按体积优化,同时把做像素的 crate 钉回opt-level 3,这一步把 wasm 从 26.3 MB 降到 18.8 MB。
依据storytold/photocraft 的 AGENTS.md、ROADMAP.md、docs/architecture.md、docs/target-app-parity.md、docs/gaps.md、docs/scorecard.md、docs/parity-checklist.md、docs/contributing.md、docs/development.md、docs/releasing.md、README.md、ATTRIBUTION.md、Cargo.toml、contributors/contributors.json、.github/workflows/ci.yml 与 release.yml、scorecard/、perf/budgets.toml,以及 crates/ 下的代码,2026-10-11 读取。
制作过程
5 个阶段- 01
这 18.5 MB 里是什么
我在 2026-10-11 克隆下来的这棵树里有 1,053 个
.rs文件、18,512,884 字节 Rust 代码,共 408,084 行。GitHub 自己的语言统计和这个数字只差零头(Rust 18,510,175 字节),排在第二的 WGSL 着色器只有 53 KB。体量集中在两处:crates/ui-egui有 129,589 行 egui 界面,crates/engine另有 87,855 行命令。再往下,algo(42,272)、io(26,545)、codecs(16,154)、psd(13,813)、compose(11,146)和raw(9,818)才是图像处理所在,那里的文件名是算法而不是管道:nonlocal.rs、inpaint.rs、matting.rs、puppet.rs、liquify.rs、seam.rs、poisson.rs、panorama.rs、camera_raw.rs。整棵树大约三分之一是测试:行内#[cfg(test)]模块里 83,731 行,tests/目录里另有 61,398 行,511 个文件里合计 5,733 个#[test],其中 511 个文件自带行内测试模块。没有留空的地方:unimplemented!()在整个仓库里出现零次,而 clippy 被配置为连同其他标记「尚未完成」的宏一起禁止它们。单文件最大的是 5,921 行的crates/ui-egui/src/canvas.rs,而它不是一张表。这 18.5 MB 不包含crates/ui-egui/src/i18n/下十六份界面翻译(约 1.9 MB 的.tsv),也不含assets/下 4.5 MB 的图标、字体和一份 SCOWL 词表。仓库自己也数过:2026-10-10 重写的docs/architecture.md写着约 393,000 行 Rust、约 1,020 个文件、约 5,460 个测试函数,是同一棵树早几个小时的测量。同一天的 README 上写的是「more than 1,700 tests」。 - 02
开头 34 次提交加了 175,558 行
仓库创建于 2026-09-30,它的第二次提交叫
one-shot,动了 241 个文件,加了 42,038 行。接下来三次一样:continued wip(181 个文件,+37,493 行)、more algorithms, progress(213 个文件,+43,275 行)、Analysis, notes, proof views, workspaces (+ in-progress work of other agents)(162 个文件,+34,026 行)。这四次提交合起来约 157,000 行,2026-10-03 之前的 34 次提交合计 175,558 行。从那之后历史才开始像一份仓库:小提交、一行标题、一段正文、一个 PR 号。 这套做法写在树里。AGENTS.md开头就说明它是给 AI agent 看的指南,第六节标题是「Parallel agents」:让每个 agent 设CARGO_TARGET_DIR=target/agent-<name>,免得抢 Cargo 的构建锁;改动要小,因为共享文件就是争用点;新命令写进新模块而不是把共享文件撑大;并提醒每个构建目录大约占 10 GB。它指向log/devlog.md,说这是下一个 agent 接手的方式,理由是会话会因为崩溃和上下文上限突然结束;而log/在 gitignore 里,所以那份记录不在克隆里。这个应用家族共用的规范放在一个叫craftrules的同级 checkout 里,文档三次重复说明它不公开。 剩下的答案在提交尾注里。main上 1,256 次提交中,898 次带Co-authored-by:其中 782 次点名某个 Claude 模型,31 次点名 Copilot,228 次点名维护者本人。换个说法:大约每三次提交里有两次把功劳记在模型头上。项目自己的计量单位也跟着来。ROADMAP.md把到 beta 的工作量估成 1,100 到 1,800 个 Opus 5.5 agent 小时,标定方法一栏写着这些小时数来自本仓库已合并的 PR。 - 03
clean room 这个说法能核到哪一步
说法写在仓库简介里:Photoshop 的 clean-room 重写。仓库对它的处理是一条规则。
AGENTS.md第 3 条说,研究 Photoshop 和其他专有编辑器时只看行为与观感,绝不复制它们的代码、着色器、配置文件或素材,实现来自公开规范,并点名 Adobe 的 PSD 规范、ICC 规范和混合模式用的 ISO 32000。 其中一部分可以从树里核。PSD 支持是独立 crate,不依赖工作区里任何东西,它的测试跑在按 sha256 钉在xtask/src/corpus_pins.rs里的语料上:项目自己用 Photoshop 生成的对照文件,加上 psd-tools、ag-psd 和 PngSuite。色彩引擎自己解析和写出 ICC 配置文件,而它唯一随附的 CMYK 配置文件是合成的,由crates/cms/src/synth.rs生成、以 CC0 发布。ATTRIBUTION.md为每一个非代码素材留一行,写清路径、标题、作者、来源和许可,而那些行都很无聊:ISC 和 MIT 的 Lucide 与 Feather 图标、OFL 的 Inter 与 JetBrains Mono、一份 SCOWL 词表。要抄,抄出来的痕迹就在这些文件里。 到对标目标这一步,就无法只靠仓库审计了。docs/target-app-parity.md说 Photoshop 2026 是在不启动的情况下检查的:Info.plist里的文档类型、各格式插件 PiPL 资源里的读写标志、.lproj语言包、Default Keyboard Shortcuts.kys,以及主二进制里的字符串。crates/ui-egui/src/menu_catalog.rs里那棵 628 项的菜单树也是照着 Photoshop 的菜单写的。读一份买来的软件包不等于读源码,但读者没法从这里核实这条界线。 这个问题挂在 issue 上,而项目没有回答。#341 由 @soapdog 于 2026-10-06 提出,问的是:由训练语料无从审计的模型生成的代码,还能不能叫 clean room。它下面 13 条评论全部来自外部账号,争论在「模型的训练集无法审计」和「人的记忆同样无法审计」之间来回,也在「拿这份代码去比对泄露的 Adobe 源码」和「无法证明一个否定命题」之间来回。仓库不在这个讨论里。另一条更安静,同样没人回:#2332(2026-10-10)指出部分主题用的 Adwaita 调色板来自 LGPL 的桌面样式表,与项目自己那条「随附素材必须使用宽松许可」的规则冲突。 - 04
628 个菜单项,以及这个数字量的是什么
仓库自己生成成绩单,而它比 README 苛刻。
cargo xtask parity把 Photoshop 的菜单树和活着的命令注册表对一遍,写出docs/parity-checklist.md,另有一个测试把结果压在 627 的下限之上,防止回退。当前文件写着 628 项菜单全部有活的命令,并逐菜单列出:File 52、Edit 75、Image 61、Layer 161、Type 44、Select 25、Filter 75、View 74、Window 61。README 随后用自己的话说明这个数字值多少:Photoshop 的每个菜单项都接上了一条命令,而这量的是接线,不是行为。 成绩单里可测的那一半在docs/scorecard.md,编号的缺口清单在docs/gaps.md,两者互相吻合。工具箱 68 件里做了 53 件,缺的 15 件有名有姓:画板、单行与单列选框、透视裁剪、框架、颜色取样器、颜色替换、历史记录艺术画笔、自由钢笔与弯度钢笔、三个锚点工具,以及两个文字蒙版工具。面板 35 个里做了 30 个。文件格式在 Photoshop 自己支持的方向上是 31 个里的 13 个,另有 4 个部分支持。149 项首选项里有 46 项什么都不做。 PSD 是树里三个数字互相打架的地方。成绩单的对照测试把 PhotoCraft 的渲染和 Photoshop 自己的合并图像比较:Photoshop 生成的对照文件 256 个里对上 133 个(52%),项目自己的 io 语料 170 个里 146 个(86%),psd-tools 集合 309 个里 236 个(76%)。README 主推的却是往返渲染:psd-tools 的 309 个文件里 307 个一致——那是另一个更容易的问题。官网写的是「134 of 135 real-world test files round-trip byte for byte」,又是第三种测法。三个数字同一天都挂在项目自己的材料上。 性能对着perf/budgets.toml里的预算测,25 项里达标 3 项。带图层样式的图层移动要 321 ms,预算是 25 ms;改不透明度 276 ms,预算 20 ms;粘贴一张 1200 万像素的图 1.2 s,预算 100 ms。人工智能是唯一一间空着的房间:树里根本没有 ML 运行时,所以选择与去除靠的是经典算法(最大流图割、非局部块补全、PatchMatch 式修补),而生成式填充、Neural Filters 和天空替换是缺席,不是近似实现。 把这些加起来,项目自己的答案就在 roadmap 第一屏:功能广度约 76%,「能用于真实工作」约 45%,给出区间 40 到 50,阶段是 alpha,而挡住 beta 的只有一类问题——Photoshop 不肯稳定地重新打开 PhotoCraft 写出的文件(#1281、#2469)。 - 05
它跑得起来,以及怎么确认这一点
构建说明是四行:克隆,然后
cargo run --release -p photocraft -- image.psd。工作区要 Rust 1.95 和 edition 2024,锁文件钉住 728 个包,Type 工具用的字体是第二个仓库的可选 checkout,不是这个仓库里的文件。十一天里发了八个版本,从 2026-10-02 的 v0.1.0 到 2026-10-10 的 v0.6.0;最新版挂了 24 个文件:Windows 的 x64、arm64、x86 各有 MSI 和便携 ZIP,macOS 有通用版已公证的 DMG 和配套命令行工具,Linux 的 x86_64 与 aarch64 各有 AppImage、Flatpak、deb、rpm 和 tarball,FreeBSD 14 有一个按/usr/local铺开的 tarball,还有一个 11 MB 的 WebAssembly 静态站点。v0.6.0 的文件被下载了 73,049 次,其中 Windows x64 安装包占了 24,040 次。 这个安装包我是自己验的,没有采信 README。对下载下来的 MSI 跑Get-AuthenticodeSignature,结果是 Valid:签名者为佐治亚州亚特兰大的CN=Learning Machines Inc,签发者一栏是Microsoft ID Verified CS EOC CA 03,并由微软的公共时间戳服务加戳,所以叶子证书过期之后签名仍然有效。而项目自己的缺口清单在同一天还把「Windows code signing(签名材料尚未取得)」列为缺失,发布清单里也还写着签名材料不存在时会跳过签名并给出警告。已发布的文件说的不是这个。 需要提醒的地方 README 和docs/gaps.md都写了,不用等人踩坑。在 Wayland 会话里把文件拖到窗口上打不开,因为底下的 winit 0.30 在那里没有拖放(#386),README 直接把绕法写在正文里。FreeBSD 版在虚拟机里构建,以纯 tarball 发布,背后没有代码签名机制。没有应用内更新检查,也没有应用内报错入口。卖下载的那个官网慢了一个版本:2026-10-11 它还在提供 0.5.0 的安装包、还要求 Rust 1.90,而仓库已经发布 0.6.0 一天了。 持续集成不是摆设。八个 workflow、6,583 次运行;ci.yml会跑格式化、clippy、Linux 与 Windows 上的全工作区测试、一遍不带可选 HEIC 解码器的测试、一遍带字体输入的测试、分层检查、wasm 检查和语料测试,macOS 留给发布流水线,因为这家组织把五个 macOS 名额留给签名。GitHub 的 API 显示,这个 workflow 最近 60 次已完成的运行是 3 次通过、22 次失败、23 次被取消、12 次在等维护者批准 fork 的工作流。被取消的里面有 12 次是推到main,而 workflow 文件里留着一句注释,说main上的运行从不取消,因为早先的策略在合并挨得近时会让 main 处于未验证状态。
他会告诉你什么
- clean room 这个问题开着,也没人回答。#341 于 2026-10-06 提出,13 条评论全部来自外部账号,没有一条来自项目;一个训练语料无人能审计的模型,无法为自己的来源背书,而仓库也没有反驳这一点。#2332(2026-10-10)指出部分主题背后的 Adwaita 调色板来自 LGPL 样式表,与项目自己那条「随附素材须为宽松许可」的规则冲突。两条都没有回复。许可是 MIT 或 Apache-2.0 二选一,但有一处例外:ArtCraft 的名称、字标和 logo 是商标,只能原样使用、且只能作为本仓库的一部分使用,所以 fork 必须把它们去掉。
- 按它自己的测量,这就是早期 alpha,而且测得很具体:「能用于真实工作」约 45%,功能广度约 76%,25 项性能预算里 22 项没达标,149 项首选项里 46 项接了等于没接,68 件工具缺 15 件,所有 AI 功能都没有 ML 运行时,另有一类被 roadmap 称作堵住 beta 的问题——Photoshop 不肯稳定地重新打开 PhotoCraft 写出的文件(#1281、#2469)。alpha 关卡被描述为通过,依据是六条核心工作流,其中四条只是深度不足。
- README 上的数字是整个仓库最弱的一环,其中三个在同一天里与代码树或彼此矛盾。它写「more than 1,700 tests」,而源码里有 5,733 个
#[test]、同一天的架构文档写的是约 5,460。它的 Windows 下载表说安装包已代码签名,而docs/gaps.md仍把 Windows 签名列为缺失,实际发布出去的 MSI 验出来是签了名的。它主推的 PSD 成绩 309 里 307,旁边放着成绩单的 256 里 133(对照 Photoshop 自己的渲染)和官网的 135 里 134,这是三个不同的问题。 - 体量和深度不是同时到的。项目最爱引用的那个数字(菜单覆盖)一天之内从 224 项涨到 532 项,第四天(2026-10-03)就满了;而真正面对用户的修补要等 0.5 和 0.6 到了人手里才开始。要判断这个项目现在是什么状态,该看的是 issue 列表。
- issue 列表才是这个东西的诚实描述。2026-10-11 这天 GitHub 在仓库上记着 784 个打开项;同一天上午把列表翻完,得到 557 条 issue 和 228 条 PR,比计数器多一个——两个数相隔几分钟读到。十一天里提了 1,276 条 issue、关了 718 条,而开着的那些标题是针对两个已发布版本的用户反馈,不是许愿:Wacom 笔偏移几个像素、大笔刷下延迟、阿拉伯语图层名显示成豆腐块、150 层的文档崩掉、Linux AppImage 上 CMYK 坏掉。项目自己排出的工作清单把这条积压算成 250 到 400 agent 小时,是 PSD 保真度和性能之后最大的一项。
- 持续集成不支持那个测试数。主 workflow 最近 60 次已完成的运行里,3 次通过、22 次失败、23 次被取消、12 次在等维护者批准 fork 的工作流。真正还管用的检查是克隆下来自己构建:release、语料钉子和一个签过名的安装包都在,而
cargo run --release -p photocraft就是这个主张的四行版本。
相关档案
全部档案 →第 083 号
OpenChatCut
一个本地优先的视频剪辑器,剪辑方式是跟它说话:内置 agent 与外部 Codex、Claude Code 会话调用的是界面自己在用的同一套剪辑工具,于是每一处改动都落在一条真实的多轨时间线上——是片段、转场、字幕、特效或音频,仍然能拖、能撤销、能导出。工程与素材留在本机,预览与最终渲染都出自 Remotion。
第 071 号
Reticle
一个 MCP 服务器加一个只在开发期生效的 SDK:让编码 agent 从应用内部去读、去操作一个正在运行的 web 或桌面应用,然后给出判词和该改的文件与行号,而不是一张截图。
第 142 号
typesafe-computer-use
它把你的 Mac 推向一句白话写下的目标:OCR 与无障碍树负责读屏,TypeSafe 分类器挑下一步动作,只有需要自由文本时才叫上写作模型。一次决策约 $0.0002,也就是五十分之一美分,而前沿模型读同一张截图要 $0.032。