Compare commits

..
6 Commits
Author SHA1 Message Date
Dr.Lt.Data 38bb9ffdf6 fixed: Switch - buggy behavior on firefox browser
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/983#issuecomment-2833471721
2025-04-28 00:54:31 +09:00
Dr.Lt.Data f939e66e1c fixed: this.widgets is undefined
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/977
2025-04-27 22:16:11 +09:00
robo b22aa90cf4 allow for .yml files in wildcards (#966)
both are valid yaml extensions so it makes sense to allow both
2025-04-25 18:50:40 +09:00
Dr.Lt.Data d18aaecb93 bump version 2025-04-25 18:46:18 +09:00
だにえる a7840b4fbf feat: tensor_paste supports RGBA images with alpha channel blending (#962)
This enhancement adds support for properly handling RGBA images in the tensor_paste function.

The previous implementation caused errors when pasting images with alpha channels.
Now the function can handle all combinations of RGB and RGBA images:
- RGB to RGB (unchanged)
- RGBA to RGBA (with proper alpha compositing)
- RGB to RGBA
- RGBA to RGB

Fix for the error: "RuntimeError: The size of tensor a (4) must match the size of tensor b (3) at non-singleton dimension 3"
2025-04-25 18:35:03 +09:00
robo efa0cb66b2 always use impact.wildcards.process fixes server side wildcards.process not getting new wildcard_dict (#967) 2025-04-25 18:21:55 +09:00
6 changed files with 63 additions and 22 deletions
+5 -3
View File
@@ -508,7 +508,7 @@ app.registerExtension({
const onConnectionsChange = nodeType.prototype.onConnectionsChange;
nodeType.prototype.onConnectionsChange = function (type, index, connected, link_info) {
const stackTrace = new Error().stack;
if(stackTrace.includes('LGraph.configure')) {
if(stackTrace.includes('loadGraphData')) {
if(this.widgets) {
this.widgets[0].options.max = this.inputs.length-3;
this.widgets[0].value = Math.min(this.widgets[0].value, this.widgets[0].options.max);
@@ -606,8 +606,10 @@ app.registerExtension({
this.addInput(`${input_name}${slot_i}`, this.outputs[0].type);
}
this.widgets[0].options.max = this.inputs.length-3;
this.widgets[0].value = Math.min(this.widgets[0].value, this.widgets[0].options.max);
if(this.widgets) {
this.widgets[0].options.max = this.inputs.length-3;
this.widgets[0].value = Math.min(this.widgets[0].value, this.widgets[0].options.max);
}
}
}
},
+1 -1
View File
@@ -1,7 +1,7 @@
import configparser
import os
version_code = [8, 13, 1]
version_code = [8, 14, 2]
version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
dependency_version = 24
+2 -3
View File
@@ -17,7 +17,6 @@ import numpy as np
import nodes
from PIL import Image
import io
import impact.wildcards as wildcards
import comfy
from io import BytesIO
import random
@@ -183,7 +182,7 @@ async def wildcards_list(request):
@PromptServer.instance.routes.post("/impact/wildcards")
async def populate_wildcards(request):
data = await request.json()
populated = wildcards.process(data['text'], data.get('seed', None))
populated = impact.wildcards.process(data['text'], data.get('seed', None))
return web.json_response({"text": populated})
@@ -512,7 +511,7 @@ def onprompt_populate_wildcards(json_data):
else:
input_seed = int(inputs['seed'])
inputs['populated_text'] = wildcards.process(inputs['wildcard_text'], input_seed)
inputs['populated_text'] = impact.wildcards.process(inputs['wildcard_text'], input_seed)
inputs['mode'] = 'reproduce'
PromptServer.instance.send_sync("impact-node-feedback", {"node_id": k, "widget_name": "populated_text", "type": "STRING", "value": inputs['populated_text']})
+53 -13
View File
@@ -178,31 +178,71 @@ def tensor2numpy(image):
def tensor_paste(image1, image2, left_top, mask):
"""Mask and image2 has to be the same size"""
"""
Pastes image2 onto image1 at position left_top using mask.
Supports both RGB and RGBA images.
"""
_tensor_check_image(image1)
_tensor_check_image(image2)
_tensor_check_mask(mask)
if image2.shape[1:3] != mask.shape[1:3]:
mask = resize_mask(mask.squeeze(dim=3), image2.shape[1:3]).unsqueeze(dim=3)
# raise ValueError(f"Inconsistent size: Image ({image2.shape[1:3]}) != Mask ({mask.shape[1:3]})")
x, y = left_top
_, h1, w1, _ = image1.shape
_, h2, w2, _ = image2.shape
# calculate image patch size
_, h1, w1, c1 = image1.shape
_, h2, w2, c2 = image2.shape
# Calculate image patch size
w = min(w1, x + w2) - x
h = min(h1, y + h2) - y
# If the patch is out of bound, nothing to do!
if w <= 0 or h <= 0:
return
mask = mask[:, :h, :w, :]
image1[:, y:y+h, x:x+w, :] = (
(1 - mask) * image1[:, y:y+h, x:x+w, :] +
mask * image2[:, :h, :w, :]
)
# Get the region to be modified
region1 = image1[:, y:y+h, x:x+w, :]
region2 = image2[:, :h, :w, :]
# Handle RGB and RGBA cases
if c1 == 3 and c2 == 3:
# Both RGB - simple case
image1[:, y:y+h, x:x+w, :] = (1 - mask) * region1 + mask * region2
elif c1 == 4 and c2 == 4:
# Both RGBA - need to handle alpha channel separately
# RGB channels
image1[:, y:y+h, x:x+w, :3] = (
(1 - mask) * region1[:, :, :, :3] +
mask * region2[:, :, :, :3]
)
# Alpha channel - use "over" composition
a1 = region1[:, :, :, 3:4]
a2 = region2[:, :, :, 3:4] * mask
new_alpha = a1 + a2 * (1 - a1)
image1[:, y:y+h, x:x+w, 3:4] = new_alpha
elif c1 == 4 and c2 == 3:
# Target is RGBA, source is RGB - assume source is fully opaque
image1[:, y:y+h, x:x+w, :3] = (
(1 - mask) * region1[:, :, :, :3] +
mask * region2
)
# Alpha channel - reduce alpha where mask is applied
image1[:, y:y+h, x:x+w, 3:4] = region1[:, :, :, 3:4] * (1 - mask) + mask
elif c1 == 3 and c2 == 4:
# Target is RGB, source is RGBA - apply source alpha to mask
effective_mask = mask * region2[:, :, :, 3:4]
image1[:, y:y+h, x:x+w, :] = (
(1 - effective_mask) * region1 +
effective_mask * region2[:, :, :, :3]
)
return
+1 -1
View File
@@ -65,7 +65,7 @@ def read_wildcard_dict(wildcard_path):
with open(file_path, 'r', encoding="UTF-8", errors="ignore") as f:
lines = f.read().splitlines()
wildcard_dict[key] = [x for x in lines if not x.strip().startswith('#')]
elif file.endswith('.yaml'):
elif file.endswith('.yaml') or file.endswith('.yml'):
file_path = os.path.join(root, file)
try:
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-impact-pack"
description = "This node pack offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler."
version = "8.13.1"
version = "8.14.2"
license = { file = "LICENSE.txt" }
dependencies = ["segment-anything", "scikit-image", "piexif", "transformers", "opencv-python-headless", "GitPython", "scipy>=1.11.4"]