PhotoBrush引擎源码解析:笔刷动态、双笔刷与压感如何复刻Photoshop手感
PhotoBrush引擎源码解析笔刷动态、双笔刷与压感如何复刻Photoshop手感【免费下载链接】photocraftAn open-source, clean-room reimplementation of Adobe Photoshop in pure Rust项目地址: https://gitcode.com/gh_mirrors/pho/photocraftPhotoBrush 是 PhotoCraft纯 Rust 重写的开源 Photoshop中的笔刷引擎源码位于crates/paint/。它用一套笔刷模型 → 动态生成 → 渲染合成的三阶段流水线把压感、倾斜、桶形旋转等数位笔数据转换成与 Photoshop 手感一致的一笔笔 dab落笔触点笔刷动态Shape/Scattering/Color Dynamics、双笔刷Dual Brush、平滑与确定性随机全部按 Photoshop 语义实现。本文带你读懂它的源码结构。1️⃣ 三阶段流水线从压感输入到像素PhotoBrush 最核心的设计决策是笔画Stroke是数据不是动作。整个渲染过程分三步见 crates/paint/src/lib.rs阶段模块输入 → 输出① 笔刷模型brush.rs笔刷设置 JSONserde 数据② 动态生成dynamics.rs输入点序列 → dab 序列③ 渲染合成render.rsdab 序列 → 笔画缓冲区 → 像素这个设计带来的好处是笔画可以被记录、被自动化脚本回放、被确定性测试——每个随机抖动都是笔刷种子 dab 序号的哈希值rng.rs同一笔画永远画出完全相同的效果。2️⃣ 压感的数据模型StrokePoint 与 Control每个输入采样点是一个 StrokePoint携带完整数位笔信息pressure压感 0..1鼠标固定为 1tilt_x / tilt_y笔身倾斜角-90..90°W3C Pointer Events 约定rotation桶形旋转 0..360°wheel笔侧滚轮喷枪笔time时间戳用于平滑追赶和喷枪堆积这些原始值通过 Control 枚举 映射到各个动态参数正是 Photoshop 里那些控制器下拉菜单PenPressure笔压、PenTilt倾斜、Rotation旋转、StylusWheel滚轮、Fade淡出、Direction方向。比如笔压控制大小就是pressure_size true时直径按size × pressure缩放base_diameter笔压控制不透明度则走pressure_opacity。这就是压感手感的第一层来源笔尖按得越重触点直径越大、覆盖越实且平滑路径在重压段更密集。3️⃣ 笔刷动态Shape Dynamics、Scattering 与 Color Dynamicsdynamics.rs 中的 DabBuilder 是手感的核心它把路径上的每个采样点展开成一串 dab逐 dab 应用 Photoshop 全套动态——形状动态大小抖动Minimum Diameter 保底、角度/圆度抖动与控制器、翻转抖动、Tilt Scale 与 Brush Projection笔倾斜时笔尖沿倾斜方向透视压扁散布触点沿行进方向垂直或双向随机偏移数量 1..16 可带抖动复刻散粉笔刷颜色动态前/背景色混合、色相/饱和度/明度抖动、纯度修正HSV 空间计算传递Transfer不透明度与流量Flow的逐 dab 控制纹理深度逐触点纹理深度的抖动。每个参数都是控制器插值到最小值 随机抖动且永不低于最小值的统一公式scalar与 Photoshop 的运算顺序一致。4️⃣ 双笔刷Dual Brush第二个笔尖如何塑形双笔刷的实现分两处配合生成DualBuilder 沿同一路径用独立的路径行走器自己的 size/spacing/scatter/count/flip生成第二组 dab渲染render.rs 中双笔刷触点不直接画颜色而是在笔画合成阶段作为遮罩dual_tipmip 纹理与主笔刷覆盖率结合支持 Multiply、Subtract、Darken、Overlay、Height 等 10 种 MaskMode 混合模式mask_combine。模型定义见 DualBrush 结构体。这套同路径、独立散布、遮罩塑形的语义正是 Photoshop 双笔刷做花瓣、叶脉等笔刷的原理。5️⃣ 平滑与喷枪把鼠标画成稳的Smoother 提供两种平滑对应 Photoshop 的 Smoothing 选项指数平滑笔尖每次向指针方向移动(1 − amount)的距离并用时间戳按 16ms 步长追赶指针catch-up拉弦平滑Lazy Mouse指针把一根amount × 100px的弦拉直后才落笔弦长随视图缩放自适应。配合 PathWalker勾选 Spacing 时按距离间隔铺 dab取消勾选则每 8ms 落一个 dab——画得越快触点越稀疏这正是 Photoshop速度决定间距的行为。喷枪Build-up则按时间间隔持续叠加触点。6️⃣ 压感从哪来tablet crate 的跨平台笔输入引擎本身不碰硬件压感数据由独立的 tablet crate 提供输出统一为 Sample压感、双轴倾斜、旋转、橡皮端标志平台实现说明macOSmacos.rsAppKit 本地事件监视器在 winit 之前读取NSEvent的笔字段Linux X11x11.rs纯 Rust 的 x11rb 建立第二条 X 连接订阅 XInput2 原始事件Abs Pressure、Abs Tilt X/Y、Abs Rotary Z原始读数经过 sanitized() 钳位与 NaN 兜底无效压感按满压处理等同鼠标保证任何设备异常都不会污染笔刷计算。7️⃣ 从命令到像素引擎层接线引擎层的笔刷命令在 crates/engine/src/brush_cmds.rspaint.brush、paint.airbrush、paint.pencil等命令把前景色、选区、锁定透明等状态填进BrushSettings经 StrokeRenderer 增量渲染——笔画先画进稀疏分块的笔画缓冲区64px 平铺类似私有笔刷层dab 按 Flow 向各自的不透明度上限堆积整笔画最后才按 Stroke Opacity 合成到画布精确复刻 Photoshop不透明度 vs 流量的双层语义。此外还有调色笔刷mixer.rs与颜色替换replace.rs。8️⃣ 源码地图速查表 ️想读什么路径笔刷完整数据模型含双笔刷/动态分区/锁定crates/paint/src/brush.rs输入点 → dab平滑、路径行走、动态计算crates/paint/src/dynamics.rsdab → 笔画缓冲区 → 像素含遮罩混合crates/paint/src/render.rs确定性随机种子 dab 序号哈希crates/paint/src/rng.rs内置笔刷预设crates/paint/src/presets.rs笔刷命令入口crates/engine/src/brush_cmds.rs跨平台压感/倾斜/旋转输入crates/tablet/src/lib.rs笔刷性能基准crates/paint/examples/bench_brush.rs一句话总结PhotoBrush 用笔画即数据 种子哈希随机 Photoshop 逐参数复刻三板斧让压感、双笔刷与笔刷动态在纯 Rust 中获得了与 Photoshop 一致的手感同时天然支持自动化回放与确定性测试。【免费下载链接】photocraftAn open-source, clean-room reimplementation of Adobe Photoshop in pure Rust项目地址: https://gitcode.com/gh_mirrors/pho/photocraft创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

TXT批量文本处理工具:去重、比对与净化实战指南

TXT批量文本处理工具:去重、比对与净化实战指南

1. 为什么我写了这个TXT批量文本处理工具先说个真实的场景。有段时间我手上有一份从老系统导出的客户数据,整整八十万行,格式乱得让人头大——有的行是电话号码,有的行是备注,有的行是空行,还有大量重复记录混在里面。…

2026/10/9 2:54:48 阅读更多 →
Java volatile 关键字

Java volatile 关键字

1. 被 volatile 变量修饰后特点:有序性 和 可见性 volatile 的内存语义 写一个 volatile 变量时, JMM 会把该线程对应的本地内存中的共享变量值立即刷新回主内存中。 当读一个 volatile 变量时,JMM 会把该线程对应的本地内存设置为无效&#…

2026/10/9 2:54:48 阅读更多 →
GitHub Desktop日常开发与代码合并实操:从克隆到冲突解决全流程

GitHub Desktop日常开发与代码合并实操:从克隆到冲突解决全流程

直接上手说吧。GitHub Desktop是我这两年主力用的Git客户端,日常开发、分支管理、代码合并全在这上面完成。团队里有人质疑“用GUI是不是不够专业”,但我实际用下来,只要把工作流理顺,GitHub Desktop的效率和安全性完全不输命令行…

2026/10/9 2:54:48 阅读更多 →

最新新闻

从元器件到LM317可调电源:零基础硬件电路设计实战指南

从元器件到LM317可调电源:零基础硬件电路设计实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 3:33:14 阅读更多 →
三秒生成Alpha通道:贴花素材自动抠图并直连Substance Painter

三秒生成Alpha通道:贴花素材自动抠图并直连Substance Painter

做3D材质的兄弟应该都有过这种经历:在素材网站上看到一张完美的磨损贴花,下载下来,丢进Substance Painter一拖——结果背景一片灰,边缘全是杂边,Alpha通道干干净净地写着“无”。于是你打开Photoshop,魔棒、…

2026/10/9 3:33:14 阅读更多 →
Uber集成缓存:把缓存嵌入MySQL存储引擎的高并发读架构

Uber集成缓存:把缓存嵌入MySQL存储引擎的高并发读架构

买卖双方都不傻,亿级流量面前,缓存方案一定不是“用 Redis 顶在前面”这么简单。Uber 这篇集成缓存(Integrated Cache)的分享,是系统设计圈里少有的、把缓存直接塞进数据库存储引擎里的实战派解法。我读完第一反应是&a…

2026/10/9 3:33:14 阅读更多 →
AMD Ross FPGA Agent 深度解析:从 Vivado 工程自动化到智能调试

AMD Ross FPGA Agent 深度解析:从 Vivado 工程自动化到智能调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 3:33:14 阅读更多 →
EtherNet/IP工业以太网协议实战:从CIP架构到PLC与SCADA联调配置

EtherNet/IP工业以太网协议实战:从CIP架构到PLC与SCADA联调配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 3:33:14 阅读更多 →
双指针算法全攻略:对撞、快慢、滑动窗口三大模板与实战总结

双指针算法全攻略:对撞、快慢、滑动窗口三大模板与实战总结

刷题刷到一定量,很多人会慢慢总结出一条规律:有一类题的解法特别“固定”——有序数组里找两个数凑目标值、链表中判断有没有环、字符串里找不重复的最长子串,题面长得完全不一样,翻开题解一看,底层全是同一个思路&…

2026/10/9 3:32:13 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →