layer_mask is not a mandatory input

This commit is contained in:
chflame163
2024-01-18 20:45:28 +08:00
committed by GitHub
parent 1cd7800ed6
commit 6c3bdf2d24
10 changed files with 93 additions and 25 deletions
+2
View File
@@ -7,6 +7,8 @@ Currently completed Drop Shadow and OuterGlow nodes, and follow-up work is in pr
[中文说明点这里](./README_CN.MD)
## Update
* Now, layer_mask is not a mandatory input. without inputting will use the layer_image's alpha channel. It is allowed to use layers and masks with different shapes, but the size must be consistent.
![image](image/title.png)
* Commit ImageBlend node.
* Remove the mask channel output from the DropShadow node; Commit OuterGlow node.
* Commit DropShadow node.
+2
View File
@@ -3,6 +3,8 @@ ComfyUI
当前已完成Drop Shadow和OuterGlow节点,后续工作进行中。
## 更新说明:
* 现在layer_mask不是输入必选。不输入将使用layer_image的alpha通道。允许使用形状不同的layer和mask,但是尺寸必须一致。
![image](image/title.png)
* 添加ImageBlend节点
* DropShadow节点去掉调试mask通道输出;添加OuterGlow节点。
* DropShadow节点上线。
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+17 -14
View File
@@ -12,7 +12,6 @@ class DropShadow:
"required": {
"background_image": ("IMAGE", ), #
"layer_image": ("IMAGE",), #
"layer_mask": ("MASK",), #
"invert_mask": ("BOOLEAN", {"default": True}), # 反转mask
"blend_mode": (chop_mode,), # 混合模式
"opacity": ("INT", {"default": 50, "min": 0, "max": 100, "step": 1}), # 透明度
@@ -23,6 +22,7 @@ class DropShadow:
"shadow_color": ("STRING", {"default": "#000000"}), # 背景颜色
},
"optional": {
"layer_mask": ("MASK",), #
}
}
@@ -34,34 +34,37 @@ class DropShadow:
CATEGORY = '😺dzNodes'
OUTPUT_NODE = True
def drop_shadow(self, background_image, layer_image, layer_mask,
def drop_shadow(self, background_image, layer_image,
invert_mask, blend_mode, opacity, distance_x, distance_y,
grow, blur, shadow_color,
layer_mask=None,
):
distance_x = -distance_x
distance_y = -distance_y
# 处理阴影mask
if invert_mask:
layer_mask = 1 - layer_mask
_layer = tensor2pil(layer_image)
_mask = mask2image(layer_mask)
_canvas = tensor2pil(background_image).convert('RGB')
_layer = tensor2pil(layer_image).convert('RGB')
_mask = tensor2pil(layer_image).convert('RGBA').split()[-1]
# 处理mask
if layer_mask is not None:
if invert_mask:
layer_mask = 1 - layer_mask
_mask = mask2image(layer_mask).convert('L')
if distance_x != 0 or distance_y != 0:
_mask = shift_image(_mask, distance_x, distance_y) # 位移
shadow_mask = expand_mask(image2mask(_mask), grow, blur, 0) #扩张,模糊
__mask = shift_image(_mask, distance_x, distance_y) # 位移
shadow_mask = expand_mask(image2mask(__mask), grow, blur, 0) #扩张,模糊
# 合成阴影
shadow_color = Image.new("RGB", _layer.size, color=shadow_color)
alpha = tensor2pil(shadow_mask).convert('L')
_canvas = tensor2pil(background_image)
_shadow = chop_image(tensor2pil(background_image), shadow_color, blend_mode, opacity)
_shadow = chop_image(_canvas, shadow_color, blend_mode, opacity)
_canvas.paste(_shadow, mask=alpha)
# 合成layer
alpha = tensor2pil(layer_mask).convert('L')
_canvas.paste(_layer, mask=alpha)
_canvas.paste(_layer, mask=_mask)
ret_image = _canvas
ret_mask = shadow_mask
# ret_mask = shadow_mask
# return (pil2tensor(ret_image), ret_mask,)
return (pil2tensor(ret_image),)
+59
View File
@@ -0,0 +1,59 @@
from .imagefunc import *
class ImageBlend:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(self):
chop_mode = ['normal','multply','screen','add','subtract','difference','darker','lighter']
return {
"required": {
"background_image": ("IMAGE", ), #
"layer_image": ("IMAGE",), #
"invert_mask": ("BOOLEAN", {"default": True}), # 反转mask
"blend_mode": (chop_mode,), # 混合模式
"opacity": ("INT", {"default": 100, "min": 0, "max": 100, "step": 1}), # 透明度
},
"optional": {
"layer_mask": ("MASK",), #
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("image",)
FUNCTION = 'image_blend'
CATEGORY = '😺dzNodes'
OUTPUT_NODE = True
def image_blend(self, background_image, layer_image,
invert_mask, blend_mode, opacity,
layer_mask=None,
):
_canvas = tensor2pil(background_image).convert('RGB')
_layer = tensor2pil(layer_image).convert('RGB')
_mask = tensor2pil(layer_image).convert('RGBA').split()[-1]
if layer_mask is not None:
if invert_mask:
layer_mask = 1 - layer_mask
_mask = mask2image(layer_mask).convert('L')
# 合成layer
_comp = chop_image(_canvas, _layer, blend_mode, opacity)
_canvas.paste(_comp, mask=_mask)
ret_image = _canvas
return (pil2tensor(ret_image),)
NODE_CLASS_MAPPINGS = {
"LayerStyle_ImageBlend": ImageBlend
}
NODE_DISPLAY_NAME_MAPPINGS = {
"LayerStyle_ImageBlend": "LayerStyle: ImageBlend"
}
-1
View File
@@ -35,7 +35,6 @@ def image2mask(image:Image) -> torch.Tensor:
def mask2image(mask:torch.Tensor) -> Image:
masks = tensor2np(mask)
# images = []
for m in masks:
_mask = Image.fromarray(m).convert("L")
_image = Image.new("RGBA", _mask.size, color='white')
+13 -10
View File
@@ -12,7 +12,6 @@ class OuterGlow:
"required": {
"background_image": ("IMAGE", ), #
"layer_image": ("IMAGE",), #
"layer_mask": ("MASK",), #
"invert_mask": ("BOOLEAN", {"default": True}), # 反转mask
"blend_mode": (chop_mode,), # 混合模式
"opacity": ("INT", {"default": 100, "min": 0, "max": 100, "step": 1}), # 透明度
@@ -21,6 +20,7 @@ class OuterGlow:
"glow_color": ("STRING", {"default": "#FFFFFF"}), # 背景颜色
},
"optional": {
"layer_mask": ("MASK",), #
}
}
@@ -32,31 +32,34 @@ class OuterGlow:
CATEGORY = '😺dzNodes'
OUTPUT_NODE = True
def outer_glow(self, background_image, layer_image, layer_mask,
def outer_glow(self, background_image, layer_image,
invert_mask, blend_mode, opacity,
grow, blur, glow_color,
layer_mask=None,
):
_canvas = tensor2pil(background_image).convert('RGB')
_layer = tensor2pil(layer_image).convert('RGB')
_mask = tensor2pil(layer_image).convert('RGBA').split()[-1]
# 处理mask
if invert_mask:
layer_mask = 1 - layer_mask
_layer = tensor2pil(layer_image)
_mask = mask2image(layer_mask)
if layer_mask is not None:
if invert_mask:
layer_mask = 1 - layer_mask
_mask = mask2image(layer_mask).convert('L')
glow_mask = expand_mask(image2mask(_mask), grow, blur, 0) #扩张,模糊
# 合成glow
glow_color = Image.new("RGB", _layer.size, color=glow_color)
alpha = tensor2pil(glow_mask).convert('L')
_canvas = tensor2pil(background_image)
_glow = chop_image(tensor2pil(background_image), glow_color, blend_mode, opacity)
_canvas.paste(_glow, mask=alpha)
# 合成layer
alpha = tensor2pil(layer_mask).convert('L')
_canvas.paste(_layer, mask=alpha)
_canvas.paste(_layer, mask=_mask)
ret_image = _canvas
ret_mask = glow_mask
# ret_mask = glow_mask
# return (pil2tensor(ret_image), ret_mask,)
return (pil2tensor(ret_image),)