diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 6d39ca3..bcc9946 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -1,6 +1,6 @@ # InpaintRegionEditor 项目交接文档 -> 版本:1.0 | 日期:2026-03-02 +> 版本:1.1 | 日期:2026-03-03 > 交接对象:开发团队 > 交接人:项目经理 Agent @@ -13,7 +13,8 @@ **InpaintRegionEditor** 是一个 ComfyUI 自定义节点,用于解决局部重绘(inpaint)工作流中的两个核心问题: 1. **图像编辑**:ComfyUI 自身没有图像编辑功能,需要集成 Photopea 实现液化、仿制图章等 PS 级功能 -2. **选区调整**:原有的扩散选区功能无法手动调整位置,导致边缘参考区域错误 +2. **蒙版编辑**:支持羽化效果的蒙版编辑,使用 Photopea 双图层模式 +3. **选区调整**:原有的扩散选区功能无法手动调整位置,导致边缘参考区域错误 ### 1.2 核心价值 @@ -25,6 +26,8 @@ 本节点解决方案: ├─ 集成 Photopea:完整的 Photoshop 功能,浏览器内完成编辑 +├─ 双模式编辑:编辑图像 / 编辑蒙版(分离操作) +├─ 羽化支持:半透明蒙版自动转换为羽化效果 ├─ 可拖动选区:手动调整参考区域位置,确保参考内容准确 └─ 一体化流程:上传 → 编辑 → 选区调整 → 执行,无需切换工具 ``` @@ -33,20 +36,24 @@ ``` 输入: - - image: 从 ComfyUI input 目录选择(支持上传) + - image: 从 ComfyUI input 目录选择(支持上传、Ctrl+V 粘贴) - padding: 扩散像素数(默认 64,范围 0-512) 自动处理: 1. 读取图像 Alpha 通道作为 MASK 2. 没有 Alpha → 报错 "请先创建蒙版" - 3. 有 Alpha → 计算蒙版边界框 + 3. 有 Alpha → 计算蒙版边界框(alpha < 255 都计入) 4. 选区 = 蒙版边界 + padding - 5. 在图像预览上绘制遮罩 + 选区框(可拖动) + 5. 在图像预览上绘制遮罩 + 选区框(可拖动、可调整大小) 用户操作: - - 右键 → "打开 Photopea 编辑":编辑图像 + 蒙版 + - 右键 → "编辑图像(Photopea)":编辑图像本身 + - 右键 → "编辑蒙版(Photopea)":双图层蒙版编辑(参考图像 + 蒙版层) + - 右键 → "Open in MaskEditor":使用 ComfyUI 自带蒙版编辑器 - 拖动选区框:手动调整参考区域位置 + - 调整选区边缘:拖动边缘/角落调整选区大小 - 调整 padding 值:改变扩散像素数 + - Ctrl+V:粘贴图片 输出: - IMAGE: RGB 图像(不含 Alpha) @@ -510,6 +517,7 @@ doc.selection.copy(); | **Region(选区)** | 定义参考区域,AI 参考这个区域内的原图内容 | | **Padding(扩散)** | 选区相对于遮罩边界的扩散像素数 | | **Alpha 通道** | PNG 的透明度通道,用于存储蒙版 | +| **羽化** | 蒙版边缘的半透明过渡效果(alpha = 1-254) | ### 12.2 版本历史 @@ -517,9 +525,53 @@ doc.selection.copy(); |------|------|------| | 0.1 | 2026-02-27 | 初始版本(简化版,仅 Photopea 集成) | | 1.0 | 2026-03-02 | 需求最终确认,编写 handoff 文档 | +| 1.1 | 2026-03-03 | Photopea 蒙版编辑功能,修复 RGB 被掏窟窿问题 | + +--- + +## 十三、关键技术实现 + +### 13.1 Canvas Premultiplied Alpha 问题 + +**问题描述**: +当 Canvas 通过 `drawImage()` 绘制带有 Alpha < 255 的 PNG 图像时,浏览器会应用 **premultiplied alpha**,导致 Alpha = 0 的像素 RGB 数据丢失(被"掏窟窿")。 + +**解决方案**: +1. **加载时**:使用 ComfyUI `/view` API 的 `channel=rgb` 和 `channel=a` 参数分别获取 RGB 和 Alpha 数据 +2. **保存时**:使用 UPNG.js 库直接编码 RGBA 数据,绑过 Canvas 的 premultiplied alpha + +### 13.2 Photopea 蒙版编辑流程 + +``` +1. 加载图像 + ├─ 获取 RGB 数据(channel=rgb)→ 完整 RGB,无窟窿 + └─ 获取 Alpha 数据(channel=a)→ 用于创建蒙版层 + +2. 创建双图层文档 + ├─ 底层:参考图像(完整 RGB) + └─ 顶层:蒙版层(用户在此绘制黑色 = 遮罩) + +3. 保存蒙版 + ├─ 隐藏参考图像层 + ├─ 只导出蒙版层 + ├─ 获取原图 RGB(channel=rgb) + └─ 合并蒙版到 Alpha 通道(UPNG.js 编码) +``` + +### 13.3 羽化逻辑 + +``` +蒙版层(用户绘制): +- 黑色不透明(alpha=255)→ 遮罩 → 最终 alpha=0 +- 黑色半透明(alpha=128)→ 羽化 → 最终 alpha=128 +- 完全透明(alpha=0)→ 不遮罩 → 最终 alpha=255 + +公式:最终 alpha = 255 - 蒙版层alpha +``` --- *文档创建时间:2026-03-02* +*最后更新时间:2026-03-03* *基于与用户的多次讨论整理* *交接完成标志:开发团队确认收到并理解本文档*