First update

This commit is contained in:
xChenNing
2025-07-12 18:15:05 +08:00
commit 1021a8863d
7 changed files with 157 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
# ComfyUI Image Pin
### 简介
ComfyUI Image Pin 是一个 ComfyUI 的自定义节点,允许您在 ComfyUI 工作流中“钉住”图像。这对于在处理图表的其他部分时保持参考图像可见非常有用。
### 安装
1. 导航到您的 ComfyUI 安装目录下的 `custom_nodes` 文件夹。
2. 克隆此仓库:
```bash
git clone https://github.com/CheNing233/ComfyUI_Image_Pin.git
```
3. 重启 ComfyUI。
### 使用方法
搜索 `ImagePin` 节点
+18
View File
@@ -0,0 +1,18 @@
# 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
+13
View File
@@ -0,0 +1,13 @@
from .image_pin import ImagePin
WEB_DIRECTORY = "js"
NODE_CLASS_MAPPINGS = {
"ImagePin": ImagePin
}
NODE_DISPLAY_NAME_MAPPINGS = {
"ImagePin": "Image PinNode (Embed image b64 to workflow)"
}
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
Binary file not shown.
Binary file not shown.
+37
View File
@@ -0,0 +1,37 @@
import torch
import numpy as np
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}),
},
}
CATEGORY = "utils"
RETURN_TYPES = ("IMAGE", "MASK")
FUNCTION = "load_image"
def load_image(self, image, image_data):
image_data = base64.b64decode(image_data.split(",")[1])
i = Image.open(BytesIO(image_data))
i = ImageOps.exif_transpose(i)
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))
+71
View File
@@ -0,0 +1,71 @@
import { ComfyApp, app } from "../../scripts/app.js";
function load_image(str) {
let base64String = canvas.toDataURL('image/png');
let img = new Image();
img.src = base64String;
}
app.registerExtension({
name: "Comfy.ImagePin",
nodeCreated(node, app) {
if(node.comfyClass === "ImagePin") {
let w = node.widgets.find(obj => obj.name === 'image_data');
w.hidden = true;
Object.defineProperty(w, 'value', {
set(v) {
if(v != '[IMAGE DATA]')
w._value = v;
},
get() {
const stackTrace = new Error().stack;
if(!stackTrace.includes('draw') && !stackTrace.includes('graphToPrompt') && stackTrace.includes('app.js')) {
return "[IMAGE DATA]";
}
else {
return w._value;
}
}
});
let set_img_act = (v) => {
node._img = v;
var canvas = document.createElement('canvas');
canvas.width = v[0].width;
canvas.height = v[0].height;
var context = canvas.getContext('2d');
context.drawImage(v[0], 0, 0, v[0].width, v[0].height);
var base64Image = canvas.toDataURL('image/png');
w.value = base64Image;
};
Object.defineProperty(node, 'imgs', {
set(v) {
if (v && !v[0].complete) {
let orig_onload = v[0].onload;
v[0].onload = function(v2) {
if(orig_onload)
orig_onload();
set_img_act(v);
};
}
else {
set_img_act(v);
}
},
get() {
if(this._img == undefined && w.value != '') {
this._img = [new Image()];
if(w.value && w.value != '[IMAGE DATA]')
this._img[0].src = w.value;
}
return this._img;
}
});
}
}
})