Files
AnyImage/docs/internals/common.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

7.6 KiB
Raw Blame History

Common 公共函数

src/anyimage/common/ 按 AI、Image、Selection、Viewport、Depth、Material、Object 和 Node 八个业务模块提供 Blender 侧复用能力。调用方直接从对应模块导入函数。

Image 数据块

image.py 处理 Blender Image 数据块及其在 Image Empty 上的完整生命周期,包括像素读取、动画帧、Job 输入、结果 Image 创建和 Empty 引用替换。

函数 职责
image.is_image_empty() 判断对象是否为带有效 Image 数据的 Empty。
image.require_image_empty() 按名称取得 Image Empty;对象已失效时抛错。
image.image_pixels() 以 Blender 原始顺序读取一维 float32 像素。
image.image_rgba() 读取为 Top-down RGBA float32 数组。
image.video_total_frames() 返回 Movie 或 Sequence 总帧数,静态图返回 1。
image.image_user_settings() 读取 Image Empty 的帧起点、偏移、时长和循环设置。
image.default_extract_frames() 取得当前 Empty 默认应处理的帧数。
image.source_start_frame() 从源 Image Empty 取得 Job 应处理的起始帧。
image.prepare_image_input() 将 Packed、Dirty、Sequence 等输入准备为 Job 可读路径,并返回临时标记。
image.prepare_image_bounds_input() 复用调用方已读取的 RGBA,按几何 bounds 写出保留原始 Alpha 的矩形 Job 输入。
image.cleanup_image_input() 清理由图片输入 helper 创建的临时文件或目录。
image.image_base_name() 去除图片或视频扩展名和 Blender 数字后缀,得到数据块基础名。
image.depth_data_name() 生成 Depth 结果数据块文件名。
image.color_data_name() 生成 Color 结果数据块文件名。
image.load_color_result_image() 加载、命名、Pack 并配置 Job 的 Color 或 Sequence 结果;不修改 Empty。
image.load_normal_result_image() 加载、命名、设为 Non-Color 并 Pack Normal Map。
image.load_packed_rgba_image() 加载已有 RGBA 文件,继承源图颜色空间和 Alpha mode,命名并 Pack。
image.create_pixel_result_image() 从本地编辑后的 RGBA 像素创建 Packed Image;不修改 Empty。
image.replace_empty_image() 执行 Image Empty 结果替换、共享引用分流、旧数据清理、帧设置继承和可选画布对齐。
image.image_empty_bounds() 计算 Image Empty 在对象局部坐标中的实际显示边界。

Image Selection 与视图交互

这组公共能力使用固定术语:

  • Selection 是用户在图片空间圈定的业务范围;SelectionPath 保存路径点和反选状态,并提供完整值的 JSON 编解码。
  • SelectionMask 是 Selection 的纯几何栅格化结果,只包含局部像素权重 values 和源图几何 bounds。
  • Mask 表示二维像素权重或 Alpha 运算。
  • Blender 对象 Selection 由上下文明确区分;图片选区细化动作称为 Refine Selection。

viewport.py 处理 View3D 中的点击、坐标投影、ImageSelectionGesture、工具设置和 Overlay 绘制;手势完成时只把内存中的 SelectionPath 交给实际工具。selection.py 负责图片空间 Selection 的值、栅格化和 Alpha 裁切;SelectionPath → SelectionMask 只在图片编辑或 Shape 生成阶段执行。

所有 Path 使用 non-zero winding 填充,同方向重复绕行的重叠区域保持选中。栅格器按路径边与像素中心扫描行的交点累计 winding:非反选只建立 Path Bounds 的局部画布,抗锯齿时增加 2 px 边缘;反选使用完整图片范围。栅格阶段不接收图片 Alpha 或颜色,内容相交、空内容和内容 bounds 由 Image Tool 或 Cutout 业务处理。

Viewport 交互

函数 职责
viewport.report_image_edit_exception() 将可预期的 Selection 警告和异常映射为 Operator Report。
viewport.image_edit_poll() 判断当前上下文是否允许启动 Image 工具。
viewport.resolve_image_edit_click() 解析点击到 Image Empty,并保持或恢复选择状态。
viewport.active_view3d_tool_id() 取得当前 View3D Workspace Tool ID。
viewport.apply_selection_settings() 将当前 Selection 工具的 Refine Selection 设置同步到手势 Operator。
viewport.draw_selection_settings() 绘制 Selection 工具的公共 Refine Selection 设置。
viewport.draw_dashed_line() 绘制手势或透视框虚线。
viewport.draw_polygon_fill() 绘制手势或透视框填充预览。
viewport.gesture_property() 声明统一的 Box、Lasso、Line 和 Polyline RNA 属性。
viewport.screen_path_to_image_pixels() 将屏幕路径投影为 Image Empty 像素坐标。
viewport.serialize_matrix() 将 4×4 Matrix 序列化为 Operator 可保存的字符串。
viewport.deserialize_matrix() 恢复已序列化的 4×4 Matrix。
viewport.drawing_in_region() 判断 Modal 绘制是否仍位于启动时的 Area 和 Region。

Selection 栅格化

函数 职责
selection.selection_path_bounds() 校验 Selection Path 并返回整数像素包围框。
selection.rasterize_selection_path() 以局部 non-zero scanline 把 SelectionPath 栅格化为纯几何 SelectionMask。
selection.crop_pixels_to_alpha() 按 Alpha 非零区域紧裁切 RGBA 像素。

Depth 产物

depth.py 负责 Blender 侧共享的 Depth 文件加载和相机尺度换算,直接加载 Server 写出的 EXR。

函数 职责
depth.load_depth_metadata() 读取并校验 depth.json 中的图片尺寸、相机内参与参考深度。
depth.load_depth_result_image() 直接加载、命名、设为 Non-Color 并 Pack vector-depth.exr 或 z-depth.exr。
depth.camera_depth_values() 从已加载 Depth Image 读取用于本地标定的 Z 与有效区。
depth.depth_uniform_scale() 根据相机内参、参考深度和 Image Empty 范围计算统一尺度。

Object 构建

material.py 构建 Image 材质;object.py 处理 Object 与 Geometry Nodes Modifier;node.py 加载节点资产。

函数 职责
node.load_node_group() 从随扩展分发的 Blend 资产加载指定 Node Group。
material.create_image_material() 从 Image Empty 创建包含颜色、位移、Normal Map、Alpha 和动画设置的完整材质。
object.modifier_input_identifier() 按接口名称解析 Geometry Nodes Modifier 输入 Identifier。
object.set_modifier_input() 跨受支持 Blender RNA 形式设置 Modifier 输入。
object.finalize_object_result() 激活结果对象,并按需替换或保留源 Empty。

AI 准备

ai.py 统一处理 AI 功能的 Environment、模型、Device、输入校验、Job 参数和公共 UI。

函数 职责
ai.draw_ai_setup() 绘制 AI 未就绪时的安装入口,并返回当前状态。
ai.draw_ai_property() 按 AI 就绪状态绘制并启用业务属性。
ai.require_input_path() 解析 Blender 路径并要求其为现存文件或目录。
ai.require_background_input_path() 在通用路径校验之外限制 BEN2 支持的媒体类型。
ai.production_device() 读取正式任务使用的计算设备。
ai.require_environment() 要求 AnyImage AI Environment 已就绪。
ai.invoke_ai_setup_if_needed() Environment 未就绪时启动安装交互。
ai.require_model() 校验模型标识和下载状态,并返回模型记录。
ai.da3_parameters() 组装 debug-da3 参数。
ai.moge2_parameters() 组装 MoGe-2 正式任务与 Debug 共用参数。