diff --git a/README.MD b/README.MD
index 7207333..0e01516 100644
--- a/README.MD
+++ b/README.MD
@@ -2,18 +2,23 @@
A set of nodes for ComfyUI that generate image like Adobe Photoshop's Layer Style.
-the Drop Shadow is first completed node, and follow-up work is in progress.
+Currently completed Drop Shadow and OuterGlow nodes, and follow-up work is in progress.
[䏿–‡è¯´æ˜Žç‚¹è¿™é‡Œ](./README_CN.MD)
+## Update
+Remove the mask channel output from the DropShadow node; Add the OuterGlow node.
+
## Node Description
### Drop Shadow:
Generate shadow
-
+
+
Node options:
+
* background_image1: The background image.
* layer_image1: Layer image for composite.
* layer_mask1: Mask for layer_image, shadows are generated according to their shape.
@@ -29,11 +34,31 @@ Node options:
1 The layer_image, layer_mask and the background_image, These three items must be of the same size.
Output type:
-* image:Completed image.
-* shadow_mask:Shadow's mask.
+* image
+
+
+### OuterGlow:
+Generate outer glow
+
+
+Node options:
+
+* background_image1: The background image.
+* layer_image1: Layer image for composite.
+* layer_mask1: Mask for layer_image, shadows are generated according to their shape.
+* invert_mask: Whether to reverse the mask.
+* blend_mode: Blending method of glow, there are **_normal, multply, screen, add, subtract, difference, darker_** and **_lighter_**.
+* opacity: Opacity of Glow.
+* grow: Glow expansion amplitude.
+* blur:Gkow blur level.
+* glow_color: Glow color, described in hexadecimal RGB format.
+
+1 The layer_image, layer_mask and the background_image, These three items must be of the same size.
+
+输出:
+* image
## Example workflow
-
image Some JSON workflow files in the workflow directory, that is example for ComfyUI.
## How to install
diff --git a/README_CN.MD b/README_CN.MD
index 6ae06e6..5ab602c 100644
--- a/README_CN.MD
+++ b/README_CN.MD
@@ -1,15 +1,20 @@
# ComfyUI Layer Style£º
ComfyUI²å¼þ£¬Í¨¹ýÒ»×é½ÚµãʵÏÖ·ÂÕÕAdobe PhotoshopµÄͼ²ãÑùʽ¡£
-Drop ShadowÊÇÊ׸öÍê³ÉµÄ½Úµã£¬ºóÐø¹¤×÷½øÐÐÖС£
+µ±Ç°ÒÑÍê³ÉDrop ShadowºÍOuterGlow½Úµã£¬ºóÐø¹¤×÷½øÐÐÖС£
+
+## ¸üÐÂ˵Ã÷£º
+DropShadow½ÚµãÈ¥µôµ÷ÊÔmaskͨµÀÊä³ö£»Ìí¼ÓOuterGlow½Úµã¡£
## ½Úµã˵Ã÷£º
-### Drop Shadow:
+### DropShadow:
Éú³ÉÒõÓ°¡£
+
+
+
+
+½ÚµãÑ¡Ïî˵Ã÷£º

-
-
-Ñ¡Ïî˵Ã÷£º
* background_image1: ±³¾°Í¼Ïñ¡£
* layer_image1: ÓÃÓںϳɵIJãͼÏñ¡£
* layer_mask1: ²ãͼÏñµÄÕÚÕÖ£¬ÒõÓ°°´´ËÉú³É¡£
@@ -25,11 +30,32 @@ Drop Shadow
1 background_image, layer_image, layer_maskÕâÈýÏî±ØÐëÊÇÏàͬµÄ³ß´ç¡£
Êä³ö£º
-* image£ºÍê³ÉµÄͼÏñ¡£
-* shadow_mask£ºÒõÓ°µÄͨµÀ¡£
+* image
+
+### OuterGlow£º
+Éú³ÉÍâ·¢¹â¡£
+
+
+½ÚµãÑ¡Ïî˵Ã÷£º
+
+* background_image1: ±³¾°Í¼Ïñ¡£
+* layer_image1: ÓÃÓںϳɵIJãͼÏñ¡£
+* layer_mask1: ²ãͼÏñµÄÕÚÕÖ£¬ÒõÓ°°´´ËÉú³É¡£
+* invert_mask: ÊÇ·ñ·´×ªÕÚÕÖ¡£
+* blend_mode: Íâ·¢¹âµÄ»ìºÏ·½Ê½£¬°üÀ¨normal¡¢multply¡¢screen¡¢add¡¢subtract¡¢difference¡¢darkerºÍlighter¡£
+* opacity: Íâ·¢¹âµÄ²»Í¸Ã÷¶È¡£
+* grow: Íâ·¢¹âÀ©ÕÅ·ù¶È¡£
+* blur£ºÍâ·¢¹âÄ£ºý³Ì¶È¡£
+* glow_color: Íâ·¢¹âÑÕÉ«£¬Ê¹ÓÃ16½øÖÆRGB¸ñʽÃèÊö¡£
+
+1 background_image, layer_image, layer_maskÕâÈýÏî±ØÐëÊÇÏàͬµÄ³ß´ç¡£
+
+Êä³ö£º
+* image
+
## ʹÓÃʾÀý£º
-
+
ÔÚworkflowĿ¼ÏÂÓÐjson¸ñʽµÄ¹¤×÷Á÷ʾÀýÎļþ¡£
## °²×°·½·¨£º
diff --git a/image/drop_shadow_example.png b/image/drop_shadow_example.png
new file mode 100644
index 0000000..5756603
Binary files /dev/null and b/image/drop_shadow_example.png differ
diff --git a/image/drop_shadow_node.png b/image/drop_shadow_node.png
index f1fd688..c481aff 100644
Binary files a/image/drop_shadow_node.png and b/image/drop_shadow_node.png differ
diff --git a/image/outer_glow_example.png b/image/outer_glow_example.png
new file mode 100644
index 0000000..14aa6b8
Binary files /dev/null and b/image/outer_glow_example.png differ
diff --git a/image/outer_glow_node.png b/image/outer_glow_node.png
new file mode 100644
index 0000000..b728c48
Binary files /dev/null and b/image/outer_glow_node.png differ
diff --git a/py/__pycache__/drop_shadow.cpython-311.pyc b/py/__pycache__/drop_shadow.cpython-311.pyc
index 8278705..f8f4174 100644
Binary files a/py/__pycache__/drop_shadow.cpython-311.pyc and b/py/__pycache__/drop_shadow.cpython-311.pyc differ
diff --git a/py/__pycache__/imagefunc.cpython-311.pyc b/py/__pycache__/imagefunc.cpython-311.pyc
index 71921f3..362acfd 100644
Binary files a/py/__pycache__/imagefunc.cpython-311.pyc and b/py/__pycache__/imagefunc.cpython-311.pyc differ
diff --git a/py/__pycache__/outer_glow.cpython-311.pyc b/py/__pycache__/outer_glow.cpython-311.pyc
new file mode 100644
index 0000000..ca2d2f3
Binary files /dev/null and b/py/__pycache__/outer_glow.cpython-311.pyc differ
diff --git a/py/drop_shadow.py b/py/drop_shadow.py
index a4461f5..13af4b3 100644
--- a/py/drop_shadow.py
+++ b/py/drop_shadow.py
@@ -23,12 +23,13 @@ class DropShadow:
"shadow_color": ("STRING", {"default": "#000000"}), # 背景颜色
},
"optional": {
- # "test_mask": ("MASK",), #
}
}
- RETURN_TYPES = ("IMAGE", "MASK",)
- RETURN_NAMES = ("image", "shadow_mask",)
+ # RETURN_TYPES = ("IMAGE", "MASK",)
+ # RETURN_NAMES = ("image", "shadow_mask",)
+ RETURN_TYPES = ("IMAGE",)
+ RETURN_NAMES = ("image",)
FUNCTION = 'drop_shadow'
CATEGORY = '😺dzNodes'
OUTPUT_NODE = True
@@ -61,12 +62,13 @@ class DropShadow:
ret_image = _canvas
ret_mask = shadow_mask
- return (pil2tensor(ret_image), ret_mask,)
+ # return (pil2tensor(ret_image), ret_mask,)
+ return (pil2tensor(ret_image),)
NODE_CLASS_MAPPINGS = {
"LayerStyle_DropShadow": DropShadow
}
NODE_DISPLAY_NAME_MAPPINGS = {
- "LayerStyle_DropShadow": "Layer Style: Drop Shadow"
+ "LayerStyle_DropShadow": "LayerStyle: DropShadow"
}
\ No newline at end of file
diff --git a/py/outer_glow.py b/py/outer_glow.py
new file mode 100644
index 0000000..b06baa4
--- /dev/null
+++ b/py/outer_glow.py
@@ -0,0 +1,69 @@
+from .imagefunc import *
+
+class OuterGlow:
+
+ 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",), #
+ "layer_mask": ("MASK",), #
+ "invert_mask": ("BOOLEAN", {"default": True}), # �转mask
+ "blend_mode": (chop_mode,), # 混�模�
+ "opacity": ("INT", {"default": 100, "min": 0, "max": 100, "step": 1}), # �明度
+ "grow": ("INT", {"default": 16, "min": -9999, "max": 9999, "step": 1}), # 扩å¼
+ "blur": ("INT", {"default": 20, "min": 0, "max": 100, "step": 1}), # 模糊
+ "glow_color": ("STRING", {"default": "#FFFFFF"}), # 背景颜色
+ },
+ "optional": {
+ }
+ }
+
+ # RETURN_TYPES = ("IMAGE", "MASK",)
+ # RETURN_NAMES = ("image", "glow_mask",)
+ RETURN_TYPES = ("IMAGE",)
+ RETURN_NAMES = ("image",)
+ FUNCTION = 'outer_glow'
+ CATEGORY = '😺dzNodes'
+ OUTPUT_NODE = True
+
+ def outer_glow(self, background_image, layer_image, layer_mask,
+ invert_mask, blend_mode, opacity,
+ grow, blur, glow_color,
+ ):
+
+ # 处�mask
+ if invert_mask:
+ layer_mask = 1 - layer_mask
+ _layer = tensor2pil(layer_image)
+ _mask = mask2image(layer_mask)
+ 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)
+
+ ret_image = _canvas
+ ret_mask = glow_mask
+ # return (pil2tensor(ret_image), ret_mask,)
+ return (pil2tensor(ret_image),)
+
+NODE_CLASS_MAPPINGS = {
+ "LayerStyle_OuterGlow": OuterGlow
+}
+
+NODE_DISPLAY_NAME_MAPPINGS = {
+ "LayerStyle_OuterGlow": "LayerStyle: OuterGlow"
+}
\ No newline at end of file
diff --git a/workflow/512x512.png b/workflow/512x512.png
new file mode 100644
index 0000000..334b79b
Binary files /dev/null and b/workflow/512x512.png differ
diff --git a/workflow/512x512bkgd.jpg b/workflow/512x512bkgd.jpg
new file mode 100644
index 0000000..0ffd73f
Binary files /dev/null and b/workflow/512x512bkgd.jpg differ
diff --git a/workflow/drop_shadow_example.json b/workflow/drop_shadow_example.json
index 33c3a2f..a4241ed 100644
--- a/workflow/drop_shadow_example.json
+++ b/workflow/drop_shadow_example.json
@@ -1,13 +1,95 @@
{
- "last_node_id": 20,
- "last_link_id": 49,
+ "last_node_id": 23,
+ "last_link_id": 58,
"nodes": [
+ {
+ "id": 22,
+ "type": "LayerStyle_DropShadow",
+ "pos": [
+ 540,
+ -660
+ ],
+ "size": {
+ "0": 315,
+ "1": 266
+ },
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "background_image",
+ "type": "IMAGE",
+ "link": 54
+ },
+ {
+ "name": "layer_image",
+ "type": "IMAGE",
+ "link": 55
+ },
+ {
+ "name": "layer_mask",
+ "type": "MASK",
+ "link": 56
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 58
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerStyle_DropShadow"
+ },
+ "widgets_values": [
+ true,
+ "normal",
+ 50,
+ 5,
+ 5,
+ 2,
+ 15,
+ "#000000"
+ ]
+ },
+ {
+ "id": 23,
+ "type": "SaveImage",
+ "pos": [
+ 890,
+ -660
+ ],
+ "size": [
+ 315,
+ 270
+ ],
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 58
+ }
+ ],
+ "properties": {},
+ "widgets_values": [
+ "ComfyUI"
+ ]
+ },
{
"id": 2,
"type": "LoadImage",
"pos": [
- 237,
- -31
+ 180,
+ -680
],
"size": {
"0": 315,
@@ -21,7 +103,7 @@
"name": "IMAGE",
"type": "IMAGE",
"links": [
- 45
+ 55
],
"shape": 3,
"slot_index": 0
@@ -30,7 +112,7 @@
"name": "MASK",
"type": "MASK",
"links": [
- 46
+ 56
],
"shape": 3,
"slot_index": 1
@@ -44,157 +126,26 @@
"image"
]
},
- {
- "id": 17,
- "type": "RGB_Picker",
- "pos": [
- 332,
- -180
- ],
- "size": {
- "0": 210,
- "1": 94
- },
- "flags": {},
- "order": 1,
- "mode": 0,
- "outputs": [
- {
- "name": "value",
- "type": "STRING",
- "links": [
- 49
- ],
- "shape": 3,
- "slot_index": 0
- }
- ],
- "properties": {
- "Node name for S&R": "RGB_Picker"
- },
- "widgets_values": [
- "#2b0303",
- "HEX"
- ]
- },
- {
- "id": 9,
- "type": "PreviewImage",
- "pos": [
- 955,
- -13
- ],
- "size": {
- "0": 210,
- "1": 246
- },
- "flags": {},
- "order": 4,
- "mode": 0,
- "inputs": [
- {
- "name": "images",
- "type": "IMAGE",
- "link": 47
- }
- ],
- "properties": {
- "Node name for S&R": "PreviewImage"
- }
- },
- {
- "id": 20,
- "type": "LayerStyle_DropShadow",
- "pos": [
- 576,
- -21
- ],
- "size": [
- 355.20001220703125,
- 266
- ],
- "flags": {},
- "order": 3,
- "mode": 0,
- "inputs": [
- {
- "name": "background_image",
- "type": "IMAGE",
- "link": 44
- },
- {
- "name": "layer_image",
- "type": "IMAGE",
- "link": 45
- },
- {
- "name": "layer_mask",
- "type": "MASK",
- "link": 46
- },
- {
- "name": "shadow_color",
- "type": "STRING",
- "link": 49,
- "widget": {
- "name": "shadow_color"
- }
- }
- ],
- "outputs": [
- {
- "name": "image",
- "type": "IMAGE",
- "links": [
- 47
- ],
- "shape": 3,
- "slot_index": 0
- },
- {
- "name": "shadow_mask",
- "type": "MASK",
- "links": [
- 48
- ],
- "shape": 3,
- "slot_index": 1
- }
- ],
- "properties": {
- "Node name for S&R": "LayerStyle_DropShadow"
- },
- "widgets_values": [
- true,
- "multply",
- 52,
- 43,
- 45,
- 2,
- 20,
- "#000000"
- ]
- },
{
"id": 3,
"type": "LoadImage",
"pos": [
- -102,
- -33
+ -160,
+ -680
],
"size": {
"0": 315,
"1": 314
},
"flags": {},
- "order": 2,
+ "order": 1,
"mode": 0,
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
- 44
+ 54
],
"shape": 3,
"slot_index": 0
@@ -213,125 +164,40 @@
"512x512bkgd.jpg",
"image"
]
- },
- {
- "id": 10,
- "type": "MaskToImage",
- "pos": [
- 957,
- 282
- ],
- "size": {
- "0": 210,
- "1": 26
- },
- "flags": {},
- "order": 5,
- "mode": 0,
- "inputs": [
- {
- "name": "mask",
- "type": "MASK",
- "link": 48
- }
- ],
- "outputs": [
- {
- "name": "IMAGE",
- "type": "IMAGE",
- "links": [
- 11
- ],
- "shape": 3,
- "slot_index": 0
- }
- ],
- "properties": {
- "Node name for S&R": "MaskToImage"
- }
- },
- {
- "id": 11,
- "type": "PreviewImage",
- "pos": [
- 1188,
- -15
- ],
- "size": {
- "0": 210,
- "1": 246
- },
- "flags": {},
- "order": 6,
- "mode": 0,
- "inputs": [
- {
- "name": "images",
- "type": "IMAGE",
- "link": 11
- }
- ],
- "properties": {
- "Node name for S&R": "PreviewImage"
- }
}
],
"links": [
[
- 11,
- 10,
- 0,
- 11,
- 0,
- "IMAGE"
- ],
- [
- 44,
+ 54,
3,
0,
- 20,
+ 22,
0,
"IMAGE"
],
[
- 45,
+ 55,
2,
0,
- 20,
+ 22,
1,
"IMAGE"
],
[
- 46,
+ 56,
2,
1,
- 20,
+ 22,
2,
"MASK"
],
[
- 47,
- 20,
+ 58,
+ 22,
0,
- 9,
+ 23,
0,
"IMAGE"
- ],
- [
- 48,
- 20,
- 1,
- 10,
- 0,
- "MASK"
- ],
- [
- 49,
- 17,
- 0,
- 20,
- 3,
- "STRING"
]
],
"groups": [],
diff --git a/workflow/outer_glow_example.json b/workflow/outer_glow_example.json
new file mode 100644
index 0000000..56e788c
--- /dev/null
+++ b/workflow/outer_glow_example.json
@@ -0,0 +1,205 @@
+{
+ "last_node_id": 24,
+ "last_link_id": 62,
+ "nodes": [
+ {
+ "id": 23,
+ "type": "SaveImage",
+ "pos": [
+ 890,
+ -660
+ ],
+ "size": [
+ 315,
+ 270
+ ],
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 62
+ }
+ ],
+ "properties": {},
+ "widgets_values": [
+ "ComfyUI"
+ ]
+ },
+ {
+ "id": 3,
+ "type": "LoadImage",
+ "pos": [
+ -160,
+ -680
+ ],
+ "size": {
+ "0": 315,
+ "1": 314
+ },
+ "flags": {},
+ "order": 0,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 59
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": null,
+ "shape": 3
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512bkgd.jpg",
+ "image"
+ ]
+ },
+ {
+ "id": 2,
+ "type": "LoadImage",
+ "pos": [
+ 180,
+ -680
+ ],
+ "size": {
+ "0": 315,
+ "1": 314
+ },
+ "flags": {},
+ "order": 1,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 60
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": [
+ 61
+ ],
+ "shape": 3,
+ "slot_index": 1
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512.png",
+ "image"
+ ]
+ },
+ {
+ "id": 24,
+ "type": "LayerStyle_OuterGlow",
+ "pos": [
+ 536,
+ -631
+ ],
+ "size": {
+ "0": 315,
+ "1": 218
+ },
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "background_image",
+ "type": "IMAGE",
+ "link": 59
+ },
+ {
+ "name": "layer_image",
+ "type": "IMAGE",
+ "link": 60
+ },
+ {
+ "name": "layer_mask",
+ "type": "MASK",
+ "link": 61
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 62
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerStyle_OuterGlow"
+ },
+ "widgets_values": [
+ true,
+ "normal",
+ 100,
+ 16,
+ 20,
+ "#FFFFFF"
+ ]
+ }
+ ],
+ "links": [
+ [
+ 59,
+ 3,
+ 0,
+ 24,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 60,
+ 2,
+ 0,
+ 24,
+ 1,
+ "IMAGE"
+ ],
+ [
+ 61,
+ 2,
+ 1,
+ 24,
+ 2,
+ "MASK"
+ ],
+ [
+ 62,
+ 24,
+ 0,
+ 23,
+ 0,
+ "IMAGE"
+ ]
+ ],
+ "groups": [],
+ "config": {},
+ "extra": {},
+ "version": 0.4
+}
\ No newline at end of file