169 lines
4.8 KiB
Python
169 lines
4.8 KiB
Python
import torch
|
|
import numpy as np
|
|
from PIL import Image, ImageDraw
|
|
import torchvision.transforms as t
|
|
from comfy_extras import nodes_mask as masks
|
|
|
|
def tensor_to_image(tensor):
|
|
return t.ToPILImage()(tensor.permute(2, 0, 1))
|
|
|
|
def image_to_tensor(image):
|
|
return t.ToTensor()(image).permute(1, 2, 0)
|
|
|
|
def get_sampler_by_name(method):
|
|
if method == "lanczos":
|
|
return Image.LANCZOS
|
|
elif method == "bicubic":
|
|
return Image.BICUBIC
|
|
elif method == "hamming":
|
|
return Image.HAMMING
|
|
elif method == "bilinear":
|
|
return Image.BILINEAR
|
|
elif method == "box":
|
|
return Image.BOX
|
|
elif method == "nearest":
|
|
return Image.NEAREST
|
|
else:
|
|
raise ValueError("Sampler not found.")
|
|
|
|
class AD_ImageDrawRectangleSimple:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 1,
|
|
"step": 1
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 1,
|
|
"step": 1
|
|
}),
|
|
"left": ("INT", {
|
|
"default": 50,
|
|
"min": 0,
|
|
"step": 1
|
|
}),
|
|
"top": ("INT", {
|
|
"default": 50,
|
|
"min": 0,
|
|
"step": 1
|
|
}),
|
|
"right": ("INT", {
|
|
"default": 50,
|
|
"min": 0,
|
|
"step": 1
|
|
}),
|
|
"bottom": ("INT", {
|
|
"default": 50,
|
|
"min": 0,
|
|
"step": 1
|
|
}),
|
|
"radius": ("INT", {
|
|
"default": 20,
|
|
"min": 0,
|
|
"step": 1
|
|
}),
|
|
"fill_red": ("INT", {
|
|
"default": 255,
|
|
"min": 0,
|
|
"max": 255,
|
|
"step": 1
|
|
}),
|
|
"fill_green": ("INT", {
|
|
"default": 255,
|
|
"min": 0,
|
|
"max": 255,
|
|
"step": 1
|
|
}),
|
|
"fill_blue": ("INT", {
|
|
"default": 255,
|
|
"min": 0,
|
|
"max": 255,
|
|
"step": 1
|
|
}),
|
|
"fill_alpha": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.01
|
|
}),
|
|
"SSAA": ("INT", {
|
|
"default": 4,
|
|
"min": 1,
|
|
"max": 16,
|
|
"step": 1
|
|
}),
|
|
"method": (["lanczos", "bicubic", "hamming", "bilinear", "box", "nearest"],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE", "MASK")
|
|
RETURN_NAMES = ("IMAGE", "MASK")
|
|
FUNCTION = "node"
|
|
CATEGORY = "🌻 Addoor/Utilities"
|
|
|
|
def node(
|
|
self,
|
|
width,
|
|
height,
|
|
left,
|
|
top,
|
|
right,
|
|
bottom,
|
|
radius,
|
|
fill_red,
|
|
fill_green,
|
|
fill_blue,
|
|
fill_alpha,
|
|
SSAA,
|
|
method
|
|
):
|
|
# Calculate the rectangle coordinates with inward offsets
|
|
rect_left = left * SSAA
|
|
rect_top = top * SSAA
|
|
rect_right = (width - right) * SSAA
|
|
rect_bottom = (height - bottom) * SSAA
|
|
|
|
canvas = Image.new("RGBA", (width * SSAA, height * SSAA), (0, 0, 0, 0))
|
|
mask_canvas = Image.new("L", (width * SSAA, height * SSAA), 0) # Create mask canvas
|
|
|
|
draw = ImageDraw.Draw(canvas)
|
|
mask_draw = ImageDraw.Draw(mask_canvas) # Create mask draw object
|
|
|
|
draw.rounded_rectangle(
|
|
(
|
|
(rect_left, rect_top),
|
|
(rect_right, rect_bottom)
|
|
),
|
|
radius * SSAA,
|
|
(fill_red, fill_green, fill_blue, int(fill_alpha * 255))
|
|
)
|
|
mask_draw.rounded_rectangle( # Draw white rectangle on mask
|
|
(
|
|
(rect_left, rect_top),
|
|
(rect_right, rect_bottom)
|
|
),
|
|
radius * SSAA,
|
|
fill=255
|
|
)
|
|
|
|
canvas = canvas.resize((width, height), get_sampler_by_name(method))
|
|
mask_canvas = mask_canvas.resize((width, height), get_sampler_by_name(method))
|
|
|
|
# Convert PIL Image to tensor
|
|
tensor = image_to_tensor(canvas)
|
|
mask_tensor = torch.from_numpy(np.array(mask_canvas)).float() / 255.0
|
|
|
|
# Add batch dimension
|
|
tensor = tensor.unsqueeze(0)
|
|
mask_tensor = mask_tensor.unsqueeze(0)
|
|
|
|
return (tensor, mask_tensor)
|
|
|