From 0d985b3b658805dfade9344dddebca30afbda49f Mon Sep 17 00:00:00 2001 From: shadowcz007 Date: Tue, 6 Aug 2024 00:14:05 +0800 Subject: [PATCH] update --- nodes/ImageNode.py | 2 +- nodes/P5.py | 74 +++++++++++++++++++++++++++++++------------- web/javascript/p5.js | 52 +++++++++++++++++++++++++++---- 3 files changed, 100 insertions(+), 28 deletions(-) diff --git a/nodes/ImageNode.py b/nodes/ImageNode.py index a218592..84c5460 100644 --- a/nodes/ImageNode.py +++ b/nodes/ImageNode.py @@ -1598,7 +1598,7 @@ class LoadImagesFromURL: def run(self,url,seed=0): global urls_image - print(urls_image) + # print(urls_image) def filter_http_urls(urls): filtered_urls = [] for url in urls.split('\n'): diff --git a/nodes/P5.py b/nodes/P5.py index 471e641..9d26cdb 100644 --- a/nodes/P5.py +++ b/nodes/P5.py @@ -1,9 +1,12 @@ import torch import numpy as np -from PIL import Image +from PIL import Image,ImageSequence,ImageOps import base64 import io import comfy.utils +import folder_paths +import node_helpers + # Tensor to PIL def tensor2pil(image): @@ -13,23 +16,51 @@ def tensor2pil(image): def pil2tensor(image): return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0) +def load_image( image): + image_path = folder_paths.get_annotated_filepath(image) + + img = node_helpers.pillow(Image.open, image_path) + + output_images = [] + output_masks = [] + w, h = None, None + excluded_formats = ['MPO'] + + for i in ImageSequence.Iterator(img): + i = node_helpers.pillow(ImageOps.exif_transpose, i) + if i.mode == 'I': + i = i.point(lambda i: i * (1 / 255)) + image = i.convert("RGB") -def base64_to_image(base64_string): - # 去除前缀 - prefix, base64_data = base64_string.split(",", 1) - - # 从base64字符串中解码图像数据 - image_data = base64.b64decode(base64_data) - - # 创建一个内存流对象 - image_stream = io.BytesIO(image_data) - - # 使用PIL的Image模块打开图像数据 - image = Image.open(image_stream) - - return image + if len(output_images) == 0: + w = image.size[0] + h = image.size[1] + + if image.size[0] != w or image.size[1] != h: + continue + + 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. - torch.from_numpy(mask) + else: + mask = torch.zeros((64,64), dtype=torch.float32, device="cpu") + output_images.append(image) + output_masks.append(mask.unsqueeze(0)) + + if len(output_images) > 1 and img.format not in excluded_formats: + output_image = torch.cat(output_images, dim=0) + output_mask = torch.cat(output_masks, dim=0) + else: + output_image = output_images[0] + output_mask = output_masks[0] + + return (output_image, output_mask) + + class P5Input: @classmethod @@ -51,13 +82,14 @@ class P5Input: OUTPUT_IS_LIST = (False,) def run(self, frames): - # print(frames) ims=[] - for im in frames['base64']: - image = base64_to_image(im) - image=image.convert('RGB') - image=pil2tensor(image) - ims.append(image) + for im in frames['images']: + print(im) + if 'type' in im and (not f"[{im['type']}]" in im['name']): + im['name']=im['name']+" "+f"[{im['type']}]" + + output_image, output_mask = load_image(im) + ims.append(output_image) if len(ims)==0: image1 = Image.new('RGB', (512, 512), color='black') diff --git a/web/javascript/p5.js b/web/javascript/p5.js index 2e65553..bda93c1 100644 --- a/web/javascript/p5.js +++ b/web/javascript/p5.js @@ -1,7 +1,42 @@ import { app } from '../../../scripts/app.js' -import { ComfyWidgets } from '../../../scripts/widgets.js' +import { api } from '../../../scripts/api.js' import { $el } from '../../../scripts/ui.js' +function base64ToBlobFromURL (base64URL, contentType) { + return fetch(base64URL).then(response => response.blob()) +} + +async function uploadImage (blob, fileType = '.svg', filename) { + // const blob = await (await fetch(src)).blob(); + const body = new FormData() + body.append( + 'image', + new File([blob], (filename || new Date().getTime()) + fileType) + ) + + const resp = await api.fetchApi('/upload/image', { + method: 'POST', + body + }) + + // console.log(resp) + let data = await resp.json() + let { name, subfolder } = data + // let src = api.apiURL( + // `/view?filename=${encodeURIComponent( + // name + // )}&type=input&subfolder=${subfolder}${app.getPreviewFormatParam()}${app.getRandParam()}` + // ) + + return data +} +// 上传得到url +async function uploadBase64ToFile (base64) { + let bg_blob = await base64ToBlobFromURL(base64) + let url = await uploadImage(bg_blob, '.png') + return url +} + function get_position_style (ctx, widget_width, y, node_height) { const MARGIN = 4 // the margin around the html element @@ -41,7 +76,7 @@ const p5InputNode = { IMAGEBASE64 (node, inputName, inputData, app) { const widget = { value: { - base64: [] + images: [] }, // 不能[x,x,x] type: inputData[0], // the type name: inputName, // the name, slice @@ -122,7 +157,6 @@ const p5InputNode = { onExecuted?.apply(this, arguments) // console.log('##onExecuted', this, message._info) // app.graph.getNodeById(8).widgets[1].div.querySelector('iframe').contentWindow.postMessage('Hello from parent', '*'); - } } }, @@ -138,7 +172,7 @@ const p5InputNode = { let framesWidget = node.widgets?.filter(w => w.name == 'frames')[0] if (node.type === 'P5Input' && widget) { if (framesWidget && !framesWidget.value) - framesWidget.value = { base64: [] } + framesWidget.value = { images: [] } framesWidget.value._seed = Math.random() @@ -149,7 +183,7 @@ const p5InputNode = { >` // 监听来自iframe的消息 - const ms = event => { + const ms = async event => { const data = event.data if ( data.from === 'p5.widget' && @@ -160,7 +194,13 @@ const p5InputNode = { ) { const frames = data.frames console.log(frames.length, nodeId) - framesWidget.value.base64 = frames; + //workflow会存储到local,会卡死 + framesWidget.value.images = [] + for (const f of frames) { + let file = await uploadBase64ToFile(f) + framesWidget.value.images.push(file) + } + // framesWidget.value.base64 = frames framesWidget.value._seed = Math.random() node.title = 'P5 Input #' + frames.length }