From f0aac52bc066f1d8f41fab9e253419fc2d8bd3b9 Mon Sep 17 00:00:00 2001 From: Leslie Perjes Date: Wed, 13 Mar 2024 22:58:09 +0100 Subject: [PATCH] V:0.5.0 - Preview saver 6 --- Nodes/Outputs.py | 2 +- components/primereserver.py | 64 +++++++++++++- components/utility.py | 11 +++ front_end/primere_output.js | 164 ++++++++++++++++-------------------- 4 files changed, 144 insertions(+), 97 deletions(-) diff --git a/Nodes/Outputs.py b/Nodes/Outputs.py index 7c4c3c8..a53addb 100644 --- a/Nodes/Outputs.py +++ b/Nodes/Outputs.py @@ -481,7 +481,7 @@ class PrimerePreviewImage(): OUTPUT_NODE = True FUNCTION = "preview_img_saver" - image_path = folder_paths.get_temp_directory() + image_path = folder_paths.get_output_directory() def __init__(self): self.output_dir = folder_paths.get_temp_directory() diff --git a/components/primereserver.py b/components/primereserver.py index c06c370..b01f531 100644 --- a/components/primereserver.py +++ b/components/primereserver.py @@ -1,6 +1,12 @@ from server import PromptServer from aiohttp import web +import json +from pathlib import Path +from ..components import utility +import os +from PIL import Image +''' # http://127.0.0.1:8188/primere/getdata/ez az adat @PromptServer.instance.routes.get("/primere/getdata/{data}") async def primere_getdata(request): @@ -18,11 +24,61 @@ async def primere_getquery(request): return web.json_response({ "input_data": "megvolt" }) +''' routes = PromptServer.instance.routes -@routes.post('/primere_post') -async def primere_post(request): +@routes.post('/primere_preview_post') +async def primere_preview_post(request): post = await request.post() - print('ez itt a post szerver') - print(post) + # print(json.loads(post.get('previewdata'))) + # {'PreviewTarget': 'CSV Prompt', 'extension': 'jpg', 'ImageName': 'ComfyUI_temp_pmzjp_00078_.png', 'ImagePath': 'H:\\ComfyUI\\temp', 'SaveImageName': 'Beast_in_the_beauty_saloon', 'maxWidth': 350, 'maxHeight': 250} + print('==============================') + + PREVIEW_DATA = json.loads(post.get('previewdata')) + print(PREVIEW_DATA) + IMG_SOURCE = os.path.join(PREVIEW_DATA['ImagePath'], PREVIEW_DATA['ImageName']) + print(IMG_SOURCE) + PRW_TYPE = PREVIEW_DATA['PreviewTarget'] + print(PRW_TYPE) + CONVERSION = utility.PREVIEW_PATH_BY_TYPE + print(CONVERSION) + TARGET_DIR = CONVERSION[PRW_TYPE] + TARGET_FILE = os.path.join(CONVERSION[PRW_TYPE], PREVIEW_DATA['SaveImageName'] + '_000test.' + PREVIEW_DATA['extension']) + print(TARGET_FILE) + print('------------------------------') + print(IMG_SOURCE) + if os.path.isfile(IMG_SOURCE): + print('létezik a source') + print('------------------------------') + print(CONVERSION[PRW_TYPE]) + if os.path.isdir(CONVERSION[PRW_TYPE]): + print('létezik a target dir') + print('------------------------------') + print(TARGET_FILE) + if os.path.isfile(TARGET_FILE): + print('létezik a target file') + print('------------------------------') + print(TARGET_DIR) + if os.path.isfile(TARGET_DIR): + print('létezik a target DIR') + + print('=================================') + + if os.path.isfile(IMG_SOURCE) and os.path.isdir(CONVERSION[PRW_TYPE]): + prw_img = Image.open(IMG_SOURCE).convert("RGB") + print('======= **** ============= **** =============') + width, height = prw_img.size + print(width) + print(height) + newsize = (PREVIEW_DATA['maxWidth'], PREVIEW_DATA['maxHeight']) + print('------------------------------') + print(newsize) + prw_img_resized = prw_img.resize(newsize) + width, height = prw_img_resized.size + print('------------------------------') + print(width) + print(height) + prw_img_resized.save(TARGET_FILE, quality = 60, optimize = True) + + return web.json_response({}) diff --git a/components/utility.py b/components/utility.py index 8910b5c..b122d23 100644 --- a/components/utility.py +++ b/components/utility.py @@ -20,12 +20,23 @@ import requests import folder_paths import comfy_extras.nodes_model_advanced as nodes_model_advanced import nodes +from ..utils import comfy_dir SUPPORTED_FORMATS = [".png", ".jpg", ".jpeg", ".webp"] STANDARD_SIDES = np.arange(64, 2049, 16).tolist() CASCADE_SIDES = np.arange(64, 2049, 16).tolist() MAX_RESOLUTION = 8192 VALID_SHAPES = np.arange(512, 2049, 256).tolist() +PREVIEW_ROOT = os.path.join(comfy_dir, "web", "extensions", "Primere", "images") + +PREVIEW_PATH_BY_TYPE = { + "Checkpoint": os.path.join(PREVIEW_ROOT, "checkpoints"), + "CSV Prompt": os.path.join(PREVIEW_ROOT, "styles"), + "Lora": os.path.join(PREVIEW_ROOT, "loras"), + "Lycoris": os.path.join(PREVIEW_ROOT, "lycoris"), + "Hypernetwork": os.path.join(PREVIEW_ROOT, "hypernetworks"), + "Embedding": os.path.join(PREVIEW_ROOT, "embeddings"), +} def merge_str_to_tuple(item1, item2): if not isinstance(item1, tuple): diff --git a/front_end/primere_output.js b/front_end/primere_output.js index 5ba2719..29c5bf0 100644 --- a/front_end/primere_output.js +++ b/front_end/primere_output.js @@ -1,8 +1,8 @@ import { app } from "/scripts/app.js"; import { api } from "/scripts/api.js"; import { ComfyWidgets } from "/scripts/widgets.js"; - let hasShownAlertForUpdatingInt = false; + let ImagePath = null; let WorkflowData = {}; const realPath = "extensions/Primere"; @@ -11,16 +11,11 @@ let PreviewTarget = 'Checkpoint'; let Convert = true; let IMGType = true; let MaxSide = -1; -let buttontitle = 'Save image as...' +let buttontitle = 'Image not available for save. Please load one.' +let SaveIsValid = false; +let TargetFileName = null; +let LoadedNode = null; -const PathByType = { - 'Checkpoint': '\\custom_nodes\\ComfyUI_Primere_Nodes\\front_end\\images\\checkpoints\\', - 'CSV Prompt': '\\custom_nodes\\ComfyUI_Primere_Nodes\\front_end\\images\\styles\\', - 'Lora': '\\custom_nodes\\ComfyUI_Primere_Nodes\\front_end\\images\\loras\\', - 'Lycoris': '\\custom_nodes\\ComfyUI_Primere_Nodes\\front_end\\images\\lycoris\\', - 'Hypernetwork': '\\custom_nodes\\ComfyUI_Primere_Nodes\\front_end\\images\\hypernetworks\\', - 'Embedding': '\\custom_nodes\\ComfyUI_Primere_Nodes\\front_end\\images\\embeddings\\' -} const NodenameByType = { 'Checkpoint': 'PrimereVisualCKPT', 'CSV Prompt': 'PrimereVisualStyle', @@ -56,7 +51,6 @@ app.registerExtension({ app.registerExtension({ name: "Primere.PrimerePreviewImage", async init(app) { - let callbackfunct = null; function PreviewHandler() { let head = document.getElementsByTagName('HEAD')[0]; @@ -72,13 +66,6 @@ app.registerExtension({ const lcg = LGraphCanvas.prototype.processNodeWidgets; LGraphCanvas.prototype.processNodeWidgets = function(node, pos, event, active_widget) { - //if (node.type == 'PrimereMetaCollector') { - // console.log('====== eeeeeeeeeeeeeeeeeeeee ======'); - // console.log(node.type) - // console.log(node); - // console.log('====== eeeeeeeeeeeeeeeeeeeee ======'); - //} - if (event.type != LiteGraph.pointerevents_method + "up") { return lcg.call(this, node, pos, event, active_widget); } @@ -87,34 +74,21 @@ app.registerExtension({ return lcg.call(this, node, pos, event, active_widget); } - if (node.type == 'PrimerePreviewImage') { - console.log('=============================='); - console.log(node); - console.log(node.type) - console.log(event) - console.log('=============================='); - } else { + if (node.type != 'PrimerePreviewImage') { return lcg.call(this, node, pos, event, active_widget); } var x = pos[0] - node.pos[0]; var y = pos[1] - node.pos[1]; var width = node.size[0]; - var that = this; buttontitle = ButtonLabelCreator(node); - console.log('ooooooooooooooooooooo') - console.log(node) - console.log('ooooooooooooooooooooo') for (var i = 0; i < node.widgets.length; ++i) { var w = node.widgets[i]; if (!w || w.disabled) continue; - //if (w.type != "boolean") - // continue - var widget_height = w.computeSize ? w.computeSize(width)[1] : LiteGraph.NODE_WIDGET_HEIGHT; var widget_width = w.width || width; var widget_name = node.widgets[i].name; @@ -135,8 +109,6 @@ app.registerExtension({ w.name = buttontitle } - //node.setProperty(active_widget.options.property, 'teszt value'); - if (w != active_widget && (x < 6 || x > widget_width - 12 || y < w.last_y || y > w.last_y + widget_height || w.last_y === undefined)) continue @@ -148,13 +120,6 @@ app.registerExtension({ } return lcg.call(this, node, pos, event, active_widget); } - - function apply_list(Selected) { - if (Selected && typeof callbackfunct == 'function') { - callbackfunct(Selected); - return false; - } - } }, async setup(app) { @@ -166,26 +131,13 @@ app.registerExtension({ if (nodeData.input.hasOwnProperty('hidden') === true) { ImagePath = nodeData.input.hidden['image_path'][0] } + if (nodeData.input.hasOwnProperty('optional') === true) { } - //console.log('---------------------------------') - //console.log(nodeData) - //console.log(nodeType) - //console.log(app) - //console.log('---------------------------------') - //const onNodeCreated = nodeType.prototype.onNodeCreated; - nodeType.prototype.onNodeCreated = function () { - console.log('---------------------------------') - console.log(nodeData.input.required) - console.log(nodeType) - console.log(app) - console.log('---------------------------------') - //const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined; PrimerePreviewSaverWidget.apply(this, [this, 'PrimerePreviewSaver']); - //return r; }; } }, @@ -193,12 +145,26 @@ app.registerExtension({ api.addEventListener("getVisualTargets", VisualDataReceiver); function VisualDataReceiver(event) { - //alert(JSON.stringify(event.detail)); WorkflowData = event.detail + if (Object.keys(WorkflowData).length >= 1) { + SaveIsValid = true; + } else { + SaveIsValid = false; + } + + buttontitle = ButtonLabelCreator(LoadedNode); + for (var iln = 0; iln < LoadedNode.widgets.length; ++iln) { + var wln = LoadedNode.widgets[iln]; + if (!wln || wln.disabled) + continue; + if (wln.type == 'button') { + wln.name = buttontitle + } + } console.log('----------- ÚJ KÉP ----------------------') console.log(WorkflowData) + console.log(buttontitle) console.log('----------- ÚJ KÉP ----------------------') - //reloadCombos(WorkflowData) } function dataURLtoFile(dataurl, filename) { @@ -234,7 +200,7 @@ class PreviewSaver { console.log('-------- start -------------'); // console.log(node['imgs'][0]['src']); // console.log(node['images'][0]['filename']); - // console.log(ImagePath) + //console.log(ImagePath) console.log(PreviewTarget); console.log(Convert); console.log(IMGType); @@ -246,7 +212,7 @@ class PreviewSaver { var maxHeight = null; if (Convert === true) { - maxWidth = 250; + maxWidth = 350; maxHeight = 250; } @@ -262,8 +228,19 @@ class PreviewSaver { maxHeight = MaxSide; } + var SizeStringFN = ''; + if (MaxSide >= 64) { + SizeStringFN = MaxSide + 'px_' + } + var ImageSource = node['imgs'][0]['src']; var ImageName = node['images'][0]['filename']; + var SaveImageName = 'PreviewImage_' + SizeStringFN + (Math.random() + 1).toString(36).substring(5); + + if (TargetFileName !== null) { + SaveImageName = TargetFileName; + } + fetch(ImageSource) .then((res) => res.blob()) .then((blob) => { @@ -272,8 +249,13 @@ class PreviewSaver { var file = dataURLtoFile(reader.result, ImageName); loadImage(file, function(img) { var resampledOriginalImage = img.toDataURL(imgMime, 0.6); - //getHandle(); - downloadImage(resampledOriginalImage, extension, PreviewTarget); + if (Convert === false) { + downloadImage(resampledOriginalImage, extension, SaveImageName); + } else { + var resampledWidth = img.width; + var resampledHeight = img.height; + sendPOSTmessage(JSON.stringify({"PreviewTarget": PreviewTarget, "extension": extension, "ImageName": ImageName, "ImagePath": ImagePath, "SaveImageName": SaveImageName, "maxWidth": resampledWidth, "maxHeight": resampledHeight})); + } }, { maxWidth: maxWidth, @@ -309,19 +291,33 @@ function ButtonLabelCreator(node) { var INIT_IMGTYPE_STRING = ""; var INIT_IMGSIZE_STRING = ""; if (IMGType === true) { - INIT_IMGTYPE_STRING = ' as JPG format' + INIT_IMGTYPE_STRING = ' JPG format' } else { - INIT_IMGTYPE_STRING = ' as PNG format' + INIT_IMGTYPE_STRING = ' PNG format' } if (MaxSide < 64) { INIT_IMGSIZE_STRING = " at original size"; } else { - INIT_IMGSIZE_STRING = " resizing to " + MaxSide + 'px'; + INIT_IMGSIZE_STRING = " resized to " + MaxSide + 'px'; } - if (Convert === true) { - buttontitle = 'Save image as: [' + WorkflowData[NodenameByType[PreviewTarget]][0] + '.jpg] to ' + PreviewTarget + ' folder.'; + + TargetFileName = null; + SaveIsValid = false; + if (Object.keys(WorkflowData).length < 1) { + buttontitle = 'Image not available for save. Please load one.'; } else { - buttontitle = 'Save image without resizing' + INIT_IMGTYPE_STRING + INIT_IMGSIZE_STRING; + if (Convert === true) { + if (WorkflowData[NodenameByType[PreviewTarget]].length < 1) { + buttontitle = 'No resource selected for preview target: ' + PreviewTarget; + } else { + SaveIsValid = true; + TargetFileName = WorkflowData[NodenameByType[PreviewTarget]][0]; + buttontitle = 'Save preview as: [' + TargetFileName + '.jpg] to ' + PreviewTarget + ' folder.'; + } + } else { + SaveIsValid = true; + buttontitle = 'Save image as' + INIT_IMGTYPE_STRING + INIT_IMGSIZE_STRING; + } } return buttontitle; @@ -335,36 +331,20 @@ function PrimerePreviewSaverWidget(node, inputName) { callback: () => {}, }; - $(document).ready(function () { - //alert(' van jquery'); - //console.log('-- jquery --') - //console.log(node) - //console.log('-- jquery --') - }); - - //buttontitle = ButtonLabelCreator(node); node.addWidget("button", buttontitle, null, () => { - //node.p_painter.list_objects_panel__items.innerHTML = ""; - //node.p_painter.clearCanvas(); - node.PreviewSaver = new PreviewSaver(node); - sendPOSTmessage('valami legyen átadva....') - //alert('megnyomtuk'); + if (SaveIsValid === true) { + node.PreviewSaver = new PreviewSaver(node); + } else { + alert('Current settings is invalid to save image.\n\nERROR: ' + buttontitle); + } + //alert('pushed...'); }); - + LoadedNode = node; return {widget: widget}; } function sendPOSTmessage(message) { - //alert('itt küldi'); const body = new FormData(); - body.append('something', message); - api.fetchApi("/primere_post", { method: "POST", body, }); + body.append('previewdata', message); + api.fetchApi("/primere_preview_post", {method: "POST", body,}); } - -/* async function getHandle() { - const handle = await window.showSaveFilePicker({ - startIn: 'pictures' - }); - return handle -} */ -