fix: image output
This commit is contained in:
@@ -2,7 +2,36 @@
|
||||
|
||||
### 简介
|
||||
|
||||
ComfyUI Image Pin 是一个 ComfyUI 的自定义节点,允许您在 ComfyUI 工作流中“钉住”图像。这对于在处理图表的其他部分时保持参考图像可见非常有用。
|
||||
ComfyUI Image Pin 是一个 ComfyUI 的插件,允许您在 ComfyUI 工作流中“钉住”图像,并转换为Base64字符串嵌入到工作流中。
|
||||
|
||||
### 功能
|
||||
|
||||

|
||||
|
||||
#### 原理
|
||||
|
||||
原生节点不会嵌入到工作流中,而是保存在ComfyUI根目录的input文件夹中,因此你导出的JSON不会带有任何图片
|
||||
|
||||
| 对比 | 原生 Load Image | ImagePin |
|
||||
| --- | --- | --- |
|
||||
| 存储位置 | Comfy 根目录 input 文件夹 | 工作流JSON文件 |
|
||||
| 保存方式 | 原文件 | Base64字符串 |
|
||||
| 导出JSON | 不会带有图片 | 带有图片 |
|
||||
| 导入JSON | 不会带有图片 | 带有图片 |
|
||||
| 工作流大小 | 较小 | 较大 |
|
||||
|
||||
#### 快速尝试
|
||||
|
||||
拖拽此图片到你的ComfyUI,你会丢失原生LoadImage节点的图片,但保留ImagePin节点的图片。
|
||||
|
||||

|
||||
|
||||
#### 建议用法
|
||||
|
||||
- 嵌入图片到工作流,生成的图片的metadata也具有该图片
|
||||
- 方便分享图片
|
||||
- 建立提示词画廊,给画师串添加图片预览
|
||||
- 等你探索
|
||||
|
||||
### 安装
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# ComfyUI Image Pin
|
||||
|
||||
### Introduction
|
||||
|
||||
ComfyUI Image Pin is a custom node for ComfyUI that allows you to pin images within the ComfyUI workflow. This is useful for keeping reference images visible while you work on other parts of your graph.
|
||||
|
||||
### Installation
|
||||
|
||||
1. Navigate to the `custom_nodes` directory of your ComfyUI installation.
|
||||
2. Clone this repository:
|
||||
```bash
|
||||
git clone https://github.com/your-username/comfyui_image_pin.git
|
||||
```
|
||||
3. Restart ComfyUI.
|
||||
|
||||
### Usage
|
||||
|
||||
Search for the `ImagePin` node
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 994 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.2 MiB |
File diff suppressed because one or more lines are too long
+22
-14
@@ -1,25 +1,31 @@
|
||||
import torch
|
||||
import numpy as np
|
||||
from PIL import Image,ImageOps
|
||||
from PIL import Image, ImageOps
|
||||
import base64
|
||||
from io import BytesIO
|
||||
import folder_paths
|
||||
import os
|
||||
|
||||
|
||||
class ImagePin:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
input_dir = folder_paths.get_input_directory()
|
||||
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
||||
return {"required": {
|
||||
"image": (sorted(files) + ["#DATA"], {"image_upload": True}),
|
||||
"image_data": ("STRING", {"multiline": False}),
|
||||
},
|
||||
}
|
||||
files = [
|
||||
f
|
||||
for f in os.listdir(input_dir)
|
||||
if os.path.isfile(os.path.join(input_dir, f))
|
||||
]
|
||||
return {
|
||||
"required": {
|
||||
"image": (sorted(files) + ["#DECODE_FROM_BASE64"], {"image_upload": True}),
|
||||
"image_data": ("STRING", {"multiline": False}),
|
||||
},
|
||||
}
|
||||
|
||||
CATEGORY = "utils"
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "MASK")
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
FUNCTION = "load_image"
|
||||
|
||||
def load_image(self, image, image_data):
|
||||
@@ -29,9 +35,11 @@ class ImagePin:
|
||||
image = i.convert("RGB")
|
||||
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")
|
||||
return (image, mask.unsqueeze(0))
|
||||
return (image,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, image, image_data):
|
||||
if image_data is None:
|
||||
return "image_data is required"
|
||||
|
||||
return True
|
||||
|
||||
+12
-9
@@ -9,18 +9,21 @@ function load_image(str) {
|
||||
app.registerExtension({
|
||||
name: "Comfy.ImagePin",
|
||||
nodeCreated(node, app) {
|
||||
if(node.comfyClass === "ImagePin") {
|
||||
if (node.comfyClass === "ImagePin") {
|
||||
let w = node.widgets.find(obj => obj.name === 'image_data');
|
||||
w.hidden = true;
|
||||
|
||||
w.disabled = true;
|
||||
|
||||
Object.defineProperty(w, 'value', {
|
||||
set(v) {
|
||||
if(v != '[IMAGE DATA]')
|
||||
if (v != '[IMAGE DATA]')
|
||||
w._value = v;
|
||||
|
||||
console.log("widget", w);
|
||||
},
|
||||
get() {
|
||||
const stackTrace = new Error().stack;
|
||||
if(!stackTrace.includes('draw') && !stackTrace.includes('graphToPrompt') && stackTrace.includes('app.js')) {
|
||||
if (!stackTrace.includes('draw') && !stackTrace.includes('graphToPrompt') && stackTrace.includes('app.js')) {
|
||||
return "[IMAGE DATA]";
|
||||
}
|
||||
else {
|
||||
@@ -46,8 +49,8 @@ app.registerExtension({
|
||||
set(v) {
|
||||
if (v && !v[0].complete) {
|
||||
let orig_onload = v[0].onload;
|
||||
v[0].onload = function(v2) {
|
||||
if(orig_onload)
|
||||
v[0].onload = function (v2) {
|
||||
if (orig_onload)
|
||||
orig_onload();
|
||||
set_img_act(v);
|
||||
};
|
||||
@@ -57,9 +60,9 @@ app.registerExtension({
|
||||
}
|
||||
},
|
||||
get() {
|
||||
if(this._img == undefined && w.value != '') {
|
||||
if (this._img == undefined && w.value != '') {
|
||||
this._img = [new Image()];
|
||||
if(w.value && w.value != '[IMAGE DATA]')
|
||||
if (w.value && w.value != '[IMAGE DATA]')
|
||||
this._img[0].src = w.value;
|
||||
}
|
||||
|
||||
@@ -67,5 +70,5 @@ app.registerExtension({
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user