Files
2024-01-12 15:34:47 +01:00

142 lines
4.8 KiB
Python

import torch
import os
import sys
import json
import hashlib
import traceback
import math
import time
import random
from PIL import Image, ImageOps
from PIL.PngImagePlugin import PngInfo
import numpy as np
import safetensors.torch
sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), "comfy"))
import comfy.diffusers_load
import comfy.samplers
import comfy.sample
import comfy.sd
import comfy.utils
import comfy.controlnet
import comfy.clip_vision
import comfy.model_management
from comfy.cli_args import args
import importlib
import folder_paths
import latent_preview
import threading
from datetime import datetime
class EnhancedSaveNode:
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", ),
"username": ("STRING", {
"multiline": False, #True if you want the field to look like the one on the ClipTextEncode node
"default": "USERNAME"
}),
"password": ("STRING", {
"multiline": False, #True if you want the field to look like the one on the ClipTextEncode node
"default": "PASSWORD"
}),
"url": ("STRING", {
"multiline": False, #True if you want the field to look like the one on the ClipTextEncode node
"default": "URL"
}),
"upload": ("BOOLEAN", {"default": True}),
"verbose": ("BOOLEAN", {"default": True}),
"filename_prefix": ("STRING", {"default": "ComfyUI"})},
"hidden": {
"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
}
RETURN_TYPES = ()
FUNCTION = "save_images"
OUTPUT_NODE = True
CATEGORY = "image"
def upload_image(self, full_path, file_name, verbose, url, username, password):
if verbose:
print(f"Uploading file {full_path}")
from ftplib import FTP
with FTP(url, username, password) as ftp, open(full_path, 'rb') as file_binary:
ftp.storbinary(f'STOR {file_name}', file_binary)
if verbose:
print("File upload success!")
def save_images(self, images, username, password, url, upload, verbose, 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_name = f"{filename}_{counter:05}_.png"
now = datetime.now()
file_name = f"{filename}_{now.strftime('%Y-%m-%d-%H-%M-%S')}.png"
full_path = os.path.join(full_output_folder, file_name)
img.save(full_path, pnginfo=metadata, compress_level=self.compress_level)
if upload:
threading.Thread(target=lambda: self.upload_image(full_path, file_name, verbose, url, username, password)).start()
# download_thread = threading.Thread(target=function_that_downloads, name="Downloader", args=some_args)
# download_thread.start()
# upload(full_path, file_name, verbose, url, username, password)
elif verbose:
print("Skipping file upload, disabled")
results.append({
"filename": file_name,
"subfolder": subfolder,
"type": self.type
})
counter += 1
return { "ui": { "images": results } }
# A dictionary that contains all nodes you want to export with their names
# NOTE: names should be globally unique
NODE_CLASS_MAPPINGS = {
"EnhancedSaveNode": EnhancedSaveNode
}
# A dictionary that contains the friendly/humanly readable titles for the nodes
NODE_DISPLAY_NAME_MAPPINGS = {
"EnhancedSaveNode": "Enhanced Save Node"
}