Introduce DynamicImageCombiner class and update init.py for node integration.
This commit adds the DynamicImageCombiner class, enabling dynamic addition of multiple image inputs and outputting a list of connected images. The init.py file now includes this new node in NODE_CLASS_MAPPINGS and NODE_DISPLAY_NAME_MAPPINGS. A new JavaScript file has also been created to manage the node's behavior, enhancing image processing functionality. 引入DynamicImageCombiner类并更新__init__.py以实现节点集成。 此提交添加了DynamicImageCombiner类,可以动态地添加多个图像输入,并输出所有连接图像的列表。init.py文件现在在NODE_CLASS_MAPPINGS和NODE_DISPLAY_NAME_MAPPINGS中包含了这个新节点。此外,还创建了一个新的JavaScript文件来管理该节点的行为,增强了图像处理功能。
This commit is contained in:
+4
-1
@@ -19,6 +19,7 @@ try:
|
||||
from .text_combiner import TextCombiner
|
||||
from .multiline_text_input import MultilineTextInput
|
||||
from .click_popup import ClickPopup
|
||||
from .dynamic_image_input import DynamicImageCombiner
|
||||
|
||||
|
||||
# 节点映射
|
||||
@@ -29,6 +30,7 @@ try:
|
||||
"TextCombiner": TextCombiner,
|
||||
"MultilineTextInput": MultilineTextInput,
|
||||
"ClickPopup": ClickPopup,
|
||||
"DynamicImageCombiner": DynamicImageCombiner,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
@@ -37,7 +39,8 @@ try:
|
||||
"RemoveEmptyLinesAndLeadingSpaces": "Remove Empty Lines And Leading Spaces",
|
||||
"TextCombiner": "Text Combiner",
|
||||
"MultilineTextInput": "Multiline Text Input",
|
||||
"ClickPopup": "Click Popup"
|
||||
"ClickPopup": "Click Popup",
|
||||
"DynamicImageCombiner": "Dynamic Image Combiner"
|
||||
}
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+50
-42
@@ -1,45 +1,53 @@
|
||||
class DynamicImageInputs:
|
||||
"""动态图片输入节点
|
||||
|
||||
这个节点允许动态添加多个图片输入端口,并将所有输入的图片合并成一个列表输出。
|
||||
|
||||
特点:
|
||||
1. 支持动态增减图片输入端口
|
||||
2. 自动忽略未连接的输入端口
|
||||
3. 输出一个包含所有输入图片的列表
|
||||
|
||||
使用方法:
|
||||
1. 将节点添加到工作流中
|
||||
2. 连接图片到输入端口
|
||||
3. 使用 get_input 方法动态增加更多输入端口
|
||||
"""
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
# Filename: dynamic_image_input.py
|
||||
# Developer: jammyfu
|
||||
# Category: 🎨Painting👓Coder/🖼️Image
|
||||
|
||||
import torch
|
||||
|
||||
class DynamicImageCombiner:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
"""定义节点的输入类型
|
||||
|
||||
Returns:
|
||||
dict: 包含默认的单个图片输入端口
|
||||
"""
|
||||
return {"required": {"image_1": ("IMAGE",)}}
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {}, # 不需要默认输入
|
||||
"optional": {}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("images",)
|
||||
OUTPUT_IS_LIST = (True,) # 标记输出为列表
|
||||
FUNCTION = "combine_images"
|
||||
CATEGORY = "🎨Painting👓Coder/🖼️Image"
|
||||
|
||||
RETURN_TYPES = ("IMAGE",) # 返回图片类型
|
||||
RETURN_NAMES = ("images",) # 输出端口名称
|
||||
OUTPUT_IS_LIST = (True,) # 标记输出为列表类型
|
||||
FUNCTION = "process_images" # 处理函数名称
|
||||
CATEGORY = "🎨Painting👓Coder/🖼️Image" # 节点分类
|
||||
def combine_images(self, **image_inputs):
|
||||
try:
|
||||
# 收集所有非空图像
|
||||
images = []
|
||||
for i in range(1, len(image_inputs) + 1):
|
||||
key = f"image_{i}"
|
||||
if key in image_inputs and image_inputs[key] is not None:
|
||||
if isinstance(image_inputs[key], torch.Tensor):
|
||||
images.append(image_inputs[key])
|
||||
|
||||
def process_images(self, **kwargs):
|
||||
"""处理所有输入的图片
|
||||
|
||||
Args:
|
||||
**kwargs: 包含所有输入图片的字典,键名格式为 "image_1", "image_2" 等
|
||||
|
||||
Returns:
|
||||
tuple: 包含所有输入图片的列表
|
||||
"""
|
||||
images = []
|
||||
for k, v in kwargs.items():
|
||||
if k.startswith("image_") and v is not None:
|
||||
images.append(v)
|
||||
return (images,)
|
||||
# 如果没有图像,返回一个包含空白图像的列表
|
||||
if not images:
|
||||
empty_image = torch.zeros((1, 512, 512, 3))
|
||||
return ([empty_image],)
|
||||
|
||||
# 直接返回图像列表
|
||||
return (images,)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error in DynamicImageCombiner: {str(e)}")
|
||||
# 发生错误时返回包含空白图像的列表
|
||||
empty_image = torch.zeros((1, 512, 512, 3))
|
||||
return ([empty_image],)
|
||||
|
||||
# 添加到 ComfyUI 节点注册
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"DynamicImageCombiner": DynamicImageCombiner,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"DynamicImageCombiner": "Dynamic Image Input 🖼️",
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { app } from "/scripts/app.js";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Comfy.PaintingCoder.DynamicImageCombiner",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (nodeData.name === "DynamicImageCombiner") {
|
||||
// 重写 onNodeCreated
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
||||
nodeType.prototype.onNodeCreated = function() {
|
||||
const result = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined;
|
||||
|
||||
// 初始化状态
|
||||
this.lastConnectedCount = 0;
|
||||
|
||||
// 添加第一个输入点
|
||||
console.log("初始化:添加第一个图像输入点");
|
||||
this.addInput("image_1", "IMAGE");
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// 添加连接监听
|
||||
nodeType.prototype.onConnectionsChange = function(connectionType, slot, isConnected) {
|
||||
if (connectionType === 1) { // 输入连接
|
||||
console.log(`连接变化 - 槽位: ${slot}, 已连接: ${isConnected}`);
|
||||
|
||||
// 计算已连接的输入点数量
|
||||
const connectedCount = this.inputs.reduce((count, input) =>
|
||||
count + (input.link ? 1 : 0), 0);
|
||||
|
||||
console.log(`当前连接数量: ${connectedCount}, 上次连接数量: ${this.lastConnectedCount}`);
|
||||
|
||||
// 只在连接数量发生变化时更新
|
||||
if (connectedCount !== this.lastConnectedCount) {
|
||||
this.lastConnectedCount = connectedCount;
|
||||
const targetCount = connectedCount + 1;
|
||||
console.log(`目标输入点数量: ${targetCount}`);
|
||||
|
||||
// 添加新的输入点
|
||||
while (this.inputs.length < targetCount) {
|
||||
const newIndex = this.inputs.length + 1;
|
||||
console.log(`添加新输入点: image_${newIndex}`);
|
||||
this.addInput(`image_${newIndex}`, "IMAGE");
|
||||
}
|
||||
|
||||
// 移除多余的输入点,但至少保留一个
|
||||
while (this.inputs.length > Math.max(targetCount, 1)) {
|
||||
const lastInput = this.inputs[this.inputs.length - 1];
|
||||
if (!lastInput.link) {
|
||||
console.log(`移除输入点: ${this.inputs.length}`);
|
||||
this.removeInput(this.inputs.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新节点大小
|
||||
console.log(`更新节点大小,当前输入点数量: ${this.inputs.length}`);
|
||||
this.setSize(this.computeSize());
|
||||
app.graph.setDirtyCanvas(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user