Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Includes 30 custom nodes committed directly, 7 Civitai-exclusive loras stored via Git LFS, and a setup script that installs all dependencies and downloads HuggingFace-hosted models on vast.ai. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3544 lines
143 KiB
Python
3544 lines
143 KiB
Python
"""
|
|
@author: JPS
|
|
@title: JPS Custom Nodes for ComfyUI
|
|
@nickname: JPS Custom Nodes
|
|
@description: Various nodes to handle SDXL Resolutions, SDXL Basic Settings, IP Adapter Settings, Revision Settings, SDXL Prompt Styler, Crop Image to Square, Crop Image to Target Size, Get Date-Time String, Resolution Multiply, Largest Integer, 5-to-1 Switches for Integer, Images, Latents, Conditioning, Model, VAE, ControlNet
|
|
"""
|
|
|
|
#------------------------------------------------------------------------#
|
|
# JPS Custom Nodes https://github.com/JPS-GER/ComfyUI_JPS-Nodes #
|
|
# for ComfyUI https://github.com/comfyanonymous/ComfyUI #
|
|
#------------------------------------------------------------------------#
|
|
|
|
import torch
|
|
import json
|
|
import os
|
|
import comfy.sd
|
|
import folder_paths
|
|
from datetime import datetime
|
|
from PIL import Image, ImageOps, ImageSequence
|
|
import numpy as np
|
|
from PIL.PngImagePlugin import PngInfo
|
|
from comfy.cli_args import args
|
|
import torch.nn.functional as F
|
|
|
|
def min_(tensor_list):
|
|
# return the element-wise min of the tensor list.
|
|
x = torch.stack(tensor_list)
|
|
mn = x.min(axis=0)[0]
|
|
return torch.clamp(mn, min=0)
|
|
|
|
def max_(tensor_list):
|
|
# return the element-wise max of the tensor list.
|
|
x = torch.stack(tensor_list)
|
|
mx = x.max(axis=0)[0]
|
|
return torch.clamp(mx, max=1)
|
|
|
|
# From https://github.com/Jamy-L/Pytorch-Contrast-Adaptive-Sharpening/
|
|
def contrast_adaptive_sharpening(image, amount):
|
|
img = F.pad(image, pad=(1, 1, 1, 1)).cpu()
|
|
|
|
a = img[..., :-2, :-2]
|
|
b = img[..., :-2, 1:-1]
|
|
c = img[..., :-2, 2:]
|
|
d = img[..., 1:-1, :-2]
|
|
e = img[..., 1:-1, 1:-1]
|
|
f = img[..., 1:-1, 2:]
|
|
g = img[..., 2:, :-2]
|
|
h = img[..., 2:, 1:-1]
|
|
i = img[..., 2:, 2:]
|
|
|
|
# Computing contrast
|
|
cross = (b, d, e, f, h)
|
|
mn = min_(cross)
|
|
mx = max_(cross)
|
|
|
|
diag = (a, c, g, i)
|
|
mn2 = min_(diag)
|
|
mx2 = max_(diag)
|
|
mx = mx + mx2
|
|
mn = mn + mn2
|
|
|
|
# Computing local weight
|
|
inv_mx = torch.reciprocal(mx)
|
|
amp = inv_mx * torch.minimum(mn, (2 - mx))
|
|
|
|
# scaling
|
|
amp = torch.sqrt(amp)
|
|
w = - amp * (amount * (1/5 - 1/8) + 1/8)
|
|
div = torch.reciprocal(1 + 4*w)
|
|
|
|
output = ((b + d + f + h)*w + e) * div
|
|
output = output.clamp(0, 1)
|
|
output = torch.nan_to_num(output)
|
|
|
|
return (output)
|
|
|
|
def read_json_file(file_path):
|
|
"""
|
|
Reads a JSON file's content and returns it.
|
|
Ensures content matches the expected format.
|
|
"""
|
|
if not os.access(file_path, os.R_OK):
|
|
print(f"Warning: No read permissions for file {file_path}")
|
|
return None
|
|
|
|
try:
|
|
with open(file_path, 'r', encoding='utf-8') as file:
|
|
content = json.load(file)
|
|
# Check if the content matches the expected format.
|
|
if not all(['name' in item and 'prompt' in item and 'negative_prompt' in item for item in content]):
|
|
print(f"Warning: Invalid content in file {file_path}")
|
|
return None
|
|
return content
|
|
except Exception as e:
|
|
print(f"An error occurred while reading {file_path}: {str(e)}")
|
|
return None
|
|
|
|
def read_sdxl_styles(json_data):
|
|
"""
|
|
Returns style names from the provided JSON data.
|
|
"""
|
|
if not isinstance(json_data, list):
|
|
print("Error: input data must be a list")
|
|
return []
|
|
|
|
return [item['name'] for item in json_data if isinstance(item, dict) and 'name' in item]
|
|
|
|
def get_all_json_files(directory):
|
|
"""
|
|
Returns all JSON files from the specified directory.
|
|
"""
|
|
return [os.path.join(directory, file) for file in os.listdir(directory) if file.endswith('.json') and os.path.isfile(os.path.join(directory, file))]
|
|
|
|
def load_styles_from_directory(directory):
|
|
"""
|
|
Loads styles from all JSON files in the directory.
|
|
Renames duplicate style names by appending a suffix.
|
|
"""
|
|
json_files = get_all_json_files(directory)
|
|
combined_data = []
|
|
seen = set()
|
|
|
|
for json_file in json_files:
|
|
json_data = read_json_file(json_file)
|
|
if json_data:
|
|
for item in json_data:
|
|
original_style = item['name']
|
|
style = original_style
|
|
suffix = 1
|
|
while style in seen:
|
|
style = f"{original_style}_{suffix}"
|
|
suffix += 1
|
|
item['name'] = style
|
|
seen.add(style)
|
|
combined_data.append(item)
|
|
|
|
unique_style_names = [item['name'] for item in combined_data if isinstance(item, dict) and 'name' in item]
|
|
|
|
return combined_data, unique_style_names
|
|
|
|
def validate_json_data(json_data):
|
|
"""
|
|
Validates the structure of the JSON data.
|
|
"""
|
|
if not isinstance(json_data, list):
|
|
return False
|
|
for template in json_data:
|
|
if 'name' not in template or 'prompt' not in template:
|
|
return False
|
|
return True
|
|
|
|
def find_template_by_name(json_data, template_name):
|
|
"""
|
|
Returns a template from the JSON data by name or None if not found.
|
|
"""
|
|
for template in json_data:
|
|
if template['name'] == template_name:
|
|
return template
|
|
return None
|
|
|
|
def split_template(template: str) -> tuple:
|
|
"""
|
|
Splits a template into two parts based on a specific pattern.
|
|
"""
|
|
if "{prompt} ." in template:
|
|
template_prompt_g, template_prompt_l = template.split("{prompt} .", 1)
|
|
template_prompt_g = template_prompt_g.strip() + " {prompt}"
|
|
template_prompt_l = template_prompt_l.strip()
|
|
else:
|
|
template_prompt_g = template
|
|
template_prompt_l = ""
|
|
|
|
return template_prompt_g, template_prompt_l
|
|
|
|
def replace_prompts_in_template(template, positive_prompt_g, positive_prompt_l, negative_prompt):
|
|
"""
|
|
Replace the placeholders in a given template with the provided prompts and split them accordingly.
|
|
|
|
Args:
|
|
- template (dict): The template containing prompt placeholders.
|
|
- positive_prompt_g (str): The main positive prompt to replace '{prompt}' in the template.
|
|
- positive_prompt_l (str): The auxiliary positive prompt to be combined in a specific manner.
|
|
- negative_prompt (str): The negative prompt to be combined with any existing negative prompt in the template.
|
|
|
|
Returns:
|
|
- tuple: A tuple containing the replaced main positive, auxiliary positive, combined positive and negative prompts.
|
|
"""
|
|
template_prompt_g, template_prompt_l_template = split_template(template['prompt'])
|
|
|
|
text_g_positive = template_prompt_g.replace("{prompt}", positive_prompt_g)
|
|
|
|
text_l_positive = f"{template_prompt_l_template}, {positive_prompt_l}" if template_prompt_l_template and positive_prompt_l else template_prompt_l_template or positive_prompt_l
|
|
|
|
json_negative_prompt = template.get('negative_prompt', "")
|
|
text_negative = f"{json_negative_prompt}, {negative_prompt}" if json_negative_prompt and negative_prompt else json_negative_prompt or negative_prompt
|
|
|
|
return text_g_positive, text_l_positive, text_negative
|
|
|
|
|
|
def read_sdxl_templates_replace_and_combine(json_data, template_name, positive_prompt_g, positive_prompt_l, negative_prompt):
|
|
"""
|
|
Find a specific template by its name, then replace and combine its placeholders with the provided prompts in an advanced manner.
|
|
|
|
Args:
|
|
- json_data (list): The list of templates.
|
|
- template_name (str): The name of the desired template.
|
|
- positive_prompt_g (str): The main positive prompt.
|
|
- positive_prompt_l (str): The auxiliary positive prompt.
|
|
- negative_prompt (str): The negative prompt to be combined.
|
|
|
|
Returns:
|
|
- tuple: A tuple containing the replaced and combined main positive, auxiliary positive, combined positive and negative prompts.
|
|
"""
|
|
if not validate_json_data(json_data):
|
|
return positive_prompt_g, positive_prompt_l, negative_prompt
|
|
|
|
template = find_template_by_name(json_data, template_name)
|
|
|
|
if template:
|
|
return replace_prompts_in_template(template, positive_prompt_g, positive_prompt_l, negative_prompt)
|
|
else:
|
|
return positive_prompt_g, positive_prompt_l, negative_prompt
|
|
|
|
accepted_ratios_horizontal = {
|
|
"12:5": (1536, 640, 2.400000000),
|
|
"7:4": (1344, 768, 1.750000000),
|
|
"19:13": (1216, 832, 1.461538462),
|
|
"9:7": (1152, 896, 1.285714286)
|
|
}
|
|
|
|
# Vertical aspect ratio
|
|
accepted_ratios_vertical = {
|
|
"7:9": (896, 1152, 0.777777778),
|
|
"13:19": (832, 1216, 0.684210526),
|
|
"4:7": (768, 1344, 0.571428571),
|
|
"5:12": (640, 1536, 0.416666667)
|
|
}
|
|
|
|
# Square aspect ratio
|
|
accepted_ratios_square = {
|
|
"1:1": (1024, 1024, 1.00000000)
|
|
}
|
|
|
|
|
|
class SDXL_Resolutions:
|
|
resolution = ["square - 1024x1024 (1:1)","landscape - 1152x896 (4:3)","landscape - 1216x832 (3:2)","landscape - 1344x768 (16:9)","landscape - 1536x640 (21:9)", "portrait - 896x1152 (3:4)","portrait - 832x1216 (2:3)","portrait - 768x1344 (9:16)","portrait - 640x1536 (9:21)"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"resolution": (s.resolution,),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("INT","INT",)
|
|
RETURN_NAMES = ("width", "height")
|
|
FUNCTION = "get_resolutions"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_resolutions(self,resolution):
|
|
width = 1024
|
|
height = 1024
|
|
width = int(width)
|
|
height = int(height)
|
|
if(resolution == "square - 1024x1024 (1:1)"):
|
|
width = 1024
|
|
height = 1024
|
|
if(resolution == "landscape - 1152x896 (4:3)"):
|
|
width = 1152
|
|
height = 896
|
|
if(resolution == "landscape - 1216x832 (3:2)"):
|
|
width = 1216
|
|
height = 832
|
|
if(resolution == "landscape - 1344x768 (16:9)"):
|
|
width = 1344
|
|
height = 768
|
|
if(resolution == "landscape - 1536x640 (21:9)"):
|
|
width = 1536
|
|
height = 640
|
|
if(resolution == "portrait - 896x1152 (3:4)"):
|
|
width = 896
|
|
height = 1152
|
|
if(resolution == "portrait - 832x1216 (2:3)"):
|
|
width = 832
|
|
height = 1216
|
|
if(resolution == "portrait - 768x1344 (9:16)"):
|
|
width = 768
|
|
height = 1344
|
|
if(resolution == "portrait - 640x1536 (9:21)"):
|
|
width = 640
|
|
height = 1536
|
|
|
|
return(int(width),int(height))
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class SDXL_Basic_Settings:
|
|
resolution = ["Use Image Resolution", "square - 1024x1024 (1:1)","landscape - 1152x896 (4:3)","landscape - 1216x832 (3:2)","landscape - 1344x768 (16:9)","landscape - 1536x640 (21:9)", "portrait - 896x1152 (3:4)","portrait - 832x1216 (2:3)","portrait - 768x1344 (9:16)","portrait - 640x1536 (9:21)"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"resolution": (s.resolution,),
|
|
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
|
|
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
|
|
"steps_total": ("INT", {"default": 60, "min": 20, "max": 250, "step": 5}),
|
|
"base_percentage": ("INT", {"default": 80, "min": 5, "max": 100, "step": 5}),
|
|
"cfg": ("FLOAT", {"default": 6.5, "min": 1, "max": 20, "step": 0.1}),
|
|
"cfg_rescale": ("FLOAT", {"default": 0.00, "min": 0.00, "max": 1.00, "step": 0.05}),
|
|
"cfg_refiner": ("FLOAT", {"default": 6.5, "min": 0, "max": 20, "step": 0.1}),
|
|
"ascore_refiner": ("FLOAT", {"default": 6, "min": 1, "max": 10, "step": 0.5}),
|
|
"res_factor": ("INT", {"default": 4, "min": 1, "max": 8, "step": 1}),
|
|
"clip_skip": ("INT", {"default": -2, "min": -24, "max": -1}),
|
|
"filename": ("STRING", {"default": "JPS"}),
|
|
}}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("sdxl_basic_settings",)
|
|
FUNCTION = "get_values"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_values(self,resolution,sampler_name,scheduler,steps_total,base_percentage,cfg,cfg_rescale,cfg_refiner,ascore_refiner,res_factor,clip_skip,filename):
|
|
width = 1024
|
|
height = 1024
|
|
width = int(width)
|
|
height = int(height)
|
|
steps_total = int(steps_total)
|
|
step_split = steps_total * base_percentage / 100
|
|
cfg = float(cfg)
|
|
cfg_rescale = float(cfg_rescale)
|
|
cfg_refiner = float (cfg_refiner)
|
|
ascore_refiner = float (ascore_refiner)
|
|
res_factor = int (res_factor)
|
|
base_percentage = int (base_percentage)
|
|
image_res = 1
|
|
|
|
if(resolution == "Use Image Resolution"):
|
|
image_res = 2
|
|
if(resolution == "square - 1024x1024 (1:1)"):
|
|
width = 1024
|
|
height = 1024
|
|
if(resolution == "landscape - 1152x896 (4:3)"):
|
|
width = 1152
|
|
height = 896
|
|
if(resolution == "landscape - 1216x832 (3:2)"):
|
|
width = 1216
|
|
height = 832
|
|
if(resolution == "landscape - 1344x768 (16:9)"):
|
|
width = 1344
|
|
height = 768
|
|
if(resolution == "landscape - 1536x640 (21:9)"):
|
|
width = 1536
|
|
height = 640
|
|
if(resolution == "portrait - 896x1152 (3:4)"):
|
|
width = 896
|
|
height = 1152
|
|
if(resolution == "portrait - 832x1216 (2:3)"):
|
|
width = 832
|
|
height = 1216
|
|
if(resolution == "portrait - 768x1344 (9:16)"):
|
|
width = 768
|
|
height = 1344
|
|
if(resolution == "portrait - 640x1536 (9:21)"):
|
|
width = 640
|
|
height = 1536
|
|
|
|
if(cfg_refiner == 0):
|
|
cfg_refiner = cfg
|
|
|
|
sdxl_basic_settings = width, height, sampler_name, scheduler, steps_total, step_split, cfg, cfg_rescale, cfg_refiner, ascore_refiner, res_factor, clip_skip, filename,image_res
|
|
|
|
return(sdxl_basic_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class SDXL_Basic_Settings_Pipe:
|
|
resolution = ["square - 1024x1024 (1:1)","landscape - 1152x896 (4:3)","landscape - 1216x832 (3:2)","landscape - 1344x768 (16:9)","landscape - 1536x640 (21:9)", "portrait - 896x1152 (3:4)","portrait - 832x1216 (2:3)","portrait - 768x1344 (9:16)","portrait - 640x1536 (9:21)"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"sdxl_basic_settings": ("BASIC_PIPE",)
|
|
},
|
|
}
|
|
RETURN_TYPES = ("INT","INT","INT",comfy.samplers.KSampler.SAMPLERS,comfy.samplers.KSampler.SCHEDULERS,"INT","INT","FLOAT","FLOAT","FLOAT","FLOAT","INT","INT","STRING",)
|
|
RETURN_NAMES = ("image_res","width","height","sampler_name","scheduler","steps_total","step_split","cfg","cfg_rescale","cfg_refiner","ascore_refiner","res_factor","clip_skip","filename",)
|
|
FUNCTION = "give_values"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def give_values(self,sdxl_basic_settings):
|
|
|
|
width, height, sampler_name, scheduler, steps_total, step_split, cfg, cfg_rescale, cfg_refiner, ascore_refiner, res_factor, clip_skip, filename,image_res = sdxl_basic_settings
|
|
|
|
return(int(image_res), int(width), int(height), sampler_name, scheduler, int(steps_total), int(step_split), float(cfg), float(cfg_rescale), float(cfg_refiner), float(ascore_refiner), int (res_factor), int(clip_skip), str(filename),)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class SDXL_Settings:
|
|
resolution = ["Use Image Resolution", "square - 1024x1024 (1:1)","landscape - 1152x896 (4:3)","landscape - 1216x832 (3:2)","landscape - 1344x768 (16:9)","landscape - 1536x640 (21:9)", "portrait - 896x1152 (3:4)","portrait - 832x1216 (2:3)","portrait - 768x1344 (9:16)","portrait - 640x1536 (9:21)"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"resolution": (s.resolution,),
|
|
"res_factor": ("INT", {"default": 4, "min": 1, "max": 8, "step": 1}),
|
|
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
|
|
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
|
|
"steps": ("INT", {"default": 60, "min": 20, "max": 250, "step": 5}),
|
|
"cfg": ("FLOAT", {"default": 6.5, "min": 1, "max": 20, "step": 0.1}),
|
|
"cfg_rescale": ("FLOAT", {"default": 0.00, "min": 0.00, "max": 1.00, "step": 0.05}),
|
|
"clip_skip": ("INT", {"default": -2, "min": -24, "max": -1}),
|
|
"filename": ("STRING", {"default": "JPS"}),
|
|
}}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("sdxl_settings",)
|
|
FUNCTION = "get_values"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_values(self,resolution,res_factor,sampler_name,scheduler,steps,cfg,cfg_rescale,clip_skip,filename):
|
|
|
|
image_res = 1
|
|
if(resolution == "Use Image Resolution"):
|
|
image_res = 2
|
|
|
|
width = 1024
|
|
height = 1024
|
|
if(resolution == "landscape - 1152x896 (4:3)"):
|
|
width = 1152
|
|
height = 896
|
|
if(resolution == "landscape - 1216x832 (3:2)"):
|
|
width = 1216
|
|
height = 832
|
|
if(resolution == "landscape - 1344x768 (16:9)"):
|
|
width = 1344
|
|
height = 768
|
|
if(resolution == "landscape - 1536x640 (21:9)"):
|
|
width = 1536
|
|
height = 640
|
|
if(resolution == "portrait - 896x1152 (3:4)"):
|
|
width = 896
|
|
height = 1152
|
|
if(resolution == "portrait - 832x1216 (2:3)"):
|
|
width = 832
|
|
height = 1216
|
|
if(resolution == "portrait - 768x1344 (9:16)"):
|
|
width = 768
|
|
height = 1344
|
|
if(resolution == "portrait - 640x1536 (9:21)"):
|
|
width = 640
|
|
height = 1536
|
|
|
|
sdxl_settings = width, height, res_factor, sampler_name, scheduler, steps, cfg, cfg_rescale, clip_skip, filename,image_res
|
|
|
|
return(sdxl_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class SDXL_Settings_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"sdxl_settings": ("BASIC_PIPE",)
|
|
},
|
|
}
|
|
RETURN_TYPES = ("INT","INT","INT","INT",comfy.samplers.KSampler.SAMPLERS,comfy.samplers.KSampler.SCHEDULERS,"INT","FLOAT","FLOAT","INT","STRING",)
|
|
RETURN_NAMES = ("image_res","width","height","res_factor","sampler_name","scheduler","steps","cfg","cfg_rescale","clip_skip","filename",)
|
|
FUNCTION = "give_values"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def give_values(self,sdxl_settings):
|
|
|
|
width, height, res_factor, sampler_name, scheduler, steps, cfg, cfg_rescale, clip_skip, filename,image_res = sdxl_settings
|
|
|
|
return(int(image_res), int(width), int(height), int (res_factor), sampler_name, scheduler, int(steps), float(cfg), float(cfg_rescale), int(clip_skip), str(filename),)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class SDXL_Prompt_Handling_Plus:
|
|
handling = ["Copy to Both if Empty","Use Positive_G + Positive_L","Copy Positive_G to Both","Copy Positive_L to Both","Ignore Positive_G Input", "Ignore Positive_L Input", "Combine Positive_G + Positive_L", "Combine Positive_L + Positive_G",]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"handling": (s.handling,),
|
|
"pos_g": ("STRING", {"multiline": True, "placeholder": "Prompt Text pos_g", "dynamicPrompts": True}),
|
|
"pos_l": ("STRING", {"multiline": True, "placeholder": "Prompt Text pos_l", "dynamicPrompts": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING","STRING",)
|
|
RETURN_NAMES = ("pos_g","pos_l",)
|
|
FUNCTION = "pick_handling"
|
|
|
|
CATEGORY="JPS Nodes/Text"
|
|
|
|
def pick_handling(self,handling,pos_g,pos_l):
|
|
|
|
if(handling == "Copy Positive_G to Both"):
|
|
pos_l = pos_g
|
|
elif(handling == "Copy Positive_L to Both"):
|
|
pos_g = pos_l
|
|
elif(handling == "Ignore Positive_G Input"):
|
|
pos_g = ''
|
|
elif(handling == "Ignore Positive_L Input"):
|
|
pos_l = ''
|
|
elif(handling == "Combine Positive_G + Positive_L"):
|
|
combine = pos_g + ' . ' + pos_l
|
|
pos_g = combine
|
|
pos_l = combine
|
|
elif(handling == "Combine Positive_L + Positive_G"):
|
|
combine = pos_l + ' . ' + pos_g
|
|
pos_g = combine
|
|
pos_l = combine
|
|
elif(handling == "Copy to Both if Empty" and pos_l == ''):
|
|
pos_l = pos_g
|
|
elif(handling == "Copy to Both if Empty" and pos_g == ''):
|
|
pos_g = pos_l
|
|
|
|
return(pos_g,pos_l,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Text_Prompt:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"text": ("STRING", {"multiline": True, "placeholder": "Prompt Text", "dynamicPrompts": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("text",)
|
|
FUNCTION = "text_prompt"
|
|
|
|
CATEGORY="JPS Nodes/Text"
|
|
|
|
def text_prompt(self,text):
|
|
|
|
return(text,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Text_Prompt_Combo:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"pos": ("STRING", {"multiline": True, "placeholder": "Prompt Text Positive", "dynamicPrompts": True}),
|
|
"neg": ("STRING", {"multiline": True, "placeholder": "Prompt Text Negative", "dynamicPrompts": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING","STRING",)
|
|
RETURN_NAMES = ("pos","neg",)
|
|
FUNCTION = "give_values"
|
|
|
|
CATEGORY="JPS Nodes/Text"
|
|
|
|
def give_values(self,pos,neg):
|
|
|
|
return(pos,neg,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class SDXL_Prompt_Handling:
|
|
handling = ["Copy to Both if Empty","Use Positive_G + Positive_L","Copy Positive_G to Both","Copy Positive_L to Both","Ignore Positive_G Input", "Ignore Positive_L Input", "Combine Positive_G + Positive_L", "Combine Positive_L + Positive_G",]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"handling": (s.handling,),
|
|
"pos_g": ("STRING", {"default": ""}),
|
|
"pos_l": ("STRING", {"default": ""}),
|
|
},
|
|
}
|
|
RETURN_TYPES = ("STRING","STRING",)
|
|
RETURN_NAMES = ("pos_g","pos_l",)
|
|
FUNCTION = "pick_handling"
|
|
|
|
CATEGORY="JPS Nodes/Text"
|
|
|
|
def pick_handling(self,handling,pos_g,pos_l,):
|
|
|
|
if(handling == "Copy Positive_G to Both"):
|
|
pos_l = pos_g
|
|
elif(handling == "Copy Positive_L to Both"):
|
|
pos_g = pos_l
|
|
elif(handling == "Ignore Positive_G Input"):
|
|
pos_g = ''
|
|
elif(handling == "Ignore Positive_L Input"):
|
|
pos_l = ''
|
|
elif(handling == "Combine Positive_G + Positive_L"):
|
|
combine = pos_g + ' . ' + pos_l
|
|
pos_g = combine
|
|
pos_l = combine
|
|
elif(handling == "Combine Positive_L + Positive_G"):
|
|
combine = pos_l + ' . ' + pos_g
|
|
pos_g = combine
|
|
pos_l = combine
|
|
elif(handling == "Copy to Both if Empty" and pos_l == ''):
|
|
pos_l = pos_g
|
|
elif(handling == "Copy to Both if Empty" and pos_g == ''):
|
|
pos_g = pos_l
|
|
|
|
return(pos_g,pos_l,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Math_Resolution_Multiply:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"width": ("INT", {"default": 1024, "min": 256, "max": 8192, "step": 16}),
|
|
"height": ("INT", {"default": 1024, "min": 256, "max": 8192, "step": 16}),
|
|
"factor": ("INT", {"default": 2, "min": 1, "max": 8, "step": 1}),
|
|
}}
|
|
RETURN_TYPES = ("INT","INT")
|
|
RETURN_NAMES = ("width_resized", "height_resized")
|
|
FUNCTION = "get_newres"
|
|
|
|
CATEGORY="JPS Nodes/Math"
|
|
|
|
def get_newres(self,width,height,factor):
|
|
factor = int(factor)
|
|
width = int(width)
|
|
width_resized = int(width) * int(factor)
|
|
height = int(height)
|
|
height_resized = int (height) * int(factor)
|
|
|
|
return(int(width_resized),int(height_resized))
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Math_Largest_Integer:
|
|
|
|
def init(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"int_a": ("INT", {"default": 1,}),
|
|
"int_b": ("INT", {"default": 1,}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("INT","INT","INT")
|
|
RETURN_NAMES = ("larger_int","smaller_int","is_a_larger")
|
|
FUNCTION = "get_lrg"
|
|
|
|
CATEGORY="JPS Nodes/Math"
|
|
|
|
def get_lrg(self,int_a,int_b):
|
|
larger_int = int(int_b)
|
|
smaller_int = int(int_a)
|
|
is_a_larger = int(0)
|
|
if int_a > int_b:
|
|
larger_int = int(int_a)
|
|
smaller_int = int(int_b)
|
|
is_a_larger = int(1)
|
|
|
|
return(int(larger_int),int(smaller_int),int(is_a_larger))
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Math_Multiply_INT_INT:
|
|
|
|
def init(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"int_a": ("INT", {"default": 1,}),
|
|
"int_b": ("INT", {"default": 1,}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("INT","FLOAT")
|
|
RETURN_NAMES = ("int_multiply","float_multiply")
|
|
FUNCTION = "get_multiply_int_int"
|
|
|
|
CATEGORY="JPS Nodes/Math"
|
|
|
|
def get_multiply_int_int(self,int_a,int_b):
|
|
int_multiply = int(int_a) * int(int_b)
|
|
float_multiply = int(int_a) * int(int_b)
|
|
|
|
return(int(int_multiply),float(float_multiply))
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Math_Multiply_INT_FLOAT:
|
|
|
|
def init(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"int_a": ("INT", {"default": 1,}),
|
|
"float_b": ("FLOAT", {"default": 1,}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("INT","FLOAT")
|
|
RETURN_NAMES = ("int_multiply","float_multiply")
|
|
FUNCTION = "get_multiply_int_float"
|
|
|
|
CATEGORY="JPS Nodes/Math"
|
|
|
|
def get_multiply_int_float(self,int_a,float_b):
|
|
int_multiply = int(int_a) * float(float_b)
|
|
float_multiply = int(int_a) * float(float_b)
|
|
|
|
return(int(int_multiply),float(float_multiply))
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Math_Multiply_FLOAT_FLOAT:
|
|
|
|
def init(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"float_a": ("FLOAT", {"default": 1,}),
|
|
"float_b": ("FLOAT", {"default": 1,}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("INT","FLOAT")
|
|
RETURN_NAMES = ("int_multiply","float_multiply")
|
|
FUNCTION = "get_multiply_float_float"
|
|
|
|
CATEGORY="JPS Nodes/Math"
|
|
|
|
def get_multiply_float_float(self,float_a,float_b):
|
|
int_multiply = float(float_a) * float(float_b)
|
|
float_multiply = float(float_a) * float(float_b)
|
|
|
|
return(int(int_multiply),float(float_multiply))
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Math_Substract_INT_INT:
|
|
|
|
def init(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"int_a": ("INT", {"default": 1,}),
|
|
"int_b": ("INT", {"default": 1,}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("INT","FLOAT")
|
|
RETURN_NAMES = ("int_substract","float_substract")
|
|
FUNCTION = "get_substract_int_int"
|
|
|
|
CATEGORY="JPS Nodes/Math"
|
|
|
|
def get_substract_int_int(self,int_a,int_b):
|
|
int_substract = int(int_a) - int(int_b)
|
|
float_substract = int(int_a) - int(int_b)
|
|
|
|
return(int(int_substract),float(float_substract))
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Text_Concatenate:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"delimiter": (["none", "space", "comma"],),
|
|
},
|
|
"optional": {
|
|
"text1": ("STRING", {"forceInput": True}),
|
|
"text2": ("STRING", {"forceInput": True}),
|
|
"text3": ("STRING", {"forceInput": True}),
|
|
"text4": ("STRING", {"forceInput": True}),
|
|
"text5": ("STRING", {"forceInput": True}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("text",)
|
|
FUNCTION = "get_contxt"
|
|
CATEGORY = "JPS Nodes/Text"
|
|
|
|
def get_contxt(self, delimiter, text1=None, text2=None, text3=None, text4=None, text5=None):
|
|
needdelim = False
|
|
delim = ""
|
|
if delimiter == "space":
|
|
delim = " "
|
|
if delimiter == "comma":
|
|
delim = ", "
|
|
|
|
concatenated = ""
|
|
|
|
if text1:
|
|
concatenated = text1
|
|
needdelim = True
|
|
|
|
if text2:
|
|
if needdelim:
|
|
concatenated += delim
|
|
concatenated += text2
|
|
needdelim = True
|
|
|
|
if text3:
|
|
if needdelim:
|
|
concatenated += delim
|
|
concatenated += text3
|
|
needdelim = True
|
|
|
|
if text4:
|
|
if needdelim:
|
|
concatenated += delim
|
|
concatenated += text4
|
|
needdelim = True
|
|
|
|
if text5:
|
|
if needdelim:
|
|
concatenated += delim
|
|
concatenated += text5
|
|
needdelim = True
|
|
|
|
return (concatenated,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Get_Date_Time_String:
|
|
time_format = ["%Y%m%d%H%M%S","%Y%m%d%H%M","%Y%m%d","%Y-%m-%d-%H_%M_%S","%Y-%m-%d-%H_%M","%Y-%m-%d","%Y-%m-%d %H_%M_%S","%Y-%m-%d %H_%M","%Y-%m-%d","%H%M","%H%M%S","%H_%M","%H_%M_%S"]
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"style": (s.time_format,),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("time_format",)
|
|
FUNCTION = "get_time"
|
|
|
|
CATEGORY = "JPS Nodes/Text"
|
|
|
|
def get_time(self, style):
|
|
now = datetime.now()
|
|
timestamp = now.strftime(style)
|
|
|
|
return (timestamp,)
|
|
|
|
@classmethod
|
|
def IS_CHANGED(s, style):
|
|
now = datetime.now()
|
|
timestamp = now.strftime(style)
|
|
return (timestamp,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Time_Seed:
|
|
# time_format = ["%Y%m%d%H%M%S","%Y%m%d%H%M","%Y%m%d","%Y-%m-%d-%H_%M_%S","%Y-%m-%d-%H_%M","%Y-%m-%d","%Y-%m-%d %H_%M_%S","%Y-%m-%d %H_%M","%Y-%m-%d","%H%M","%H%M%S","%H_%M","%H_%M_%S"]
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"fixed_seed": ("INT", {"default": 0, "min": 0, "max": 99999999999, "step": 1}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("INT",)
|
|
RETURN_NAMES = ("seed",)
|
|
FUNCTION = "get_seed"
|
|
|
|
CATEGORY = "JPS Nodes/Text"
|
|
|
|
def get_seed(self, fixed_seed):
|
|
now = datetime.now()
|
|
time = now.strftime("%Y%m%d%H%M%S")
|
|
seed_out = int(time) + np.random.randint(999999)
|
|
if fixed_seed != 0:
|
|
seed_out=fixed_seed
|
|
|
|
return (int(seed_out),)
|
|
|
|
@classmethod
|
|
def IS_CHANGED(s, seed_out):
|
|
now = datetime.now()
|
|
forceupdate = now.strftime("%Y%m%d%H%M%S")
|
|
forceupdate = forceupdate + np.random.randint(99999999) + seed_out
|
|
return (forceupdate,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class SDXL_Recommended_Resolution_Calc:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"target_width": ("INT", {
|
|
"default": 1024,
|
|
"min": 0,
|
|
"max": 8192,
|
|
"step": 2
|
|
}),
|
|
"target_height": ("INT", {
|
|
"default": 1024,
|
|
"min": 0,
|
|
"max": 8192,
|
|
"step": 2
|
|
}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("INT","INT",)
|
|
RETURN_NAMES = ("SDXL_width","SDXL_height",)
|
|
FUNCTION = "calcSDXLres"
|
|
|
|
CATEGORY = "JPS Nodes/Math"
|
|
|
|
def calcSDXLres(self, target_width, target_height):
|
|
target_ratio = target_width / target_height
|
|
|
|
closest_ratio = None
|
|
closest_diff = float('inf')
|
|
|
|
for ratio, (x_size, y_size, num_ratio) in accepted_ratios_horizontal.items():
|
|
diff = abs(num_ratio - target_ratio)
|
|
if diff < closest_diff:
|
|
closest_ratio = ratio
|
|
closest_diff = diff
|
|
|
|
for ratio, (x_size, y_size, num_ratio) in accepted_ratios_vertical.items():
|
|
diff = abs(num_ratio - target_ratio)
|
|
if diff < closest_diff:
|
|
closest_ratio = ratio
|
|
closest_diff = diff
|
|
|
|
# Compare with square aspect ratio
|
|
x_size, y_size, num_ratio = accepted_ratios_square["1:1"]
|
|
diff = abs(num_ratio - target_ratio)
|
|
if diff < closest_diff:
|
|
closest_ratio = "1:1"
|
|
|
|
if closest_ratio in accepted_ratios_horizontal:
|
|
SDXL_width, SDXL_height, _ = accepted_ratios_horizontal[closest_ratio]
|
|
elif closest_ratio in accepted_ratios_vertical:
|
|
SDXL_width, SDXL_height, _ = accepted_ratios_vertical[closest_ratio]
|
|
else:
|
|
SDXL_width, SDXL_height, _ = accepted_ratios_square[closest_ratio]
|
|
|
|
return (SDXL_width, SDXL_height)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Generation_TXT_IMG_Settings:
|
|
mode = ["Txt2Img","Img2Img"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"mode": (s.mode,),
|
|
"img_percentage": ("INT", {"default": 50, "min": 0, "max": 100, "step": 5}),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("INT","FLOAT",)
|
|
RETURN_NAMES = ("gen_mode", "img_strength")
|
|
FUNCTION = "get_genmode"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_genmode(self,mode,img_percentage):
|
|
gen_mode = 1
|
|
img_strength = 0
|
|
if(mode == "Txt2Img"):
|
|
gen_mode = int(1)
|
|
img_strength = 0.001
|
|
if(mode == "Img2Img"):
|
|
gen_mode = int(2)
|
|
img_strength = img_percentage / 100
|
|
|
|
return(int(gen_mode),float(img_strength))
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CropImage_Settings:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"source_crop_pos": (["center","top", "bottom", "left", "right"],),
|
|
"source_crop_offset": ("INT", { "default": 0, "min": -2048, "max": 2048, "step": 1, "display": "number" }),
|
|
"support_crop_pos": (["center","top", "bottom", "left", "right"],),
|
|
"support_crop_offset": ("INT", { "default": 0, "min": -2048, "max": 2048, "step": 1, "display": "number" }),
|
|
"crop_intpol": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("cropimage_settings",)
|
|
FUNCTION = "get_cropimage"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_cropimage(self, source_crop_pos, source_crop_offset, support_crop_pos, support_crop_offset, crop_intpol,):
|
|
|
|
cropimage_settings = source_crop_pos, source_crop_offset, support_crop_pos, support_crop_offset, crop_intpol
|
|
|
|
return(cropimage_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CropImage_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"cropimage_settings": ("BASIC_PIPE",)
|
|
},
|
|
}
|
|
RETURN_TYPES = (["center","top", "bottom", "left", "right"],"INT",["center","top", "bottom", "left", "right"],"INT",["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],)
|
|
RETURN_NAMES = ("source_crop_pos", "source_crop_offset", "support_crop_pos", "support_crop_offset", "crop_intpol",)
|
|
FUNCTION = "give_values"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def give_values(self,cropimage_settings):
|
|
|
|
source_crop_pos, source_crop_offset, support_crop_pos, support_crop_offset, crop_intpol = cropimage_settings
|
|
|
|
return(source_crop_pos, source_crop_offset, support_crop_pos, support_crop_offset, crop_intpol,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class ImageToImage_Settings:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"img2img_strength": ("INT", {"default": 50, "min": 0, "max": 100, "step": 1}),
|
|
"inpaint_strength": ("INT", {"default": 100, "min": 2, "max": 100, "step": 1}),
|
|
"inpaint_grow_mask": ("INT", {"default": 20, "min": 0, "max": 200, "step": 2}),
|
|
"unsampler_strength": ("INT", {"default": 30, "min": 0, "max": 100, "step": 1}),
|
|
"unsampler_cfg": ("FLOAT", {"default": 1, "min": 1, "max": 10, "step": 0.1}),
|
|
"unsampler_sampler": (comfy.samplers.KSampler.SAMPLERS,),
|
|
"unsampler_scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("img2img_settings",)
|
|
FUNCTION = "get_img2img"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_img2img(self, img2img_strength, inpaint_strength, inpaint_grow_mask, unsampler_strength, unsampler_cfg, unsampler_sampler, unsampler_scheduler,):
|
|
|
|
img2img_strength = (img2img_strength + 0.001) / 100
|
|
|
|
inpaint_strength = (100 - inpaint_strength + 0.001) / 100
|
|
|
|
unsampler_strength = (unsampler_strength + 0.001) / 100
|
|
|
|
img2img_settings = img2img_strength, inpaint_strength, inpaint_grow_mask, unsampler_strength, unsampler_cfg, unsampler_sampler, unsampler_scheduler
|
|
|
|
return(img2img_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class ImageToImage_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"img2img_settings": ("BASIC_PIPE",)
|
|
},
|
|
}
|
|
RETURN_TYPES = ("FLOAT", "FLOAT", "INT", "FLOAT", "FLOAT", comfy.samplers.KSampler.SAMPLERS, comfy.samplers.KSampler.SCHEDULERS,)
|
|
RETURN_NAMES = ("img2img_strength", "inpaint_strength", "inpaint_grow_mask", "unsampler_strength", "unsampler_cfg", "unsampler_sampler", "unsampler_scheduler",)
|
|
FUNCTION = "give_values"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def give_values(self,img2img_settings):
|
|
|
|
img2img_strength, inpaint_strength, inpaint_grow_mask, unsampler_strength, unsampler_cfg, unsampler_sampler, unsampler_scheduler = img2img_settings
|
|
|
|
return(img2img_strength, inpaint_strength, inpaint_grow_mask, unsampler_strength, unsampler_cfg, unsampler_sampler, unsampler_scheduler,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CtrlNet_CannyEdge_Settings:
|
|
cannyedgefrom = ["Source Image", "Support Image", "Support Direct"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"cannyedge_from": (s.cannyedgefrom,),
|
|
"cannyedge_strength": ("FLOAT", {"default": 1.00, "min": 0.00, "max": 10.00, "step": 0.10}),
|
|
"cannyedge_start": ("FLOAT", {"default": 0.000, "min": 0.000, "max": 1.000, "step": 0.05}),
|
|
"cannyedge_end": ("FLOAT", {"default": 1.000, "min": 0.000, "max": 1.000, "step": 0.05}),
|
|
"cannyedge_low": ("INT", {"default": 100, "min": 0, "max": 255, "step": 1}),
|
|
"cannyedge_high": ("INT", {"default": 200, "min": 0, "max": 255, "step": 1}),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("cannyedge_settings",)
|
|
FUNCTION = "get_ctrlnet_cannyedge"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_ctrlnet_cannyedge(self, cannyedge_from, cannyedge_strength, cannyedge_start, cannyedge_end, cannyedge_low, cannyedge_high):
|
|
|
|
cannyedge_source = int (1)
|
|
if (cannyedge_from == "Support Image"):
|
|
cannyedge_source = int(2)
|
|
if (cannyedge_from == "Support Direct"):
|
|
cannyedge_source = int(3)
|
|
|
|
cannyedge_settings = cannyedge_source, cannyedge_strength, cannyedge_start, cannyedge_end, cannyedge_low, cannyedge_high
|
|
|
|
return(cannyedge_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CtrlNet_CannyEdge_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"cannyedge_settings": ("BASIC_PIPE",)
|
|
},
|
|
}
|
|
RETURN_TYPES = ("INT", "FLOAT", "FLOAT", "FLOAT", "INT", "INT", )
|
|
RETURN_NAMES = ("cannyedge_source", "cannyedge_strength", "cannyedge_start", "cannyedge_end", "cannyedge_low", "cannyedge_high",)
|
|
FUNCTION = "give_values"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def give_values(self,cannyedge_settings):
|
|
|
|
cannyedge_source, cannyedge_strength, cannyedge_start, cannyedge_end, cannyedge_low, cannyedge_high = cannyedge_settings
|
|
|
|
return(cannyedge_source, cannyedge_strength, cannyedge_start, cannyedge_end, cannyedge_low, cannyedge_high,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CtrlNet_OpenPose_Settings:
|
|
openposefrom = ["Source Image", "Support Image", "Support Direct"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"openpose_from": (s.openposefrom,),
|
|
"openpose_strength": ("FLOAT", {"default": 1.00, "min": 0.00, "max": 10.00, "step": 0.10}),
|
|
"openpose_start": ("FLOAT", {"default": 0.000, "min": 0.000, "max": 1.000, "step": 0.05}),
|
|
"openpose_end": ("FLOAT", {"default": 1.000, "min": 0.000, "max": 1.000, "step": 0.05}),
|
|
"openpose_body": (["enable","disable"],),
|
|
"openpose_face": (["enable","disable"],),
|
|
"openpose_hand": (["enable","disable"],),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("openpose_settings",)
|
|
FUNCTION = "get_ctrlnet_openpose"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_ctrlnet_openpose(self, openpose_from, openpose_strength, openpose_start, openpose_end, openpose_body, openpose_face, openpose_hand):
|
|
|
|
openpose_source = int (1)
|
|
if (openpose_from == "Support Image"):
|
|
openpose_source = int(2)
|
|
if (openpose_from == "Support Direct"):
|
|
openpose_source = int(3)
|
|
|
|
openpose_settings = openpose_source, openpose_strength, openpose_start, openpose_end, openpose_body, openpose_face, openpose_hand
|
|
|
|
return(openpose_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CtrlNet_OpenPose_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"openpose_settings": ("BASIC_PIPE",)
|
|
},
|
|
}
|
|
RETURN_TYPES = ("INT", "FLOAT", "FLOAT", "FLOAT", ["enable","disable"], ["enable","disable"], ["enable","disable"],)
|
|
RETURN_NAMES = ("openpose_source", "openpose_strength", "openpose_start", "openpose_end", "openpose_body", "openpose_face", "openpose_hand",)
|
|
FUNCTION = "give_values"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def give_values(self,openpose_settings):
|
|
|
|
openpose_source, openpose_strength, openpose_start, openpose_end, openpose_body, openpose_face, openpose_hand = openpose_settings
|
|
|
|
return(openpose_source, openpose_strength, openpose_start, openpose_end, openpose_body, openpose_face, openpose_hand,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CtrlNet_MiDaS_Settings:
|
|
midasfrom = ["Source Image", "Support Image", "Support Direct"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"midas_from": (s.midasfrom,),
|
|
"midas_strength": ("FLOAT", {"default": 1.00, "min": 0.00, "max": 10.00, "step": 0.10}),
|
|
"midas_start": ("FLOAT", {"default": 0.000, "min": 0.000, "max": 1.000, "step": 0.05}),
|
|
"midas_end": ("FLOAT", {"default": 1.000, "min": 0.000, "max": 1.000, "step": 0.05}),
|
|
"midas_a": ("FLOAT", {"default": 6.28, "min": 0.00, "max": 15.71, "step": 0.05}),
|
|
"midas_bg": ("FLOAT", {"default": 0.10, "min": 0.00, "max": 1.00, "step": 0.05}),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("midas_settings",)
|
|
FUNCTION = "get_ctrlnet_midas"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_ctrlnet_midas(self, midas_from, midas_strength, midas_start, midas_end, midas_a, midas_bg):
|
|
|
|
midas_source = int (1)
|
|
if (midas_from == "Support Image"):
|
|
midas_source = int(2)
|
|
if (midas_from == "Support Direct"):
|
|
midas_source = int(3)
|
|
|
|
midas_settings = midas_source, midas_strength, midas_start, midas_end, midas_a, midas_bg
|
|
|
|
return(midas_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CtrlNet_MiDaS_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"midas_settings": ("BASIC_PIPE",)
|
|
},
|
|
}
|
|
RETURN_TYPES = ("INT", "FLOAT", "FLOAT", "FLOAT", "FLOAT", "FLOAT",)
|
|
RETURN_NAMES = ("midas_source", "midas_strength", "midas_start", "midas_end", "midas_a", "midas_bg",)
|
|
FUNCTION = "give_values"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def give_values(self,midas_settings):
|
|
|
|
midas_source, midas_strength, midas_start, midas_end, midas_a, midas_bg = midas_settings
|
|
|
|
return(midas_source, midas_strength, midas_start, midas_end, midas_a, midas_bg,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CtrlNet_ZoeDepth_Settings:
|
|
zoefrom = ["Source Image", "Support Image", "Support Direct"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"zoe_from": (s.zoefrom,),
|
|
"zoe_strength": ("FLOAT", {"default": 1.00, "min": 0.00, "max": 10.00, "step": 0.10}),
|
|
"zoe_start": ("FLOAT", {"default": 0.000, "min": 0.000, "max": 1.000, "step": 0.05}),
|
|
"zoe_end": ("FLOAT", {"default": 1.000, "min": 0.000, "max": 1.000, "step": 0.05}),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("zoedepth_settings",)
|
|
FUNCTION = "get_ctrlnet_zoedepth"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_ctrlnet_zoedepth(self, zoe_from, zoe_strength, zoe_start, zoe_end):
|
|
|
|
zoe_source = int (1)
|
|
if (zoe_from == "Support Image"):
|
|
zoe_source = int(2)
|
|
if (zoe_from == "Support Direct"):
|
|
zoe_source = int(3)
|
|
|
|
zoedepth_settings = zoe_source, zoe_strength, zoe_start, zoe_end
|
|
|
|
return(zoedepth_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CtrlNet_ZoeDepth_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"zoedepth_settings": ("BASIC_PIPE",)
|
|
},
|
|
}
|
|
RETURN_TYPES = ("INT", "FLOAT", "FLOAT", "FLOAT",)
|
|
RETURN_NAMES = ("zoe_source", "zoe_strength", "zoe_start", "zoe_end",)
|
|
FUNCTION = "give_values"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def give_values(self,zoedepth_settings):
|
|
|
|
zoe_source, zoe_strength, zoe_start, zoe_end = zoedepth_settings
|
|
|
|
return(zoe_source, zoe_strength, zoe_start, zoe_end,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class IP_Adapter_Settings:
|
|
ipamasktype = ["No Mask","Mask Editor","Mask Editor (inverted)","Red from Image","Green from Image","Blue from Image"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"ipa_weight": ("FLOAT", {"default": 0.5, "min": 0, "max": 3, "step": 0.01}),
|
|
"ipa_wtype": (["linear", "ease in", "ease out", "ease in-out", "reverse in-out", "weak input", "weak output", "weak middle", "strong middle"],),
|
|
"ipa_noise": ("FLOAT", {"default": 0.0, "min": 0, "max": 1, "step": 0.05}),
|
|
"ipa_start": ("FLOAT", {"default": 0.00, "min": 0, "max": 1, "step": 0.05}),
|
|
"ipa_stop": ("FLOAT", {"default": 1.00, "min": 0, "max": 1, "step": 0.05}),
|
|
"ipa_crop": (["center","top", "bottom", "left", "right"],),
|
|
"ipa_zoom": ("FLOAT", { "default": 1, "min": 1, "max": 5, "step": 0.1, "display": "number" }),
|
|
"ipa_offset_x": ("INT", { "default": 0, "min": -4096, "max": 4096, "step": 1, "display": "number" }),
|
|
"ipa_offset_y": ("INT", { "default": 0, "min": -4096, "max": 4096, "step": 1, "display": "number" }),
|
|
"ipa_mask": (s.ipamasktype,),
|
|
"crop_intpol": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"sharpening": ("FLOAT", { "default": 0.0, "min": 0, "max": 1, "step": 0.05, "display": "number" }),
|
|
"ipa_model": (["SDXL ViT-H", "SDXL Plus ViT-H", "SDXL Plus Face ViT-H"],),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("ip_adapter_single_settings",)
|
|
FUNCTION = "get_ipamodesingle"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_ipamodesingle(self,ipa_weight,ipa_wtype,ipa_noise,ipa_start,ipa_stop,ipa_crop,ipa_zoom,ipa_offset_x,ipa_offset_y,ipa_mask,crop_intpol,sharpening,ipa_model):
|
|
|
|
ipamask = int(0)
|
|
if(ipa_mask == "Mask Editor"):
|
|
ipamask = int(1)
|
|
elif(ipa_mask == "Mask Editor (inverted)"):
|
|
ipamask = int(2)
|
|
elif(ipa_mask == "Red from Image"):
|
|
ipamask = int(3)
|
|
elif(ipa_mask == "Green from Image"):
|
|
ipamask = int(4)
|
|
elif(ipa_mask == "Blue from Image"):
|
|
ipamask = int(5)
|
|
|
|
ipamodel = int (0)
|
|
if(ipa_model == "SDXL ViT-H"):
|
|
ipamodel = int(1)
|
|
elif(ipa_model == "SDXL Plus ViT-H"):
|
|
ipamodel = int(2)
|
|
elif(ipa_model == "SDXL Plus Face ViT-H"):
|
|
ipamodel = int(3)
|
|
|
|
ipaweight = ipa_weight
|
|
ipawtype = ipa_wtype
|
|
ipanoise = ipa_noise
|
|
ipastart = ipa_start
|
|
ipastop = ipa_stop
|
|
ipacrop = ipa_crop
|
|
ipazoom = ipa_zoom
|
|
ipaoffsetx = ipa_offset_x
|
|
ipaoffsety = ipa_offset_y
|
|
cropintpol = crop_intpol
|
|
|
|
ip_adapter_settings = ipaweight,ipawtype,ipanoise,ipastart,ipastop,ipacrop,ipazoom,ipaoffsetx,ipaoffsety,ipamask,cropintpol,sharpening,ipamodel
|
|
|
|
return(ip_adapter_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class IP_Adapter_Settings_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"ip_adapter_settings": ("BASIC_PIPE",),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("FLOAT",["linear", "ease in", "ease out", "ease in-out", "reverse in-out", "weak input", "weak output", "weak middle", "strong middle"],"FLOAT","FLOAT","FLOAT",["center","top", "bottom", "left", "right"],"FLOAT","INT","INT","INT",["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],"FLOAT","INT")
|
|
RETURN_NAMES = ("ipa_weight","ipa_wtype","ipa_noise","ipa_start","ipa_stop","ipa_crop","ipa_zoom","ipa_offset_x","ipa_offset_y","ipa_mask","crop_intpol","sharpening","ipa_model")
|
|
FUNCTION = "get_ipamode_single"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def get_ipamode_single(self,ip_adapter_settings):
|
|
|
|
ipaweight,ipawtype,ipanoise,ipastart,ipastop,ipacrop,ipazoom,ipaoffsetx,ipaoffsety,ipamask,cropintpol,sharpening,ipamodel = ip_adapter_settings
|
|
|
|
return(float(ipaweight),ipawtype,float(ipanoise),float(ipastart),float(ipastop),ipacrop,float(ipazoom),int(ipaoffsetx),int(ipaoffsety),int(ipamask),cropintpol,float(sharpening),int(ipamodel),)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class IP_Adapter_Tiled_Settings:
|
|
|
|
preparetypes = ["Target AR + Target Res", "Target AR + Tile Res", "Tile AR + Target Res", "Source AR + Source Res", "Source AR + Tile Res", "Tile AR + Source Res", "Square AR + Target Res", "Square AR + Tile Res", "Direct Source" ]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"ipa_model": (["SDXL ViT-H", "SDXL Plus ViT-H", "SDXL Plus Face ViT-H"],),
|
|
"ipa_wtype": (["linear", "ease in", "ease out", "ease in-out", "reverse in-out", "weak input", "weak output", "weak middle", "strong middle"],),
|
|
"ipa_weight": ("FLOAT", {"default": 0.5, "min": 0, "max": 3, "step": 0.01}),
|
|
"ipa_noise": ("FLOAT", {"default": 0.0, "min": 0, "max": 1, "step": 0.05}),
|
|
"ipa_start": ("FLOAT", {"default": 0.00, "min": 0, "max": 1, "step": 0.05}),
|
|
"ipa_end": ("FLOAT", {"default": 1.00, "min": 0, "max": 1, "step": 0.05}),
|
|
"tile_short": ("INT", { "default": 2, "min": 1, "max": 5, "step": 1, "display": "number" }),
|
|
"tile_weight": ("FLOAT", {"default": 0.55, "min": 0, "max": 1, "step": 0.05}),
|
|
"zoom": ("INT", {"default": 100, "min": 1, "max": 500, "step": 1}),
|
|
"offset_w": ("INT", { "default": 0, "min": -4096, "max": 4096, "step": 1, "display": "number" }),
|
|
"offset_h": ("INT", { "default": 0, "min": -4096, "max": 4096, "step": 1, "display": "number" }),
|
|
"prepare_type": (s.preparetypes,),
|
|
"prepare_intpol": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"prepare_sharpening": ("FLOAT", { "default": 0.0, "min": 0, "max": 1, "step": 0.05, "display": "number" }),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("ip_adapter_tiled_settings",)
|
|
FUNCTION = "get_ipatiled"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_ipatiled(self,ipa_model,ipa_wtype,ipa_weight,ipa_noise,ipa_start,ipa_end,tile_short,tile_weight,zoom,offset_w,offset_h,prepare_type,prepare_intpol,prepare_sharpening,):
|
|
|
|
ipamodel = int (0)
|
|
if(ipa_model == "SDXL ViT-H"):
|
|
ipamodel = int(1)
|
|
elif(ipa_model == "SDXL Plus ViT-H"):
|
|
ipamodel = int(2)
|
|
elif(ipa_model == "SDXL Plus Face ViT-H"):
|
|
ipamodel = int(3)
|
|
|
|
preparetype = int (0)
|
|
if(prepare_type == "Target AR + Target Res"):
|
|
preparetype = int(1)
|
|
elif(prepare_type == "Target AR + Tile Res"):
|
|
preparetype = int(2)
|
|
elif(prepare_type == "Tile AR + Target Res"):
|
|
preparetype = int(3)
|
|
elif(prepare_type == "Source AR + Source Res"):
|
|
preparetype = int(4)
|
|
elif(prepare_type == "Source AR + Tile Res"):
|
|
preparetype = int(5)
|
|
elif(prepare_type == "Tile AR + Source Res"):
|
|
preparetype = int(6)
|
|
elif(prepare_type == "Square AR + Target Res"):
|
|
preparetype = int(7)
|
|
elif(prepare_type == "Square AR + Tile Res"):
|
|
preparetype = int(8)
|
|
elif(prepare_type == "Direct Source"):
|
|
preparetype = int(9)
|
|
|
|
ip_adapter_settings = ipamodel,ipa_wtype,ipa_weight,ipa_noise,ipa_start,ipa_end,tile_short,tile_weight,zoom,offset_w,offset_h,preparetype,prepare_intpol,prepare_sharpening
|
|
|
|
return(ip_adapter_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class IP_Adapter_Tiled_Settings_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"ip_adapter_settings": ("BASIC_PIPE",),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("INT",["linear", "ease in", "ease out", "ease in-out", "reverse in-out", "weak input", "weak output", "weak middle", "strong middle"],"FLOAT","FLOAT","FLOAT","FLOAT","INT","FLOAT","INT","INT","INT","INT",["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],"FLOAT")
|
|
RETURN_NAMES = ("ipa_model","ipa_wtype","ipa_weight","ipa_noise","ipa_start","ipa_end","tile_short","tile_weight","zoom","offset_w","offset_h","prepare_type","prepare_intpol","prepare_sharpening")
|
|
FUNCTION = "get_ipatiled"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def get_ipatiled(self,ip_adapter_settings):
|
|
|
|
ipamodel,ipa_wtype,ipa_weight,ipa_noise,ipa_start,ipa_end,tile_short,tile_weight,zoom,offset_w,offset_h,preparetype,prepare_intpol,prepare_sharpening = ip_adapter_settings
|
|
|
|
return(ipamodel,ipa_wtype,ipa_weight,ipa_noise,ipa_start,ipa_end,tile_short,tile_weight,zoom,offset_w,offset_h,preparetype,prepare_intpol,prepare_sharpening)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class InstantID_Settings:
|
|
|
|
ipamasktype = ["No Mask","Mask Editor","Mask Editor (inverted)","Red from Image","Green from Image","Blue from Image"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"ip_weight": ("FLOAT", {"default": 0.8, "min": 0, "max": 1, "step": 0.01}),
|
|
"cn_strength": ("FLOAT", {"default": 0.65, "min": 0, "max": 10, "step": 0.01}),
|
|
"noise": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.1, }),
|
|
"start": ("FLOAT", {"default": 0.00, "min": 0, "max": 1, "step": 0.05}),
|
|
"end": ("FLOAT", {"default": 1.00, "min": 0, "max": 1, "step": 0.05}),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("instantid_settings",)
|
|
FUNCTION = "get_instantid"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_instantid(self,ip_weight,cn_strength,noise,start,end):
|
|
|
|
instantid_settings = ip_weight,cn_strength,noise,start,end
|
|
|
|
return(instantid_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class InstantID_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"instantid_settings": ("BASIC_PIPE",),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("FLOAT","FLOAT","FLOAT","FLOAT","FLOAT",)
|
|
RETURN_NAMES = ("ip_weight","cn_strength","noise","start","end",)
|
|
FUNCTION = "get_instantid"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def get_instantid(self,instantid_settings):
|
|
|
|
ip_weight,cn_strength,noise,start,end = instantid_settings
|
|
|
|
return(ip_weight,cn_strength,noise,start,end)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class ImagePrepare_Settings:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"offset_width": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
|
|
"offset_height": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
|
|
"crop_left": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_right": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_top": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_bottom": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"padding_left": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_right": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_top": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_bottom": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"interpolation": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"sharpening": ("FLOAT", { "default": 0.0, "min": 0, "max": 1, "step": 0.05, "display": "number" }),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("imageprepare_settings",)
|
|
FUNCTION = "get_imageprepare"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_imageprepare(self,offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening):
|
|
|
|
imageprepare_settings = offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening
|
|
|
|
return(imageprepare_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class ImagePrepare_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"imageprepare_settings": ("BASIC_PIPE",),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("INT","INT","INT","INT","INT","INT","INT","INT","INT","INT",["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],"FLOAT",)
|
|
RETURN_NAMES = ("offset_width","offset_height","crop_left","crop_right","crop_top","crop_bottom","padding_left","padding_right","padding_top","padding_bottom","interpolation","sharpening",)
|
|
FUNCTION = "get_imageprepare"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def get_imageprepare(self,imageprepare_settings):
|
|
|
|
offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening = imageprepare_settings
|
|
|
|
return(offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class InstantIDSourcePrepare_Settings:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"resize_to": (["Resize to Target","Keep Size"],),
|
|
"offset_width": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
|
|
"offset_height": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
|
|
"crop_left": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_right": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_top": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_bottom": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"interpolation": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"sharpening": ("FLOAT", { "default": 0.0, "min": 0, "max": 1, "step": 0.05, "display": "number" }),
|
|
"flip": (["No", "X-Axis", "Y-Axis"],),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("imageprepare_settings",)
|
|
FUNCTION = "get_imageprepare"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_imageprepare(self,resize_to,offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,interpolation,sharpening,flip):
|
|
|
|
resizeto = int (0)
|
|
if(resize_to == "Keep Size"):
|
|
resizeto = int(1)
|
|
elif(resize_to == "Resize to Target"):
|
|
resizeto = int(2)
|
|
|
|
imageprepare_settings = resizeto, offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,interpolation,sharpening,flip
|
|
|
|
return(imageprepare_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class InstantIDSourcePrepare_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"imageprepare_settings": ("BASIC_PIPE",),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("INT","INT","INT","INT","INT","INT","INT",["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],"FLOAT",["No", "X-Axis", "Y-Axis"],)
|
|
RETURN_NAMES = ("resize_to","offset_width","offset_height","crop_left","crop_right","crop_top","crop_bottom","interpolation","sharpening","flip",)
|
|
FUNCTION = "get_imageprepare"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def get_imageprepare(self,imageprepare_settings):
|
|
|
|
resizeto,offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,interpolation,sharpening,flip = imageprepare_settings
|
|
|
|
return(resizeto,offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,interpolation,sharpening,flip)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class InstantIDPosePrepare_Settings:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"resize_to": (["Resize to Target","Resize to Source","Keep Size"],),
|
|
"offset_width": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
|
|
"offset_height": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
|
|
"crop_left": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_right": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_top": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_bottom": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"padding_left": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_right": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_top": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_bottom": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"interpolation": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"sharpening": ("FLOAT", { "default": 0.0, "min": 0, "max": 1, "step": 0.05, "display": "number" }),
|
|
"flip": (["No", "X-Axis", "Y-Axis"],),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("imageprepare_settings",)
|
|
FUNCTION = "get_imageprepare"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_imageprepare(self,resize_to,offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening,flip):
|
|
|
|
resizeto = int (0)
|
|
if(resize_to == "Keep Size"):
|
|
resizeto = int(1)
|
|
elif(resize_to == "Resize to Target"):
|
|
resizeto = int(2)
|
|
elif(resize_to == "Resize to Source"):
|
|
resizeto = int(3)
|
|
|
|
imageprepare_settings = resizeto, offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening,flip
|
|
|
|
return(imageprepare_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class InstantIDPosePrepare_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"imageprepare_settings": ("BASIC_PIPE",),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("INT","INT","INT","INT","INT","INT","INT","INT","INT","INT","INT",["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],"FLOAT",["No", "X-Axis", "Y-Axis"],)
|
|
RETURN_NAMES = ("resize_to","offset_width","offset_height","crop_left","crop_right","crop_top","crop_bottom","padding_left","padding_right","padding_top","padding_bottom","interpolation","sharpening","flip")
|
|
FUNCTION = "get_imageprepare"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def get_imageprepare(self,imageprepare_settings):
|
|
|
|
resizeto,offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening,flip = imageprepare_settings
|
|
|
|
return(resizeto,offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening,flip)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class InstantIDMaskPrepare_Settings:
|
|
|
|
masktypes = ["No Mask","Mask Editor","Mask Editor (inverted)","Red from Image","Green from Image","Blue from Image"]
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"mask_type": (s.masktypes,),
|
|
"resize_to": (["Resize to Target","Resize to Source","Keep Size"],),
|
|
"resize_type": (["Crop","Stretch"],),
|
|
"offset_width": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
|
|
"offset_height": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
|
|
"crop_left": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_right": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_top": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_bottom": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"padding_left": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_right": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_top": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_bottom": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"interpolation": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"sharpening": ("FLOAT", { "default": 0.0, "min": 0, "max": 1, "step": 0.05, "display": "number" }),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("imageprepare_settings",)
|
|
FUNCTION = "get_imageprepare"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_imageprepare(self,mask_type,resize_to,resize_type,offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening):
|
|
|
|
resizeto = int (0)
|
|
if(resize_to == "Keep Size"):
|
|
resizeto = int(1)
|
|
elif(resize_to == "Resize to Target"):
|
|
resizeto = int(2)
|
|
elif(resize_to == "Resize to Source"):
|
|
resizeto = int(3)
|
|
|
|
resizetype = "Crop"
|
|
if(resize_type == "Stretch"):
|
|
resizetype = "Stretch"
|
|
|
|
masktype = int(0)
|
|
if(mask_type == "Mask Editor"):
|
|
masktype = int(1)
|
|
elif(mask_type == "Mask Editor (inverted)"):
|
|
masktype = int(2)
|
|
elif(mask_type == "Red from Image"):
|
|
masktype = int(3)
|
|
elif(mask_type == "Green from Image"):
|
|
masktype = int(4)
|
|
elif(mask_type == "Blue from Image"):
|
|
masktype = int(5)
|
|
|
|
imageprepare_settings = masktype, resizeto, resizetype, offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening
|
|
|
|
return(imageprepare_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class InstantIDMaskPrepare_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"imageprepare_settings": ("BASIC_PIPE",),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("INT","INT",["Crop","Stretch"],"INT","INT","INT","INT","INT","INT","INT","INT","INT","INT",["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],"FLOAT",)
|
|
RETURN_NAMES = ("mask_type","resize_to","resize_type","offset_width","offset_height","crop_left","crop_right","crop_top","crop_bottom","padding_left","padding_right","padding_top","padding_bottom","interpolation","sharpening",)
|
|
FUNCTION = "get_imageprepare"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def get_imageprepare(self,imageprepare_settings):
|
|
|
|
masktype,resizeto,resizetype,offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening = imageprepare_settings
|
|
|
|
return(masktype,resizeto,resizetype,offset_width,offset_height,crop_left,crop_right,crop_top,crop_bottom,padding_left,padding_right,padding_top,padding_bottom,interpolation,sharpening)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Revision_Settings:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"rev1_strength": ("FLOAT", {"default": 1, "min": 0, "max": 10, "step": 0.1}),
|
|
"rev2_strength": ("FLOAT", {"default": 1, "min": 0, "max": 10, "step": 0.1}),
|
|
|
|
"rev1_noiseaug": ("FLOAT", {"default": 0, "min": 0, "max": 1, "step": 0.1}),
|
|
"rev2_noiseaug": ("FLOAT", {"default": 0, "min": 0, "max": 1, "step": 0.1}),
|
|
|
|
"rev1_crop": (["center","top", "bottom", "left", "right"],),
|
|
"rev1_offset": ("INT", { "default": 0, "min": -2048, "max": 2048, "step": 1, "display": "number" }),
|
|
|
|
"rev2_crop": (["center","top", "bottom", "left", "right"],),
|
|
"rev2_offset": ("INT", { "default": 0, "min": -2048, "max": 2048, "step": 1, "display": "number" }),
|
|
|
|
"crop_intpol": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"crop_res": ("INT", { "default": 224 , "min": 224, "max": 1792, "step": 224, "display": "number" }),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("revision_settings",)
|
|
FUNCTION = "get_revmode"
|
|
|
|
CATEGORY="JPS Nodes/Settings"
|
|
|
|
def get_revmode(self,crop_res,crop_intpol,rev1_crop,rev1_offset,rev2_crop,rev2_offset,rev1_strength,rev2_strength,rev1_noiseaug,rev2_noiseaug,):
|
|
rev1strength = 0
|
|
rev1noiseaug = 0
|
|
rev2strength = 0
|
|
rev2noiseaug = 0
|
|
|
|
rev1strength = rev1_strength
|
|
rev1noiseaug = rev1_noiseaug
|
|
rev2strength = rev2_strength
|
|
rev2noiseaug = rev2_noiseaug
|
|
|
|
revision_settings = crop_res,crop_intpol,rev1_crop,rev1_offset,rev2_crop,rev2_offset,rev1strength,rev2strength,rev1noiseaug,rev2_noiseaug
|
|
|
|
return(revision_settings,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Revision_Settings_Pipe:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"revision_settings": ("BASIC_PIPE",),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("INT",["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],["center","top", "bottom", "left", "right"],"INT",["center","top", "bottom", "left", "right"],"INT","FLOAT","FLOAT","FLOAT","FLOAT",)
|
|
RETURN_NAMES = ("crop_res", "crop_intpol", "rev1_crop", "rev1_offset", "rev2_crop", "rev2_offset", "rev1_strength", "rev2_strength", "rev1_noiseaug", "rev2_noiseaug",)
|
|
FUNCTION = "get_revmode"
|
|
|
|
CATEGORY="JPS Nodes/Pipes"
|
|
|
|
def get_revmode(self,revision_settings):
|
|
|
|
crop_res,crop_intpol,rev1_crop,rev1_offset,rev2_crop,rev2_offset,rev1strength,rev2strength,rev1noiseaug,rev2noiseaug = revision_settings
|
|
|
|
return(int(crop_res),crop_intpol,rev1_crop,int(rev1_offset),rev2_crop,int(rev2_offset),float(rev1strength),float(rev2strength),float(rev1noiseaug),float(rev2noiseaug),)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Sampler_Scheduler_Settings:
|
|
CATEGORY = 'JPS Nodes/Settings'
|
|
RETURN_TYPES = (comfy.samplers.KSampler.SAMPLERS,comfy.samplers.KSampler.SCHEDULERS,)
|
|
RETURN_NAMES = ("sampler_name","scheduler",)
|
|
FUNCTION = "get_samsched"
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {"required": {"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),"scheduler": (comfy.samplers.KSampler.SCHEDULERS,)}}
|
|
|
|
def get_samsched(self, sampler_name, scheduler):
|
|
return (sampler_name, scheduler, )
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Image_Switch:
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("img_out",)
|
|
FUNCTION = "get_image"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {}),
|
|
},
|
|
"optional": {
|
|
"img_1": ("IMAGE",),
|
|
"img_2": ("IMAGE",),
|
|
"img_3": ("IMAGE",),
|
|
"img_4": ("IMAGE",),
|
|
"img_5": ("IMAGE",),
|
|
}
|
|
}
|
|
|
|
def get_image(self,select,img_1,img_2=None,img_3=None,img_4=None,img_5=None,):
|
|
|
|
img_out = img_1
|
|
|
|
if (select == 2):
|
|
img_out = img_2
|
|
elif (select == 3):
|
|
img_out = img_3
|
|
elif (select == 4):
|
|
img_out = img_4
|
|
elif (select == 5):
|
|
img_out = img_5
|
|
|
|
return (img_out,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Conditioning_Switch:
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = ("CONDITIONING",)
|
|
RETURN_NAMES = ("con_out",)
|
|
FUNCTION = "get_con"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {}),
|
|
},
|
|
"optional": {
|
|
"con_1": ("CONDITIONING",),
|
|
"con_2": ("CONDITIONING",),
|
|
"con_3": ("CONDITIONING",),
|
|
"con_4": ("CONDITIONING",),
|
|
"con_5": ("CONDITIONING",),
|
|
}
|
|
}
|
|
|
|
def get_con(self,select,con_1,con_2=None,con_3=None,con_4=None,con_5=None,):
|
|
|
|
con_out = con_1
|
|
|
|
if (select == 2):
|
|
con_out = con_2
|
|
elif (select == 3):
|
|
con_out = con_3
|
|
elif (select == 4):
|
|
con_out = con_4
|
|
elif (select == 5):
|
|
con_out = con_5
|
|
|
|
return (con_out,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Model_Switch:
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = ("MODEL",)
|
|
RETURN_NAMES = ("model_out",)
|
|
FUNCTION = "get_model"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {}),
|
|
},
|
|
"optional": {
|
|
"model_1": ("MODEL",),
|
|
"model_2": ("MODEL",),
|
|
"model_3": ("MODEL",),
|
|
"model_4": ("MODEL",),
|
|
"model_5": ("MODEL",),
|
|
}
|
|
}
|
|
|
|
def get_model(self,select,model_1,model_2=None,model_3=None,model_4=None,model_5=None,):
|
|
|
|
model_out = model_1
|
|
|
|
if (select == 2):
|
|
model_out = model_2
|
|
elif (select == 3):
|
|
model_out = model_3
|
|
elif (select == 4):
|
|
model_out = model_4
|
|
elif (select == 5):
|
|
model_out = model_5
|
|
|
|
return (model_out,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class IPA_Switch:
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = ("IPADAPTER",)
|
|
RETURN_NAMES = ("IPA_out",)
|
|
FUNCTION = "get_ipa"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {}),
|
|
},
|
|
"optional": {
|
|
"ipa_1": ("IPADAPTER",),
|
|
"ipa_2": ("IPADAPTER",),
|
|
"ipa_3": ("IPADAPTER",),
|
|
"ipa_4": ("IPADAPTER",),
|
|
"ipa_5": ("IPADAPTER",),
|
|
}
|
|
}
|
|
|
|
def get_ipa(self,select,ipa_1,ipa_2=None,ipa_3=None,ipa_4=None,ipa_5=None,):
|
|
|
|
ipa_out = ipa_1
|
|
|
|
if (select == 2):
|
|
ipa_out = ipa_2
|
|
elif (select == 3):
|
|
ipa_out = ipa_3
|
|
elif (select == 4):
|
|
ipa_out = ipa_4
|
|
elif (select == 5):
|
|
ipa_out = ipa_5
|
|
|
|
return (ipa_out,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Latent_Switch:
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = ("LATENT",)
|
|
RETURN_NAMES = ("latent_out",)
|
|
FUNCTION = "get_latent"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {}),
|
|
},
|
|
"optional": {
|
|
"latent_1": ("LATENT",),
|
|
"latent_2": ("LATENT",),
|
|
"latent_3": ("LATENT",),
|
|
"latent_4": ("LATENT",),
|
|
"latent_5": ("LATENT",),
|
|
}
|
|
}
|
|
|
|
def get_latent(self,select,latent_1=None,latent_2=None,latent_3=None,latent_4=None,latent_5=None,):
|
|
|
|
latent_out = latent_1
|
|
|
|
if (select == 2):
|
|
latent_out = latent_2
|
|
elif (select == 3):
|
|
latent_out = latent_3
|
|
elif (select == 4):
|
|
latent_out = latent_4
|
|
elif (select == 5):
|
|
latent_out = latent_5
|
|
|
|
return (latent_out,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class VAE_Switch:
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = ("VAE",)
|
|
RETURN_NAMES = ("vae_out",)
|
|
FUNCTION = "get_vae"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {}),
|
|
},
|
|
"optional": {
|
|
"vae_1": ("VAE",),
|
|
"vae_2": ("VAE",),
|
|
"vae_3": ("VAE",),
|
|
"vae_4": ("VAE",),
|
|
"vae_5": ("VAE",),
|
|
}
|
|
}
|
|
|
|
def get_vae(self,select,vae_1=None,vae_2=None,vae_3=None,vae_4=None,vae_5=None,):
|
|
|
|
vae_out = vae_1
|
|
|
|
if (select == 2):
|
|
vae_out = vae_2
|
|
elif (select == 3):
|
|
vae_out = vae_3
|
|
elif (select == 4):
|
|
vae_out = vae_4
|
|
elif (select == 5):
|
|
vae_out = vae_5
|
|
|
|
return (vae_out,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Integer_Switch:
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = ("INT",)
|
|
RETURN_NAMES = ("int_out",)
|
|
FUNCTION = "get_int"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {}),
|
|
},
|
|
"optional": {
|
|
"int_1": ("INT", {}),
|
|
"int_2": ("INT", {}),
|
|
"int_3": ("INT", {}),
|
|
"int_4": ("INT", {}),
|
|
"int_5": ("INT", {}),
|
|
}
|
|
}
|
|
|
|
def get_int(self,select,int_1=None,int_2=None,int_3=None,int_4=None,int_5=None,):
|
|
|
|
int_out = int_1
|
|
|
|
if (select == 2):
|
|
int_out = int_2
|
|
elif (select == 3):
|
|
int_out = int_3
|
|
elif (select == 4):
|
|
int_out = int_4
|
|
elif (select == 5):
|
|
int_out = int_5
|
|
|
|
return (int_out,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Mask_Switch:
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = ("MASK",)
|
|
RETURN_NAMES = ("mask_out",)
|
|
FUNCTION = "get_mask"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {}),
|
|
},
|
|
"optional": {
|
|
"mask_1": ("MASK",),
|
|
"mask_2": ("MASK",),
|
|
"mask_3": ("MASK",),
|
|
"mask_4": ("MASK",),
|
|
"mask_5": ("MASK",),
|
|
}
|
|
}
|
|
|
|
def get_mask(self,select,mask_1=None,mask_2=None,mask_3=None,mask_4=None,mask_5=None,):
|
|
|
|
mask_out = None
|
|
|
|
if (select == 1):
|
|
mask_out = mask_1
|
|
if (select == 2):
|
|
mask_out = mask_2
|
|
elif (select == 3):
|
|
mask_out = mask_3
|
|
elif (select == 4):
|
|
mask_out = mask_4
|
|
elif (select == 5):
|
|
mask_out = mask_5
|
|
|
|
return (mask_out,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class ControlNet_Switch:
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = ("CONTROL_NET",)
|
|
RETURN_NAMES = ("ctrlnet_out",)
|
|
FUNCTION = "get_ctrlnet"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {}),
|
|
},
|
|
"optional": {
|
|
"ctrlnet_1": ("CONTROL_NET",),
|
|
"ctrlnet_2": ("CONTROL_NET",),
|
|
"ctrlnet_3": ("CONTROL_NET",),
|
|
"ctrlnet_4": ("CONTROL_NET",),
|
|
"ctrlnet_5": ("CONTROL_NET",),
|
|
}
|
|
}
|
|
|
|
def get_ctrlnet(self,select,ctrlnet_1=None,ctrlnet_2=None,ctrlnet_3=None,ctrlnet_4=None,ctrlnet_5=None,):
|
|
|
|
ctrlnet_out = ctrlnet_1
|
|
|
|
if (select == 2):
|
|
ctrlnet_out = ctrlnet_2
|
|
elif (select == 3):
|
|
ctrlnet_out = ctrlnet_3
|
|
elif (select == 4):
|
|
ctrlnet_out = ctrlnet_4
|
|
elif (select == 5):
|
|
ctrlnet_out = ctrlnet_5
|
|
|
|
return (ctrlnet_out,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class SDXL_Fundamentals_MultiPipe:
|
|
|
|
CATEGORY = 'JPS Nodes/Pipes'
|
|
RETURN_TYPES = ("VAE","MODEL","MODEL","CLIP","CLIP","CONDITIONING","CONDITIONING","CONDITIONING","CONDITIONING","INT",)
|
|
RETURN_NAMES = ("vae","model_base","model_refiner","clip_base","clip_refiner","pos_base","neg_base","pos_refiner","neg_refiner","seed",)
|
|
FUNCTION = "get_sdxlfund"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {},
|
|
"optional": {
|
|
"vae": ("VAE",),
|
|
"model_base": ("MODEL",),
|
|
"model_refiner": ("MODEL",),
|
|
"clip_base": ("CLIP",),
|
|
"clip_refiner": ("CLIP",),
|
|
"pos_base": ("CONDITIONING",),
|
|
"neg_base": ("CONDITIONING",),
|
|
"pos_refiner": ("CONDITIONING",),
|
|
"neg_refiner": ("CONDITIONING",),
|
|
"seed": ("INT", {}),
|
|
}
|
|
}
|
|
|
|
def get_sdxlfund(self,vae=None,model_base=None,model_refiner=None,clip_base=None,clip_refiner=None,pos_base=None,neg_base=None,pos_refiner=None,neg_refiner=None,seed=None):
|
|
|
|
return (vae,model_base,model_refiner,clip_base,clip_refiner,pos_base,neg_base,pos_refiner,neg_refiner,seed,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Images_Masks_MultiPipe:
|
|
|
|
CATEGORY = 'JPS Nodes/Pipes'
|
|
RETURN_TYPES = ("IMAGE","MASK","IMAGE","IMAGE","MASK","MASK","IMAGE","IMAGE","MODEL",)
|
|
RETURN_NAMES = ("generation_img","generation_mask","ipa1_img","ipa2_img","ipa1_mask","ipa2_mask","revision1_img","revision2_img","inpaint_model",)
|
|
FUNCTION = "get_imagemask"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {},
|
|
"optional": {
|
|
"generation_img": ("IMAGE",),
|
|
"generation_mask": ("MASK",),
|
|
"ipa1_img": ("IMAGE",),
|
|
"ipa2_img": ("IMAGE",),
|
|
"ipa1_mask": ("MASK",),
|
|
"ipa2_mask": ("MASK",),
|
|
"revision1_img": ("IMAGE",),
|
|
"revision2_img": ("IMAGE",),
|
|
"inpaint_model": ("MODEL",),
|
|
}
|
|
}
|
|
|
|
def get_imagemask(self,generation_img=None,generation_mask=None,ipa1_img=None,ipa2_img=None,ipa1_mask=None,ipa2_mask=None,revision1_img=None,revision2_img=None,inpaint_model=None,):
|
|
|
|
return (generation_img,generation_mask,ipa1_img,ipa2_img,ipa1_mask,ipa2_mask,revision1_img,revision2_img,inpaint_model,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Disable_Enable_Switch:
|
|
match = ["Set to Disable","Set to Enable"]
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = (["disable","enable"],)
|
|
RETURN_NAMES = ("disable_enable",)
|
|
FUNCTION = "get_disenable"
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {"default": 1, "min": 1, "max": 9, "step": 1}),
|
|
"compare": ("INT", {"default": 1, "min": 1, "max": 9, "step": 1}),
|
|
"match": (s.match,),
|
|
}
|
|
}
|
|
|
|
def get_disenable(self,select,compare,match):
|
|
disable_enable = "disable"
|
|
if match == "Set to Enable" and (int(select) == int(compare)):
|
|
disable_enable = "enable"
|
|
elif match == "Set to Disable" and (int(select) == int(compare)):
|
|
disable_enable = "disable"
|
|
elif match == "Set to Enable" and (int(select) != int(compare)):
|
|
disable_enable = "disable"
|
|
elif match == "Set to Disable" and (int(select) != int(compare)):
|
|
disable_enable = "enable"
|
|
|
|
return (disable_enable, )
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Enable_Disable_Switch:
|
|
match = ["Set to Enable","Set to Disable"]
|
|
|
|
CATEGORY = 'JPS Nodes/Switches'
|
|
RETURN_TYPES = (["enable","disable"],)
|
|
RETURN_NAMES = ("enable_disable",)
|
|
FUNCTION = "get_endisable"
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"select": ("INT", {"default": 1, "min": 1, "max": 9, "step": 1}),
|
|
"compare": ("INT", {"default": 1, "min": 1, "max": 9, "step": 1}),
|
|
"match": (s.match,),
|
|
}
|
|
}
|
|
|
|
def get_endisable(self,select,compare,match):
|
|
enable_disable = "disable"
|
|
if match == "Set to Enable" and (int(select) == int(compare)):
|
|
enable_disable = "enable"
|
|
elif match == "Set to Disable" and (int(select) == int(compare)):
|
|
enable_disable = "disable"
|
|
elif match == "Set to Enable" and (int(select) != int(compare)):
|
|
enable_disable = "disable"
|
|
elif match == "Set to Disable" and (int(select) != int(compare)):
|
|
enable_disable = "enable"
|
|
|
|
return (enable_disable, )
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class IO_Lora_Loader:
|
|
def __init__(self):
|
|
self.loaded_lora = None
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
file_list = folder_paths.get_filename_list("loras")
|
|
file_list.insert(0, "None")
|
|
return {"required": { "model": ("MODEL",),
|
|
"clip": ("CLIP", ),
|
|
"switch": ([
|
|
"Off",
|
|
"On"],),
|
|
"lora_name": (file_list, ),
|
|
"strength_model": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}),
|
|
"strength_clip": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}),
|
|
}}
|
|
RETURN_TYPES = ("MODEL", "CLIP")
|
|
FUNCTION = "load_lora"
|
|
|
|
CATEGORY = "JPS Nodes/IO"
|
|
|
|
def load_lora(self, model, clip, switch, lora_name, strength_model, strength_clip):
|
|
if strength_model == 0 and strength_clip == 0:
|
|
return (model, clip)
|
|
|
|
if switch == "Off" or lora_name == "None":
|
|
return (model, clip)
|
|
|
|
lora_path = folder_paths.get_full_path("loras", lora_name)
|
|
lora = None
|
|
if self.loaded_lora is not None:
|
|
if self.loaded_lora[0] == lora_path:
|
|
lora = self.loaded_lora[1]
|
|
else:
|
|
del self.loaded_lora
|
|
|
|
if lora is None:
|
|
lora = comfy.utils.load_torch_file(lora_path, safe_load=True)
|
|
self.loaded_lora = (lora_path, lora)
|
|
|
|
model_lora, clip_lora = comfy.sd.load_lora_for_models(model, clip, lora, strength_model, strength_clip)
|
|
return (model_lora, clip_lora)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Get_Image_Size:
|
|
def __init__(self) -> None:
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE",),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("INT", "INT",)
|
|
RETURN_NAMES = ("width", "height",)
|
|
CATEGORY = "JPS Nodes/Image"
|
|
|
|
FUNCTION = 'get_imagesize'
|
|
|
|
def get_imagesize(self, image):
|
|
samples = image.movedim(-1,1)
|
|
size_w = samples.shape[3]
|
|
size_h = samples.shape[2]
|
|
|
|
return (size_w, size_h, )
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class SDXL_Prompt_Styler:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
uni_neg = ["OFF","ON"]
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(self):
|
|
current_directory = os.path.dirname(os.path.realpath(__file__))
|
|
self.json_data_artists, artists = load_styles_from_directory(os.path.join(current_directory, 'styles', 'artists'))
|
|
self.json_data_movies, movies = load_styles_from_directory(os.path.join(current_directory, 'styles', 'movies'))
|
|
self.json_data_styles, styles = load_styles_from_directory(os.path.join(current_directory, 'styles', 'main'))
|
|
|
|
return {
|
|
"required": {
|
|
"text_positive_g": ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}),
|
|
"text_positive_l": ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}),
|
|
"text_negative": ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}),
|
|
"artist": ((artists), ),
|
|
"movie": ((movies), ),
|
|
"style": ((styles), ),
|
|
"fooocus_enhance": (self.uni_neg,),
|
|
"fooocus_negative": (self.uni_neg,),
|
|
"universal_negative": (self.uni_neg,),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ('STRING','STRING','STRING','STRING',)
|
|
RETURN_NAMES = ('text_positive_g','text_positive_l','text_positive','text_negative',)
|
|
FUNCTION = 'sdxlpromptstyler'
|
|
CATEGORY = 'JPS Nodes/Style'
|
|
|
|
def sdxlpromptstyler(self, text_positive_g, text_positive_l, text_negative, artist, movie, style, fooocus_enhance, fooocus_negative, universal_negative):
|
|
# Process and combine prompts in templates
|
|
# The function replaces the positive prompt placeholder in the template,
|
|
# and combines the negative prompt with the template's negative prompt, if they exist.
|
|
|
|
text_pos_g_style = ""
|
|
text_pos_l_style = ""
|
|
text_pos_style = ""
|
|
text_neg_style = ""
|
|
|
|
text_pos_g_artist, text_pos_l_artist, text_neg_artist = read_sdxl_templates_replace_and_combine(self.json_data_artists, artist, text_positive_g, text_positive_l, text_negative)
|
|
|
|
if(text_positive_g == text_positive_l):
|
|
if(text_pos_l_artist != text_positive_l and text_pos_g_artist != text_positive_g):
|
|
text_positive_l = ""
|
|
text_pos_g_artist, text_pos_l_artist, text_neg_artist = read_sdxl_templates_replace_and_combine(self.json_data_artist, artist, text_positive_g, text_positive_l, text_negative)
|
|
elif(text_pos_g_artist != text_positive_g):
|
|
text_pos_l_artist = text_pos_g_artist
|
|
elif(text_pos_l_artist != text_positive_l):
|
|
text_pos_g_artist = text_pos_l_artist
|
|
|
|
text_pos_g_movie, text_pos_l_movie, text_neg_movie = read_sdxl_templates_replace_and_combine(self.json_data_movies, movie, text_pos_g_artist, text_pos_l_artist, text_negative)
|
|
|
|
if(text_pos_g_artist == text_pos_l_artist):
|
|
if(text_pos_l_movie != text_pos_l_artist and text_pos_g_movie != text_pos_g_artist):
|
|
text_pos_l_artist = ""
|
|
text_pos_g_movie, text_pos_l_movie, text_neg_movie = read_sdxl_templates_replace_and_combine(self.json_data_movie, movie, text_positive_g, text_positive_l, text_negative)
|
|
elif(text_pos_g_movie != text_pos_g_artist):
|
|
text_pos_l_movie = text_pos_g_movie
|
|
elif(text_pos_l_movie != text_pos_l_artist):
|
|
text_pos_g_movie = text_pos_l_movie
|
|
|
|
text_pos_g_style, text_pos_l_style, text_neg_style = read_sdxl_templates_replace_and_combine(self.json_data_styles, style, text_pos_g_movie, text_pos_l_movie, text_neg_movie)
|
|
|
|
if(text_pos_g_movie == text_pos_l_movie):
|
|
if(text_pos_l_movie != text_pos_l_style and text_pos_g_movie != text_pos_g_style):
|
|
text_pos_l_movie = ""
|
|
text_pos_g_style, text_pos_l_style, text_neg_style = read_sdxl_templates_replace_and_combine(self.json_data_styles, style, text_pos_g_movie, text_pos_l_movie, text_neg_movie)
|
|
elif(text_pos_g_movie != text_pos_g_style):
|
|
text_pos_l_style = text_pos_g_style
|
|
elif(text_pos_l_movie != text_pos_l_style):
|
|
text_pos_g_style = text_pos_l_style
|
|
|
|
if(text_pos_g_style != text_pos_l_style):
|
|
if(text_pos_l_style != ""):
|
|
text_pos_style = text_pos_g_style + ' . ' + text_pos_l_style
|
|
else:
|
|
text_pos_style = text_pos_g_style
|
|
else:
|
|
text_pos_style = text_pos_g_style
|
|
|
|
if(fooocus_enhance == "ON"):
|
|
if (text_neg_style != ''):
|
|
text_neg_style = text_neg_style + ', (worst quality, low quality, normal quality, lowres, low details, oversaturated, undersaturated, overexposed, underexposed, grayscale, bw, bad photo, bad photography, bad art:1.4), (watermark, signature, text font, username, error, logo, words, letters, digits, autograph, trademark, name:1.2), (blur, blurry, grainy), morbid, ugly, asymmetrical, mutated malformed, mutilated, poorly lit, bad shadow, draft, cropped, out of frame, cut off, censored, jpeg artifacts, out of focus, glitch, duplicate, (airbrushed, cartoon, anime, semi-realistic, cgi, render, blender, digital art, manga, amateur:1.3), (3D ,3D Game, 3D Game Scene, 3D Character:1.1), (bad hands, bad anatomy, bad body, bad face, bad teeth, bad arms, bad legs, deformities:1.3)'
|
|
else:
|
|
text_neg_style = '(worst quality, low quality, normal quality, lowres, low details, oversaturated, undersaturated, overexposed, underexposed, grayscale, bw, bad photo, bad photography, bad art:1.4), (watermark, signature, text font, username, error, logo, words, letters, digits, autograph, trademark, name:1.2), (blur, blurry, grainy), morbid, ugly, asymmetrical, mutated malformed, mutilated, poorly lit, bad shadow, draft, cropped, out of frame, cut off, censored, jpeg artifacts, out of focus, glitch, duplicate, (airbrushed, cartoon, anime, semi-realistic, cgi, render, blender, digital art, manga, amateur:1.3), (3D ,3D Game, 3D Game Scene, 3D Character:1.1), (bad hands, bad anatomy, bad body, bad face, bad teeth, bad arms, bad legs, deformities:1.3)'
|
|
|
|
if(fooocus_negative == "ON"):
|
|
if (text_neg_style != ''):
|
|
text_neg_style = text_neg_style + ', deformed, bad anatomy, disfigured, poorly drawn face, mutated, extra limb, ugly, poorly drawn hands, missing limb, floating limbs, disconnected limbs, disconnected head, malformed hands, long neck, mutated hands and fingers, bad hands, missing fingers, cropped, worst quality, low quality, mutation, poorly drawn, huge calf, bad hands, fused hand, missing hand, disappearing arms, disappearing thigh, disappearing calf, disappearing legs, missing fingers, fused fingers, abnormal eye proportion, Abnormal hands, abnormal legs, abnormal feet, abnormal fingers, drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch'
|
|
else:
|
|
text_neg_style = 'deformed, bad anatomy, disfigured, poorly drawn face, mutated, extra limb, ugly, poorly drawn hands, missing limb, floating limbs, disconnected limbs, disconnected head, malformed hands, long neck, mutated hands and fingers, bad hands, missing fingers, cropped, worst quality, low quality, mutation, poorly drawn, huge calf, bad hands, fused hand, missing hand, disappearing arms, disappearing thigh, disappearing calf, disappearing legs, missing fingers, fused fingers, abnormal eye proportion, Abnormal hands, abnormal legs, abnormal feet, abnormal fingers, drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch'
|
|
|
|
if(universal_negative == "ON"):
|
|
if (text_neg_style != ''):
|
|
text_neg_style = text_neg_style + ', text, watermark, low-quality, signature, moire pattern, downsampling, aliasing, distorted, blurry, glossy, blur, jpeg artifacts, compression artifacts, poorly drawn, low-resolution, bad, distortion, twisted, excessive, exaggerated pose, exaggerated limbs, grainy, symmetrical, duplicate, error, pattern, beginner, pixelated, fake, hyper, glitch, overexposed, high-contrast, bad-contrast'
|
|
else:
|
|
text_neg_style = 'text, watermark, low-quality, signature, moire pattern, downsampling, aliasing, distorted, blurry, glossy, blur, jpeg artifacts, compression artifacts, poorly drawn, low-resolution, bad, distortion, twisted, excessive, exaggerated pose, exaggerated limbs, grainy, symmetrical, duplicate, error, pattern, beginner, pixelated, fake, hyper, glitch, overexposed, high-contrast, bad-contrast'
|
|
|
|
return text_pos_g_style, text_pos_l_style, text_pos_style, text_neg_style
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Crop_Image_Square:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE",),
|
|
"crop_position": (["center", "top", "bottom", "left", "right"],),
|
|
"offset_x": ("INT", { "default": 0, "min": -4096, "max": 4096, "step": 1, "display": "number" }),
|
|
"offset_y": ("INT", { "default": 0, "min": -4096, "max": 4096, "step": 1, "display": "number" }),
|
|
"zoom": ("FLOAT", { "default": 1, "min": 1, "max": 5, "step": 0.1, "display": "number" }),
|
|
"interpolation": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"target_rez": ("INT", { "default": 0 , "min": 0, "step": 8, "display": "number" }),
|
|
"sharpening": ("FLOAT", {"default": 0.0, "min": 0, "max": 1, "step": 0.05}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "crop_square"
|
|
CATEGORY = "JPS Nodes/Image"
|
|
|
|
def crop_square(self, image, crop_position, offset_x, offset_y, zoom, interpolation, target_rez,sharpening):
|
|
_, h, w, _ = image.shape
|
|
crop_size = min(h, w)
|
|
|
|
offset_x = int (offset_x * zoom)
|
|
offset_y = int (offset_y * zoom)
|
|
|
|
if "center" in crop_position:
|
|
x = round((w*zoom-crop_size) / 2)
|
|
y = round((h*zoom-crop_size) / 2)
|
|
if "top" in crop_position:
|
|
x = round((w*zoom-crop_size) / 2)
|
|
y = 0
|
|
if "bottom" in crop_position:
|
|
x = round((w*zoom-crop_size) / 2)
|
|
y = h*zoom-crop_size
|
|
if "left" in crop_position:
|
|
x = 0
|
|
y = round((h*zoom-crop_size) / 2)
|
|
if "right" in crop_position:
|
|
x = w*zoom-crop_size
|
|
y = round((h*zoom-crop_size) / 2)
|
|
|
|
x = int(x)
|
|
y = int(y)
|
|
|
|
if (x + offset_x >= 0 and x + crop_size + offset_x <= int(w*zoom)):
|
|
x = x + offset_x
|
|
elif (x + offset_x >= 0):
|
|
x = int(w*zoom) - crop_size
|
|
elif (x + crop_size + offset_x <= int(w*zoom)):
|
|
x = 0
|
|
|
|
if (y + offset_y >= 0 and y + crop_size + offset_y <= int(h*zoom)):
|
|
y = y + offset_y
|
|
elif (y + offset_y >= 0):
|
|
y = int(h*zoom) - crop_size
|
|
elif (y + crop_size + offset_y <= int(h*zoom)):
|
|
y = 0
|
|
|
|
x2 = x+crop_size
|
|
y2 = y+crop_size
|
|
|
|
zoomedimage = image[:, 0:h, 0:w, :]
|
|
|
|
zoomedimage = zoomedimage.permute([0,3,1,2])
|
|
|
|
zoomedimage = comfy.utils.lanczos(zoomedimage, int(w*zoom), int(h*zoom))
|
|
|
|
zoomedimage = zoomedimage.permute([0,2,3,1])
|
|
|
|
output = zoomedimage[:, y:y2, x:x2, :]
|
|
|
|
output = output.permute([0,3,1,2])
|
|
|
|
if target_rez != 0:
|
|
if interpolation == "lanczos":
|
|
output = comfy.utils.lanczos(output, target_rez, target_rez)
|
|
else:
|
|
output = F.interpolate(output, size=(target_rez, target_rez), mode=interpolation)
|
|
|
|
if sharpening > 0:
|
|
output = contrast_adaptive_sharpening(output, sharpening)
|
|
|
|
output = output.permute([0,2,3,1])
|
|
|
|
return(output, )
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Crop_Image_TargetSize:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE",),
|
|
"target_w": ("INT", { "default": 0 , "min": 0, "step": 8, "display": "number" }),
|
|
"target_h": ("INT", { "default": 0 , "min": 0, "step": 8, "display": "number" }),
|
|
"crop_position": (["center","top", "bottom", "left", "right"],),
|
|
"offset": ("INT", { "default": 0, "min": -2048, "max": 2048, "step": 1, "display": "number" }),
|
|
"interpolation": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"sharpening": ("FLOAT", {"default": 0.0, "min": 0, "max": 1, "step": 0.05}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "crop_targetsize"
|
|
CATEGORY = "JPS Nodes/Image"
|
|
|
|
def crop_targetsize(self, image, target_w, target_h, crop_position, offset, interpolation, sharpening):
|
|
_, current_h, current_w, _ = image.shape
|
|
|
|
current_ar = current_w / current_h
|
|
|
|
if target_w / current_ar >= target_h:
|
|
new_w = target_w
|
|
new_h = round(new_w / current_ar)
|
|
offset_h = offset
|
|
offset_w = 0
|
|
else:
|
|
new_h = target_h
|
|
new_w = round(new_h * current_ar)
|
|
offset_w = offset
|
|
offset_h = 0
|
|
|
|
# print("New Size")
|
|
# print(new_w)
|
|
# print(new_h)
|
|
|
|
resized_image = image.permute([0,3,1,2])
|
|
|
|
if interpolation == "lanczos":
|
|
resized_image = comfy.utils.lanczos(resized_image, new_w, new_h)
|
|
else:
|
|
resized_image = F.interpolate(resized_image, size=(new_h, new_w), mode=interpolation)
|
|
|
|
resized_image = resized_image.permute([0,2,3,1])
|
|
|
|
output_image = resized_image
|
|
|
|
if (crop_position == "left"):
|
|
newoffset_w = offset_w
|
|
elif (crop_position == "right"):
|
|
newoffset_w = new_w - target_w + offset_w
|
|
else:
|
|
newoffset_w = (new_w - target_w) // 2 + offset_w
|
|
|
|
if (crop_position == "top"):
|
|
newoffset_h = offset_h
|
|
elif (crop_position == "bottom"):
|
|
newoffset_h = new_h - target_h + offset_h
|
|
else:
|
|
newoffset_h = (new_h - target_h) // 2 + offset_h
|
|
|
|
if newoffset_w < 0:
|
|
newoffset_w = 0
|
|
elif newoffset_w + target_w > new_w:
|
|
newoffset_w = new_w - target_w
|
|
|
|
if newoffset_h < 0:
|
|
newoffset_h = 0
|
|
elif newoffset_h + target_h > new_h:
|
|
newoffset_h = new_h - target_h
|
|
|
|
x = newoffset_w
|
|
x2 = newoffset_w+target_w
|
|
y = newoffset_h
|
|
y2 = newoffset_h+target_h
|
|
|
|
# print("x: "+str(x))
|
|
# print("x2: "+str(x2))
|
|
# print("y: "+str(y))
|
|
# print("y2: "+str(y2))
|
|
|
|
if sharpening > 0:
|
|
output_image = contrast_adaptive_sharpening(output_image, sharpening)
|
|
|
|
output_image = output_image[:, y:y2, x:x2, :]
|
|
|
|
return(output_image, )
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Prepare_Image_Tiled_IPA:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE",),
|
|
"target_w": ("INT", { "default": 0 , "min": 0, "step": 8, "display": "number" }),
|
|
"target_h": ("INT", { "default": 0 , "min": 0, "step": 8, "display": "number" }),
|
|
"zoom": ("INT", {"default": 1.0, "min": 1, "max": 500, "step": 1}),
|
|
"offset_w": ("INT", { "default": 0, "min": -4096, "max": 4096, "step": 1, "display": "number" }),
|
|
"offset_h": ("INT", { "default": 0, "min": -4096, "max": 4096, "step": 1, "display": "number" }),
|
|
"interpolation": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"sharpening": ("FLOAT", {"default": 0.0, "min": 0, "max": 1, "step": 0.05}),
|
|
"tile_short": ("INT", {"default": 2.0, "min": 1, "max": 5, "step": 1}),
|
|
"prepare_type": ("INT", {"default": 1, "min": 1, "max": 9, "step": 1}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "crop_targetsize"
|
|
CATEGORY = "JPS Nodes/Image"
|
|
|
|
def crop_targetsize(self, image, target_w, target_h, zoom, offset_w, offset_h, interpolation, sharpening,tile_short,prepare_type):
|
|
_, input_h, input_w, _ = image.shape
|
|
|
|
tilelength = tile_short * 224
|
|
|
|
#Direct Source
|
|
if prepare_type == 9:
|
|
copyimage = image
|
|
|
|
#Source_AR + Source_Res
|
|
if prepare_type == 4:
|
|
target_w = input_w
|
|
target_h = input_h
|
|
|
|
#Source_AR + Tile_Res
|
|
if prepare_type == 5:
|
|
target_w = input_w
|
|
target_h = input_h
|
|
prepare_type = 2
|
|
|
|
#Tile_AR + Source_Res
|
|
if prepare_type == 6:
|
|
target_w = input_w
|
|
target_h = input_h
|
|
prepare_type = 3
|
|
|
|
#Square_AR + Target_Res
|
|
if prepare_type == 7:
|
|
target_ar = target_w / target_h
|
|
if target_ar >= 1:
|
|
target_w = target_h
|
|
else:
|
|
target_h = target_w
|
|
|
|
#Square_AR + Tile_Res
|
|
if prepare_type == 8:
|
|
target_w = tilelength
|
|
target_h = tilelength
|
|
|
|
#Target_AR + Tile_Res
|
|
if prepare_type == 2:
|
|
target_ar = target_w / target_h
|
|
if target_ar >= 1:
|
|
target_h = tilelength
|
|
target_w = round(tilelength * target_ar)
|
|
else:
|
|
target_w = tilelength
|
|
target_h = round(tilelength / target_ar)
|
|
|
|
#Tile_AR + Target_Res
|
|
if prepare_type == 3:
|
|
target_ar = target_w / target_h
|
|
if target_ar >= 1:
|
|
target_h = tilelength
|
|
if target_ar < 1.5:
|
|
target_w = tilelength
|
|
elif target_ar < 2:
|
|
target_w = round(tilelength * 1.5)
|
|
elif target_ar < 2.5:
|
|
target_w = round(tilelength * 2)
|
|
elif target_ar < 3:
|
|
target_w = round(tilelength * 2.5)
|
|
elif target_ar < 3.5:
|
|
target_w = round(tilelength * 3)
|
|
else:
|
|
target_w = round(tilelength * target_ar)
|
|
else:
|
|
target_w = tilelength
|
|
target_ar = target_h / target_w
|
|
if target_ar < 1.5:
|
|
target_h = tilelength
|
|
elif target_ar < 2:
|
|
target_h = round(tilelength * 1.5)
|
|
elif target_ar < 2.5:
|
|
target_h = round(tilelength * 2)
|
|
elif target_ar < 3:
|
|
target_h = round(tilelength * 2.5)
|
|
elif target_ar < 3.5:
|
|
target_h = round(tilelength * 3)
|
|
else:
|
|
target_h = round(tilelength * target_ar)
|
|
|
|
zoom = float(zoom / 100)
|
|
|
|
resize_needed_w = target_w / input_w
|
|
resize_needed_h = target_h / input_h
|
|
|
|
if resize_needed_w >= resize_needed_h:
|
|
min_zoom_factor = resize_needed_w
|
|
else:
|
|
min_zoom_factor = resize_needed_h
|
|
|
|
if zoom <= min_zoom_factor:
|
|
zoom_factor = min_zoom_factor
|
|
# elif zoom > min_zoom_factor and min_zoom_factor >=1:
|
|
# zoom_factor = zoom
|
|
# elif zoom > min_zoom_factor and min_zoom_factor < 1:
|
|
# zoom_factor = min_zoom_factor
|
|
else:
|
|
zoom_factor = zoom
|
|
|
|
zoomed_w = round(input_w * zoom_factor)
|
|
zoomed_h = round(input_h * zoom_factor)
|
|
|
|
resized_image = image.permute([0,3,1,2])
|
|
|
|
if interpolation == "lanczos":
|
|
resized_image = comfy.utils.lanczos(resized_image, zoomed_w, zoomed_h)
|
|
else:
|
|
resized_image = F.interpolate(resized_image, size=(zoomed_h, zoomed_w), mode=interpolation)
|
|
|
|
resized_image = resized_image.permute([0,2,3,1])
|
|
|
|
x0 = round((zoomed_w - target_w) / 2)
|
|
x1 = x0 + target_w
|
|
y0 = round((zoomed_h - target_h) / 2)
|
|
y1 = y0 + target_h
|
|
|
|
if x0 + offset_w + target_w < zoomed_w and offset_w > 0:
|
|
x0 = x0 + offset_w
|
|
x1 = x0 + target_w
|
|
elif x0 + offset_w + target_w >= zoomed_w and offset_w > 0:
|
|
x0 = zoomed_w - target_w
|
|
x1 = zoomed_w
|
|
elif x0 + offset_w > 0 and offset_w < 0:
|
|
x0 = x0 + offset_w
|
|
x1 = x0 + target_w
|
|
elif x0 + offset_w <= 0 and offset_w < 0:
|
|
x0 = 0
|
|
x1 = target_w
|
|
|
|
if y0 + offset_h + target_h < zoomed_h and offset_h > 0:
|
|
y0 = y0 + offset_h
|
|
y1 = y0 + target_h
|
|
elif y0 + offset_h + target_h >= zoomed_h and offset_h > 0:
|
|
y0 = zoomed_h - target_h
|
|
y1 = zoomed_h
|
|
elif y0 + offset_h > 0 and offset_h < 0:
|
|
y0 = y0 + offset_h
|
|
y1 = y0 + target_h
|
|
elif y0 + offset_h <= 0 and offset_h < 0:
|
|
y0 = 0
|
|
y1 = target_h
|
|
|
|
output_image = resized_image
|
|
|
|
# print("x0: "+str(x0))
|
|
# print("x1: "+str(x1))
|
|
# print("y0: "+str(y0))
|
|
# print("y1: "+str(y1))
|
|
|
|
if sharpening > 0:
|
|
output_image = contrast_adaptive_sharpening(output_image, sharpening)
|
|
|
|
output_image = output_image[:, y0:y1, x0:x1, :]
|
|
|
|
if prepare_type == 9:
|
|
output_image = copyimage
|
|
|
|
return(output_image,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Prepare_Image:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE",),
|
|
"target_w": ("INT", { "default": 1024 , "min": 0, "step": 8, "display": "number" }),
|
|
"target_h": ("INT", { "default": 1024 , "min": 0, "step": 8, "display": "number" }),
|
|
"crop_w_percent": ("INT", { "default": 100 , "min": 10, "max": 100, "step": 1, "display": "number" }),
|
|
"crop_h_percent": ("INT", { "default": 100 , "min": 10, "max": 100, "step": 1, "display": "number" }),
|
|
"offset_w": ("INT", { "default": 0, "min": -4096, "max": 4096, "step": 1, "display": "number" }),
|
|
"offset_h": ("INT", { "default": 0, "min": -4096, "max": 4096, "step": 1, "display": "number" }),
|
|
"interpolation": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"sharpening": ("FLOAT", {"default": 0.0, "min": 0, "max": 1, "step": 0.05}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "prepare_image"
|
|
CATEGORY = "JPS Nodes/Image"
|
|
|
|
def prepare_image(self, image, target_w, target_h, crop_w_percent, crop_h_percent, offset_w, offset_h, interpolation, sharpening, padding_left, padding_right, padding_top, padding_bottom):
|
|
_, input_h, input_w, _ = image.shape
|
|
|
|
resize_needed_w = target_w / input_w / crop_w_percent * 100
|
|
resize_needed_h = target_h / input_h / crop_h_percent * 100
|
|
|
|
if resize_needed_w >= resize_needed_h:
|
|
min_zoom_factor = resize_needed_w
|
|
else:
|
|
min_zoom_factor = resize_needed_h
|
|
|
|
zoom_factor = min_zoom_factor
|
|
|
|
zoomed_w = round(input_w * zoom_factor)
|
|
zoomed_h = round(input_h * zoom_factor)
|
|
|
|
resized_image = image.permute([0,3,1,2])
|
|
|
|
if interpolation == "lanczos":
|
|
resized_image = comfy.utils.lanczos(resized_image, zoomed_w, zoomed_h)
|
|
else:
|
|
resized_image = F.interpolate(resized_image, size=(zoomed_h, zoomed_w), mode=interpolation)
|
|
|
|
resized_image = resized_image.permute([0,2,3,1])
|
|
|
|
x0 = round((zoomed_w - target_w) / 2)
|
|
x1 = round(x0 + target_w)
|
|
y0 = round((zoomed_h - target_h) / 2)
|
|
y1 = round(y0 + target_h)
|
|
|
|
if x0 + offset_w + target_w < zoomed_w and offset_w > 0:
|
|
x0 = x0 + offset_w
|
|
x1 = x0 + target_w
|
|
elif x0 + offset_w + target_w >= zoomed_w and offset_w > 0:
|
|
x0 = zoomed_w - target_w
|
|
x1 = zoomed_w
|
|
elif x0 + offset_w > 0 and offset_w < 0:
|
|
x0 = x0 + offset_w
|
|
x1 = x0 + target_w
|
|
elif x0 + offset_w <= 0 and offset_w < 0:
|
|
x0 = 0
|
|
x1 = target_w
|
|
|
|
if y0 + offset_h + target_h < zoomed_h and offset_h > 0:
|
|
y0 = y0 + offset_h
|
|
y1 = y0 + target_h
|
|
elif y0 + offset_h + target_h >= zoomed_h and offset_h > 0:
|
|
y0 = zoomed_h - target_h
|
|
y1 = zoomed_h
|
|
elif y0 + offset_h > 0 and offset_h < 0:
|
|
y0 = y0 + offset_h
|
|
y1 = y0 + target_h
|
|
elif y0 + offset_h <= 0 and offset_h < 0:
|
|
y0 = 0
|
|
y1 = target_h
|
|
|
|
output_image = resized_image
|
|
|
|
if sharpening > 0:
|
|
output_image = contrast_adaptive_sharpening(output_image, sharpening)
|
|
|
|
output_image = output_image[:, y0:y1, x0:x1, :]
|
|
|
|
return(output_image,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Prepare_Image_Plus:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE",),
|
|
"target_w": ("INT", { "default": 1024 , "min": 0, "step": 8, "display": "number" }),
|
|
"target_h": ("INT", { "default": 1024 , "min": 0, "step": 8, "display": "number" }),
|
|
"offset_w": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
|
|
"offset_h": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
|
|
"crop_left": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_right": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_top": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"crop_bottom": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
|
|
"padding_left": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_right": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_top": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"padding_bottom": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
|
|
"interpolation": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
|
|
"sharpening": ("FLOAT", {"default": 0.0, "min": 0, "max": 1, "step": 0.05}),
|
|
"resize_type": (["Crop", "Stretch"],),
|
|
"flip": (["No", "X-Axis", "Y-Axis"],),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "prepare_image"
|
|
CATEGORY = "JPS Nodes/Image"
|
|
|
|
def prepare_image(self, image, target_w, target_h, offset_w, offset_h, crop_left, crop_right, crop_top, crop_bottom, padding_left, padding_right, padding_top, padding_bottom,interpolation, sharpening,resize_type,flip):
|
|
_, input_h, input_w, _ = image.shape
|
|
|
|
dim = ()
|
|
if flip == "X-Axis":
|
|
dim += (2,)
|
|
image = torch.flip(image, dim)
|
|
if flip == "Y-Axis":
|
|
dim += (2,)
|
|
image = torch.flip(image, dim)
|
|
|
|
if crop_left + crop_right > 90:
|
|
crop_left = 90 / (crop_left + crop_right) * crop_left
|
|
crop_right = 90 / (crop_left + crop_right) * crop_right
|
|
|
|
if crop_top + crop_bottom > 90:
|
|
crop_top = 90 / (crop_top + crop_bottom) * crop_top
|
|
crop_bottom = 90 / (crop_top + crop_bottom) * crop_bottom
|
|
|
|
left = int(input_w-(input_w * (100-crop_left) / 100))
|
|
right = int(input_w-(input_w * (100-crop_right) / 100))
|
|
top = int(input_h-(input_h * (100-crop_top) / 100))
|
|
bottom = int(input_h-(input_h * (100-crop_bottom) / 100))
|
|
|
|
image = image[:, 0+top:input_h-bottom, 0+left:input_w-right, :]
|
|
|
|
input_h = input_h - top - bottom
|
|
input_w = input_w - left - right
|
|
|
|
left = int(((input_w * (100+padding_left) / 100) - input_w))
|
|
right = int(((input_w * (100+padding_right) / 100) - input_w))
|
|
top = int(((input_h * (100+padding_top) / 100) - input_h))
|
|
bottom = int(((input_h * (100+padding_bottom) / 100) - input_h))
|
|
|
|
pil_image = Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8))
|
|
padded_image = Image.new("RGB", (pil_image.width + left + right, pil_image.height + top + bottom), color="black")
|
|
padded_image.paste(pil_image, (left, top))
|
|
image = torch.from_numpy(np.array(padded_image).astype(np.float32) / 255.0).unsqueeze(0)
|
|
|
|
input_h = input_h + top + bottom
|
|
input_w = input_w + left + right
|
|
|
|
if resize_type != "Stretch":
|
|
|
|
resize_needed_w = target_w / input_w
|
|
resize_needed_h = target_h / input_h
|
|
|
|
if resize_needed_w >= resize_needed_h:
|
|
min_zoom_factor = resize_needed_w
|
|
else:
|
|
min_zoom_factor = resize_needed_h
|
|
|
|
zoom_factor = min_zoom_factor
|
|
|
|
zoomed_w = round(input_w * zoom_factor)
|
|
zoomed_h = round(input_h * zoom_factor)
|
|
|
|
offset_w = int(zoomed_w / 100 * offset_w / 2)
|
|
offset_h = int(zoomed_h / 100 * offset_h / 2)
|
|
|
|
resized_image = image.permute([0,3,1,2])
|
|
|
|
if interpolation == "lanczos":
|
|
resized_image = comfy.utils.lanczos(resized_image, zoomed_w, zoomed_h)
|
|
else:
|
|
resized_image = F.interpolate(resized_image, size=(zoomed_h, zoomed_w), mode=interpolation)
|
|
|
|
resized_image = resized_image.permute([0,2,3,1])
|
|
|
|
x0 = round((zoomed_w - target_w) / 2)
|
|
x1 = round(x0 + target_w)
|
|
y0 = round((zoomed_h - target_h) / 2)
|
|
y1 = round(y0 + target_h)
|
|
|
|
if x0 + offset_w + target_w < zoomed_w and offset_w > 0:
|
|
x0 = x0 + offset_w
|
|
x1 = x0 + target_w
|
|
elif x0 + offset_w + target_w >= zoomed_w and offset_w > 0:
|
|
x0 = zoomed_w - target_w
|
|
x1 = zoomed_w
|
|
elif x0 + offset_w > 0 and offset_w < 0:
|
|
x0 = x0 + offset_w
|
|
x1 = x0 + target_w
|
|
elif x0 + offset_w <= 0 and offset_w < 0:
|
|
x0 = 0
|
|
x1 = target_w
|
|
|
|
if y0 + offset_h + target_h < zoomed_h and offset_h > 0:
|
|
y0 = y0 + offset_h
|
|
y1 = y0 + target_h
|
|
elif y0 + offset_h + target_h >= zoomed_h and offset_h > 0:
|
|
y0 = zoomed_h - target_h
|
|
y1 = zoomed_h
|
|
elif y0 + offset_h > 0 and offset_h < 0:
|
|
y0 = y0 + offset_h
|
|
y1 = y0 + target_h
|
|
elif y0 + offset_h <= 0 and offset_h < 0:
|
|
y0 = 0
|
|
y1 = target_h
|
|
output_image = resized_image
|
|
|
|
output_image = output_image[:, y0:y1, x0:x1, :]
|
|
|
|
else:
|
|
|
|
resized_image = image.permute([0,3,1,2])
|
|
|
|
if interpolation == "lanczos":
|
|
resized_image = comfy.utils.lanczos(resized_image, target_w, target_h)
|
|
else:
|
|
resized_image = F.interpolate(resized_image, size=(target_h, target_w), mode=interpolation)
|
|
|
|
resized_image = resized_image.permute([0,2,3,1])
|
|
output_image = resized_image
|
|
|
|
if sharpening > 0:
|
|
output_image = contrast_adaptive_sharpening(output_image, sharpening)
|
|
|
|
return(output_image,)
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class Save_Images_Plus:
|
|
def __init__(self):
|
|
self.output_dir = folder_paths.get_output_directory()
|
|
self.type = "output"
|
|
self.prefix_append = ""
|
|
self.compress_level = 4
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {"required":
|
|
{"images": ("IMAGE", ),
|
|
"filename_prefix": ("STRING", {"default": "ComfyUI"})},
|
|
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
|
|
}
|
|
|
|
RETURN_TYPES = ("INT",)
|
|
RETURN_NAMES = ("dummy_out",)
|
|
FUNCTION = "save_images_plus"
|
|
|
|
OUTPUT_NODE = True
|
|
|
|
CATEGORY = "JPS Nodes/IO"
|
|
|
|
def save_images_plus(self, images, filename_prefix="ComfyUI", prompt=None, extra_pnginfo=None):
|
|
filename_prefix += self.prefix_append
|
|
full_output_folder, filename, counter, subfolder, filename_prefix = folder_paths.get_save_image_path(filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0])
|
|
results = list()
|
|
for image in images:
|
|
i = 255. * image.cpu().numpy()
|
|
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
|
metadata = None
|
|
if not args.disable_metadata:
|
|
metadata = PngInfo()
|
|
if prompt is not None:
|
|
metadata.add_text("prompt", json.dumps(prompt))
|
|
if extra_pnginfo is not None:
|
|
for x in extra_pnginfo:
|
|
metadata.add_text(x, json.dumps(extra_pnginfo[x]))
|
|
|
|
file = f"{filename} {counter:03}.png"
|
|
img.save(os.path.join(full_output_folder, file), pnginfo=metadata, compress_level=self.compress_level)
|
|
results.append({
|
|
"filename": file,
|
|
"subfolder": subfolder,
|
|
"type": self.type
|
|
})
|
|
counter += 1
|
|
|
|
#return { "ui": { "images": results } }
|
|
return(int(1), )
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
class CLIPTextEncodeSDXL_Plus:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {"required": {
|
|
"width": ("INT", {"default": 1024.0, "min": 0, "max": 12288}),
|
|
"height": ("INT", {"default": 1024.0, "min": 0, "max": 12288}),
|
|
"res_factor": ("INT", {"default": 4, "min": 1, "max": 8}),
|
|
"text_pos": ("STRING", {"multiline": True, "default": "", "dynamicPrompts": True}),
|
|
"text_neg": ("STRING", {"multiline": True, "default": "", "dynamicPrompts": True}),
|
|
"clip": ("CLIP", ),
|
|
}}
|
|
RETURN_TYPES = ("CONDITIONING","CONDITIONING",)
|
|
RETURN_NAMES = ("cond_pos", "cond_neg",)
|
|
FUNCTION = "execute"
|
|
CATEGORY = "JPS Nodes/Conditioning"
|
|
|
|
def execute(self, clip, width, height, res_factor, text_pos, text_neg):
|
|
crop_w = 0
|
|
crop_h = 0
|
|
width = width*res_factor
|
|
height = height*res_factor
|
|
target_width = width
|
|
target_height = height
|
|
text_g_pos = text_l_pos = text_pos
|
|
text_g_neg = text_l_neg = text_neg
|
|
|
|
tokens_pos = clip.tokenize(text_g_pos)
|
|
tokens_pos["l"] = clip.tokenize(text_l_pos)["l"]
|
|
if len(tokens_pos["l"]) != len(tokens_pos["g"]):
|
|
empty_pos = clip.tokenize("")
|
|
while len(tokens_pos["l"]) < len(tokens_pos["g"]):
|
|
tokens_pos["l"] += empty_pos["l"]
|
|
while len(tokens_pos["l"]) > len(tokens_pos["g"]):
|
|
tokens_pos["g"] += empty_pos["g"]
|
|
cond_pos, pooled_pos = clip.encode_from_tokens(tokens_pos, return_pooled=True)
|
|
|
|
tokens_neg = clip.tokenize(text_g_neg)
|
|
tokens_neg["l"] = clip.tokenize(text_l_neg)["l"]
|
|
if len(tokens_neg["l"]) != len(tokens_neg["g"]):
|
|
empty_neg = clip.tokenize("")
|
|
while len(tokens_neg["l"]) < len(tokens_neg["g"]):
|
|
tokens_neg["l"] += empty_neg["l"]
|
|
while len(tokens_pos["l"]) > len(tokens_pos["g"]):
|
|
tokens_neg["g"] += empty_neg["g"]
|
|
cond_neg, pooled_neg = clip.encode_from_tokens(tokens_neg, return_pooled=True)
|
|
|
|
return ([[cond_pos, {"pooled_output": pooled_pos, "width": width, "height": height, "crop_w": crop_w, "crop_h": crop_h, "target_width": target_width, "target_height": target_height}]], [[cond_neg, {"pooled_output": pooled_neg, "width": width, "height": height, "crop_w": crop_w, "crop_h": crop_h, "target_width": target_width, "target_height": target_height}]])
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------------------------------#
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"Lora Loader (JPS)": IO_Lora_Loader,
|
|
"SDXL Resolutions (JPS)": SDXL_Resolutions,
|
|
"SDXL Basic Settings (JPS)": SDXL_Basic_Settings,
|
|
"SDXL Settings (JPS)": SDXL_Settings,
|
|
"Generation TXT IMG Settings (JPS)": Generation_TXT_IMG_Settings,
|
|
"Crop Image Settings (JPS)": CropImage_Settings,
|
|
"ImageToImage Settings (JPS)": ImageToImage_Settings,
|
|
"CtrlNet CannyEdge Settings (JPS)": CtrlNet_CannyEdge_Settings,
|
|
"CtrlNet ZoeDepth Settings (JPS)": CtrlNet_ZoeDepth_Settings,
|
|
"CtrlNet MiDaS Settings (JPS)": CtrlNet_MiDaS_Settings,
|
|
"CtrlNet OpenPose Settings (JPS)": CtrlNet_OpenPose_Settings,
|
|
"Revision Settings (JPS)": Revision_Settings,
|
|
"IP Adapter Settings (JPS)": IP_Adapter_Settings,
|
|
"IP Adapter Tiled Settings (JPS)": IP_Adapter_Tiled_Settings,
|
|
"InstantID Settings (JPS)": InstantID_Settings,
|
|
"Image Prepare Settings (JPS)": ImagePrepare_Settings,
|
|
"InstantID Source Prepare Settings (JPS)": InstantIDSourcePrepare_Settings,
|
|
"InstantID Pose Prepare Settings (JPS)": InstantIDPosePrepare_Settings,
|
|
"InstantID Mask Prepare Settings (JPS)": InstantIDMaskPrepare_Settings,
|
|
"Sampler Scheduler Settings (JPS)": Sampler_Scheduler_Settings,
|
|
"Integer Switch (JPS)": Integer_Switch,
|
|
"Image Switch (JPS)": Image_Switch,
|
|
"Latent Switch (JPS)": Latent_Switch,
|
|
"Conditioning Switch (JPS)": Conditioning_Switch,
|
|
"Model Switch (JPS)": Model_Switch,
|
|
"IPA Switch (JPS)": IPA_Switch,
|
|
"VAE Switch (JPS)": VAE_Switch,
|
|
"Mask Switch (JPS)": Mask_Switch,
|
|
"ControlNet Switch (JPS)": ControlNet_Switch,
|
|
"Disable Enable Switch (JPS)": Disable_Enable_Switch,
|
|
"Enable Disable Switch (JPS)": Enable_Disable_Switch,
|
|
"SDXL Basic Settings Pipe (JPS)": SDXL_Basic_Settings_Pipe,
|
|
"SDXL Settings Pipe (JPS)": SDXL_Settings_Pipe,
|
|
"Crop Image Pipe (JPS)": CropImage_Pipe,
|
|
"ImageToImage Pipe (JPS)": ImageToImage_Pipe,
|
|
"CtrlNet CannyEdge Pipe (JPS)": CtrlNet_CannyEdge_Pipe,
|
|
"CtrlNet ZoeDepth Pipe (JPS)": CtrlNet_ZoeDepth_Pipe,
|
|
"CtrlNet MiDaS Pipe (JPS)": CtrlNet_MiDaS_Pipe,
|
|
"CtrlNet OpenPose Pipe (JPS)": CtrlNet_OpenPose_Pipe,
|
|
"IP Adapter Settings Pipe (JPS)": IP_Adapter_Settings_Pipe,
|
|
"IP Adapter Tiled Settings Pipe (JPS)": IP_Adapter_Tiled_Settings_Pipe,
|
|
"InstantID Pipe (JPS)": InstantID_Pipe,
|
|
"Image Prepare Pipe (JPS)": ImagePrepare_Pipe,
|
|
"InstantID Source Prepare Pipe (JPS)": InstantIDSourcePrepare_Pipe,
|
|
"InstantID Pose Prepare Pipe (JPS)": InstantIDPosePrepare_Pipe,
|
|
"InstantID Mask Prepare Pipe (JPS)": InstantIDMaskPrepare_Pipe,
|
|
"Revision Settings Pipe (JPS)": Revision_Settings_Pipe,
|
|
"SDXL Fundamentals MultiPipe (JPS)": SDXL_Fundamentals_MultiPipe,
|
|
"Images Masks MultiPipe (JPS)": Images_Masks_MultiPipe,
|
|
"SDXL Recommended Resolution Calc (JPS)": SDXL_Recommended_Resolution_Calc,
|
|
"Resolution Multiply (JPS)": Math_Resolution_Multiply,
|
|
"Largest Int (JPS)": Math_Largest_Integer,
|
|
"Multiply Int Int (JPS)": Math_Multiply_INT_INT,
|
|
"Multiply Int Float (JPS)": Math_Multiply_INT_FLOAT,
|
|
"Multiply Float Float (JPS)": Math_Multiply_FLOAT_FLOAT,
|
|
"Substract Int Int (JPS)": Math_Substract_INT_INT,
|
|
"Text Concatenate (JPS)": Text_Concatenate,
|
|
"Get Date Time String (JPS)": Get_Date_Time_String,
|
|
"Get Image Size (JPS)": Get_Image_Size,
|
|
"Crop Image Square (JPS)": Crop_Image_Square,
|
|
"Crop Image TargetSize (JPS)": Crop_Image_TargetSize,
|
|
"Prepare Image (JPS)": Prepare_Image,
|
|
"Prepare Image Plus (JPS)": Prepare_Image_Plus,
|
|
"Prepare Image Tiled IPA (JPS)": Prepare_Image_Tiled_IPA,
|
|
"SDXL Prompt Styler (JPS)": SDXL_Prompt_Styler,
|
|
"SDXL Prompt Handling (JPS)": SDXL_Prompt_Handling,
|
|
"SDXL Prompt Handling Plus (JPS)": SDXL_Prompt_Handling_Plus,
|
|
"Text Prompt (JPS)": Text_Prompt,
|
|
"Text Prompt Combo (JPS)": Text_Prompt_Combo,
|
|
"Save Images Plus (JPS)": Save_Images_Plus,
|
|
"CLIPTextEncode SDXL Plus (JPS)": CLIPTextEncodeSDXL_Plus,
|
|
"Time Seed (JPS)": Time_Seed,
|
|
}
|