Files
AnyImage/docs/internals/operators/image-tool.md
nan 7f6e47432e feat(selection): separate selection geometry from image content processing
- Introduced a new design for selection rasterization that decouples the selection geometry from the image content, ensuring that the SelectionMask is independent of the source image's alpha and color.
- Updated the `rasterize_selection_path` function to only accept selection paths and image dimensions, removing parameters related to source alpha and alpha thresholds.
- Implemented a new approach for handling selection paths using non-zero winding fill, ensuring overlapping areas are preserved.
- Enhanced performance by utilizing a scanline algorithm for rasterization, significantly reducing processing time for high-resolution images.
- Updated internal documentation and added comprehensive tests to validate the new behavior and performance improvements.
- Ensured backward compatibility by maintaining existing interfaces where necessary while introducing breaking changes in the selection processing logic.
2026-09-01 22:36:20 +08:00

48 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Image Tool
Image Tool 从 Box、Lasso、Line 或 Polyline 手势得到一个图片 Selection,再用它修改当前 Image Empty 的 Alpha。
## 执行过程
```mermaid
flowchart TD
Tool["Box / Lasso / Line / Polyline"] --> Gesture["采集图片空间手势"]
Gesture --> Path["构建 SelectionPath"]
Path --> Selection["SelectionPath → 几何 SelectionMask"]
Selection --> Refine{"Refine Selection?"}
Refine -- "否" --> Alpha["读取局部 RGBA<br/>源 Alpha × Selection 值"]
Alpha --> Crop["计算内容 bounds<br/>创建并写回 Image"]
Refine -- "是" --> Bounds["读取 RGBA<br/>写出几何 bounds 矩形"]
Bounds --> Job["refine-image-selection"]
Job --> Result["加载并 Pack BEN2 RGBA"]
Result --> Replace["按响应内容 bounds 替换 Empty"]
```
四个工具共用 `EditImageMask`。Box 和 Lasso 可以执行 Refine Selection;Line 与 Polyline 始终保留几何边界,直接使用本地 `SelectionMask`。
## 节点说明
### 选择工具并采集手势
`operators/image_tool/__init__.py` 汇总注册类型;`box.py`、`lasso.py`、`line.py` 和 `polyline.py` 分别定义四个 WorkspaceTool。它们都把操作交给 `edit_mask.py` 中的 `EditImageMask`。
屏幕坐标投射、点击选择、轨迹预览和状态切换来自 `common/viewport.py`。Lasso 按移动距离采点并合并近似共线点;Line 扩展为有向半平面;Polyline 在确认时闭合路径。
### SelectionPath → SelectionMask
`ImageSelectionGesture` 把手势整理为内存中的 `SelectionPath`,其中 Points 与 Invert 共同定义 Selection,并直接交给同一个 `EditImageMask` Operator,不经过 JSON。预览和最终 Mask 统一使用 non-zero winding,同方向重复绕行的重叠区域保持选中。实际图片编辑开始后,`EditImageMask` 通过 `common/selection.py` 在必要画布内把路径栅格化为一次纯几何 `SelectionMask`;这一阶段不读取或接收源图 Alpha。预览缓存只在轨迹变化时更新。
Box 和 Lasso 分别读取自己的 **Refine Selection** 设置。Line 与 Polyline 直接使用几何边界。
### Refine Selection
未开启 Refine Selection 时,`edit_mask.py` 在实际编辑阶段读取 RGBA 并使用本地几何 `SelectionMask`。开启后,它按 Selection 几何 bounds 写出完整矩形 RGBA 并提交给 `server/jobs/refine_image_selection.py`;矩形内、Lasso 外的源像素与 Alpha 保持原样。Job 调用 `server/selection/refine_selection.py` 运行 BEN2,并返回按结果 Alpha 收紧后的图片和局部内容 `bounds`。
Lasso 在 Refine 中只提供矩形上下文,不再作为 BEN2 输出的硬 Mask。响应阶段把局部内容 bounds 映射回源图,并直接加载、配置和 Pack BEN2 已编码的 RGBA 后替换 Empty;不再提取输出 Alpha、重读源图或重新创建同一颜色图片。
### 源 Alpha × SelectionMask
`edit_mask.py` 在 `SelectionMask.bounds` 内复用源 RGBA,只把几何 Selection 值乘入源 Alpha,再按行列可见范围计算内容 bounds 并紧裁切。几何 SelectionMask 在合并前后保持不变。像素读取、结果 Image 创建和共享引用处理使用 `common/image.py`。
公共 Image Empty 替换入口同步更新 `empty_display_size` 和 `empty_image_offset`,使裁切后的内容对齐原图片平面并保持对象 `matrix_world`。