feat: update external image node to have default value
This commit is contained in:
parent
6ed468d7d4
commit
bf00580562
@ -21,8 +21,9 @@ class ComfyUIDeployExternalImage:
|
|||||||
),
|
),
|
||||||
"description": (
|
"description": (
|
||||||
"STRING",
|
"STRING",
|
||||||
{"multiline": True, "default": ""},
|
{"multiline": False, "default": ""},
|
||||||
),
|
),
|
||||||
|
"default_value_url": ("STRING", {"image_preview": True, "default": ""}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,32 +34,44 @@ class ComfyUIDeployExternalImage:
|
|||||||
|
|
||||||
CATEGORY = "image"
|
CATEGORY = "image"
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, display_name=None, description=None):
|
def run(self, input_id, default_value=None, display_name=None, description=None, default_value_url=None):
|
||||||
image = default_value
|
image = default_value
|
||||||
try:
|
|
||||||
if input_id.startswith('http'):
|
# Try both input_id and default_value_url
|
||||||
import requests
|
urls_to_try = [url for url in [input_id, default_value_url] if url]
|
||||||
from io import BytesIO
|
|
||||||
print("Fetching image from url: ", input_id)
|
print(default_value_url)
|
||||||
response = requests.get(input_id)
|
|
||||||
image = Image.open(BytesIO(response.content))
|
for url in urls_to_try:
|
||||||
elif input_id.startswith('data:image/png;base64,') or input_id.startswith('data:image/jpeg;base64,') or input_id.startswith('data:image/jpg;base64,'):
|
try:
|
||||||
import base64
|
if url.startswith('http'):
|
||||||
from io import BytesIO
|
import requests
|
||||||
print("Decoding base64 image")
|
from io import BytesIO
|
||||||
base64_image = input_id[input_id.find(",")+1:]
|
print(f"Fetching image from url: {url}")
|
||||||
decoded_image = base64.b64decode(base64_image)
|
response = requests.get(url)
|
||||||
image = Image.open(BytesIO(decoded_image))
|
image = Image.open(BytesIO(response.content))
|
||||||
else:
|
break
|
||||||
raise ValueError("Invalid image url provided.")
|
elif url.startswith(('data:image/png;base64,', 'data:image/jpeg;base64,', 'data:image/jpg;base64,')):
|
||||||
|
import base64
|
||||||
image = ImageOps.exif_transpose(image)
|
from io import BytesIO
|
||||||
image = image.convert("RGB")
|
print("Decoding base64 image")
|
||||||
image = np.array(image).astype(np.float32) / 255.0
|
base64_image = url[url.find(",")+1:]
|
||||||
image = torch.from_numpy(image)[None,]
|
decoded_image = base64.b64decode(base64_image)
|
||||||
return [image]
|
image = Image.open(BytesIO(decoded_image))
|
||||||
except:
|
break
|
||||||
return [image]
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if image is not None:
|
||||||
|
try:
|
||||||
|
image = ImageOps.exif_transpose(image)
|
||||||
|
image = image.convert("RGB")
|
||||||
|
image = np.array(image).astype(np.float32) / 255.0
|
||||||
|
image = torch.from_numpy(image)[None,]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return [image]
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalImage": ComfyUIDeployExternalImage}
|
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalImage": ComfyUIDeployExternalImage}
|
||||||
|
@ -53,9 +53,9 @@ function sendEventToCD(event, data) {
|
|||||||
function sendDirectEventToCD(event, data) {
|
function sendDirectEventToCD(event, data) {
|
||||||
const message = {
|
const message = {
|
||||||
type: event,
|
type: event,
|
||||||
data: data
|
data: data,
|
||||||
}
|
};
|
||||||
window.parent.postMessage(message, '*')
|
window.parent.postMessage(message, "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
function dispatchAPIEventData(data) {
|
function dispatchAPIEventData(data) {
|
||||||
@ -494,6 +494,13 @@ const ext = {
|
|||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
nodeData?.input?.optional?.default_value_url?.[1]?.image_preview === true
|
||||||
|
) {
|
||||||
|
nodeData.input.optional.default_value_url = ["IMAGEPREVIEW"];
|
||||||
|
console.log(nodeData.input.optional.default_value_url);
|
||||||
|
}
|
||||||
|
|
||||||
// const origonNodeCreated = nodeType.prototype.onNodeCreated;
|
// const origonNodeCreated = nodeType.prototype.onNodeCreated;
|
||||||
// nodeType.prototype.onNodeCreated = function () {
|
// nodeType.prototype.onNodeCreated = function () {
|
||||||
// const r = origonNodeCreated
|
// const r = origonNodeCreated
|
||||||
@ -620,6 +627,78 @@ const ext = {
|
|||||||
ComfyDeploy.category = "deploy";
|
ComfyDeploy.category = "deploy";
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getCustomWidgets() {
|
||||||
|
return {
|
||||||
|
IMAGEPREVIEW(node, inputName, inputData) {
|
||||||
|
// Find or create the URL input widget
|
||||||
|
const urlWidget = node.addWidget(
|
||||||
|
"string",
|
||||||
|
inputName,
|
||||||
|
/* value=*/ "",
|
||||||
|
() => {},
|
||||||
|
{ serialize: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
const buttonWidget = node.addWidget(
|
||||||
|
"button",
|
||||||
|
"Open Assets Browser",
|
||||||
|
/* value=*/ "",
|
||||||
|
() => {
|
||||||
|
sendEventToCD("assets", {
|
||||||
|
node: node.id,
|
||||||
|
inputName: inputName,
|
||||||
|
})
|
||||||
|
// console.log("load image");
|
||||||
|
},
|
||||||
|
{ serialize: false },
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(node.widgets);
|
||||||
|
|
||||||
|
console.log("urlWidget", urlWidget);
|
||||||
|
|
||||||
|
// Add image preview functionality
|
||||||
|
function showImage(url) {
|
||||||
|
const img = new Image();
|
||||||
|
img.onload = () => {
|
||||||
|
node.imgs = [img];
|
||||||
|
app.graph.setDirtyCanvas(true);
|
||||||
|
node.setSizeForImage?.();
|
||||||
|
};
|
||||||
|
img.onerror = () => {
|
||||||
|
node.imgs = [];
|
||||||
|
app.graph.setDirtyCanvas(true);
|
||||||
|
};
|
||||||
|
img.src = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up URL widget value handling
|
||||||
|
let default_value = urlWidget.value;
|
||||||
|
Object.defineProperty(urlWidget, "value", {
|
||||||
|
set: function (value) {
|
||||||
|
this._real_value = value;
|
||||||
|
// Preview image when URL changes
|
||||||
|
if (value) {
|
||||||
|
showImage(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
get: function () {
|
||||||
|
return this._real_value || default_value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show initial image if URL exists
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
if (urlWidget.value) {
|
||||||
|
showImage(urlWidget.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { widget: urlWidget };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
async setup() {
|
async setup() {
|
||||||
// const graphCanvas = document.getElementById("graph-canvas");
|
// const graphCanvas = document.getElementById("graph-canvas");
|
||||||
|
|
||||||
@ -661,8 +740,8 @@ const ext = {
|
|||||||
console.warn("api.handlePromptGenerated is not a function");
|
console.warn("api.handlePromptGenerated is not a function");
|
||||||
}
|
}
|
||||||
sendEventToCD("cd_plugin_onQueuePrompt", prompt);
|
sendEventToCD("cd_plugin_onQueuePrompt", prompt);
|
||||||
} else if (message.type === 'configure_queue_buttons') {
|
} else if (message.type === "configure_queue_buttons") {
|
||||||
addQueueButtons(message.data)
|
addQueueButtons(message.data);
|
||||||
} else if (message.type === "get_prompt") {
|
} else if (message.type === "get_prompt") {
|
||||||
const prompt = await app.graphToPrompt();
|
const prompt = await app.graphToPrompt();
|
||||||
sendEventToCD("cd_plugin_onGetPrompt", prompt);
|
sendEventToCD("cd_plugin_onGetPrompt", prompt);
|
||||||
@ -1903,117 +1982,118 @@ api.fetchApi = async (route, options) => {
|
|||||||
return await orginal_fetch_api.call(api, route, options);
|
return await orginal_fetch_api.call(api, route, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Intercept window drag and drop events
|
// Intercept window drag and drop events
|
||||||
const originalDropHandler = document.ondrop
|
const originalDropHandler = document.ondrop;
|
||||||
document.ondrop = async (e) => {
|
document.ondrop = async (e) => {
|
||||||
console.log('Drop event intercepted:', e)
|
console.log("Drop event intercepted:", e);
|
||||||
|
|
||||||
// Prevent default browser behavior
|
// Prevent default browser behavior
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
|
|
||||||
// Handle files if present
|
// Handle files if present
|
||||||
if (e.dataTransfer?.files?.length > 0) {
|
if (e.dataTransfer?.files?.length > 0) {
|
||||||
const files = Array.from(e.dataTransfer.files)
|
const files = Array.from(e.dataTransfer.files);
|
||||||
|
|
||||||
// Send file data to parent directly as JSON
|
// Send file data to parent directly as JSON
|
||||||
sendDirectEventToCD('file_drop', {
|
sendDirectEventToCD("file_drop", {
|
||||||
files: files,
|
files: files,
|
||||||
x: e.clientX,
|
x: e.clientX,
|
||||||
y: e.clientY,
|
y: e.clientY,
|
||||||
timestamp: Date.now()
|
timestamp: Date.now(),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call original handler if exists
|
// Call original handler if exists
|
||||||
if (originalDropHandler) {
|
if (originalDropHandler) {
|
||||||
originalDropHandler(e)
|
originalDropHandler(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const originalDragEnterHandler = document.ondragenter
|
const originalDragEnterHandler = document.ondragenter;
|
||||||
document.ondragenter = (e) => {
|
document.ondragenter = (e) => {
|
||||||
// Prevent default to allow drop
|
// Prevent default to allow drop
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
|
|
||||||
// Send dragenter event to parent directly as JSON
|
// Send dragenter event to parent directly as JSON
|
||||||
sendDirectEventToCD('file_dragenter', {
|
sendDirectEventToCD("file_dragenter", {
|
||||||
x: e.clientX,
|
x: e.clientX,
|
||||||
y: e.clientY,
|
y: e.clientY,
|
||||||
timestamp: Date.now()
|
timestamp: Date.now(),
|
||||||
})
|
});
|
||||||
|
|
||||||
if (originalDragEnterHandler) {
|
if (originalDragEnterHandler) {
|
||||||
originalDragEnterHandler(e)
|
originalDragEnterHandler(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const originalDragLeaveHandler = document.ondragleave
|
const originalDragLeaveHandler = document.ondragleave;
|
||||||
document.ondragleave = (e) => {
|
document.ondragleave = (e) => {
|
||||||
// Prevent default to allow drop
|
// Prevent default to allow drop
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
|
|
||||||
// Send dragleave event to parent directly as JSON
|
// Send dragleave event to parent directly as JSON
|
||||||
sendDirectEventToCD('file_dragleave', {
|
sendDirectEventToCD("file_dragleave", {
|
||||||
x: e.clientX,
|
x: e.clientX,
|
||||||
y: e.clientY,
|
y: e.clientY,
|
||||||
timestamp: Date.now()
|
timestamp: Date.now(),
|
||||||
})
|
});
|
||||||
|
|
||||||
if (originalDragLeaveHandler) {
|
if (originalDragLeaveHandler) {
|
||||||
originalDragLeaveHandler(e)
|
originalDragLeaveHandler(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const originalDragOverHandler = document.ondragover
|
const originalDragOverHandler = document.ondragover;
|
||||||
document.ondragover = (e) => {
|
document.ondragover = (e) => {
|
||||||
// Prevent default to allow drop
|
// Prevent default to allow drop
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
|
|
||||||
// Send dragover event to parent directly as JSON
|
// Send dragover event to parent directly as JSON
|
||||||
sendDirectEventToCD('file_dragover', {
|
sendDirectEventToCD("file_dragover", {
|
||||||
x: e.clientX,
|
x: e.clientX,
|
||||||
y: e.clientY,
|
y: e.clientY,
|
||||||
timestamp: Date.now()
|
timestamp: Date.now(),
|
||||||
})
|
});
|
||||||
|
|
||||||
if (originalDragOverHandler) {
|
if (originalDragOverHandler) {
|
||||||
originalDragOverHandler(e)
|
originalDragOverHandler(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Function to create a single button
|
// Function to create a single button
|
||||||
function createQueueButton(config) {
|
function createQueueButton(config) {
|
||||||
const button = document.createElement('button')
|
const button = document.createElement("button");
|
||||||
button.id = `cd-button-${config.id}`
|
button.id = `cd-button-${config.id}`;
|
||||||
button.className = 'p-button p-component p-button-icon-only p-button-secondary p-button-text'
|
button.className =
|
||||||
|
"p-button p-component p-button-icon-only p-button-secondary p-button-text";
|
||||||
button.innerHTML = `
|
button.innerHTML = `
|
||||||
<span class="p-button-icon pi ${config.icon}"></span>
|
<span class="p-button-icon pi ${config.icon}"></span>
|
||||||
<span class="p-button-label"> </span>
|
<span class="p-button-label"> </span>
|
||||||
`
|
`;
|
||||||
button.onclick = () => {
|
button.onclick = () => {
|
||||||
const eventData = typeof config.eventData === 'function' ?
|
const eventData =
|
||||||
config.eventData() :
|
typeof config.eventData === "function"
|
||||||
config.eventData || {}
|
? config.eventData()
|
||||||
sendEventToCD(config.event, eventData)
|
: config.eventData || {};
|
||||||
}
|
sendEventToCD(config.event, eventData);
|
||||||
button.setAttribute('data-pd-tooltip', config.tooltip)
|
};
|
||||||
return button
|
button.setAttribute("data-pd-tooltip", config.tooltip);
|
||||||
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to add buttons to queue group
|
// Function to add buttons to queue group
|
||||||
function addQueueButtons(buttonConfigs = DEFAULT_BUTTONS) {
|
function addQueueButtons(buttonConfigs = DEFAULT_BUTTONS) {
|
||||||
const queueButtonGroup = document.querySelector('.queue-button-group.flex')
|
const queueButtonGroup = document.querySelector(".queue-button-group.flex");
|
||||||
if (!queueButtonGroup) return
|
if (!queueButtonGroup) return;
|
||||||
|
|
||||||
// Remove any existing CD buttons
|
// Remove any existing CD buttons
|
||||||
const existingButtons = queueButtonGroup.querySelectorAll('[id^="cd-button-"]')
|
const existingButtons =
|
||||||
existingButtons.forEach(button => button.remove())
|
queueButtonGroup.querySelectorAll('[id^="cd-button-"]');
|
||||||
|
existingButtons.forEach((button) => button.remove());
|
||||||
|
|
||||||
// Add new buttons
|
// Add new buttons
|
||||||
buttonConfigs.forEach(config => {
|
buttonConfigs.forEach((config) => {
|
||||||
const button = createQueueButton(config)
|
const button = createQueueButton(config);
|
||||||
queueButtonGroup.appendChild(button)
|
queueButtonGroup.appendChild(button);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user