Compare commits

...
13 Commits
Author SHA1 Message Date
Dr.Lt.Data d29c41809f FIXED: ConcatConditioningsWithMultiplier - version compatibility patch
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/issues/160#issuecomment-2416008408
2024-10-16 21:33:53 +09:00
Dr.Lt.Data 667dead8c1 improved: IPAdapterModelHelper - support Kolors model 2024-10-16 00:24:58 +09:00
Dr.Lt.Data 08cdc7358b add opencv-python to requirements.txt 2024-10-13 17:25:11 +09:00
Dr.Lt.Data 81485bcf4c version marker 2024-10-13 17:22:06 +09:00
Dr.Lt.Data f6a8c65094 Merge pull request #173 from geroldmeisinger/main
support named colors via webcolors module
2024-10-13 17:21:10 +09:00
Gerold Meisinger 37bc51713f support named colors via webcolors module 2024-10-12 14:32:44 +02:00
Dr.Lt.Data 004a9534e4 Merge branch 'fix/backward_compatibility' 2024-10-02 01:58:16 +09:00
Dr.Lt.Data ca710caaab Merge pull request #170 from fAIseh00d/main
Add xinsir black pixel support to inpainting controlnet preprocessor
2024-10-02 01:58:07 +09:00
Dr.Lt.Data c657cf152a backward compatiblity patch 2024-10-02 01:56:15 +09:00
Ivan R 9678d685c2 Add xinsir black pixel support 2024-09-30 22:00:24 +05:00
Dr.Lt.Data 51cace6f1c better error message
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/issues/163#issuecomment-2367951331
2024-09-24 01:00:59 +09:00
Dr.Lt.Data c0d54d8a88 fix: KSampler Progress - 1st latent shape mismatch if flux/sd3
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/issues/161
2024-09-16 01:37:12 +09:00
Dr.Lt.Data 74b2856499 feat: LoadPromptFromFile/Dir - reload
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/issues/156
2024-09-08 12:03:51 +09:00
9 changed files with 120 additions and 30 deletions
+1 -1
View File
@@ -7,7 +7,7 @@
import importlib
version_code = [1, 1]
version_code = [1, 5, 1]
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
print(f"### Loading: ComfyUI-Inspire-Pack ({version_str})")
+15 -8
View File
@@ -8,19 +8,26 @@ from nodes import MAX_RESOLUTION
class ConcatConditioningsWithMultiplier:
@classmethod
def INPUT_TYPES(s):
flex_inputs = {}
stack = inspect.stack()
if stack[1].function == 'get_input_data':
if stack[1].function == 'get_input_info':
# bypass validation
for x in range(0, 100):
flex_inputs[f"multiplier{x}"] = ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01})
else:
flex_inputs["multiplier1"] = ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01})
class AllContainer:
def __contains__(self, item):
return True
def __getitem__(self, key):
# Return a default value appropriate for your use case
# Adjust the return value as needed
return "FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}
return {
"required": {"conditioning1": ("CONDITIONING",), },
"optional": AllContainer()
}
return {
"required": {"conditioning1": ("CONDITIONING",), },
"optional": flex_inputs
"optional": {"multiplier1": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), },
}
RETURN_TYPES = ("CONDITIONING",)
+8 -3
View File
@@ -19,6 +19,7 @@ model_preset = {
"SDXL ViT-H": ("ip-adapter_sdxl_vit-h", "CLIP-ViT-H-14-laion2B-s32B-b79K", None, False),
"SDXL Plus ViT-H": ("ip-adapter-plus_sdxl_vit-h", "CLIP-ViT-H-14-laion2B-s32B-b79K", None, False),
"SDXL Plus Face ViT-H": ("ip-adapter-plus-face_sdxl_vit-h", "CLIP-ViT-H-14-laion2B-s32B-b79K", None, False),
"Kolors Plus": ("Kolors-IP-Adapter-Plus", "clip-vit-large-patch14-336", None, False),
# faceid
"SD1.5 FaceID": ("ip-adapter-faceid_sd15", "CLIP-ViT-H-14-laion2B-s32B-b79K", "ip-adapter-faceid_sd15_lora", True),
@@ -29,6 +30,7 @@ model_preset = {
"SDXL FaceID": ("ip-adapter-faceid_sdxl", "CLIP-ViT-H-14-laion2B-s32B-b79K", "ip-adapter-faceid_sdxl_lora", True),
"SDXL FaceID Portrait": ("ip-adapter-faceid-portrait_sdxl", "CLIP-ViT-H-14-laion2B-s32B-b79K", None, True),
"SDXL FaceID Portrait unnorm": ("ip-adapter-faceid-portrait_sdxl_unnorm", "CLIP-ViT-H-14-laion2B-s32B-b79K", None, True),
"Kolors FaceID Plus": ("Kolors-IP-Adapter-FaceID-Plus", "clip-vit-large-patch14-336", None, True),
# composition
"SD1.5 Plus Composition": ("ip-adapter_sd15", "CLIP-ViT-H-14-laion2B-s32B-b79K", None, False),
@@ -56,7 +58,6 @@ class IPAdapterModelHelper:
return {
"required": {
"model": ("MODEL",),
"clip": ("CLIP",),
"preset": (list(model_preset.keys()),),
"lora_strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
"lora_strength_clip": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
@@ -64,6 +65,7 @@ class IPAdapterModelHelper:
"cache_mode": (["insightface only", "clip_vision only", "all", "none"], {"default": "insightface only"}),
},
"optional": {
"clip": ("CLIP",),
"insightface_model_name": (['buffalo_l', 'antelopev2'],),
},
"hidden": {"unique_id": "UNIQUE_ID"}
@@ -75,14 +77,17 @@ class IPAdapterModelHelper:
CATEGORY = "InspirePack/models"
def doit(self, model, clip, preset, lora_strength_model, lora_strength_clip, insightface_provider, cache_mode="none", unique_id=None, insightface_model_name='buffalo_l'):
def doit(self, model, preset, lora_strength_model, lora_strength_clip, insightface_provider, clip=None, cache_mode="none", unique_id=None, insightface_model_name='buffalo_l'):
if 'IPAdapter' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/cubiq/ComfyUI_IPAdapter_plus',
"To use 'IPAdapterModelHelper' node, 'ComfyUI IPAdapter Plus' extension is required.")
raise Exception(f"[ERROR] To use IPAdapterModelHelper, you need to install 'ComfyUI IPAdapter Plus'")
is_sdxl_preset = 'SDXL' in preset
is_sdxl_model = isinstance(clip.tokenizer, sdxl_clip.SDXLTokenizer)
if clip is not None:
is_sdxl_model = isinstance(clip.tokenizer, sdxl_clip.SDXLTokenizer)
else:
is_sdxl_model = False
if is_sdxl_preset != is_sdxl_model:
server.PromptServer.instance.send_sync("inspire-node-output-label", {"node_id": unique_id, "output_idx": 1, "label": "IPADAPTER (fail)"})
+66 -9
View File
@@ -12,6 +12,7 @@ import folder_paths
import comfy
import traceback
import random
import hashlib
from server import PromptServer
from .libs import utils, common
@@ -37,7 +38,7 @@ try:
with open(pb_yaml_path, 'r', encoding="utf-8") as f:
prompt_builder_preset = yaml.load(f, Loader=yaml.FullLoader)
except Exception as e:
print(f"[Inspire Pack] Failed to load 'prompt-builder.yaml'")
print(f"[Inspire Pack] Failed to load 'prompt-builder.yaml'\nNOTE: Only files with UTF-8 encoding are supported.")
class LoadPromptsFromDir:
@@ -49,7 +50,13 @@ class LoadPromptsFromDir:
except Exception:
prompt_dirs = []
return {"required": {"prompt_dir": (prompt_dirs,)}}
return {"required": {
"prompt_dir": (prompt_dirs,)
},
"optional": {
"reload": ("BOOLEAN", { "default": False, "label_on": "if file changed", "label_off": "if value changed"}),
}
}
RETURN_TYPES = ("ZIPPED_PROMPT",)
OUTPUT_IS_LIST = (True,)
@@ -59,7 +66,30 @@ class LoadPromptsFromDir:
CATEGORY = "InspirePack/Prompt"
@staticmethod
def doit(prompt_dir):
def IS_CHANGED(prompt_dir, reload=False):
if not reload:
return prompt_dir
else:
global prompts_path
prompt_dir = os.path.join(prompts_path, prompt_dir)
files = [f for f in os.listdir(prompt_dir) if f.endswith(".txt")]
md5 = hashlib.md5()
files.sort()
for file in files:
md5.update(file.encode('utf-8'))
with open(os.path.join(prompt_dir, file), 'rb') as f:
while True:
chunk = f.read(4096)
if not chunk:
break
md5.update(chunk)
return md5.hexdigest()
@staticmethod
def doit(prompt_dir, reload=False):
global prompts_path
prompt_dir = os.path.join(prompts_path, prompt_dir)
files = [f for f in os.listdir(prompt_dir) if f.endswith(".txt")]
@@ -85,7 +115,7 @@ class LoadPromptsFromDir:
else:
print(f"[WARN] LoadPromptsFromDir: invalid prompt format in '{file_name}'")
except Exception as e:
print(f"[ERROR] LoadPromptsFromDir: an error occurred while processing '{file_name}': {str(e)}")
print(f"[ERROR] LoadPromptsFromDir: an error occurred while processing '{file_name}': {str(e)}\nNOTE: Only files with UTF-8 encoding are supported.")
return (prompts, )
@@ -105,8 +135,14 @@ class LoadPromptsFromFile:
except Exception:
prompt_files = []
return {"required": {"prompt_file": (prompt_files,)},
"optional": {"text_data_opt": ("STRING", {"defaultInput": True})}}
return {"required": {
"prompt_file": (prompt_files,)
},
"optional": {
"text_data_opt": ("STRING", {"defaultInput": True}),
"reload": ("BOOLEAN", {"default": False, "label_on": "if file changed", "label_off": "if value changed"}),
}
}
RETURN_TYPES = ("ZIPPED_PROMPT",)
OUTPUT_IS_LIST = (True,)
@@ -116,7 +152,28 @@ class LoadPromptsFromFile:
CATEGORY = "InspirePack/Prompt"
@staticmethod
def doit(prompt_file, text_data_opt=None):
def IS_CHANGED(prompt_file, text_data_opt=None, reload=False):
md5 = hashlib.md5()
if text_data_opt is not None:
md5.update(text_data_opt)
return md5.hexdigest()
elif not reload:
return prompt_file
else:
prompt_path = os.path.join(prompts_path, prompt_file)
with open(prompt_path, 'rb') as f:
while True:
chunk = f.read(4096)
if not chunk:
break
md5.update(chunk)
return md5.hexdigest()
@staticmethod
def doit(prompt_file, text_data_opt=None, reload=False):
prompt_path = os.path.join(prompts_path, prompt_file)
prompts = []
@@ -142,7 +199,7 @@ class LoadPromptsFromFile:
else:
print(f"[WARN] LoadPromptsFromFile: invalid prompt format in '{prompt_file}'")
except Exception as e:
print(f"[ERROR] LoadPromptsFromFile: an error occurred while processing '{prompt_file}': {str(e)}")
print(f"[ERROR] LoadPromptsFromFile: an error occurred while processing '{prompt_file}': {str(e)}\nNOTE: Only files with UTF-8 encoding are supported.")
return (prompts, )
@@ -205,7 +262,7 @@ class LoadSinglePromptFromFile:
else:
print(f"[WARN] LoadSinglePromptFromFile: invalid prompt format in '{prompt_file}'")
except Exception as e:
print(f"[ERROR] LoadSinglePromptFromFile: an error occurred while processing '{prompt_file}': {str(e)}")
print(f"[ERROR] LoadSinglePromptFromFile: an error occurred while processing '{prompt_file}': {str(e)}\nNOTE: Only files with UTF-8 encoding are supported.")
return (prompts, )
+4 -2
View File
@@ -4,6 +4,7 @@ import comfy
import nodes
import torch
import re
import webcolors
from . import prompt_support
from .libs import utils, common
@@ -81,8 +82,9 @@ class RegionalPromptSimple:
def color_to_mask(color_mask, mask_color):
try:
if mask_color.startswith("#"):
selected = int(mask_color[1:], 16)
if mask_color.startswith("#") or mask_color.isalpha():
hex = mask_color[1:] if mask_color.startswith("#") else webcolors.name_to_hex(mask_color)[1:]
selected = int(hex, 16)
else:
selected = int(mask_color, 10)
except Exception:
+1 -1
View File
@@ -44,7 +44,7 @@ class KSampler_progress(a1111_compat.KSampler_inspire):
if omit_start_latent:
result = []
else:
result = [latent_image['samples']]
result = [comfy.sample.fix_empty_latent_channels(model, latent_image['samples']).cpu()]
def progress_callback(step, x0, x, total_steps):
if (total_steps-1) != step and step % interval != 0:
+21 -4
View File
@@ -110,6 +110,9 @@ class Color_Preprocessor_wrapper:
class InpaintPreprocessor_wrapper:
def __init__(self, black_pixel_for_xinsir_cn):
self.black_pixel_for_xinsir_cn = black_pixel_for_xinsir_cn
def apply(self, image, mask=None):
if 'InpaintPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
@@ -120,7 +123,16 @@ class InpaintPreprocessor_wrapper:
if mask is None:
mask = torch.ones((image.shape[1], image.shape[2]), dtype=torch.float32, device="cpu").unsqueeze(0)
return obj.preprocess(image, mask)[0]
try:
res = obj.preprocess(image, mask, black_pixel_for_xinsir_cn=self.black_pixel_for_xinsir_cn)[0]
except Exception as e:
if self.black_pixel_for_xinsir_cn:
raise e
else:
res = obj.preprocess(image, mask)[0]
print(f"[Inspire Pack] Installed 'ComfyUI's ControlNet Auxiliary Preprocessors.' is outdated.")
return res
class TilePreprocessor_wrapper:
@@ -547,14 +559,19 @@ class Color_Preprocessor_Provider_for_SEGS:
class InpaintPreprocessor_Provider_for_SEGS:
@classmethod
def INPUT_TYPES(s):
return {"required": {}}
return {
"required": {},
"optional": {
"black_pixel_for_xinsir_cn": ("BOOLEAN", {"default": False, "label_on": "enable", "label_off": "disable"}),
}
}
RETURN_TYPES = ("SEGS_PREPROCESSOR",)
FUNCTION = "doit"
CATEGORY = "InspirePack/SEGS/ControlNet"
def doit(self):
obj = InpaintPreprocessor_wrapper()
def doit(self, black_pixel_for_xinsir_cn=False):
obj = InpaintPreprocessor_wrapper(black_pixel_for_xinsir_cn)
return (obj, )
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-inspire-pack"
description = "This extension provides various nodes to support Lora Block Weight and the Impact Pack. Provides many easily applicable regional features and applications for Variation Seed."
version = "1.1"
version = "1.5.1"
license = { file = "LICENSE" }
dependencies = ["matplotlib", "cachetools"]
+3 -1
View File
@@ -1,3 +1,5 @@
matplotlib
cachetools
numpy<2
numpy<2
webcolors
opencv-python