Split node into two One for transmitting to editor one for receiving from editor. Added the ability to close images,

This commit is contained in:
Neil Graham
2023-08-28 22:52:10 +12:00
parent e78d04425a
commit 0d61c15cd5
5 changed files with 132 additions and 25 deletions
+55 -15
View File
@@ -14,13 +14,51 @@ def image_to_data_url(image):
img_base64 = base64.b64encode(buffered.getvalue())
return f"data:image/png;base64,{img_base64.decode()}"
class Send_To_Editor:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
return {
"required": {
},
"hidden": {
"unique_id":"UNIQUE_ID",
},
"optional": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ()
FUNCTION = "collect_images"
OUTPUT_NODE = True
CATEGORY = "image"
def collect_images(self, unique_id, images=None):
collected_images = list()
if images is not None:
for image in images:
i = 255. * image.cpu().numpy()
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
collected_images.append(image_to_data_url(img))
return { "ui": {"collected_images":collected_images}}
class Canvas_Tab:
"""
A Image Buffer for handling an editor in another tab.
"""
def __init__(self):
self.testState = {}
pass
@classmethod
@@ -33,9 +71,9 @@ class Canvas_Tab:
"hidden": {
"unique_id":"UNIQUE_ID",
},
"optional": {
"images": ("IMAGE",),
},
# "optional": {
# "images": ("IMAGE",),
# },
}
@@ -49,14 +87,14 @@ class Canvas_Tab:
def image_buffer(self, unique_id, mask, canvas, images=None):
collected_images = list()
if images is not None:
for image in images:
i = 255. * image.cpu().numpy()
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
collected_images.append(image_to_data_url(img))
# collected_images = list()
# if images is not None:
# for image in images:
# i = 255. * image.cpu().numpy()
# img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
# collected_images.append(image_to_data_url(img))
#
# print(f"Node {unique_id}: images: {images}")
image_path = folder_paths.get_annotated_filepath(canvas)
i = Image.open(image_path)
@@ -80,15 +118,17 @@ class Canvas_Tab:
return { "ui": {"collected_images":collected_images}, "result": (rgb_image, mask_data) }
return (rgb_image, mask_data)
WEB_DIRECTORY = "web"
NODE_CLASS_MAPPINGS = {
"Canvas_Tab": Canvas_Tab
"Canvas_Tab": Canvas_Tab,
"Send_To_Editor": Send_To_Editor
}
NODE_DISPLAY_NAME_MAPPINGS = {
"Canvas_Tab": "Edit In Another Tab"
"Canvas_Tab": "Edit In Another Tab",
"Send_To_Editor": "Send to Editor Tab"
}
+24 -2
View File
@@ -64,11 +64,17 @@ app.registerExtension({
if (title==="Edit In Another Tab") {
initEditorNode(node)
}
else if (title==="Send to Editor Tab") {
initTransmitNode(node)
}
}
});
function initEditorNode(node)
{
node.collected_images = [];
@@ -81,15 +87,31 @@ function initEditorNode(node)
node.maskWidget.onTopOf = node.canvasWidget;
/*
node.onExecuted = (output)=> {
if (output?.collected_images && editor.channel) {
editor.channel.port1.postMessage( {images:output.collected_images})
}
}
}
*/
return;
}
function initTransmitNode(node)
{
node.collected_images = [];
node.onExecuted = (output)=> {
if (output?.collected_images && editor.channel) {
editor.channel.port1.postMessage( {images:output.collected_images})
}
}
return;
}
function openOrFocusEditor() {
if (!editor.window || editor.window.closed) {
if (getSignal('clientPage')) {
+23 -4
View File
@@ -47,8 +47,9 @@ var activePic;
function setActivePic(newValue) {
activePic=newValue;
activePic.bringToFront();
updateLayerList()
if (!activePic) return;
activePic.bringToFront();
}
@@ -71,6 +72,15 @@ function setExportPic(pic) {
transmitMask(pic.mask.canvas);
}
function closePic(pic) {
pic.element.parentElement.removeChild(pic.element);
if (pic === activePic) {
const newActive = document.querySelector("#workspace .pic");
setActivePic(newActive.pic);
}
}
var lastUsedMaskColor = "#402040";
class Layer {
@@ -121,13 +131,18 @@ function createDrawArea(canvas = blankCanvas()) {
const ctx=canvas.getContext("2d");
const eventOverlay = document.createElement("div");
const sidebar = document.createElement("div");
const closeButton = document.createElement("div");
sidebar.className = "sidebutton";
closeButton.className = "closebutton";
element.className="pic";
eventOverlay.className="eventoverlay fillparent";
element.appendChild(sidebar);
element.appendChild(canvas);
element.appendChild(eventOverlay);
element.appendChild(closeButton);
canvas.ctx=ctx;
const activeOperationCanvas = document.createElement("canvas");
@@ -272,6 +287,7 @@ function createDrawArea(canvas = blankCanvas()) {
}
eventOverlay.pic = result;
sidebar.addEventListener("mousedown",_=> setExportPic(result))
closeButton.addEventListener("click",_=> closePic(result))
result.setTransform();
setActivePic(result)
@@ -361,6 +377,7 @@ function addNewLayer(image) {
console.log("new layer", layer)
console.log(layer.canvas.width, layer.canvas.height)
pic.layers.push(layer);
pic.activeLayer=layer;
updateLayerList();
pic.updateVisualRepresentation();
}
@@ -683,7 +700,7 @@ function poulateLayerControl() {
const content = $(`
<div class="layer-attributes">
<div class="imageLayer">
<select class="composite-mode">
<select name="composite-node" class="composite-mode">
<option value="source-over">Color</option>
<option value="lighter">Lighter</option>
<option value="multiply">Multiply</option>
@@ -780,10 +797,12 @@ function updateLayerList() {
const layer_control=document.querySelector("#layer_control")
const layer_list =layer_control.querySelector(".layer_list")
const newControls = activePic.layers.map(makeLayerWidget);
while(layer_list.firstChild) layer_list.removeChild(layer_list.firstChild)
if (!activePic) return;
const newControls = activePic.layers.map(makeLayerWidget);
newControls.reverse().forEach(element=>layer_list.appendChild(element))
$(".layer-attributes").toggleClass("mask", activePic.activeLayer.mask)
+4 -1
View File
@@ -146,7 +146,10 @@ window.addEventListener('message', (event) => {
portToMain.onmessage = (messageEvent) => {
console.log(messageEvent)
if (messageEvent.data instanceof Object) {
loadImagefromURL(messageEvent.data.images[0]);
const images=messageEvent.data.images[0];
if (images?.length > 0) {
loadImagefromURL(messageEvent.data.images[0]);
}
} else console.log('Message received from main page:', messageEvent.data);
};
}
+26 -3
View File
@@ -6,7 +6,7 @@ body {
--left-panel-width : 80px;
--right-panel-width : 210px;
background:#f8fcff;
--label : "image";
}
canvas {
display: block;
@@ -114,6 +114,29 @@ canvas {
transform: translate(var(--translateX),var(--translateY)) scale(var(--scalefactor) )
}
.pic .closebutton {
position: absolute;
top: -20px;
left: 3px;
width: 16px;
height: 16px;
background: #8008;
border-radius: 16px;
box-sizing: border-box;
border: 1px solid black;
cursor: default;
}
.pic .closebutton:hover {
background: #f33f;
}
.pic .closebutton:active {
background: #f00f;
border: 3px solid black;
}
input[type="color"] {
width:48px;
height:32px;
@@ -155,7 +178,7 @@ input[type="color"] {
}
.pic>.eventoverlay::before {
content: "label";
content: var(--label);
position: absolute;
height: 19px;
display: inline-block;
@@ -163,7 +186,7 @@ input[type="color"] {
transform-origin: left;
background-color: palegoldenrod;
border-radius: 0 11px 0 0;
padding-left: 8px;
padding-left: 32px;
padding-right: 17px;
box-shadow: 0px 0px 0px 2px;
font-family: sans-serif;