PhotoSuite开发者指南:从cargo xtask到PSD语料库测试,参与开源图像编辑器的完整流程
PhotoSuite开发者指南:从cargo xtask到PSD语料库测试,参与开源图像编辑器的完整流程
PhotoSuite 是一款用 100% Rust 编写的开源图像编辑器,忠实复刻经典 Photoshop 的操作体验,并原生支持 PSD/PSB 无损往返读写。本文为新手准备的完整开发者指南:从环境搭建、首次构建运行,到 cargo xtask 工具链和 PSD 语料库测试流程,帮助你在一小时内走上第一条贡献之路。
一、前置环境:Rust 1.90+ 与系统依赖
PhotoSuite 要求 Rust stable(1.90 及以上),并建议提前安装 Web 构建目标:
rustup target add wasm32-unknown-unknown
三大平台(macOS / Windows / Linux)均可开发,Linux 需额外安装图形库依赖:
# Debian/Ubuntu 示例
sudo apt install libxkbcommon-dev libwayland-dev libx11-dev \
libxrandr-dev libxi-dev libgl1-mesa-dev libgtk-3-dev
完整说明见 docs/development.md。
二、克隆仓库并第一次构建运行
git clone https://gitcode.com/gh_mirrors/ph/photosuite
cd photosuite
cargo run --release -p photosuite # 启动桌面应用
cargo run --release -p photosuite -- some/file.psd # 直接打开一个 PSD
几个实用细节:
- 首次冷构建要编译整个依赖图,耗时较长但后续增量构建很快;
- 图像代码在
opt-level 0下很慢,交互式体验请用--release; - macOS 用户可以用 scripts/dev-macos.sh 获得更快的反馈:
CHECK=1只做类型检查,PROFILE=release跑优化版; - 项目内置
devfast构建 profile(保留断言与增量构建,同时把依赖优化到opt-level 2),通过cargo dev别名调用。
三、认识 cargo xtask:开发者的瑞士军刀 🧰
PhotoSuite 把所有高频开发操作收拢在 xtask/ 工具 crate 中,完整命令清单定义在 xtask/src/main.rs。新手只需先记熟下表:
| 命令 | 作用 | 什么时候用 |
|---|---|---|
cargo xtask ci |
一次跑完 fmt + clippy + 全量测试 + 分层检查 + wasm 检查 | 提交 PR 前必跑 |
cargo xtask layers |
校验 crate 依赖分层(只允许依赖更低层) | 新增/调整依赖后 |
cargo xtask corpus [--all] |
拉取测试语料库(固定提交 + sha256 校验) | 跑语料库测试前 |
cargo xtask test-corpus |
拉取语料并运行 corpus feature 测试 |
改动 psd/io/codecs 等 crate 后 |
cargo xtask parity |
对比 Photoshop 菜单覆盖率,重写 docs/parity.md | 新增命令后 |
cargo xtask perf [--quick] |
运行 release 基准测试并检查性能预算 | 触碰性能热点后 |
cargo xtask scorecard |
生成本地成绩单 docs/scorecard.md | 任何数字变化后 |
cargo xtask stats |
统计各 crate 的测试数与代码行数 | 熟悉代码库规模 |
cargo xtask wasm |
检查 L0–L6 核心 crate 能否编译到 wasm32 |
改动核心 crate 后 |
四、PSD 语料库测试:用真实文件当 oracle 🧪
这是本项目最有特色的测试设计:真实文件是最好的 oracle。语料库文件很大,因此永远不提交进仓库,而是按固定提交拉取到 gitignored 的 corpus/ 目录,并用已提交的 sha256 清单逐文件校验。所有 pin 集中在一处:xtask/src/corpus_pins.rs。
| 目录 | 内容 | 来源 |
|---|---|---|
corpus/photoshop/ |
256 个用 Photoshop 制作的 PSD:智能滤镜、图层样式、文字引擎、全模式全位深调整层 | 项目自研 oracle(MIT OR Apache-2.0) |
corpus/psd/ |
170 个小体积 psd-tools 与 ag-psd 文件混集 | 上游测试集(MIT) |
corpus/psd-tools/ |
psd-tools 完整测试集(309 个文件) | 上游测试集(MIT) |
corpus/pngsuite/ |
PngSuite 经典 PNG 测试集 | 公有领域 |
常用命令组合:
cargo xtask corpus --all # 拉取全部缺失语料(冷启动约 15 秒,已校验的不动)
cargo xtask test-corpus # 拉取 + 运行 psd/codecs/io/engine 的 corpus feature 测试
cargo xtask test-corpus -p io # 只测某一个 crate(可重复 -p)
cargo xtask test-corpus --changed # 仅当 psd/io/codecs/compose/gpu/text/format 相对 origin/main 有改动才跑
规则很严格,也很清晰:
- 语料库测试藏在
corpuscargo feature 后面,普通cargo test既不编译也不需要它们; - 一旦开启该 feature,语料缺失会被判为失败(提示运行
cargo xtask corpus --all),绝不允许静默跳过; - 只要触碰了
psd、io、codecs、compose、gpu、text、format中任何一个,结束前必须跑一次cargo xtask test-corpus; - 永远不要把语料文件提交进仓库。
渲染保真度:composite oracle
语料测试的核心是"oracle 对比":把我们的合成器输出与 PSD 内嵌的 Photoshop merged image 逐像素比较(PASS 阈值 ≤ 2/255),各语料的通过率底线(floors)定义在 crates/io/tests/corpus.rs,只许上调、不许下调。想深挖单个文件的差异,一条命令即可并排导出"我们的结果 | Photoshop | 差异热图":
cargo run --release -p photosuite-io --example oracle_diff -- \
corpus/psd/<file>.psd 0 png /tmp/diff.png
五、命令而非界面:贡献一个新功能的正确姿势
PhotoSuite 的架构原则是 "Everything is a command":菜单、快捷键、控制面板、自动化通道派发的是同一组引擎命令。因此贡献新功能的标准路径是(完整清单见 docs/contributing.md):
- 在 crates/ui-egui/src/menu_catalog.rs 里找到对应 Photoshop 菜单项的 id,复用它可让菜单项自动点亮;
- 算法写进最低合适的 crate(成像算法放
algo,画笔放paint,字体放text),带单元测试; - 命令写进 crates/engine/ 的
<area>_cmds.rs模块并在 crates/engine/src/commands.rs 注册; - 补齐测试:行为、撤销重做、禁用状态、错误参数、多位深;
- 运行
cargo xtask parity并提交重新生成的 docs/parity.md。
六、提交前的检查清单:5 步不踩坑 ✅
AGENTS.md 第 5 节给出了结束任务前的标准流程,直接照着跑:
cargo test -p <你改动的crate>
cargo clippy -p <你改动的crate> --all-targets -- -D warnings
cargo xtask layers
cargo xtask wasm # 若触碰了 L0–L6 核心 crate
cargo xtask parity # 若新增了命令
cargo xtask test-corpus # 若触碰 psd/io/codecs/compose/gpu/text/format
cargo xtask perf --quick # 若触碰了性能热点
此外还有两条"红线"值得新手提前知道:
- Never crash(绝不高优先级):非测试代码禁止
unwrap/expect/panic!,禁止unsafe(由 clippy 配置强制);输入派生的索引和长度必须做边界检查; - Clean-room(干净室):只按公开规范(Adobe PSD 规格、ICC 标准)和观察行为实现,绝不复制专有软件的任何代码、着色器或素材。
七、性能预算与成绩单:用数据说话 ⚡
PhotoSuite 把性能也做成了"可贡献"的部分:
- perf/budgets.toml 定义了每个基准场景的毫秒级预算(目标来自 issue #209–#211),
enforce = false标记"尚未达标"的目标,达标的那个 PR 里把它翻成true; cargo xtask perf跑完基准后,p50 相对基线回退超过 15% 即判失败,跨机器型号的数字绝不互相比;- scorecard/ 下每个
*.toml是一域一清单(工具、文件兼容、UI、自动化等),条目含状态与证据(file:line),cargo xtask scorecard汇总生成本地成绩单——找活干的好去处:missing和partial的行就是现成的任务列表。
八、延伸阅读:按顺序读文档效率最高
| 文档 | 读它为了 |
|---|---|
| docs/architecture.md | crate 分层地图、引擎/UI 边界、文档模型 |
| docs/development.md | 构建 profile、调试技巧、语料库与 oracle 细节 |
| docs/contributing.md | 贡献规则与"添加命令"清单 |
| docs/control-protocol.md | JSON 控制通道:程序化驱动与截图应用 |
| docs/upstream-sync.md | cargo xtask upstream 上游同步台账 |
| AGENTS.md | 黄金法则与工作选择指南 |
按照"读文档 → cargo xtask ci 保持绿 → 挑一个 scorecard 里的 missing 条目"这个节奏,你就能从第一个 PR 开始,参与这个 100% Rust、无 Electron、原生支持三大平台的开源图像编辑器。祝编码愉快 🚀