diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5bc5ca3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1 @@ +# v1.0.0 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..47cac5d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License/X11 License + +Copyright (c) 2025 KLL535 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..be3b9e9 --- /dev/null +++ b/__init__.py @@ -0,0 +1,7 @@ +from .nodes.nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS + +WEB_DIRECTORY = "./js" + +__all__ = ['NODE_CLASS_MAPPINGS','NODE_DISPLAY_NAME_MAPPINGS','WEB_DIRECTORY'] + +print("\033[34mComfyUI_simpleButcher Node Suite: \033[92mLoaded\033[0m") diff --git a/js/SimpleLoadLineFromTextFile.js b/js/SimpleLoadLineFromTextFile.js new file mode 100644 index 0000000..c5f9d28 --- /dev/null +++ b/js/SimpleLoadLineFromTextFile.js @@ -0,0 +1,29 @@ +import { app } from "../../scripts/app.js"; +import { api } from "../../scripts/api.js"; + +app.registerExtension({ + name: "Simple Load Line From Text File", + async beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "Simple Load Line From Text File") { + const origOnNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function() { + const r = origOnNodeCreated ? origOnNodeCreated.apply(this) : undefined; + let counter = 0; + function find_count(w) { + return w.name === "count" + } + const count = this.widgets.find(find_count); + count.type = "converted-widget"; // hidden + function do_counter() { + return counter++; + } + count.serializeValue = do_counter; + function reset_counter() { + counter = 0; + } + api.addEventListener("promptQueued", reset_counter); // reset + return r; + } + } + } +}) diff --git a/nodes/nodes.py b/nodes/nodes.py new file mode 100644 index 0000000..65d272c --- /dev/null +++ b/nodes/nodes.py @@ -0,0 +1,606 @@ +import random +import glob +import numpy as np +import torch +import os +import sys +import re +import json +import hashlib +import comfy.sd +import folder_paths +import requests +import piexif + +from safetensors import safe_open +from collections import deque +from datetime import datetime +from PIL import Image +from PIL.PngImagePlugin import PngInfo +from typing import Dict + +LORA_PATH = folder_paths.folder_names_and_paths["loras"][0][0] + +class AnyType(str): + def __ne__(self, __value: object) -> bool: + return False + +any = AnyType("*") + +################################ + +class SimpleLoadLineFromTextFile: + + def __init__(self): + self.batch_counter = 0 + self.line_counter = 0 + self.random_list = [] + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "start": ("INT", {"default": 0, "min": 0, "step": 1, "tooltip": "Start position for increment or decrement methods"}), + "load_file": ("BOOLEAN", {"default": True, "tooltip": "if True, load center of prompt from file"}), + "file_path": ("STRING", {"default": "", "tooltip": "Path to the file from which the lines for the central part of the prompt will be taken"}), + "next": (["increment", "decrement", "random", "random no repetitions"], {"default":"increment", "tooltip": "Option for enumerating lines, in case of randomness the start parameter is ignored"}), + "count": ("INT", {"default": 0, "min": 0, "step": 1}), + }, + "optional": { + "prefix": ("STRING", {"multiline": True, "default": "", "tooltip": "Add text to the beginning of the prompt", "forceInput": True}), + "postfix": ("STRING", {"multiline": True, "default": "", "tooltip": "Add text to the ending of the prompt", "forceInput": True}), + } + } + + RETURN_TYPES = ("STRING","INT","INT","INT") + RETURN_NAMES = ("text","batch_counter","line_counter","lines") + FUNCTION = "read_text_file" + CATEGORY = "πŸ“š SimpleButcher" + DESCRIPTION = "Simple prompt loader from a text file to automate the batch process. Can be combined with each other and create total randomness text and lora that is taken from your text and lora templates" + + def read_text_file(self, start = 0, load_file = False, file_path = "", next = "increment", prefix = "", postfix = "", count = 0): + + if count == 0: + self.batch_counter = 0 + self.line_counter = start + print(f"\033[93mClear counter\033[0m") + + self.batch_counter = self.batch_counter + 1 + + lines2 = [] + line_count = 0 + + if file_path != "": + if load_file == True: + file_path = os.path.expandvars(file_path) + if not os.path.isfile(file_path): + raise FileNotFoundError(f"The file at path '{file_path}' does not exist.") + with open(file_path, 'r', encoding='utf-8') as file: + lines = file.readlines() + + for line in lines: + line = line.replace("\r","") + line = line.strip() + if line != "": + lines2.append(line) + + line_count = len(lines2) + + text = "" + if prefix != "": + text = prefix + " " + + current_line = 0 + if line_count > 0: + + if next == "random no repetitions": + if count == 0: + # generate random numbers + print(f"\033[93mRandomize\033[0m") + self.random_list = list(range(0, line_count)) + random.shuffle(self.random_list) + self.line_counter = self.random_list[self.batch_counter % len(self.random_list)] + elif next == "random": + self.line_counter = random.randint(0, line_count-1) + + self.line_counter = self.line_counter % line_count + text = text + lines2[self.line_counter] + current_line = self.line_counter + + console_text = f"[\033[95mBatch: {self.batch_counter}\033[0m -> \033[92mLine: {str(current_line)}/{str(line_count)}\033[0m]" + print(f"{console_text}") + + if next == "increment": + self.line_counter = self.line_counter+1 + elif next == "decrement": + self.line_counter = self.line_counter-1 + if self.line_counter < 0: + self.line_counter = line_count-1 + else: + console_text = f"[\033[95mBatch: {self.batch_counter}\033[0m]" + print(f"{console_text}") + + if postfix != "": + text = text + " " + postfix + + text = text.replace("\r","") + text = text.replace("\n"," ") + text = text.replace("<"," <") + text = text.replace(" "," ") + + return (text,self.batch_counter,current_line,line_count) + +################################ + +class SimpleExtractLoraFromText: + + @classmethod + def INPUT_TYPES(cls): + + return {"required": { + "text": ("STRING", {"multiline": True, "default": "", "tooltip": "Text with mixed lora and prompt", "forceInput": True}), + } + } + + RETURN_TYPES = ("STRING","STRING") + RETURN_NAMES = ("lora_text","prompt") + FUNCTION = "extract_lora" + CATEGORY = "πŸ“š SimpleButcher" + DESCRIPTION = "If the text contains lore, written in Forge style: or , this node splits the text into prompts and lore separately" + + def extract_lora(self, text): + + text_prompt = text + + text_loras = re.findall(r']*>', text) + text_lora = ' '.join(text_loras) + + text_lora = text_lora.strip() + text_lora = text_lora.replace(" "," ") + + text_lora2 = text_lora.replace('\n',' ') + + #text_prompt = ' '.join(s for s in text.split() if not (s.startswith("<") and s.endswith(">"))) + #text_prompt = ' '.join(word for word in text.split() if not re.search('<.*?>', word)) + text_prompt = re.sub('<.*?>', '', text) + + text_prompt = text_prompt.replace(",,",",") + text_prompt = text_prompt.replace(" ,",",") + text_prompt = text_prompt.replace(",",", ") + text_prompt = text_prompt.replace(" "," ") + text_prompt = text_prompt.strip() + text_prompt = text_prompt.strip(",") + text_prompt = text_prompt.strip() + + return (text_lora,text_prompt) + +################################ + +class SimpleLoraLoader: + + def __init__(self): + self.loaded_lora = [] + self.cache_size = 0 + + @classmethod + def INPUT_TYPES(cls): + return {"required": { + "model": ("MODEL", {"tooltip": "The diffusion model the LoRA will be applied to"}), + "clip": ("CLIP", {"tooltip": "The CLIP model the LoRA will be applied to"}), + "lora_text": ("STRING", {"multiline": False, "default": "", "tooltip": "Multiple LoRAs discriptions in Forge style: or ", "forceInput": True}), + }, + "optional": { + "multiple_strength_unet": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.05, "tooltip": "Multiple of unet strength"}), + "multiple_strength_clip": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.05, "tooltip": "Multiple of clip strength"}), + "limit_strength_unet": ("FLOAT", {"default": 2.0, "min": -10.0, "max": 10.0, "step": 0.05, "tooltip": "Max of unet strength"}), + "limit_strength_clip": ("FLOAT", {"default": 2.0, "min": -10.0, "max": 10.0, "step": 0.05, "tooltip": "Max of clip strength"}), + } + } + + RETURN_TYPES = ("MODEL","CLIP","STRING","STRING") + RETURN_NAMES = ("model","clip","civitai_lora","civitai_lora_hash") + FUNCTION = "lora_loader" + CATEGORY = "πŸ“š SimpleButcher" + DESCRIPTION = "Multiple LoRAs loader, understands discriptions in Forge style: or . Understands both file names and internal lore names (Forge style). Once creates a lora_name.json dictionary and places it in the lora folder to speed up. Once creates a lora templates to __txt folder. In case of lora update just delete these files and press F5 in confy-ui." + + def file_sha256(self, filename): + hasher = hashlib.sha256() + with open(filename, 'rb') as f: + while True: + data = f.read(65536) # Read in 64k chunks + if not data: + break + hasher.update(data) + return hasher.hexdigest() + + def load_lora_name(self): + + directory = LORA_PATH + json_path = os.path.join(directory,"lora_name.json") + + name_lines = [] + json_lines = [] + + console_text = f"[\033[94mLora File:\033[0m]" + print(f"{console_text}") + + for root, dirs, files in os.walk(directory): + for file in files: + if file.endswith(".safetensors"): + full_filepath = os.path.join(root, file) + filepath = full_filepath.replace(directory+"\\", "") + lora_name1 = os.path.splitext(file)[0] + lora_name2 = "None" + with safe_open(full_filepath, framework="pt", device="cpu") as f: + if f.metadata() != None: + if "ss_output_name" in f.metadata(): + lora_name2 = f.metadata()["ss_output_name"] + if lora_name2 == "lora": + lora_name2 = "None" + if lora_name2 == "": + lora_name2 = "None" + #elif "modelspec.title" in f.metadata(): + # lora_name2 = f.metadata()["modelspec.title"] + + hash_value = self.file_sha256(full_filepath) + hash_value_10_chars = hash_value[:10] + + subdirectory = os.path.dirname(filepath) + if subdirectory == "": + subdirectory = "root" + subdirectory = subdirectory.replace("\\","_") + + if lora_name2 == "None": + console_text = f"[\033[95m{hash_value_10_chars}\033[0m] {filepath} -> \033[91m{lora_name2}\033[0m" + name_lines.append([subdirectory,""]) + else: + console_text = f"[\033[95m{hash_value_10_chars}\033[0m] {filepath} -> \033[92m{lora_name2}\033[0m" + name_lines.append([subdirectory,""]) + print(f"{console_text}") + + json_lines.append([filepath,lora_name1,lora_name2,hash_value_10_chars]) + + console_text = "End" + console_text = f"[\033[94m{console_text}\033[0m]" + print(f"{console_text}") + + with open(json_path, 'w') as file: + json.dump(json_lines, file) + + txt_path = directory + "\\__txt" + if not os.path.exists(txt_path): + os.makedirs(txt_path, exist_ok=True) + + data_dict = {} + for name, value in name_lines: + if name not in data_dict: + data_dict[name] = [] + data_dict[name].append(value) + + for name, values in data_dict.items(): + with open(txt_path+f"\\Lora in {name}.txt", "w", encoding="utf-8") as file: + for value in values: + file.write(f"{value}\n") + + return () + + + def lora_loader(self, model, clip, lora_text, multiple_strength_unet = 1.0, multiple_strength_clip = 1.0, limit_strength_unet = 2.0, limit_strength_clip = 2.0): + + json_path = os.path.join(LORA_PATH,"lora_name.json") + + if not os.path.isfile(json_path): + self.load_lora_name() + + dic = [] + if os.path.isfile(json_path): + with open(json_path, 'r') as file: + data = json.load(file) + dic = [tuple(item) for item in data] + + loras = re.findall(r']*>', lora_text) + + civitai_lora = "" + civitai_lora_hash = "" + + #print(f"Cache size = {len(self.loaded_lora)}") + + for item in self.loaded_lora: + item[2] = False + + for lora in loras: + lora = lora.replace("","") + parts = lora.split(":", 1) + lora_prompt_name = parts[0] + lora_path = "" + lora_hash = "" + for item in dic: # find filename + if item[1] == lora_prompt_name: + lora_path = item[0] + lora_hash = item[3] + break + if lora_path == "": + for item in dic: # or find lora name + if item[2] == lora_prompt_name: + lora_path = item[0] + lora_hash = item[3] + break + if lora_path == "": + console_text = "-Lora: "+lora_prompt_name + console_text = f"[\033[91m{console_text}\033[0m]" + print(f"{console_text}") + continue + +########################## +##### parce strength ##### + + strength_model = 1.0 + strength_clip = 1.0 + + if len(parts) == 2: + lora_parameter = parts[1] + parts = lora_parameter.split(":") + if len(parts) == 1: + try: + strength_model = float(lora_parameter) + strength_model = round(strength_model, 2) + except: + strength_model = 1.0 + strength_clip = strength_model + else: + for part in parts: + parts2 = part.split("=") + if parts2[0] == "unet": + try: + strength_model = float(parts2[1]) + strength_model = round(strength_model, 2) + except: + strength_model = 1.0 + elif parts2[0] == "te": + try: + strength_clip = float(parts2[1]) + strength_clip = round(strength_clip, 2) + except: + strength_clip = 1.0 + + if multiple_strength_unet != 1.0: + strength_model = round(strength_model * multiple_strength_unet, 2) + + if multiple_strength_clip != 1.0: + strength_clip = round(strength_clip * multiple_strength_clip, 2) + + if strength_model > limit_strength_unet: + strength_model = limit_strength_unet + + if strength_clip > limit_strength_clip: + strength_clip = limit_strength_clip + +##### parce strength ##### +########################## + + strength_model_str = "{:.2f}".format(strength_model) + strength_clip_str = "{:.2f}".format(strength_clip) + + if strength_model == strength_clip: + civitai_lora = civitai_lora + " " + else: + civitai_lora = civitai_lora + " " + + civitai_lora_hash = civitai_lora_hash + lora_prompt_name + ": " + lora_hash + ", " + + lora = None + postfix = "" + for item in self.loaded_lora: + if item[0] == lora_path: + lora = item[1] + item[2] = True + postfix = " cache" + if lora == None: + full_path = folder_paths.get_full_path_or_raise("loras", lora_path) + lora = comfy.utils.load_torch_file(full_path, safe_load=True) + self.loaded_lora.append([lora_path,lora,True]) + postfix = " load" + model,clip = comfy.sd.load_lora_for_models(model, clip, lora, strength_model, strength_clip) + + if strength_model == strength_clip: + console_text = f"[\033[94m+Lora: {lora_path}:\033[92m{strength_model_str}\033[0m]{postfix}" + print(f"{console_text}") + else: + console_text = f"[\033[94m+Lora: {lora_path}:\033[92m{strength_model_str}:{strength_clip_str}\033[0m]{postfix}" + print(f"{console_text}") + +##### Empty catch ##### + for i in range(len(self.loaded_lora)-1, -1, -1): #reverse order + if not self.loaded_lora[i][2]: + temp = self.loaded_lora[i][1] + del self.loaded_lora[i] + del temp + + civitai_lora_hash = civitai_lora_hash.rstrip(", ") + civitai_lora = civitai_lora.strip() + + return (model,clip,civitai_lora,civitai_lora_hash) + + +################################ + +class SimpleImageSaver: + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "images": ("IMAGE", { "tooltip": "image(s) to save", "forceInput": True}), + "prompt": ("STRING", {"default": "", "multiline": False, "tooltip": "STRING", "forceInput": True}), + "output_path": ("STRING", {"default": "", "multiline": False, "tooltip": "Path where images will be saved"}), + "SEED": ("INT", {"default": '0', "tooltip": "INT", "forceInput": True}), + "modelname": ("STRING", {"default": '', "multiline": False, "tooltip": "STRING, use Checkpoint Loader with Name (Image Saver) node", "forceInput": True}), + }, + "optional": { + "steps": ("INT", {"default": 0, "tooltip": "INT", "forceInput": True}), + "sampler": (any, {"default": None, "tooltip": "ANY, use Sampler Selector (Image Saver) node", "forceInput": True}), + "schedule": (any, {"default": None, "tooltip": "ANY, use Scheduler Selector (Image Saver) node", "forceInput": True}), + "CFG_scale": ("FLOAT", {"default": 0.0, "tooltip": "FLOAT", "forceInput": True}), + "distilled_CFG_scale": ("FLOAT", {"default": 0.0, "tooltip": "FLOAT", "forceInput": True}), + "width": ("INT", {"default": 0, "tooltip": "INT", "forceInput": True}), + "height": ("INT", {"default": 0, "tooltip": "INT", "forceInput": True}), + "beta_schedule_alpha": ("FLOAT", {"default": 0.0, "tooltip": "FLOAT", "forceInput": True}), + "beta_schedule_beta": ("FLOAT", {"default": 0.0, "tooltip": "FLOAT", "forceInput": True}), + "civitai_lora": ("STRING", {"default": '', "multiline": False, "tooltip": "STRING, Loras name from Simple Lora Loader node", "forceInput": True}), + "civitai_lora_hash": ("STRING", {"default": '', "multiline": False, "tooltip": "STRING, Loras hash from Simple Lora Loader node", "forceInput": True}), + "negative": ("STRING", {"default": '', "multiline": False, "tooltip": "STRING, Negative prompt", "forceInput": True}), + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("metadata_text",) + FUNCTION = "image_saver" + CATEGORY = "πŸ“š SimpleButcher" + DESCRIPTION = "SimpleImageSaver" + OUTPUT_NODE = True + DESCRIPTION = "Image Saver with metadata in Forge style. Loras name and hash could be obtained from Simple Lora Loader node. Π‘reated subfolders with date, output files contain a sequence number and seed, as Forge does." + + + def find_free_number(self, path): + i = -1 + for filename in os.listdir(path): + if os.path.isfile(os.path.join(path, filename)): + new = -1 + try: + new = int(filename[:5]) + except: + new = -1 + if new > i: + i = new + return i+1 + + def get_sha256(self, file_path: str): + file_no_ext = os.path.splitext(file_path)[0] + hash_file = file_no_ext + ".sha256" + + if os.path.exists(hash_file): + try: + with open(hash_file, "r") as f: + return f.read().strip() + except OSError as e: + print(f"ComfyUI-Image-Saver: Error reading existing hash file: {e}") + + sha256_hash = hashlib.sha256() + with open(file_path, "rb") as f: + for byte_block in iter(lambda: f.read(4096), b""): + sha256_hash.update(byte_block) + + try: + with open(hash_file, "w") as f: + f.write(sha256_hash.hexdigest()) + except OSError as e: + print(f"ComfyUI-Image-Saver: Error writing hash to {hash_file}: {e}") + + return sha256_hash.hexdigest() + + + def image_saver(self, images, prompt, output_path, SEED, modelname, steps=0, sampler=None, schedule=None, CFG_scale=0.0, distilled_CFG_scale=0.0, width=0, height=0, beta_schedule_alpha=0.0, beta_schedule_beta=0.0, civitai_lora="", civitai_lora_hash="",negative=""): + + metadata_text = "" + + now = datetime.now() + date = now.strftime("%Y-%m-%d") + + output_path = output_path.strip() + if output_path == '': + return () + + output_path = os.path.join(output_path, date) + + if not os.path.exists(output_path): + os.makedirs(output_path, exist_ok=True) + + for image in images: + i = 255. * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + + free_number = self.find_free_number(output_path) + if free_number > 99999: + print(f"\033[91mToo many files\033[0m") + return () + + seed_text = str(SEED) + +#################### +##### metadata ##### + + metadata_text = prompt + if civitai_lora != "": + metadata_text = metadata_text + ' ' + civitai_lora + + metadata_text = metadata_text + '\n' + + if negative != "": + metadata_text = metadata_text + "Negative prompt: "+ negative + '\n' + + if steps != 0: + metadata_text = metadata_text + "Steps: "+str(steps)+", " + if sampler != None: + metadata_text = metadata_text + "Sampler: "+str(sampler)+", " + if schedule != None: + metadata_text = metadata_text + "Schedule type: "+str(schedule)+", " + if CFG_scale != 0.0: + metadata_text = metadata_text + "CFG scale: "+str(CFG_scale)+", " + if distilled_CFG_scale != 0.0: + metadata_text = metadata_text + "Distilled CFG Scale: "+str(distilled_CFG_scale)+", " + metadata_text = metadata_text + "Seed: "+seed_text+", " + if width != 0: + if height != 0: + metadata_text = metadata_text + "Size: " + str(width) + "x" + str(height) + ", " + + ckpt_path = folder_paths.get_full_path("checkpoints", modelname) + if not ckpt_path: + ckpt_path = folder_paths.get_full_path("diffusion_models", modelname) + if ckpt_path: + modelhash = self.get_sha256(ckpt_path)[:10] + else: + modelhash = "" + metadata_text = metadata_text + "Model hash: "+modelhash+", " + modelname = os.path.basename(modelname) + modelname = os.path.splitext(modelname)[0] + metadata_text = metadata_text + "Model: "+modelname+", " + + if beta_schedule_alpha != 0.0: + metadata_text = metadata_text + "Beta schedule alpha: "+str(beta_schedule_alpha)+", " + if beta_schedule_beta != 0.0: + metadata_text = metadata_text + "Beta schedule beta: "+str(beta_schedule_beta)+", " + + if civitai_lora_hash != "": + metadata_text = metadata_text + "Lora hashes: \"" + civitai_lora_hash + "\", " + + metadata_text = metadata_text + "Version: ComfyUI" + +##### metadata ##### +#################### + + metadata = PngInfo() + metadata.add_text("parameters", metadata_text) + + filename = f"{free_number:05d}-{seed_text}.png" + img.save(os.path.join(output_path, filename), pnginfo=metadata, optimize=False) + + return (metadata_text,) + + +################################ + +NODE_CLASS_MAPPINGS = { + "Simple Load Line From Text File": SimpleLoadLineFromTextFile, + "Simple Extract Lora From Text": SimpleExtractLoraFromText, + "Simple Lora Loader": SimpleLoraLoader, + "Simple Image Saver (as Forge)": SimpleImageSaver +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "Simple Load Line From Text File": "Simple Load Line From Text File πŸ“š", + "Simple Extract Lora From Text": "Simple Extract Lora From Text πŸ“š", + "Simple Lora Loader": "Simple Lora Loader πŸ“š", + "Simple Image Saver (as Forge)": "Simple Image Saver (as Forge) πŸ“š", +} + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..dfe1a52 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ + +piexif diff --git a/workflows/flux_workflow_test.json b/workflows/flux_workflow_test.json new file mode 100644 index 0000000..92c6f85 --- /dev/null +++ b/workflows/flux_workflow_test.json @@ -0,0 +1 @@ +{"last_node_id":90,"last_link_id":162,"nodes":[{"id":60,"type":"SamplerCustomAdvanced","pos":[2053.389892578125,1210.1732177734375],"size":[236.8000030517578,326],"flags":{},"order":25,"mode":0,"inputs":[{"name":"noise","type":"NOISE","link":123,"localized_name":"noise"},{"name":"guider","type":"GUIDER","link":120,"localized_name":"guider"},{"name":"sampler","type":"SAMPLER","link":138,"localized_name":"sampler"},{"name":"sigmas","type":"SIGMAS","link":142,"localized_name":"sigmas"},{"name":"latent_image","type":"LATENT","link":133,"localized_name":"latent_image"}],"outputs":[{"name":"output","type":"LATENT","links":[126],"slot_index":0,"localized_name":"output"},{"name":"denoised_output","type":"LATENT","links":null,"slot_index":1,"localized_name":"denoised_output"}],"properties":{"Node name for S&R":"SamplerCustomAdvanced"},"widgets_values":[]},{"id":61,"type":"BasicGuider","pos":[1682.2447509765625,1317.73828125],"size":[161.1999969482422,46],"flags":{},"order":24,"mode":0,"inputs":[{"name":"model","type":"MODEL","link":132,"localized_name":"model"},{"name":"conditioning","type":"CONDITIONING","link":140,"localized_name":"conditioning"}],"outputs":[{"name":"GUIDER","type":"GUIDER","links":[120],"slot_index":0,"localized_name":"GUIDER"}],"properties":{"Node name for S&R":"BasicGuider"},"widgets_values":[]},{"id":66,"type":"EmptySD3LatentImage","pos":[1715.586181640625,1615.176025390625],"size":[210,78],"flags":{},"order":13,"mode":0,"inputs":[{"name":"width","type":"INT","link":127,"widget":{"name":"width"}},{"name":"height","type":"INT","link":128,"widget":{"name":"height"}}],"outputs":[{"name":"LATENT","type":"LATENT","links":[133],"slot_index":0,"localized_name":"LATENT"}],"properties":{"Node name for S&R":"EmptySD3LatentImage"},"widgets_values":[896,1152,1]},{"id":71,"type":"BasicScheduler","pos":[1696.5687255859375,1436.494140625],"size":[210,98],"flags":{},"order":22,"mode":0,"inputs":[{"name":"model","type":"MODEL","link":145,"localized_name":"model"},{"name":"scheduler","type":"COMBO","link":143,"widget":{"name":"scheduler"}},{"name":"steps","type":"INT","link":146,"widget":{"name":"steps"}},{"name":"denoise","type":"FLOAT","link":147,"widget":{"name":"denoise"}}],"outputs":[{"name":"SIGMAS","type":"SIGMAS","links":[142],"slot_index":0,"localized_name":"SIGMAS"}],"properties":{"Node name for S&R":"BasicScheduler"},"widgets_values":["beta",20,1]},{"id":67,"type":"ModelSamplingFlux","pos":[1306.2962646484375,1282.681884765625],"size":[210,122],"flags":{},"order":20,"mode":0,"inputs":[{"name":"model","type":"MODEL","link":134,"localized_name":"model"},{"name":"width","type":"INT","link":129,"widget":{"name":"width"}},{"name":"height","type":"INT","link":130,"widget":{"name":"height"}}],"outputs":[{"name":"MODEL","type":"MODEL","links":[132,145],"slot_index":0,"localized_name":"MODEL"}],"properties":{"Node name for S&R":"ModelSamplingFlux"},"widgets_values":[1.15,0.5,896,1152]},{"id":73,"type":"PrimitiveNode","pos":[1327.6978759765625,1457.555908203125],"size":[210,82],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"FLOAT","type":"FLOAT","links":[147,148],"slot_index":0,"widget":{"name":"denoise"}}],"title":"DENOISE","properties":{"Run widget replace on values":false},"widgets_values":[1,"fixed"],"color":"#322","bgcolor":"#533"},{"id":65,"type":"PrimitiveNode","pos":[930.60888671875,1231.6962890625],"size":[252.7154998779297,82],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"INT","type":"INT","links":[128,130,135],"slot_index":0,"widget":{"name":"height"}}],"title":"HEIGHT","properties":{"Run widget replace on values":false},"widgets_values":[1152,"fixed"],"color":"#322","bgcolor":"#533"},{"id":55,"type":"Simple Image Saver (as Forge)","pos":[1229.3135986328125,538.9656372070312],"size":[278.79998779296875,358],"flags":{},"order":28,"mode":0,"inputs":[{"name":"images","type":"IMAGE","link":92,"localized_name":"images"},{"name":"sampler","type":"*","link":93,"shape":7,"localized_name":"sampler"},{"name":"schedule","type":"*","link":94,"shape":7,"localized_name":"schedule"},{"name":"SEED","type":"INT","link":97,"widget":{"name":"SEED"}},{"name":"steps","type":"INT","link":98,"widget":{"name":"steps"},"shape":7},{"name":"prompt","type":"STRING","link":99,"widget":{"name":"prompt"}},{"name":"width","type":"INT","link":136,"widget":{"name":"width"},"shape":7},{"name":"height","type":"INT","link":135,"widget":{"name":"height"},"shape":7},{"name":"civitai_lora","type":"STRING","link":102,"widget":{"name":"civitai_lora"},"shape":7},{"name":"civitai_lora_hash","type":"STRING","link":103,"widget":{"name":"civitai_lora_hash"},"shape":7},{"name":"CFG_scale","type":"FLOAT","link":148,"widget":{"name":"CFG_scale"},"shape":7},{"name":"modelname","type":"STRING","link":118,"widget":{"name":"modelname"}},{"name":"distilled_CFG_scale","type":"FLOAT","link":150,"widget":{"name":"distilled_CFG_scale"},"shape":7},{"name":"beta_schedule_alpha","type":"FLOAT","link":null,"widget":{"name":"beta_schedule_alpha"},"shape":7},{"name":"beta_schedule_beta","type":"FLOAT","link":null,"widget":{"name":"beta_schedule_beta"},"shape":7},{"name":"negative","type":"STRING","link":null,"widget":{"name":"negative"},"shape":7}],"outputs":[{"name":"metadata_text","type":"STRING","links":[151],"slot_index":0,"localized_name":"metadata_text"}],"properties":{"Node name for S&R":"Simple Image Saver (as Forge)"},"widgets_values":["","H:\\IMAGES2",2030,"",20,1,3.5,896,1152,0,0,"","",""],"color":"#232","bgcolor":"#353"},{"id":8,"type":"VAEDecode","pos":[2040.831298828125,1071.5465087890625],"size":[210,46],"flags":{},"order":26,"mode":0,"inputs":[{"name":"samples","type":"LATENT","link":126,"localized_name":"samples"},{"name":"vae","type":"VAE","link":119,"localized_name":"vae"}],"outputs":[{"name":"IMAGE","type":"IMAGE","links":[81,92],"slot_index":0,"localized_name":"IMAGE"}],"properties":{"Node name for S&R":"VAEDecode"},"widgets_values":[]},{"id":49,"type":"PreviewImage","pos":[2357.725830078125,1065.293701171875],"size":[450,483],"flags":{},"order":27,"mode":0,"inputs":[{"name":"images","type":"IMAGE","link":81,"localized_name":"images"}],"outputs":[],"properties":{"Node name for S&R":"PreviewImage"},"widgets_values":[]},{"id":51,"type":"Scheduler Selector (Comfy) (Image Saver)","pos":[1306.84033203125,1598.59423828125],"size":[268.79998779296875,78],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"scheduler","type":"COMBO","links":[143],"slot_index":0,"localized_name":"scheduler"},{"name":"scheduler_name","type":"STRING","links":[94],"slot_index":1,"localized_name":"scheduler_name"}],"title":"Scheduler Selector (Image Saver)","properties":{"Node name for S&R":"Scheduler Selector (Comfy) (Image Saver)"},"widgets_values":["beta"],"color":"#322","bgcolor":"#533"},{"id":46,"type":"PrimitiveNode","pos":[1300.9166259765625,1730.296142578125],"size":[286.49749755859375,98.39232635498047],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[{"name":"INT","type":"INT","links":[98,146],"slot_index":0,"widget":{"name":"steps"}}],"title":"STEPS","properties":{"Run widget replace on values":false},"widgets_values":[20,"fixed"],"color":"#322","bgcolor":"#533"},{"id":69,"type":"KSamplerSelect","pos":[1652.417236328125,1217.6163330078125],"size":[210,34],"flags":{},"order":12,"mode":0,"inputs":[{"name":"sampler_name","type":"COMBO","link":139,"widget":{"name":"sampler_name"}}],"outputs":[{"name":"SAMPLER","type":"SAMPLER","links":[138],"slot_index":0,"localized_name":"SAMPLER"}],"properties":{"Node name for S&R":"KSamplerSelect"},"widgets_values":["euler"]},{"id":62,"type":"RandomNoise","pos":[1648.8858642578125,1115.9100341796875],"size":[210,34],"flags":{},"order":14,"mode":0,"inputs":[{"name":"noise_seed","type":"INT","link":124,"widget":{"name":"noise_seed"}}],"outputs":[{"name":"NOISE","type":"NOISE","links":[123],"slot_index":0,"localized_name":"NOISE"}],"properties":{"Node name for S&R":"RandomNoise"},"widgets_values":[2030,"fixed"]},{"id":75,"type":"PrimitiveNode","pos":[1006.8265991210938,1492.9464111328125],"size":[241.67599487304688,82],"flags":{},"order":4,"mode":0,"inputs":[],"outputs":[{"name":"FLOAT","type":"FLOAT","links":[149,150],"slot_index":0,"widget":{"name":"guidance"}}],"title":"GUIDANCE","properties":{"Run widget replace on values":false},"widgets_values":[3.5,"fixed"],"color":"#322","bgcolor":"#533"},{"id":70,"type":"FluxGuidance","pos":[1059.70947265625,1372.9534912109375],"size":[211.60000610351562,58],"flags":{},"order":23,"mode":0,"inputs":[{"name":"conditioning","type":"CONDITIONING","link":141,"localized_name":"conditioning"},{"name":"guidance","type":"FLOAT","link":149,"widget":{"name":"guidance"}}],"outputs":[{"name":"CONDITIONING","type":"CONDITIONING","links":[140],"slot_index":0,"localized_name":"CONDITIONING"}],"properties":{"Node name for S&R":"FluxGuidance"},"widgets_values":[3.5]},{"id":6,"type":"CLIPTextEncode","pos":[813.3372192382812,1374.58740234375],"size":[210,54],"flags":{},"order":21,"mode":0,"inputs":[{"name":"clip","type":"CLIP","link":63,"localized_name":"clip"},{"name":"text","type":"STRING","link":154,"widget":{"name":"text"}}],"outputs":[{"name":"CONDITIONING","type":"CONDITIONING","links":[141],"slot_index":0,"localized_name":"CONDITIONING"}],"title":"CLIP Text Encode","properties":{"Node name for S&R":"CLIPTextEncode"},"widgets_values":["a bottle with a beautiful rainbow galaxy inside it on top of a wooden table in the middle of a modern kitchen beside a plate of vegetables and mushrooms and a wine glasse that contains a planet earth with a plate with a half eaten apple pie on it"]},{"id":40,"type":"Simple Lora Loader","pos":[454.6371154785156,1218.4957275390625],"size":[272.1906433105469,190],"flags":{},"order":17,"mode":0,"inputs":[{"name":"model","type":"MODEL","link":116,"localized_name":"model"},{"name":"clip","type":"CLIP","link":115,"localized_name":"clip"},{"name":"lora_text","type":"STRING","link":84,"widget":{"name":"lora_text"}}],"outputs":[{"name":"model","type":"MODEL","links":[134],"slot_index":0,"localized_name":"model"},{"name":"clip","type":"CLIP","links":[63],"slot_index":1,"localized_name":"clip"},{"name":"civitai_lora","type":"STRING","links":[102],"slot_index":2,"localized_name":"civitai_lora"},{"name":"civitai_lora_hash","type":"STRING","links":[103],"slot_index":3,"localized_name":"civitai_lora_hash"}],"properties":{"Node name for S&R":"Simple Lora Loader"},"widgets_values":["",1,1,0.8,0.8],"color":"#232","bgcolor":"#353"},{"id":77,"type":"ShowText|pysssss","pos":[1557.774658203125,546.9102172851562],"size":[507.4925231933594,288.6661376953125],"flags":{},"order":29,"mode":0,"inputs":[{"name":"text","type":"STRING","link":151,"widget":{"name":"text"}}],"outputs":[{"name":"STRING","type":"STRING","links":null,"shape":6,"localized_name":"STRING"}],"properties":{"Node name for S&R":"ShowText|pysssss"},"widgets_values":["","A super detailed digital painting features a white cat with big, expressive green eyes and a playful expression. The cat sports a snazzy red wizard hat with a black band and a little golden bell, giving off a magical vibe. A red cape with a golden clasp is draped over its back. The fur is super detailed with dark and light stripes, showing off its sleek coat. In the background, a fantasy village with rustic, wooden buildings and thatched roofs sprawls across a lush, green landscape. The village is partially destroyed, with wooden beams and debris scattered around. Red and pink flowers, with some white blooms, pop up among the ruins, adding a splash of color. The sky is bright with soft, fluffy clouds, adding to the whimsical and enchanting atmosphere. The whole scene is bursting with texture and color, blending fantasy and realism to create a vivid and immersive world. The style is reminiscent of modern fantasy art with a dash of magical realism. \nSteps: 20, Sampler: euler, Schedule type: beta, CFG scale: 1.0, Distilled CFG Scale: 3.5, Seed: 691, Size: 896x1152, Model hash: 2eda627c8a, Model: flux_dev, Lora hashes: \"Illustration_Style_IV: 66bb6c51f2, kmix0001: 112907f433, kfox0001: ccb0a3738b\", Version: ComfyUI"]},{"id":81,"type":"Text Multiline","pos":[-374.9679260253906,1837.04736328125],"size":[354.63140869140625,117.97437286376953],"flags":{},"order":5,"mode":0,"inputs":[],"outputs":[{"name":"STRING","type":"STRING","links":[160],"slot_index":0,"localized_name":"STRING"}],"title":"EXTRA LORA","properties":{"Node name for S&R":"Text Multiline"},"widgets_values":["\n"]},{"id":80,"type":"Text Multiline","pos":[-816.0723266601562,1534.8564453125],"size":[398.2131042480469,193.7460174560547],"flags":{},"order":6,"mode":0,"inputs":[],"outputs":[{"name":"STRING","type":"STRING","links":[162],"slot_index":0,"localized_name":"STRING"}],"title":"EXTRA PROMPT","properties":{"Node name for S&R":"Text Multiline"},"widgets_values":[""]},{"id":52,"type":"Sampler Selector (Image Saver)","pos":[1273.7012939453125,1156.2021484375],"size":[252,78],"flags":{},"order":7,"mode":0,"inputs":[],"outputs":[{"name":"sampler","type":"COMBO","links":[139],"slot_index":0,"localized_name":"sampler"},{"name":"sampler_name","type":"STRING","links":[93],"slot_index":1,"localized_name":"sampler_name"}],"properties":{"Node name for S&R":"Sampler Selector (Image Saver)"},"widgets_values":["euler"],"color":"#322","bgcolor":"#533"},{"id":64,"type":"PrimitiveNode","pos":[932.538818359375,1090.94482421875],"size":[247.58969116210938,82],"flags":{},"order":8,"mode":0,"inputs":[],"outputs":[{"name":"INT","type":"INT","links":[127,129,136],"slot_index":0,"widget":{"name":"width"}}],"title":"WIDTH","properties":{"Run widget replace on values":false},"widgets_values":[896,"fixed"],"color":"#322","bgcolor":"#533"},{"id":50,"type":"Simple Extract Lora From Text","pos":[418.1015930175781,1533.8770751953125],"size":[268.79998779296875,54],"flags":{},"order":16,"mode":0,"inputs":[{"name":"text","type":"STRING","link":158,"widget":{"name":"text"}}],"outputs":[{"name":"lora_text","type":"STRING","links":[84,156],"slot_index":0,"localized_name":"lora_text"},{"name":"prompt","type":"STRING","links":[99,154,157],"slot_index":1,"localized_name":"prompt"}],"properties":{"Node name for S&R":"Simple Extract Lora From Text"},"widgets_values":[""],"color":"#232","bgcolor":"#353"},{"id":84,"type":"Simple Load Line From Text File","pos":[51.91370391845703,1534.8341064453125],"size":[345.4118347167969,214],"flags":{},"order":15,"mode":0,"inputs":[{"name":"prefix","type":"STRING","link":161,"widget":{"name":"prefix"},"shape":7},{"name":"postfix","type":"STRING","link":160,"widget":{"name":"postfix"},"shape":7}],"outputs":[{"name":"text","type":"STRING","links":[158],"slot_index":0,"localized_name":"text"},{"name":"batch_counter","type":"INT","links":null,"localized_name":"batch_counter"},{"name":"line_counter","type":"INT","links":null,"localized_name":"line_counter"},{"name":"lines","type":"INT","links":null,"localized_name":"lines"}],"title":"Simple Load Line From Text File πŸ“š (LORA)","properties":{"Node name for S&R":"Simple Load Line From Text File"},"widgets_values":[0,true,"D:\\ComfyUI\\ComfyUI_windows_portable\\ComfyUI\\custom_nodes\\ComfyUI_SimpleButcher\\workflows\\lora_test.txt","random no repetitions",0,"",""],"color":"#232","bgcolor":"#353"},{"id":83,"type":"ShowText|pysssss","pos":[757.8388061523438,1639.7752685546875],"size":[492.27801513671875,221.50765991210938],"flags":{},"order":19,"mode":0,"inputs":[{"name":"text","type":"STRING","link":157,"widget":{"name":"text"}}],"outputs":[{"name":"STRING","type":"STRING","links":null,"shape":6,"localized_name":"STRING"}],"properties":{"Node name for S&R":"ShowText|pysssss"},"widgets_values":["","A super detailed digital painting features a white cat with big, expressive green eyes and a playful expression. The cat sports a snazzy red wizard hat with a black band and a little golden bell, giving off a magical vibe. A red cape with a golden clasp is draped over its back. The fur is super detailed with dark and light stripes, showing off its sleek coat. In the background, a fantasy village with rustic, wooden buildings and thatched roofs sprawls across a lush, green landscape. The village is partially destroyed, with wooden beams and debris scattered around. Red and pink flowers, with some white blooms, pop up among the ruins, adding a splash of color. The sky is bright with soft, fluffy clouds, adding to the whimsical and enchanting atmosphere. The whole scene is bursting with texture and color, blending fantasy and realism to create a vivid and immersive world. The style is reminiscent of modern fantasy art with a dash of magical realism."]},{"id":82,"type":"ShowText|pysssss","pos":[758.918701171875,1919.8802490234375],"size":[488.42315673828125,90.3868637084961],"flags":{},"order":18,"mode":0,"inputs":[{"name":"text","type":"STRING","link":156,"widget":{"name":"text"}}],"outputs":[{"name":"STRING","type":"STRING","links":null,"shape":6,"localized_name":"STRING"}],"properties":{"Node name for S&R":"ShowText|pysssss"},"widgets_values":[""," "]},{"id":43,"type":"PrimitiveNode","pos":[1254.8123779296875,1011.0907592773438],"size":[283.76544189453125,84.04904174804688],"flags":{},"order":9,"mode":0,"inputs":[],"outputs":[{"name":"INT","type":"INT","links":[97,124],"slot_index":0,"widget":{"name":"SEED"}}],"title":"SEED","properties":{"Run widget replace on values":false},"widgets_values":[2030,"fixed"],"color":"#322","bgcolor":"#533"},{"id":59,"type":"Checkpoint Loader with Name (Image Saver)","pos":[-155.81375122070312,996.8579711914062],"size":[344.3999938964844,118],"flags":{},"order":10,"mode":0,"inputs":[],"outputs":[{"name":"MODEL","type":"MODEL","links":[116],"slot_index":0,"localized_name":"MODEL"},{"name":"CLIP","type":"CLIP","links":[115],"slot_index":1,"localized_name":"CLIP"},{"name":"VAE","type":"VAE","links":[119],"slot_index":2,"localized_name":"VAE"},{"name":"model_name","type":"STRING","links":[118],"slot_index":3,"localized_name":"model_name"}],"properties":{"Node name for S&R":"Checkpoint Loader with Name (Image Saver)"},"widgets_values":["flux\\flux_dev.safetensors"]},{"id":85,"type":"Simple Load Line From Text File","pos":[-372.4047546386719,1535.5604248046875],"size":[361.20001220703125,214],"flags":{},"order":11,"mode":0,"inputs":[{"name":"prefix","type":"STRING","link":162,"widget":{"name":"prefix"},"shape":7},{"name":"postfix","type":"STRING","link":null,"widget":{"name":"postfix"},"shape":7}],"outputs":[{"name":"text","type":"STRING","links":[161],"slot_index":0,"localized_name":"text"},{"name":"batch_counter","type":"INT","links":null,"localized_name":"batch_counter"},{"name":"line_counter","type":"INT","links":null,"localized_name":"line_counter"},{"name":"lines","type":"INT","links":null,"localized_name":"lines"}],"title":"Simple Load Line From Text File πŸ“š (PROMPT)","properties":{"Node name for S&R":"Simple Load Line From Text File"},"widgets_values":[0,true,"D:\\ComfyUI\\ComfyUI_windows_portable\\ComfyUI\\custom_nodes\\ComfyUI_SimpleButcher\\workflows\\prompt_test.txt","random no repetitions",0,"",""],"color":"#232","bgcolor":"#353"}],"links":[[63,40,1,6,0,"CLIP"],[81,8,0,49,0,"IMAGE"],[84,50,0,40,2,"STRING"],[92,8,0,55,0,"IMAGE"],[93,52,1,55,1,"*"],[94,51,1,55,2,"*"],[97,43,0,55,3,"INT"],[98,46,0,55,4,"INT"],[99,50,1,55,5,"STRING"],[102,40,2,55,8,"STRING"],[103,40,3,55,9,"STRING"],[115,59,1,40,1,"CLIP"],[116,59,0,40,0,"MODEL"],[118,59,3,55,11,"STRING"],[119,59,2,8,1,"VAE"],[120,61,0,60,1,"GUIDER"],[123,62,0,60,0,"NOISE"],[124,43,0,62,0,"INT"],[126,60,0,8,0,"LATENT"],[127,64,0,66,0,"INT"],[128,65,0,66,1,"INT"],[129,64,0,67,1,"INT"],[130,65,0,67,2,"INT"],[132,67,0,61,0,"MODEL"],[133,66,0,60,4,"LATENT"],[134,40,0,67,0,"MODEL"],[135,65,0,55,7,"INT"],[136,64,0,55,6,"INT"],[138,69,0,60,2,"SAMPLER"],[139,52,0,69,0,"COMBO"],[140,70,0,61,1,"CONDITIONING"],[141,6,0,70,0,"CONDITIONING"],[142,71,0,60,3,"SIGMAS"],[143,51,0,71,1,"COMBO"],[145,67,0,71,0,"MODEL"],[146,46,0,71,2,"INT"],[147,73,0,71,3,"FLOAT"],[148,73,0,55,10,"FLOAT"],[149,75,0,70,1,"FLOAT"],[150,75,0,55,12,"FLOAT"],[151,55,0,77,0,"STRING"],[154,50,1,6,1,"STRING"],[156,50,0,82,0,"STRING"],[157,50,1,83,0,"STRING"],[158,84,0,50,0,"STRING"],[160,81,0,84,1,"STRING"],[161,85,0,84,0,"STRING"],[162,80,0,85,0,"STRING"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.8954302432554904,"offset":[1002.6123093550094,-1016.4995430938893]},"node_versions":{"comfy-core":"v0.3.10","comfyui-image-saver":"f8520bcfe5339ba7b4bb64ba96f6ed03da87fb89","comfyui-custom-scripts":"dff506c7dea0e715f05518354f1f7e1986609703","pr-was-node-suite-comfyui-47064894":"056badacda52e88d29d6a65f9509cd3115ace0f2"}},"version":0.4} \ No newline at end of file diff --git a/workflows/lora_test.txt b/workflows/lora_test.txt new file mode 100644 index 0000000..a576181 --- /dev/null +++ b/workflows/lora_test.txt @@ -0,0 +1,9 @@ + hkevil, + + + ghiblistyle, + dreadmirthart, + + + ArsMJStyle, impressionism, + \ No newline at end of file diff --git a/workflows/prompt_test.txt b/workflows/prompt_test.txt new file mode 100644 index 0000000..64ac07b --- /dev/null +++ b/workflows/prompt_test.txt @@ -0,0 +1,9 @@ +A quiet, reclusive individual who prefers solitude to large crowds; an introverted homebody who finds comfort in the familiar surroundings of their own space, shunning social gatherings and instead enjoying solitary pursuits such as reading, writing, or hobbies that allow for deep focus and introspection. This person is content with their own company, valuing personal growth and inner peace over constant social interaction. +The image is an illustration of a female elf holding a crystal ball in her hand. She is standing in a forest with tall trees and colorful foliage in the background. The elf is wearing a green hooded cloak with a pointed hat and has long white hair. She has a fierce expression on her face and is holding the crystal ball with both hands. The crystal ball has a blue and white swirl pattern on it. The overall mood of the image is mystical and mystical. +The image is a digital illustration of a white cat with blue eyes. The cat is standing on its hind legs with its front paws resting on an open book. The book is resting on a wooden surface and the background is dark with small white dots scattered around. The overall mood of the image is peaceful and serene. +The image is a digital illustration of a futuristic landscape with a planet in the background. The sky is filled with stars and planets, and the sun is setting in the distance, casting a warm orange glow over the scene. The planet is large and round, with a blue planet on the left side and a smaller planet in front of it. On the right side of the image, there are several smaller planets and stars scattered across the sky. +The image is a promotional poster for a movie or TV show. It features a man in a military uniform, standing in front of a rocky background. The man is wearing a black cape with gold buttons and a gold emblem on the left side. He has a beard and is looking off to the side with a serious expression on his face. +The image is a painting of a beautiful night scene with a full moon in the background. The sky is filled with stars and the moon is shining brightly, creating a soft glow. The scene is set in a forest with tall trees on both sides of the river. The trees are covered in bluebells and the ground is covered in green grass. The river is calm and there is a wooden bridge crossing over it. The water is still and reflects the colors of the sky and the trees. The overall mood of the painting is peaceful and serene. +The image is a digital illustration of a young, anthropomorphic female character with animal-like ears protruding from her head. She has a petite, slender physique with fair skin and large, expressive brown eyes. Her hair is short and tousled, with dark brown and light blonde streaks, and her ears are large and pointed, with a darker hue. She has a small, pointed nose and a slightly flushed complexion, with a few freckles on her cheeks. She wears a brown, fur-lined crop top and arm bands, adorned with geometric patterns and fur accents. The background is a dark, muted blue, with small, glowing yellow dots and small, floating orbs, giving the impression of a night sky with stars. The texture of the illustration is smooth, with a glossy finish and a detailed, vibrant color palette. The overall style is reminiscent of anime, with a focus on expressive eyes and exaggerated features, combined with a realistic, detailed approach to the textures and shading. The illustration is highly polished and detailed, with a focus on the character's facial expression and the texture of her clothing and hair. +A super detailed digital painting features a white cat with big, expressive green eyes and a playful expression. The cat sports a snazzy red wizard hat with a black band and a little golden bell, giving off a magical vibe. A red cape with a golden clasp is draped over its back. The fur is super detailed with dark and light stripes, showing off its sleek coat. In the background, a fantasy village with rustic, wooden buildings and thatched roofs sprawls across a lush, green landscape. The village is partially destroyed, with wooden beams and debris scattered around. Red and pink flowers, with some white blooms, pop up among the ruins, adding a splash of color. The sky is bright with soft, fluffy clouds, adding to the whimsical and enchanting atmosphere. The whole scene is bursting with texture and color, blending fantasy and realism to create a vivid and immersive world. The style is reminiscent of modern fantasy art with a dash of magical realism. +In this photo report, we explore a dramatic space battle scene that captures the essence of warfare in a visually stunning way. The backdrop for this narrative is the planet Saturn, known for its iconic rings, which provides an impressive setting. Two imposing Dreadnought-class spaceships, similar to the attached image, are engaged in combat against a group of smaller space fighters. These ships are characterized by their numerous protrusions, weapons, and prominent blue light elements, enhancing the visual spectacle. The small space fighters, resembling speedy space planes, maneuver swiftly through the darkness, leaving behind dynamic light trails that add movement and tension to the scene. The overall illumination comes from Saturn's bright light, which not only reflects off the metal surfaces of the ships but also contributes to the dramatic atmosphere of the battle. To further emphasize scale and depth in the space landscape, several moons of Saturn are visible, adding a sense of grandeur to this cosmic conflict. Through the use of photo-realistic imagery, attention to detail, and an emphasis on action and drama, this report successfully conveys the intensity and complexity of a space battle while also showcasing the beauty and wonder of our universe. \ No newline at end of file diff --git a/workflows/workflow.png b/workflows/workflow.png new file mode 100644 index 0000000..e7759a4 Binary files /dev/null and b/workflows/workflow.png differ