cocccck / custom_nodes /ComfyUI-Chibi-Nodes /nodes /LoadImageExtended.py
bbbboiwow's picture
Upload folder using huggingface_hub
edb09f2 verified
Raw
History Blame Contribute Delete
7.45 kB
import folder_paths
import os
import json
import re
from PIL import Image, ImageOps
import numpy as np
import torch
import hashlib
class LoadImageExtended:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
input_dir = folder_paths.get_input_directory()
files = [
f
for f in os.listdir(input_dir)
if os.path.isfile(os.path.join(input_dir, f))
]
return {
"required": {
"image": (sorted(files), {"image_upload": True}),
},
"optional": {"vae": ("VAE",)},
}
CATEGORY = "Chibi-Nodes/Image"
# changes here
RETURN_TYPES = (
"IMAGE",
"MASK",
"LATENT",
"STRING",
"STRING",
"INT",
"INT",
)
RETURN_NAMES = (
"IMAGE",
"MASK",
"LATENT",
"filename",
"image Info",
"width",
"height",
)
#
FUNCTION = "load_image"
def load_image(self, image, vae=None):
image_path = folder_paths.get_annotated_filepath(image)
# Check if os is windows for backwards paths.
if os.name == "nt":
filename = image_path.rsplit("\\", 1)[-1]
else:
filename = image_path.rsplit("/", 1)[-1]
im = Image.open(image_path)
# Start ai-info.py section, with no exif
def type_changer(value):
if value.isnumeric():
return int(value)
else:
return value
im.load()
prompt = {}
if "prompt" in im.info.keys():
# comfyui, workflow is also available but we aren't getting that today
# prompt = {}
prompt.update({"prompt": json.loads(im.info["prompt"])})
else:
# automatic111, gosh this is a mess.
if "parameters" in im.info.keys():
parameters = im.info["parameters"]
prompt = {"parameters": {}}
parameters = re.split(
"(Negative prompt): |(Negative Template): |(Template): |(ControlNet): |\n",
parameters,
)
# removes None and new lines
parameters_clean_none = []
for i in range(0, len(parameters)):
if parameters[i] is None:
pass
elif parameters[i] == "":
pass
else:
parameters_clean_none.append(parameters[i])
parameters = parameters_clean_none
# settings field
parameters_settings = {}
for i in range(0, len(parameters)):
if parameters[i].split(":", 1)[0] == "Steps":
parameters[i] = re.split(", ", parameters[i])
for k in parameters[i]:
k = k.split(": ", 1)
if len(k) == 2:
k[1] = type_changer(k[1])
# makes "Size" : "(widthxheight)" into two keys
if k[0] == "Size":
k[1] = k[1].split("x")
for s in range(0, len(k[1])):
k[1][s] = type_changer(k[1][s])
parameters_settings.update(
{"width": k[1][0]})
parameters_settings.update(
{"height": k[1][1]})
else:
parameters_settings.update({k[0]: k[1]})
parameters[i] = parameters_settings
# builder
parameters_built = {}
for i in range(0, len(parameters)):
match parameters[i]:
case "Negative prompt":
parameters_built.update(
{parameters[i]: parameters[i + 1]})
case "Negative Template":
parameters_built.update(
{parameters[i]: parameters[i + 1]})
case "Template":
parameters_built.update(
{parameters[i]: parameters[i + 1]})
case "ControlNet":
parameters_built.update(
{parameters[i]: parameters[i + 1]})
case dict():
parameters_built.update(parameters[i])
case _:
if i == 0:
parameters_built.update(
{"Positive prompt": parameters[i]}
)
pass
prompt["parameters"] = parameters_built
if type(prompt) is dict:
prompt = json.dumps(prompt, indent=2)
elif type(prompt) is str:
prompt = json.dumps(json.loads(prompt), indent=2)
# end section
im = ImageOps.exif_transpose(im)
image = im.convert("RGB")
image = np.array(image).astype(np.float32) / 255.0
image = torch.from_numpy(image)[None,]
shape = image.shape
width = shape[2]
height = shape[1]
if "A" in im.getbands():
mask = np.array(im.getchannel("A")).astype(np.float32) / 255.0
mask = 1.0 - torch.from_numpy(mask)
else:
mask = torch.zeros((64, 64), dtype=torch.float32, device="cpu")
if vae is not None:
latent = image
x = (latent.shape[1] // 8) * 8
y = (latent.shape[2] // 8) * 8
if latent.shape[1] is not x or latent.shape[2] is not y:
x_offset = (latent.shape[1] % 8) // 2
y_offset = (latent.shape[2] % 8) // 2
latent = latent[:, x_offset: x +
x_offset, y_offset: y + y_offset, :]
latent = vae.encode(latent[:, :, :, :3])
return (
image,
mask.unsqueeze(0),
{"samples": latent},
filename,
str(prompt),
width,
height,
)
else:
return (
image,
mask.unsqueeze(0),
None,
filename,
str(prompt),
width,
height,
)
@classmethod
def IS_CHANGED(s, image, vae=None):
image_path = folder_paths.get_annotated_filepath(image)
m = hashlib.sha256()
with open(image_path, "rb") as f:
m.update(f.read())
return m.digest().hex()
@classmethod
def VALIDATE_INPUTS(s, image, vae=None):
if not folder_paths.exists_annotated_filepath(image):
return "Invalid image file: {}".format(image)
return True