333 lines
9.8 KiB
Python
333 lines
9.8 KiB
Python
import io
|
|
import os
|
|
import json
|
|
import torch
|
|
import base64
|
|
import requests
|
|
from typing import Dict
|
|
|
|
from PIL import Image, ImageOps
|
|
from PIL.PngImagePlugin import PngInfo
|
|
import numpy as np
|
|
|
|
from .logger import logger
|
|
from .utils import upload_to_av
|
|
|
|
import folder_paths
|
|
|
|
|
|
class UtilLoadImageFromUrl:
|
|
def __init__(self) -> None:
|
|
self.output_dir = folder_paths.get_temp_directory()
|
|
self.filename_prefix = "TempImageFromUrl"
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {"url": ("STRING", {"default": ""})},
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE", "MASK")
|
|
CATEGORY = "image"
|
|
FUNCTION = "load_image_from_url"
|
|
|
|
def load_image_from_url(self, url: str):
|
|
if url.startswith("data:image/"):
|
|
i = Image.open(io.BytesIO(base64.b64decode(url.split(",")[1])))
|
|
else:
|
|
response = requests.get(url, timeout=5)
|
|
if response.status_code != 200:
|
|
raise Exception(response.text)
|
|
|
|
i = Image.open(io.BytesIO(response.content))
|
|
|
|
i = ImageOps.exif_transpose(i)
|
|
image = i.convert("RGB")
|
|
|
|
# save image to temp folder
|
|
(
|
|
outdir,
|
|
filename,
|
|
counter,
|
|
subfolder,
|
|
_,
|
|
) = folder_paths.get_save_image_path(
|
|
self.filename_prefix, self.output_dir, image.width, image.height
|
|
)
|
|
file = f"{filename}_{counter:05}.png"
|
|
image.save(os.path.join(outdir, file), format="PNG", compress_level=4)
|
|
preview = {
|
|
"filename": file,
|
|
"subfolder": subfolder,
|
|
"type": "temp",
|
|
}
|
|
|
|
image = np.array(image).astype(np.float32) / 255.0
|
|
image = torch.from_numpy(image)[None,]
|
|
if "A" in i.getbands():
|
|
mask = np.array(i.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")
|
|
|
|
return {"ui": {"images": [preview]}, "result": (image, mask)}
|
|
|
|
|
|
class AVOutputUploadImage:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {"images": ("IMAGE",)},
|
|
"optional": {
|
|
"folder_id": ("STRING", {"multiline": False}),
|
|
},
|
|
"hidden": {
|
|
"prompt": "PROMPT",
|
|
"extra_pnginfo": "EXTRA_PNGINFO",
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ()
|
|
OUTPUT_NODE = True
|
|
CATEGORY = "Art Venture"
|
|
FUNCTION = "upload_images"
|
|
|
|
def upload_images(
|
|
self,
|
|
images,
|
|
folder_id: str = None,
|
|
prompt=None,
|
|
extra_pnginfo=None,
|
|
):
|
|
files = list()
|
|
for idx, image in enumerate(images):
|
|
i = 255.0 * image.cpu().numpy()
|
|
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
|
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:
|
|
logger.debug(f"Adding {x} to pnginfo: {extra_pnginfo[x]}")
|
|
metadata.add_text(x, json.dumps(extra_pnginfo[x]))
|
|
|
|
buffer = io.BytesIO()
|
|
img.save(buffer, format="PNG", pnginfo=metadata, compress_level=4)
|
|
buffer.seek(0)
|
|
files.append(
|
|
(
|
|
"files",
|
|
(f"image-{idx}.png", buffer, "image/png"),
|
|
)
|
|
)
|
|
|
|
additional_data = {"success": "true"}
|
|
if folder_id is not None:
|
|
additional_data["folderId"] = folder_id
|
|
|
|
upload_to_av(files, additional_data=additional_data)
|
|
return ("Uploaded to ArtVenture!",)
|
|
|
|
|
|
class AVCheckpointModelsToParametersPipe:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"ckpt_name": (
|
|
folder_paths.get_filename_list("checkpoints"),
|
|
),
|
|
},
|
|
"optional": {
|
|
"pipe": ("PIPE",),
|
|
"secondary_ckpt_name": (
|
|
["None"] + folder_paths.get_filename_list("checkpoints"),
|
|
),
|
|
"vae_name": (["None"] + folder_paths.get_filename_list("vae"),),
|
|
"upscaler_name": (
|
|
["None"] + folder_paths.get_filename_list("upscale_models"),
|
|
),
|
|
"secondary_upscaler_name": (
|
|
["None"] + folder_paths.get_filename_list("upscale_models"),
|
|
),
|
|
"lora_1_name": (["None"] + folder_paths.get_filename_list("loras"),),
|
|
"lora_2_name": (["None"] + folder_paths.get_filename_list("loras"),),
|
|
"lora_3_name": (["None"] + folder_paths.get_filename_list("loras"),),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("PIPE",)
|
|
CATEGORY = "Art Venture/Parameters"
|
|
FUNCTION = "checkpoint_models_to_parameter_pipe"
|
|
|
|
def checkpoint_models_to_parameter_pipe(
|
|
self,
|
|
ckpt_name,
|
|
pipe: Dict = {},
|
|
secondary_ckpt_name="None",
|
|
vae_name="None",
|
|
upscaler_name="None",
|
|
secondary_upscaler_name="None",
|
|
lora_1_name="None",
|
|
lora_2_name="None",
|
|
lora_3_name="None",
|
|
):
|
|
pipe["ckpt_name"] = ckpt_name if ckpt_name != "None" else None
|
|
pipe["secondary_ckpt_name"] = (
|
|
secondary_ckpt_name if secondary_ckpt_name != "None" else None
|
|
)
|
|
pipe["vae_name"] = vae_name if vae_name != "None" else None
|
|
pipe["upscaler_name"] = upscaler_name if upscaler_name != "None" else None
|
|
pipe["secondary_upscaler_name"] = (
|
|
secondary_upscaler_name if secondary_upscaler_name != "None" else None
|
|
)
|
|
pipe["lora_1_name"] = lora_1_name if lora_1_name != "None" else None
|
|
pipe["lora_2_name"] = lora_2_name if lora_2_name != "None" else None
|
|
pipe["lora_3_name"] = lora_3_name if lora_3_name != "None" else None
|
|
return (pipe,)
|
|
|
|
|
|
class AVPromptsToParametersPipe:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"positive": ("STRING", {"multiline": True, "default": "Positive"}),
|
|
"negative": ("STRING", {"multiline": True, "default": "Negative"}),
|
|
},
|
|
"optional": {
|
|
"pipe": ("PIPE",),
|
|
"image": ("IMAGE",),
|
|
"mask": ("MASK",),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("PIPE",)
|
|
CATEGORY = "Art Venture/Parameters"
|
|
FUNCTION = "prompt_to_parameter_pipe"
|
|
|
|
def prompt_to_parameter_pipe(
|
|
self, positive, negative, pipe: Dict = {}, image=None, mask=None
|
|
):
|
|
pipe["positive"] = positive
|
|
pipe["negative"] = negative
|
|
pipe["image"] = image
|
|
pipe["mask"] = mask
|
|
return (pipe,)
|
|
|
|
|
|
class AVParametersPipeToCheckpointModels:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"pipe": ("PIPE",),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (
|
|
"PIPE",
|
|
"STRING",
|
|
"STRING",
|
|
"STRING",
|
|
"STRING",
|
|
"STRING",
|
|
"STRING",
|
|
"STRING",
|
|
"STRING",
|
|
)
|
|
RETURN_NAMES = (
|
|
"pipe",
|
|
"ckpt_name",
|
|
"secondary_ckpt_name",
|
|
"vae_name",
|
|
"upscaler_name",
|
|
"secondary_upscaler_name",
|
|
"lora_1_name",
|
|
"lora_2_name",
|
|
"lora_3_name",
|
|
)
|
|
CATEGORY = "Art Venture/Parameters"
|
|
FUNCTION = "parameter_pipe_to_checkpoint_models"
|
|
|
|
def parameter_pipe_to_checkpoint_models(self, pipe: Dict = {}):
|
|
ckpt_name = pipe.get("ckpt_name", None)
|
|
secondary_ckpt_name = pipe.get("secondary_ckpt_name", None)
|
|
vae_name = pipe.get("vae_name", None)
|
|
upscaler_name = pipe.get("upscaler_name", None)
|
|
secondary_upscaler_name = pipe.get("secondary_upscaler_name", None)
|
|
lora_1_name = pipe.get("lora_1_name", None)
|
|
lora_2_name = pipe.get("lora_2_name", None)
|
|
lora_3_name = pipe.get("lora_3_name", None)
|
|
|
|
return (
|
|
pipe,
|
|
ckpt_name,
|
|
secondary_ckpt_name,
|
|
vae_name,
|
|
upscaler_name,
|
|
secondary_upscaler_name,
|
|
lora_1_name,
|
|
lora_2_name,
|
|
lora_3_name,
|
|
)
|
|
|
|
|
|
class AVParametersPipeToPrompts:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"pipe": ("PIPE",),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (
|
|
"PIPE",
|
|
"STRING",
|
|
"STRING",
|
|
"IMAGE",
|
|
"MASK",
|
|
)
|
|
RETURN_NAMES = (
|
|
"pipe",
|
|
"positive",
|
|
"negative",
|
|
"image",
|
|
"mask",
|
|
)
|
|
CATEGORY = "Art Venture/Parameters"
|
|
FUNCTION = "parameter_pipe_to_prompt"
|
|
|
|
def parameter_pipe_to_prompt(self, pipe: Dict = {}):
|
|
positive = pipe.get("positive", None)
|
|
negative = pipe.get("negative", None)
|
|
image = pipe.get("image", None)
|
|
mask = pipe.get("mask", None)
|
|
|
|
return (
|
|
pipe,
|
|
positive,
|
|
negative,
|
|
image,
|
|
mask,
|
|
)
|
|
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"LoadImageFromUrl": UtilLoadImageFromUrl,
|
|
"AV_UploadImage": AVOutputUploadImage,
|
|
"AV_CheckpointModelsToParametersPipe": AVCheckpointModelsToParametersPipe,
|
|
"AV_PromptsToParametersPipe": AVPromptsToParametersPipe,
|
|
"AV_ParametersPipeToCheckpointModels": AVParametersPipeToCheckpointModels,
|
|
"AV_ParametersPipeToPrompts": AVParametersPipeToPrompts,
|
|
}
|
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
"LoadImageFromUrl": "Load Image From URL",
|
|
"AV_UploadImage": "Upload to Art Venture",
|
|
"AV_CheckpointModelsToParametersPipe": "Checkpoint Models to Pipe",
|
|
"AV_PromptsToParametersPipe": "Prompts to Pipe",
|
|
"AV_ParametersPipeToCheckpointModels": "Pipe to Checkpoint Models",
|
|
"AV_ParametersPipeToPrompts": "Pipe to Prompts",
|
|
}
|