Fix manual region reset and allow no-mask pass-through
This commit is contained in:
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.6.0] - 2026-03-04
|
||||
|
||||
### Fixed
|
||||
- **保留手动调整的参考区**:图像重新加载、关闭编辑器窗口后,优先恢复 `region_coords` 中保存的手动选区,不再重置回 padding 计算值
|
||||
- **padding 变化时同步 widget**:调整 padding 后同步更新 `region_coords`,保证前端显示与后端输出一致
|
||||
|
||||
### Changed
|
||||
- **允许无蒙版运行**:没有 Alpha 通道或蒙版为空时不再报错,输出空蒙版并把参考区设为整张图像,使节点可作为纯图像输入使用
|
||||
|
||||
## [1.5.0] - 2026-03-04
|
||||
|
||||
### Added
|
||||
|
||||
@@ -75,13 +75,8 @@ class InpaintRegionEditor:
|
||||
mask = np.array(img.getchannel("A")).astype(np.float32) / 255.0
|
||||
mask = 1.0 - mask # ComfyUI 约定:1=遮罩区域
|
||||
else:
|
||||
raise ValueError(
|
||||
"Please create a mask first (inpainting requires a mask)\n"
|
||||
"You can create one by:\n"
|
||||
"1. Upload a PNG with Alpha channel\n"
|
||||
"2. Edit in Photopea and save\n"
|
||||
"3. Use ComfyUI's built-in mask editor"
|
||||
)
|
||||
# 没有 Alpha 通道时允许作为纯图像输入,输出空蒙版
|
||||
mask = np.zeros((img_height, img_width), dtype=np.float32)
|
||||
|
||||
# 计算蒙版边界框
|
||||
mask_bounds = self._calculate_mask_bounds(mask)
|
||||
@@ -94,11 +89,20 @@ class InpaintRegionEditor:
|
||||
except:
|
||||
pass
|
||||
|
||||
if not region_rect:
|
||||
# 没有有效蒙版时直接返回全图作为参考区,不再强制要求绘制蒙版
|
||||
has_mask = mask_bounds["width"] > 0 and mask_bounds["height"] > 0
|
||||
if not has_mask:
|
||||
region_rect = {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": img_width,
|
||||
"height": img_height,
|
||||
}
|
||||
elif not region_rect:
|
||||
region_rect = self._calculate_region_rect(mask_bounds, padding)
|
||||
|
||||
# 验证
|
||||
if (
|
||||
# 只有在有蒙版时才验证选区必须包含蒙版
|
||||
if has_mask and (
|
||||
region_rect["width"] < mask_bounds["width"]
|
||||
or region_rect["height"] < mask_bounds["height"]
|
||||
):
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui-inpaint-region-editor"
|
||||
description = "A ComfyUI custom node for inpainting workflows with integrated Photopea editing and adjustable region selection."
|
||||
version = "1.5.1"
|
||||
version = "1.6.0"
|
||||
license = { file = "LICENSE" }
|
||||
dependencies = []
|
||||
|
||||
|
||||
+42
-4
@@ -665,6 +665,14 @@ function closePhotopeaMaskModal() {
|
||||
|
||||
const nodeImageData = new Map(); // 存储每个节点的图像和选区数据
|
||||
|
||||
// 检查选区是否包含蒙版边界框
|
||||
function regionContainsMask(region, mask) {
|
||||
return region.x <= mask.x &&
|
||||
region.y <= mask.y &&
|
||||
region.x + region.width >= mask.x + mask.width &&
|
||||
region.y + region.height >= mask.y + mask.height;
|
||||
}
|
||||
|
||||
// 约束选区:框住蒙版且不超出图像边界
|
||||
function constrainRegion(data, padding) {
|
||||
if (!data.hasMask || !data.maskBounds) return;
|
||||
@@ -773,11 +781,31 @@ async function loadImageAndDetectMask(node, imageName) {
|
||||
|
||||
if (hasMask && minX <= maxX && minY <= maxY) {
|
||||
data.maskBounds = { x: minX, y: minY, width: maxX - minX + 1, height: maxY - minY + 1 };
|
||||
// 使用统一的约束函数计算选区
|
||||
constrainRegion(data, padding);
|
||||
|
||||
// 同步到 region_coords widget
|
||||
|
||||
// 优先恢复用户手动调整过的选区(如果仍然包含当前蒙版)
|
||||
// 避免图像重新加载、关闭编辑器窗口等操作把手动调整重置回 padding 计算值
|
||||
const coordsWidget = node.widgets?.find(w => w.name === "region_coords");
|
||||
let restored = false;
|
||||
if (coordsWidget && coordsWidget.value && coordsWidget.value !== "{}") {
|
||||
try {
|
||||
const saved = JSON.parse(coordsWidget.value);
|
||||
if (saved && saved.width > 0 && saved.height > 0 &&
|
||||
regionContainsMask(saved, data.maskBounds)) {
|
||||
data.regionX = saved.x;
|
||||
data.regionY = saved.y;
|
||||
data.regionWidth = saved.width;
|
||||
data.regionHeight = saved.height;
|
||||
restored = true;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
if (!restored) {
|
||||
// 使用统一的约束函数计算选区
|
||||
constrainRegion(data, padding);
|
||||
}
|
||||
|
||||
// 同步到 region_coords widget
|
||||
if (coordsWidget) {
|
||||
coordsWidget.value = JSON.stringify({
|
||||
x: Math.round(data.regionX),
|
||||
@@ -1339,6 +1367,16 @@ app.registerExtension({
|
||||
if (data && data.hasMask && data.maskBounds) {
|
||||
// 使用统一的约束函数重新计算选区
|
||||
constrainRegion(data, v);
|
||||
// 同步到 region_coords widget,保证显示与后端使用一致
|
||||
const coordsWidget = node.widgets?.find(w => w.name === "region_coords");
|
||||
if (coordsWidget) {
|
||||
coordsWidget.value = JSON.stringify({
|
||||
x: Math.round(data.regionX),
|
||||
y: Math.round(data.regionY),
|
||||
width: Math.round(data.regionWidth),
|
||||
height: Math.round(data.regionHeight)
|
||||
});
|
||||
}
|
||||
}
|
||||
node.setDirtyCanvas(true);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user