Add comprehensive tests for image processing and mask functionalities

- Introduced tests for color image handling, ensuring source preservation and premultiplied alpha usage.
- Implemented tests for brush stroke operations, validating segment boundaries and brush anti-aliasing.
- Added tests for frame anti-aliasing, confirming correct rendering behavior with various alpha values and depth settings.
- Created tests for frame projection, ensuring accurate overlap calculations and half-plane clipping.
- Developed tests for image premultiplied retention, verifying behavior during loading and packing processes.
- Added undo functionality tests for mask operations, ensuring single transaction behavior during edits.
This commit is contained in:
2026-09-05 21:33:11 +08:00
parent bbaa4bff46
commit 1994d38ccd
111 changed files with 7691 additions and 2341 deletions

View File

@@ -0,0 +1,81 @@
## ADDED Requirements
### Requirement: Frame samples geometric boundary coverage
Frame SHALL 在输出像素与源投射轮廓或前后层级交界相交时使用固定 4×4 均匀子像素中心样本,分别判断有效覆盖及深度顺序。每个样本 SHALL 沿用现有底层 RGB 打底、前景预乘采样与独立 Alpha 合成公式。
#### Scenario: An opaque tilted edge covers half a pixel
- **WHEN** 单张不透明图片仅覆盖该像素的 8 个子样本,其余 8 个没有源覆盖
- **THEN** 输出 Alpha SHALL 为 0.5
- **AND** 该像素 SHALL 不因中心点位于边缘某一侧而变为全有或全无
#### Scenario: The center misses a narrow projection
- **WHEN** 像素中心未命中投射,但 4×4 网格存在有效命中
- **THEN** 有效子样本 SHALL 参与边界合成
#### Scenario: Depth order changes inside a pixel
- **WHEN** 两个源平面在像素覆盖区域内交换前后关系
- **THEN** 每个子样本 SHALL 使用自己的深度顺序
- **AND** 同深度 SHALL 沿用 active 置顶及现有稳定顺序
### Requirement: Frame resolves RGB and alpha with independent coverage weights
边界像素 Alpha SHALL 为全部 16 个子样本 Alpha 的算术平均,无源样本贡献零。RGB SHALL 为具有几何源覆盖的子样本合成 RGB 的等权平均,SHALL NOT 以源 Alpha 作为 RGB 平均权重。全无覆盖像素 SHALL 保持透明黑色,不向 Frame Canvas 外扩展 RGB。
#### Scenario: Mask Add reveals the canvas outside every source
- **WHEN** Frame 范围大于所有源投射,随后 Mask Add 将完全无覆盖区域的 Alpha 恢复为 1
- **THEN** 该区域 RGB SHALL 保持黑色
- **AND** 源边缘颜色 SHALL NOT 形成一像素外框
#### Scenario: A half-transparent foreground partially covers a transparent bottom image
- **WHEN** 透明蓝色底图覆盖全部 16 个样本,Alpha 为 0.5 的红色前图覆盖其中 8 个
- **THEN** 输出 RGB SHALL 为 (0.25, 0, 0.75)
- **AND** 输出 Alpha SHALL 为 0.25
#### Scenario: A white outer edge meets empty canvas
- **WHEN** 不透明白色源覆盖 8 个子样本,其余没有源覆盖
- **THEN** 输出 RGB SHALL 保持 (1, 1, 1),Alpha SHALL 为 0.5
- **AND** 无源区域的黑色 SHALL 不混入白色边缘
#### Scenario: Transparent layers meet along an oblique boundary
- **WHEN** 子样本合成结果 Alpha 均为零,但各自底层 RGB 不同
- **THEN** 输出 SHALL 保留这些有效 RGB 的覆盖平均
- **AND** Alpha SHALL 保持零
### Requirement: Restoring alpha preserves antialiased layer boundaries
Frame SHALL 将边界颜色过渡存入结果 RGB,使实际 Packed Image 经 Mask Add 后仍保留图层间的抗锯齿过渡。
#### Scenario: Mask Add reveals a tilted foreground over a background
- **WHEN** 倾斜图片与黑色或白色底图合成,经 Pack 后执行 Mask Add 恢复 Alpha
- **THEN** 边界 RGB SHALL 保留子像素覆盖混合的中间颜色
- **AND** Mask Add SHALL 不将边缘恢复为单点覆盖产生的两色跳变
### Requirement: Frame keeps interior detail and bounded output processing
Frame SHALL 对覆盖与层级稳定的内部像素保留现有中心双线性采样。结果 Canvas、输出尺寸限制和对象放置 SHALL 保持原约定;子样本处理 SHALL 按块执行并保持跨块结果一致。
#### Scenario: Pixel-aligned interior contains fine detail
- **WHEN** 原尺寸对齐的图片内部包含交替明暗像素,且该区域没有几何层级边界
- **THEN** 内部 RGB 与 Alpha SHALL 保持现有采样结果
#### Scenario: A boundary crosses processing chunks
- **WHEN** 相同斜边使用不同的行块尺寸执行 Frame
- **THEN** 输出 SHALL 在浮点误差范围内一致
- **AND** 边界 SHALL 不出现行块接缝
#### Scenario: Frame uses the maximum output resolution
- **WHEN** 输出达到配置的最大分辨率
- **THEN** 抗锯齿 SHALL 保持原输出尺寸
- **AND** 系统 SHALL 不为全部源分配完整 4 倍宽、4 倍高的输出副本

View File

@@ -0,0 +1,94 @@
## ADDED Requirements
### Requirement: Image Empty results enable alpha blending
AnyImage SHALL 为新建的 Reference Image Empty 及成功提交图片编辑结果的 Image Empty 设置 `use_empty_image_alpha = True`,并保留对象原有整体不透明度与深度设置。
#### Scenario: An alpha editing operation succeeds
- **WHEN** Mask、Frame、Rectify 或 Remove Background 成功替换 Image Empty 图片
- **THEN** 承载结果的 Empty SHALL 开启 Alpha Blending
- **AND** 对象 `color[3]` 与 `empty_image_depth` SHALL 保持原值
#### Scenario: A reference image is pasted
- **WHEN** AnyImage 新建剪贴板 Reference Image Empty
- **THEN** 对象 SHALL 默认开启 Alpha Blending
#### Scenario: Editing is cancelled or fails
- **WHEN** 用户取消手势或结果提交失败
- **THEN** 原 Image 和 Empty Alpha Blending 状态 SHALL 保持或恢复到操作前
### Requirement: Edited color images default to PREMUL
AnyImage SHALL 将本地图片编辑结果及公共图片编辑 Job 加载结果的最终 `Image.alpha_mode` 设置为 `PREMUL`。该默认值 SHALL 在成功交付后生效,SHALL NOT 依赖源图片原模式。
#### Scenario: Local alpha editing creates a packed result
- **WHEN** Mask、Frame 或 Rectify 从 STRAIGHT、CHANNEL_PACKED 或 PREMUL 源创建结果
- **THEN** 结果 Image SHALL 使用 PREMUL 并保留现有 Pack 规则
#### Scenario: A background removal result is loaded
- **WHEN** Remove Background 或共享图片编辑结果加载入口的 Upscale 返回 RGBA 图片
- **THEN** 加载结果 SHALL 使用 PREMUL
- **AND** 序列结果 SHALL 保留原有帧映射、播放范围及逐帧像素内容
### Requirement: Alpha presentation preserves editable pixel content
Alpha 呈现默认值 SHALL 保留既有业务编辑算法产出的 RGB 与 Alpha 数值,包括完全透明 RGB,并 SHALL 保证 Pack、保存重载和重复编辑后仍可读取与恢复这些内容。系统 SHALL NOT 为设置 PREMUL 而永久清除透明 RGB 或重复乘入 Alpha。
#### Scenario: Mask Add restores hidden color after reload
- **WHEN** 图片经过 Mask Subtract、结果 Pack、blend 保存重开,再执行 Mask Add
- **THEN** 恢复区域 SHALL 保留原隐藏 RGB,误差仅限既有编码精度
- **AND** 结果 SHALL 继续使用 PREMUL
#### Scenario: A PREMUL result is framed again
- **WHEN** PREMUL 结果以像素对齐映射再次执行 Frame
- **THEN** RGB 和 Alpha SHALL 符合 Frame 图层合成与边界覆盖采样规则
- **AND** 模式设置 SHALL 不导致额外 Alpha 相乘或颜色衰减
#### Scenario: Foreground alpha is restored over a white bottom image
- **WHEN** 当前 Frame 合成包含透明白色底图及 Alpha 渐变前景,随后恢复结果 Alpha
- **THEN** RGB SHALL 保留前景到白色的连续混合
- **AND** Alpha SHALL 沿用当前独立合成与编辑公式
#### Scenario: Packed pixels and exported PNG are inspected
- **WHEN** 检查 byte buffer 编辑结果、浮点源派生结果及加载的 PNG 结果
- **THEN** 操作前后、Pack 和导出重载后的业务 RGB/Alpha SHALL 在约定编码精度内一致
### Requirement: Mesh Color images use PREMUL independently of data textures
AnyImage 为 Plane、Depth Plane 及 Cutout 创建的材质 SHALL 将 Color Image 配置为 PREMUL,并保持独立 Color/Alpha 连线及当前材质透明策略。Depth 和 Normal Image SHALL 保留各自数据通道、Alpha 模式与颜色空间约定。
#### Scenario: A local mesh uses copied or cropped color
- **WHEN** Plane 使用源图片副本或 Cutout 使用裁剪 Color 图片构建材质
- **THEN** Color Image SHALL 为 PREMUL
- **AND** 构建过程 SHALL 保留既有 Color 像素及颜色空间策略
#### Scenario: AI geometry uses generated textures
- **WHEN** Depth Plane 或 Cutout 加载 AI Color、Depth 和 Normal 结果
- **THEN** Color Image SHALL 为 PREMUL
- **AND** Depth 与 Normal SHALL 保留原有数据解释方式
#### Scenario: Source images have other users
- **WHEN** 被编辑或转换的源 Image 同时被未参与的对象引用
- **THEN** 模式设置 SHALL 作用于结果 Image 或独立 Color 副本
- **AND** 未参与对象引用的源 Image 模式与像素 SHALL 保持不变
### Requirement: Defaults are applied at operation boundaries
AnyImage SHALL 在新建或成功交付范围内应用本策略,SHALL NOT 在注册、加载场景或普通重绘时批量修改已有图片。
#### Scenario: An existing scene is opened
- **WHEN** 用户打开含有已有 Image Empty 和材质的场景
- **THEN** 未参与 AnyImage 新操作的图片及对象设置 SHALL 保持原样