.project 工程包 vs PSDCompositor 非破坏性编辑的格式野心与兼容困局【免费下载链接】CompositorThe Photoshop alternative for Mac项目地址: https://gitcode.com/gh_mirrors/compos/Compositor编辑永远不损原图是所有专业图像软件的共同承诺但承诺背后的文档格式设计却千差万别。Compositor——一个定位Photoshop alternative for Mac的开源项目——在这件事上选择了与 Adobe 完全不同的路径它不把能打开 PSD当作终点而是设计了一套从零开始的.comp工程包格式同时把 PSD 导入做成了一件能进、但不保证全的精细活。这套组合拳既是它的差异化卖点也是它最尴尬的兼容困局。本文结合仓库源码拆解这份野心与代价。一、非破坏性一切编辑都不触碰原始像素Compositor 的非破坏性不是一句口号而是数据结构层面的硬约束。在 Compositor/Document/LayerTransform.swift 中图层的位置、尺寸、旋转和翻转被建模为独立的LayerTransform结构体nonisolated struct LayerTransform: Equatable, Codable, Sendable { var origin: CGPoint var size: CGSize var rotation: CGFloat 0 var flipX false var flipY false var sampling: LayerSampling .high ... }注意这里的语义size是绘制多大而图层像素本身始终以原始分辨率保存。把图层缩小到 10%写入磁盘的 PNG 仍然是 100% 分辨率的原始像素——docs/project-format.md 里写得很直白Embedded PNGs preserve source pixels and transparency; transforms remain separate。缩放、旋转、翻转这些编辑只改 transform 里的几个数字代价是渲染层要实时重算。在 Compositor/Rendering/LayerRenderer.swift 中可以看到渲染时如何把 transform 拆解成平移、旋转、翻转三步context.translateBy(x: center.x, y: center.y) context.rotate(by: transform.radians) context.scaleBy(x: transform.flipX ? -1 : 1, y: transform.flipY ? 1 : -1)为了在大幅缩小时不糊项目还维护了一个基于 vImage Lanczos 重采样的降采样缓存链Compositor/Rendering/DownsampleCache.swift每次绘制只让 Core Graphics 做最后一层最多 2× 的缩小。非破坏性的收益是双重的像素永不被破坏撤销历史因此可以极简——因为大多数编辑只是参数的改变而不是像素的替换。二、.comp 工程包一个看得见的文档格式Compositor 没有选择发明一个封闭的二进制格式而是让工程文件成为 macOS 的文档包package一个.comp就是一个文件夹里面是manifest.json加一个images/目录每张图层 PNG 以 UUID 命名。这个设计最激进的地方在于——任何能写文件的程序都能创建或编辑一个 Compositor 工程。仓库里的 docs/writing-comp-files.md 明确定位了它的读者AI agents and scripts can build and edit projects directlyREADME 也专门列了 Works with AI agents 一节并给出了一个最小 manifest 示例{ format: com.compositor.project, version: 11, colorSpace: sRGB, documentID: 0C5E7A91-3B2D-4F6A-8E1C-9D0B7A6F5E4D, width: 1920, height: 1080, layers: [ { id: 6F1D3C2A-0B7E-4E8A-9C4D-2A1B3C4D5E6F, name: Background, imageFile: 6F1D3C2A-0B7E-4E8A-9C4D-2A1B3C4D5E6F.png, isVisible: true, opacity: 1, blendMode: Normal, transform: { origin: [0, 0], size: [1920, 1080], rotation: 0, flipX: false, flipY: false } } ] }图层变换、混合模式、蒙版、调整图层、形状、文字、图层效果全部是 manifest 里的普通 JSON——没有二进制魔法也没有需要逆向的私有段。一个外部 AI agent 每写完一批 PNG 和 manifest正在运行中的 Compositor 会在约 0.3 秒内热更新画布。这背后的机制在 Compositor/IO/ProjectWatcher.swift它用O_EVTONLY监听包目录、manifest 和 images 目录的内核文件系统事件300 毫秒合并一次并且每次原子替换后按路径重新武装监听保证包被整个换掉后依然能被感知。格式的版本演进同样克制。从 v1 到 v11每个版本只做加法docs/project-format.md 记录了 v2 加图层组parentID/isGroup、v3 加透明度和混合模式、v4 加图层蒙版、v5 加裁剪蒙版的 live alphamaskSourceID、v7 加调整图层、v8 给文件夹加自身透明度并新增参考线、v9 增加高斯模糊/动感模糊/加噪三种采样相邻像素的调整、v10 和 v11 分别让文字图层支持分段着色和分段字体。关键约束是新版本字段全部可选、旧版本字段缺省有明确默认值缺省即全透明度和 Normal 混合因此新版本文件对旧读取器是逐字段兼容的。而校验在保存端就已经完成Compositor/IO/ProjectStore.swift 在写入前检查 manifest 大小不超过 4 MiB、编码使用FileWrapper.write(to:options:.atomic)做原子包替换读取端则拒绝不支持的版本、损坏的元数据、缺失资源、不安全路径和超大数据失败的加载不会替换当前文档——错误信息会明确告诉你当前文档没有被替换。保存管线本身也是一道防线保存发生在后台用户编辑不被打断PNG 导出只是展平的派生品不会把工程标记为已保存。换句话说只有 manifest 与图层资源的真实状态才算数这让外部工具与 GUI 的协作有了一个干净的一致性模型。三、PSD 兼容的边界能进不能全PSD 是绕不开的兼容债任何自称Photoshop 替代的软件都必须能打开它而 PSD 是 Adobe 私有规格、跨了 30 多年版本。Compositor 的处理方式是照着规范正面实现同时把每一处降级都摆在明面上。在 Compositor/IO/PSD/PSDReader.swift 的文件头注释里作者明确声明这是依据 Adobe 官方《Photoshop File Formats Specification》(2019) 独立实现的读取器并强调没有从 GIMP、psd-tools 等 GPL 读取器复制或改写——这一句声明对开源项目来说就是生死攸关的许可合规问题。入口检查非常干脆魔数必须是8BPS版本号 1 是 PSD、2 是 PSB随后逐段解析文件头、色彩模式、图像资源、图层与蒙版信息。但边界从第一行就开始收紧guard depth 8 else { throw PSDError.unsupportedDepth } guard mode 3 else { throw PSDError.unsupportedColorMode }Compositor/IO/PSD/PSDTypes.swift 把这份限制翻译成了人话Only 8-bit RGB Photoshop files can be imported。CMYK、16/32 位深度的 PSD 一律拒绝——这是和 Photopea、GIMP 拉开差距的地方后两者对色彩空间的兼容要宽得多。在能进的范围内Compositor/IO/PSD/PSDDocumentBuilder.swift 里写满了精确的降级清单每一类都被明确标注保持可编辑文件夹图层组、图层蒙版、混合模式PSD 的四字符键如mul、scrn映射到本地枚举、矩形/椭圆填充形状通过vogk/SoCo还原为 live shape 图层、简单的水平文字TySh块解析为可重排的文字图层栅格化为像素智能对象Linked contents cant be edited、矢量路径、非水平/带 warp 的文字直接丢弃图层样式/效果lfx2 等导入时提示appearance may differ、不支持的调整图层种类、Dissolve等没有本地对应物的混合模式内存降级超过像素预算的 PSD图层会被裁到画布范围内cropToCanvas并如实报告canvas 外的像素没有被导入。对蒙版的转换尤其讲究Compositor/IO/PSD/PSDReader.swift 解析 PSD 只存非默认值的那块补丁maskBounds/maskDefault导入时再由 PSDDocumentBuilder.swift 的maskOnLayerGrid把它放回图层自己的像素网格——PSD 只存非默认部分这个细节如果处理不好蒙版会整体错位。而折叠文字的boxSize解析失败时会整个放弃导入而不是降级为点文字因为导入成点文字会丢失换行却不告诉你。所有这些降级都不是静默发生的。导入前会弹出转换报告逐图层列出将发生什么Compositor/UI/PSDConversionSheet.swift标题就是 Compositor will convert these Photoshop features. Nothing is applied until you continue.——先看报告、确认后才应用。这正是能进不能全的正确姿势兼容的边界是明确的边界内外的分界线用户事先就知道而不是导入之后才发现文件变样了。四、格式生态困局单机项目如何说服用户迁移把视角拉回工程与产品层面Compositor 的处境其实是矛盾的comp格式越精致它与 PSD 生态的距离就越远——因为它没有导出 PSD 的能力。从仓库源码看Compositor/IO/ImageExporter.swift 的导出能力只有 PNG、JPEG 和一页 PDF按打印尺寸导出PSD 方向是单行道只进不出。这意味着任何用 Compositor 做完的工程想回到 Photoshop 生态继续协作都只能导出一张扁平的 PNG——图层、蒙版、调整全部被烧死在像素里。对一个以合成与后期为核心工作流的软件这是协作层面最硬的墙。更现实的问题在迁移成本侧。第一道门槛是平台锁定README 的 Requirements 写得很清楚——macOS 26.0 及以上、仅 Apple silicon构建还需要 Xcode 26。社区对此早有反馈CSDN 上CompositorSwift 原生图像编辑器100% 开源免费对标 Photoshop一文2026-09虽然给出 424 次阅读、16 次收藏的热度也同时点出存在平台锁定与学习成本等约束另一篇6 条路子绕开 PS的盘点把 Compositor 与 Photopea、GIMP、Krita 并列时给它的定位标签是macOS 原生非破坏性编辑——在兼容 PSD这个维度上它显然不如 Photopea 那样能打。而最尖锐的舆情来自一篇标题本身就把话说透的讨论别吹开源版 Adobe 了复杂 PSD 打不开这算毛坯房。8-bit RGB、无 CMYK、图层样式丢弃、智能对象栅格化——对习惯把 PSD 当作交付格式的平面设计师来说这些限制确实会让它显得只能算毛坯房。第二道门槛是维护形态。README 的 Translations 一节直白地交代了单点风险Its maintained by one person。一个人维护意味着格式演进要极其克制确实如此v1–v11 全是向后兼容的加法PSD 兼容的覆盖面只能缓慢扩大目前调整图层只映射了 Levels、Curves、Hue/Saturation 三种其余levl/curv/hue2之外的grdm、blwh等键在 PSDReader.swift 的adjustmentKeys集合里出现却在解析层被跳过。格式生态的残酷之处正在于此一个格式的价值 使用它的人数而单机项目靠口碑积累用户的速度永远追不上 Adobe 生态的存量。但换个角度看这份困局同时也是它最有辨识度的资产。.comp的开放性给了它一个 PSD 永远给不了的东西——机器可读、可脚本化、可审计。格式是纯 JSON 加标准 PNG没有私有二进制段任何 CI、任何 AI agent、任何未来要出现的自动化工具都能无授权地读写它。这恰好命中了当下AI agent 直接操作设计资产的趋势PSD 对 agent 是黑盒.comp对 agent 是打开的抽屉。README 里那句 AI agents and scripts can build and edit projects directly: a .comp is a folder of PNG layers and a manifest, and an open project updates live as its written 已经把这个差异化讲透了。所以与其说 Compositor 在兼容 PSD上失败了不如说它押注了一个完全不同的未来不试图在存量 PSD 生态里当第二而是用开放格式在增量生态里做第一。这个赌注的代价是今天的迁移门槛回报是明天的 agent 工作流——而能不能打开复杂 PSD只是这份赌注在当下最直观的试金石。对一个由一人维护、MIT 协议、目标pixel-perfect final image的项目来说把格式的野心押在开放与可编程上或许正是它唯一能赢的姿势。【免费下载链接】CompositorThe Photoshop alternative for Mac项目地址: https://gitcode.com/gh_mirrors/compos/Compositor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考