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:
+55
-15
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user