Add files via upload
This commit is contained in:
+15
-4
@@ -87,11 +87,22 @@ class BoxReinsertNode:
|
||||
y1 = box_meta.get("y1", 0)
|
||||
y2 = box_meta.get("y2", 0)
|
||||
|
||||
# Applica fattore di scala se la preview era stata scalata
|
||||
display_scale_factor = box_meta.get("displayScaleFactor", 1.0)
|
||||
if display_scale_factor and display_scale_factor != 1.0:
|
||||
# Se le coordinate sono state prese da una preview scalata,
|
||||
# dividi per il fattore di scala per ottenere le coordinate originali
|
||||
x1 = x1 / display_scale_factor
|
||||
x2 = x2 / display_scale_factor
|
||||
y1 = y1 / display_scale_factor
|
||||
y2 = y2 / display_scale_factor
|
||||
print(f"[BoxReinsertNode] Scale factor detected: {display_scale_factor}x. Adjusted coordinates.")
|
||||
|
||||
# Normalizza coordinate (assicura che x1 < x2, y1 < y2)
|
||||
box_x_start = min(x1, x2)
|
||||
box_x_end = max(x1, x2)
|
||||
box_y_start = min(y1, y2)
|
||||
box_y_end = max(y1, y2)
|
||||
box_x_start = int(round(min(x1, x2)))
|
||||
box_x_end = int(round(max(x1, x2)))
|
||||
box_y_start = int(round(min(y1, y2)))
|
||||
box_y_end = int(round(max(y1, y2)))
|
||||
|
||||
crop_width = box_x_end - box_x_start
|
||||
crop_height = box_y_end - box_y_start
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "ComfyUI-BoxBox"
|
||||
description = "BoxBox is a lightweight ComfyUI extension for visualizing image boxes and controlling regions interactively inside the node interface."
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
license = {file = "LICENSE"}
|
||||
# classifiers = [
|
||||
# # For OS-independent nodes (works on all operating systems)
|
||||
|
||||
@@ -73,6 +73,17 @@ class RegionCropNode:
|
||||
else:
|
||||
raise ValueError("No region coordinates provided in metadata")
|
||||
|
||||
# Estrai il fattore di scala se la preview era stata scalata
|
||||
display_scale_factor = metadata.get("displayScaleFactor", 1.0)
|
||||
if display_scale_factor and display_scale_factor != 1.0:
|
||||
# Se le coordinate sono state prese da una preview scalata,
|
||||
# dividi per il fattore di scala per ottenere le coordinate originali
|
||||
x1 = x1 / display_scale_factor
|
||||
x2 = x2 / display_scale_factor
|
||||
y1 = y1 / display_scale_factor
|
||||
y2 = y2 / display_scale_factor
|
||||
print(f"[BoxCrop] Scale factor detected: {display_scale_factor}x. Adjusted coordinates.")
|
||||
|
||||
# Assicura che le coordinate siano integer
|
||||
x1 = int(round(x1))
|
||||
x2 = int(round(x2))
|
||||
|
||||
+51
-47
@@ -1,45 +1,29 @@
|
||||
"""
|
||||
Region Selector Node - Nodo per selezionare regioni di immagini con interfaccia popup
|
||||
Region Selector Node - con endpoint di ridimensionamento lato backend.
|
||||
Riduce automaticamente le immagini oltre 1024px quando viene aperta
|
||||
l'interfaccia "Select Box", salvandole in /temp/.
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
from PIL import Image
|
||||
import folder_paths
|
||||
import server
|
||||
|
||||
|
||||
class RegionSelectorNode:
|
||||
"""
|
||||
Nodo che permette di selezionare una regione rettangolare su un'immagine
|
||||
tramite un'interfaccia interattiva in popup.
|
||||
|
||||
Outputs:
|
||||
- IMAGE: L'immagine passata
|
||||
- STRING: Metadata JSON con coordinate della regione selezionata
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# Metadata di default con coordinate x1, x2, y1, y2 (lati, non posizione+dimensioni)
|
||||
self.last_metadata = json.dumps({
|
||||
"x1": 0,
|
||||
"y1": 0,
|
||||
"x2": 0,
|
||||
"y2": 0,
|
||||
"zoom": 1,
|
||||
"borderWidth": 0,
|
||||
"borderPosition": "inside",
|
||||
"selected": False
|
||||
"x1": 0, "y1": 0, "x2": 0, "y2": 0,
|
||||
"zoom": 1, "borderWidth": 0,
|
||||
"borderPosition": "inside", "selected": False
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
},
|
||||
"optional": {
|
||||
"region_metadata": ("STRING", {
|
||||
"default": "{}",
|
||||
"multiline": True,
|
||||
}),
|
||||
}
|
||||
"required": {"image": ("IMAGE",)},
|
||||
"optional": {"region_metadata": ("STRING", {"default": "{}", "multiline": True})}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING")
|
||||
@@ -49,27 +33,47 @@ class RegionSelectorNode:
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def process_region_selection(self, image, region_metadata="{}"):
|
||||
"""
|
||||
Processa l'immagine e ritorna l'immagine + metadata della regione selezionata.
|
||||
|
||||
Args:
|
||||
image: Tensor immagine (B, H, W, C)
|
||||
region_metadata: JSON string con coordinate della regione (x1, x2, y1, y2)
|
||||
|
||||
Returns:
|
||||
(image, region_metadata_json): Immagine originale e metadata JSON
|
||||
"""
|
||||
|
||||
# Usa il metadata fornito, o l'ultimo salvato se vuoto
|
||||
if region_metadata and region_metadata.strip() and region_metadata != "{}":
|
||||
metadata_to_return = region_metadata
|
||||
if region_metadata.strip() and region_metadata != "{}":
|
||||
self.last_metadata = region_metadata
|
||||
else:
|
||||
# Se nessun metadata è stato fornito, usa l'ultimo salvato
|
||||
metadata_to_return = self.last_metadata
|
||||
return (image, self.last_metadata)
|
||||
|
||||
print(f"[RegionSelectorNode] Processing selection, metadata: {metadata_to_return}")
|
||||
return (image, metadata_to_return)
|
||||
|
||||
def scale_image_if_needed(filename, max_size=1024):
|
||||
input_path = folder_paths.get_input_directory()
|
||||
full_path = os.path.join(input_path, filename)
|
||||
if not os.path.exists(full_path):
|
||||
return {"error": "file non trovato"}
|
||||
|
||||
with Image.open(full_path) as im:
|
||||
w, h = im.size
|
||||
if w <= max_size and h <= max_size:
|
||||
return {"scaled": False, "path": f"view?filename={filename}&type=input"}
|
||||
|
||||
scale_factor = min(max_size / w, max_size / h)
|
||||
new_size = (int(w * scale_factor), int(h * scale_factor))
|
||||
im_resized = im.resize(new_size, Image.Resampling.LANCZOS)
|
||||
|
||||
os.makedirs("temp", exist_ok=True)
|
||||
scaled_name = f"scaled_{filename}"
|
||||
scaled_path = os.path.join("temp", scaled_name)
|
||||
im_resized.save(scaled_path)
|
||||
print(f"[RegionSelector] Immagine scalata {w}x{h} -> {new_size[0]}x{new_size[1]}")
|
||||
|
||||
return {"scaled": True, "path": f"view?filename={scaled_name}&type=temp", "scale": scale_factor}
|
||||
|
||||
|
||||
@server.PromptServer.instance.routes.post("/region_selector/scale")
|
||||
async def scale_image_endpoint(request):
|
||||
try:
|
||||
data = await request.json()
|
||||
filename = data.get("filename")
|
||||
if not filename:
|
||||
return {"error": "filename mancante"}
|
||||
result = scale_image_if_needed(filename)
|
||||
return result
|
||||
except Exception as e:
|
||||
print(f"[RegionSelector] Errore endpoint scale: {e}")
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {"BoxSelector": RegionSelectorNode}
|
||||
|
||||
Reference in New Issue
Block a user