mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-01-11 06:40:48 +08:00
Merge c3c8d5fc79 into 1ca89b810e
This commit is contained in:
commit
7fdd3430af
@ -106,7 +106,7 @@ class SaveAnimatedWEBP:
|
|||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
return {"required":
|
return {"required":
|
||||||
{"images": ("IMAGE", ),
|
{"images": ("IMAGE", ),
|
||||||
"filename_prefix": ("STRING", {"default": "ComfyUI"}),
|
"filename_prefix": ("STRING", {"default": "%date:yyyy-MM-dd%/ComfyUI"}),
|
||||||
"fps": ("FLOAT", {"default": 6.0, "min": 0.01, "max": 1000.0, "step": 0.01}),
|
"fps": ("FLOAT", {"default": 6.0, "min": 0.01, "max": 1000.0, "step": 0.01}),
|
||||||
"lossless": ("BOOLEAN", {"default": True}),
|
"lossless": ("BOOLEAN", {"default": True}),
|
||||||
"quality": ("INT", {"default": 80, "min": 0, "max": 100}),
|
"quality": ("INT", {"default": 80, "min": 0, "max": 100}),
|
||||||
@ -171,7 +171,7 @@ class SaveAnimatedPNG:
|
|||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
return {"required":
|
return {"required":
|
||||||
{"images": ("IMAGE", ),
|
{"images": ("IMAGE", ),
|
||||||
"filename_prefix": ("STRING", {"default": "ComfyUI"}),
|
"filename_prefix": ("STRING", {"default": "%date:yyyy-MM-dd%/ComfyUI"}),
|
||||||
"fps": ("FLOAT", {"default": 6.0, "min": 0.01, "max": 1000.0, "step": 0.01}),
|
"fps": ("FLOAT", {"default": 6.0, "min": 0.01, "max": 1000.0, "step": 0.01}),
|
||||||
"compress_level": ("INT", {"default": 4, "min": 0, "max": 9})
|
"compress_level": ("INT", {"default": 4, "min": 0, "max": 9})
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import logging
|
import logging
|
||||||
@ -431,45 +432,100 @@ def get_save_image_path(filename_prefix: str, output_dir: str, image_width=0, im
|
|||||||
prefix = filename[:prefix_len + 1]
|
prefix = filename[:prefix_len + 1]
|
||||||
try:
|
try:
|
||||||
digits = int(filename[prefix_len + 1:].split('_')[0])
|
digits = int(filename[prefix_len + 1:].split('_')[0])
|
||||||
except:
|
except ValueError:
|
||||||
digits = 0
|
digits = 0
|
||||||
return digits, prefix
|
return digits, prefix
|
||||||
|
|
||||||
def compute_vars(input: str, image_width: int, image_height: int) -> str:
|
def compute_vars(input_str: str, image_width: int, image_height: int) -> str:
|
||||||
input = input.replace("%width%", str(image_width))
|
date_pattern = re.compile(r'%date:(.+?)%')
|
||||||
input = input.replace("%height%", str(image_height))
|
|
||||||
now = time.localtime()
|
def replace_date(match):
|
||||||
input = input.replace("%year%", str(now.tm_year))
|
date_format = match.group(1)
|
||||||
input = input.replace("%month%", str(now.tm_mon).zfill(2))
|
|
||||||
input = input.replace("%day%", str(now.tm_mday).zfill(2))
|
dateformat_conversion_map = {
|
||||||
input = input.replace("%hour%", str(now.tm_hour).zfill(2))
|
"yyyy": "%Y",
|
||||||
input = input.replace("%minute%", str(now.tm_min).zfill(2))
|
"yy": "%y",
|
||||||
input = input.replace("%second%", str(now.tm_sec).zfill(2))
|
"MM": "%m",
|
||||||
return input
|
"dd": "%d",
|
||||||
|
"hh": "%H",
|
||||||
|
"mm": "%M",
|
||||||
|
"ss": "%S",
|
||||||
|
}
|
||||||
|
|
||||||
|
strftime_format = date_format
|
||||||
|
for old, new in dateformat_conversion_map.items():
|
||||||
|
strftime_format = strftime_format.replace(old, new)
|
||||||
|
|
||||||
|
now = time.localtime()
|
||||||
|
formatted_date = time.strftime(strftime_format, now)
|
||||||
|
return formatted_date
|
||||||
|
|
||||||
|
input_str = date_pattern.sub(replace_date, input_str)
|
||||||
|
|
||||||
|
now = time.localtime()
|
||||||
|
input_str = input_str.replace("%year%", str(now.tm_year))
|
||||||
|
input_str = input_str.replace("%month%", str(now.tm_mon).zfill(2))
|
||||||
|
input_str = input_str.replace("%day%", str(now.tm_mday).zfill(2))
|
||||||
|
input_str = input_str.replace("%hour%", str(now.tm_hour).zfill(2))
|
||||||
|
input_str = input_str.replace("%minute%", str(now.tm_min).zfill(2))
|
||||||
|
input_str = input_str.replace("%second%", str(now.tm_sec).zfill(2))
|
||||||
|
|
||||||
|
input_str = input_str.replace("%width%", str(image_width))
|
||||||
|
input_str = input_str.replace("%height%", str(image_height))
|
||||||
|
|
||||||
|
return input_str
|
||||||
|
|
||||||
if "%" in filename_prefix:
|
|
||||||
filename_prefix = compute_vars(filename_prefix, image_width, image_height)
|
filename_prefix = compute_vars(filename_prefix, image_width, image_height)
|
||||||
|
|
||||||
subfolder = os.path.dirname(os.path.normpath(filename_prefix))
|
subfolder = os.path.dirname(os.path.normpath(filename_prefix))
|
||||||
filename = os.path.basename(os.path.normpath(filename_prefix))
|
filename = os.path.basename(os.path.normpath(filename_prefix))
|
||||||
|
|
||||||
|
if not subfolder and ("%date:" in filename_prefix or "%year%" in filename_prefix or
|
||||||
|
"%month%" in filename_prefix or "%day%" in filename_prefix or
|
||||||
|
"%hour%" in filename_prefix or "%minute%" in filename_prefix or
|
||||||
|
"%second%" in filename_prefix or "ComfyUI" in filename_prefix):
|
||||||
|
import locale
|
||||||
|
try:
|
||||||
|
locale.setlocale(locale.LC_TIME, '')
|
||||||
|
default_date_format = locale.nl_langinfo(locale.D_FMT).replace("%y", "%Y")
|
||||||
|
if os.name == 'nt':
|
||||||
|
default_date_format = default_date_format.replace("/", "-").replace("\\", "-").replace(":","-")
|
||||||
|
subfolder = time.strftime(default_date_format)
|
||||||
|
|
||||||
|
except (locale.Error, AttributeError):
|
||||||
|
subfolder = time.strftime("%Y-%m-%d")
|
||||||
|
if os.name == 'nt':
|
||||||
|
subfolder = subfolder.replace("/", "-").replace("\\", "-").replace(":","-")
|
||||||
|
|
||||||
full_output_folder = os.path.join(output_dir, subfolder)
|
full_output_folder = os.path.join(output_dir, subfolder)
|
||||||
|
|
||||||
if os.path.commonpath((output_dir, os.path.abspath(full_output_folder))) != output_dir:
|
if os.path.commonpath((output_dir, os.path.abspath(full_output_folder))) != output_dir:
|
||||||
err = "**** ERROR: Saving image outside the output folder is not allowed." + \
|
err = ("**** ERROR: Saving outside the output folder is not allowed."
|
||||||
"\n full_output_folder: " + os.path.abspath(full_output_folder) + \
|
f"\n full_output_folder: {os.path.abspath(full_output_folder)}"
|
||||||
"\n output_dir: " + output_dir + \
|
f"\n output_dir: {output_dir}"
|
||||||
"\n commonpath: " + os.path.commonpath((output_dir, os.path.abspath(full_output_folder)))
|
f"\n commonpath: {os.path.commonpath((output_dir, os.path.abspath(full_output_folder)))}")
|
||||||
logging.error(err)
|
logging.error(err)
|
||||||
raise Exception(err)
|
raise Exception(err)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
counter = max(filter(lambda a: os.path.normcase(a[1][:-1]) == os.path.normcase(filename) and a[1][-1] == "_", map(map_filename, os.listdir(full_output_folder))))[0] + 1
|
files = [f for f in os.listdir(full_output_folder) if os.path.isfile(os.path.join(full_output_folder, f))]
|
||||||
except ValueError:
|
mapped_files = [map_filename(f) for f in files]
|
||||||
|
filtered_files = [
|
||||||
|
(digits, prefix) for digits, prefix in mapped_files
|
||||||
|
if os.path.normcase(prefix[:-1]) == os.path.normcase(filename) and prefix[-1] == "_"
|
||||||
|
]
|
||||||
|
|
||||||
|
if filtered_files:
|
||||||
|
counter = max(digits for digits, _ in filtered_files) + 1
|
||||||
|
else:
|
||||||
counter = 1
|
counter = 1
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
os.makedirs(full_output_folder, exist_ok=True)
|
os.makedirs(full_output_folder, exist_ok=True)
|
||||||
counter = 1
|
counter = 1
|
||||||
|
except OSError as e:
|
||||||
|
logging.error(f"Error accessing directory: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
return full_output_folder, filename, counter, subfolder, filename_prefix
|
return full_output_folder, filename, counter, subfolder, filename_prefix
|
||||||
|
|
||||||
def get_input_subfolders() -> list[str]:
|
def get_input_subfolders() -> list[str]:
|
||||||
|
|||||||
2
nodes.py
2
nodes.py
@ -1583,7 +1583,7 @@ class SaveImage:
|
|||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"images": ("IMAGE", {"tooltip": "The images to save."}),
|
"images": ("IMAGE", {"tooltip": "The images to save."}),
|
||||||
"filename_prefix": ("STRING", {"default": "ComfyUI", "tooltip": "The prefix for the file to save. This may include formatting information such as %date:yyyy-MM-dd% or %Empty Latent Image.width% to include values from nodes."})
|
"filename_prefix": ("STRING", {"default": "%date:yyyy-MM-dd%/ComfyUI", "tooltip": "The prefix for the file to save. This may include formatting information such as '%date:yyyy-MM-dd%', '%year%-%month%-%day%' or %Empty Latent Image.width% to include values from nodes."})
|
||||||
},
|
},
|
||||||
"hidden": {
|
"hidden": {
|
||||||
"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"
|
"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user