commit ImageMaskScaleAsV2,ColorImage V3 nodes
This commit is contained in:
@@ -49,7 +49,7 @@ class ColorImageV2:
|
||||
width = int(_s[0].strip())
|
||||
height = int(_s[1].strip())
|
||||
except Exception as e:
|
||||
log(f"Warning: {self.NODE_NAME} invalid size, check {custom_size_file}", message_type='warning')
|
||||
log(f'Warning: {self.NODE_NAME} invalid size, check "custom_size.ini"', message_type='warning')
|
||||
width = custom_width
|
||||
height = custom_height
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
from PIL import Image
|
||||
from .imagefunc import log, tensor2pil, pil2tensor, AnyType, load_custom_size
|
||||
from .color_name import LS_ColorName
|
||||
|
||||
|
||||
any = AnyType("*")
|
||||
|
||||
class LS_ColorImageV3:
|
||||
|
||||
def __init__(self):
|
||||
self.NODE_NAME = 'ColorImage V3'
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(self):
|
||||
size_list = ['custom']
|
||||
size_list.extend(load_custom_size())
|
||||
return {
|
||||
"required": {
|
||||
"size": (size_list,),
|
||||
"custom_width": ("INT", {"default": 512, "min": 4, "max": 99999, "step": 1}),
|
||||
"custom_height": ("INT", {"default": 512, "min": 4, "max": 99999, "step": 1}),
|
||||
"color": ("STRING", {"default": "#000000"},),
|
||||
},
|
||||
"optional": {
|
||||
"size_as": (any, {}),
|
||||
"color_name": ("STRING", {"default": "white",},),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING", )
|
||||
RETURN_NAMES = ("image", "color",)
|
||||
FUNCTION = 'color_image_v2'
|
||||
CATEGORY = '😺dzNodes/LayerUtility'
|
||||
|
||||
def color_image_v2(self, size, custom_width, custom_height, color, size_as=None, color_name=None):
|
||||
|
||||
if size_as is not None:
|
||||
if size_as.shape[0] > 0:
|
||||
_asimage = tensor2pil(size_as[0])
|
||||
else:
|
||||
_asimage = tensor2pil(size_as)
|
||||
width, height = _asimage.size
|
||||
else:
|
||||
if size == 'custom':
|
||||
width = custom_width
|
||||
height = custom_height
|
||||
else:
|
||||
try:
|
||||
_s = size.split('x')
|
||||
width = int(_s[0].strip())
|
||||
height = int(_s[1].strip())
|
||||
except Exception as e:
|
||||
log(f'Warning: {self.NODE_NAME} invalid size, check "custom_size.ini"', message_type='warning')
|
||||
width = custom_width
|
||||
height = custom_height
|
||||
|
||||
if color_name is not None:
|
||||
try:
|
||||
color_table = LS_ColorName()
|
||||
color = color_table.XKCD_NAME_TO_HEX[color_name]
|
||||
except KeyError:
|
||||
log(f"{self.NODE_NAME}: {color_name} not in XKCD color table, use custom color value.")
|
||||
ret_image = Image.new('RGB', (width, height), color=color)
|
||||
return (pil2tensor(ret_image), color,)
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"LayerUtility: ColorImage V3": LS_ColorImageV3
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"LayerUtility: ColorImage V3": "LayerUtility: ColorImage V3"
|
||||
}
|
||||
@@ -53,7 +53,7 @@ class GradientImageV2:
|
||||
width = int(_s[0].strip())
|
||||
height = int(_s[1].strip())
|
||||
except Exception as e:
|
||||
log(f"Warning: {self.NODE_NAME} invalid size, check {custom_size_file}", message_type='warning')
|
||||
log(f'Warning: {self.NODE_NAME} invalid size, check "custom_size.ini"', message_type='warning')
|
||||
width = custom_width
|
||||
height = custom_height
|
||||
|
||||
|
||||
@@ -90,10 +90,100 @@ class ImageMaskScaleAs:
|
||||
log(f"Error: {self.NODE_NAME} skipped, because the available image or mask is not found.", message_type='error')
|
||||
return (None, None, [orig_width, orig_height], 0, 0,)
|
||||
|
||||
|
||||
class LS_ImageMaskScaleAsV2:
|
||||
|
||||
def __init__(self):
|
||||
self.NODE_NAME = 'ImageMaskScaleAsV2'
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(self):
|
||||
|
||||
fit_mode = ['letterbox', 'crop', 'fill']
|
||||
method_mode = ['lanczos', 'bicubic', 'hamming', 'bilinear', 'box', 'nearest']
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"scale_as": (any, {}),
|
||||
"fit": (fit_mode,),
|
||||
"method": (method_mode,),
|
||||
"background_color": ("STRING", {"default": "#000000"},),
|
||||
},
|
||||
"optional": {
|
||||
"image": ("IMAGE",), #
|
||||
"mask": ("MASK",), #
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "MASK", "BOX", "INT", "INT")
|
||||
RETURN_NAMES = ("image", "mask", "original_size", "widht", "height",)
|
||||
FUNCTION = 'image_mask_scale_as_v2'
|
||||
CATEGORY = '😺dzNodes/LayerUtility'
|
||||
|
||||
def image_mask_scale_as_v2(self, scale_as, fit, method, background_color,
|
||||
image=None, mask=None,
|
||||
):
|
||||
if scale_as.shape[0] > 0:
|
||||
_asimage = tensor2pil(scale_as[0])
|
||||
else:
|
||||
_asimage = tensor2pil(scale_as)
|
||||
target_width, target_height = _asimage.size
|
||||
_mask = Image.new('L', size=_asimage.size, color='black')
|
||||
_image = Image.new('RGB', size=_asimage.size, color=background_color)
|
||||
orig_width = 4
|
||||
orig_height = 4
|
||||
resize_sampler = Image.LANCZOS
|
||||
if method == "bicubic":
|
||||
resize_sampler = Image.BICUBIC
|
||||
elif method == "hamming":
|
||||
resize_sampler = Image.HAMMING
|
||||
elif method == "bilinear":
|
||||
resize_sampler = Image.BILINEAR
|
||||
elif method == "box":
|
||||
resize_sampler = Image.BOX
|
||||
elif method == "nearest":
|
||||
resize_sampler = Image.NEAREST
|
||||
|
||||
ret_images = []
|
||||
ret_masks = []
|
||||
|
||||
if image is not None:
|
||||
for i in image:
|
||||
i = torch.unsqueeze(i, 0)
|
||||
_image = tensor2pil(i).convert('RGB')
|
||||
orig_width, orig_height = _image.size
|
||||
_image = fit_resize_image(_image, target_width, target_height, fit, resize_sampler, background_color=background_color)
|
||||
ret_images.append(pil2tensor(_image))
|
||||
if mask is not None:
|
||||
if mask.dim() == 2:
|
||||
mask = torch.unsqueeze(mask, 0)
|
||||
for m in mask:
|
||||
m = torch.unsqueeze(m, 0)
|
||||
_mask = tensor2pil(m).convert('L')
|
||||
orig_width, orig_height = _mask.size
|
||||
_mask = fit_resize_image(_mask, target_width, target_height, fit, resize_sampler, background_color=background_color).convert('L')
|
||||
ret_masks.append(image2mask(_mask))
|
||||
if len(ret_images) > 0 and len(ret_masks) > 0:
|
||||
log(f"{self.NODE_NAME} Processed {len(ret_images)} image(s).", message_type='finish')
|
||||
return (torch.cat(ret_images, dim=0), torch.cat(ret_masks, dim=0), [orig_width, orig_height], target_width,
|
||||
target_height,)
|
||||
elif len(ret_images) > 0 and len(ret_masks) == 0:
|
||||
log(f"{self.NODE_NAME} Processed {len(ret_images)} image(s).", message_type='finish')
|
||||
return (torch.cat(ret_images, dim=0), None, [orig_width, orig_height], target_width, target_height,)
|
||||
elif len(ret_images) == 0 and len(ret_masks) > 0:
|
||||
log(f"{self.NODE_NAME} Processed {len(ret_masks)} image(s).", message_type='finish')
|
||||
return (None, torch.cat(ret_masks, dim=0), [orig_width, orig_height], target_width, target_height,)
|
||||
else:
|
||||
log(f"Error: {self.NODE_NAME} skipped, because the available image or mask is not found.",
|
||||
message_type='error')
|
||||
return (None, None, [orig_width, orig_height], 0, 0,)
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"LayerUtility: ImageMaskScaleAs": ImageMaskScaleAs
|
||||
"LayerUtility: ImageMaskScaleAs": ImageMaskScaleAs,
|
||||
"LayerUtility: ImageMaskScaleAsV2": LS_ImageMaskScaleAsV2,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"LayerUtility: ImageMaskScaleAs": "LayerUtility: ImageMaskScaleAs"
|
||||
"LayerUtility: ImageMaskScaleAs": "LayerUtility: Image Mask Scale As",
|
||||
"LayerUtility: ImageMaskScaleAsV2": "LayerUtility: Image Mask Scale As V2",
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui_layerstyle"
|
||||
description = "A set of nodes for ComfyUI it generate image like Adobe Photoshop's Layer Style. the Drop Shadow is first completed node, and follow-up work is in progress."
|
||||
version = "2.0.10"
|
||||
version = "2.0.11"
|
||||
license = "MIT"
|
||||
dependencies = ["numpy", "pillow", "torch", "matplotlib", "Scipy", "scikit_image", "scikit_learn", "opencv-contrib-python", "pymatting", "timm", "colour-science", "transformers", "blend_modes", "huggingface_hub", "loguru"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user