diff --git a/README.MD b/README.MD
index 01a3e65..cd87016 100644
--- a/README.MD
+++ b/README.MD
@@ -1,12 +1,16 @@
# ComfyUI Layer Style
A set of nodes for ComfyUI that generate image like Adobe Photoshop's Layer Style.
-Currently completed the Drop Shadow, OuterGlow, and some auxiliary nodes. follow-up work is in progress.
+The completed nodes are as follows, and further work is in progress.
+
[䏿–‡è¯´æ˜Žç‚¹è¿™é‡Œ](./README_CN.MD)
## Update
-* OuterGlow node has undergone significant modifications by adding options for **_brightness_**, **_light_color_**, and **_glow_color_**. workflows containing old version nodes need to be manually replaced with new version nodes.
+* Commit InnerGlow, InnerShadow and MotionBlur nodes.
+* Renaming all completed nodes, the nodes are divided into 4 groups:LayerStyle, LayerMask, LayerUtility, LayerFilter. workflows containing old version nodes need to be manually replaced with new version nodes.
+* Fix OuterGlow, add 3 new options: brightness, light_color and glow_color.
+* OuterGlow node has undergone significant modifications by adding options for **_brightness_**, **_light_color_**, and **_glow_color_**.
* Commit MaskInvert node.
* Commit ColorPick node.
* Commit Stroke node.
@@ -17,7 +21,7 @@ Currently completed the Drop Shadow, OuterGlow, and some auxiliary nodes. follow
* Commit OuterGlow node.
* Commit DropShadow node.
-## Node Description
+# LayerStyle
### DropShadow:
Generate shadow
@@ -38,10 +42,6 @@ Node options:
* blur: Shadow blur level.
* shadow_color4: Shadow color.
-Output type:
-* image
-
-
### OuterGlow:
Generate outer glow

@@ -60,10 +60,6 @@ Node options:
* light_color4: Light color.
* glow_color4: Edge part color of glow.
-
-Output type:
-* image
-
### Stroke:
Generate a stroke of layer。

@@ -76,14 +72,31 @@ Node options:
* invert_mask: Whether to reverse the mask.
* blend_mode3: Blending mode of stroke.
* opacity: Opacity of stroke.
-* inner_stroke*: Stroke shrinkage amplitude.
-* outer_stroke*: Stroke expansion amplitude.
+* stroke_grow: Stroke expansion/contraction amplitude, positive values indicate expansion and negative values indicate contraction.
+* stroke_width: Stroke width.
* stroke_color4: Stroke color, described in hexadecimal RGB format.
-*The width of the stroke is equal to inner_stroke plus outer_stroke value. Setting two values separately can make it more convenient to adjust the border range.
-Output type:
-* image
+#### Annotation for LayerStyle nodes:
+1 The layer_image, layer_mask and the background_image(if have input), These three items must be of the same size.。
+
+2 The mask not a mandatory input item. the alpha channel of the image is used by default. If the image input does not include an alpha channel, the entire image's alpha channel will be automatically created. if have masks input simultaneously, the alpha channel will be overwrite by the mask.
+
+3 The blend mode include **_normal, multply, screen, add, subtract, difference, darker_** and **_lighter_**.
+
+4 The RGB color described by hexadecimal RGB format, like '#FA3D86'.
+
+# LayerMask
+
+### MaskPreview:
+Preview the input mask
+
+
+### MaskInvert:
+Invert the mask
+
+
+# LayerUtility
### ImageBlend:
Composit layer image and background image, multiple blend modes are available for option, and transparency can be set.
@@ -98,9 +111,6 @@ Node options:
* blend_mode3: Blending mode.
* opacity: Opacity of blend.
-Output type:
-* image
-
### ImageOpacity:
Adjust image opacity

@@ -111,27 +121,6 @@ Node option:
* invert_mask: Whether to reverse the mask.
* opacity: Opacity of image.
-Output type:
-* image(RGBA)
-* mask
-
-
-### MaskPreview:
-Preview the input mask
-
-
-input:mask
-
-### MaskInvert:
-Invert the mask
-
-
-Input:
-* mask
-
-Output type:
-* mask
-
### ColorPicker:
Modify web extensions from [mtb nodes](https://github.com/melMass/comfy_mtb). Select colors on the color palette and output RGB values.

@@ -142,24 +131,20 @@ Node options:
Output Type:
* string
+# LayerUtility
-### Annotation:
-1 The layer_image, layer_mask and the background_image(if have input), These three items must be of the same size.。
+### MotionBlur:
+Make the image motion blur
-2 The mask not a mandatory input item. the alpha channel of the image is used by default. If the image input does not include an alpha channel, the entire image's alpha channel will be automatically created. if have masks input simultaneously, the alpha channel will be overwrite by the mask.
-
-3 The blend mode include **_normal, multply, screen, add, subtract, difference, darker_** and **_lighter_**.
-
-4 The RGB color described by hexadecimal RGB format, like '#FA3D86'.
+Node options:
+* angle: The angle of blur.
+* blur: The size of blur.
## Example workflow
image Some JSON workflow files in the workflow directory, that is example for ComfyUI.
## The following tasks are in the planned list
-* Inner Shadow
-* Inner Glow
-* Texture
* Color Overlay
* Gradient Overlay
diff --git a/README_CN.MD b/README_CN.MD
index 892c8c1..1679a58 100644
--- a/README_CN.MD
+++ b/README_CN.MD
@@ -1,10 +1,13 @@
# ComfyUI Layer Style£º
ComfyUI²å¼þ£¬Í¨¹ýÒ»×é½ÚµãʵÏÖ·ÂÕÕAdobe PhotoshopµÄͼ²ãÑùʽ¡£
-µ±Ç°ÒÑÍê³ÉDrop ShadowºÍOuterGlow½ÚµãºÍһЩ¸¨Öú½Úµã£¬ºóÐø¹¤×÷½øÐÐÖС£
+ÒÑÍê³ÉµÄ½ÚµãÈçÏ£¬ºóÐø¹¤×÷½øÐÐÖС£
+
## ¸üÐÂ˵Ã÷£º
-* OuterGlow½ÚµãÖØ´óÐ޸ģ¬Ôö¼ÓÁÁ¶È¡¢µÆ¹âÑÕÉ«¡¢»Ô¹âÑÕɫѡÏî¡£°üº¬¾É°æ½ÚµãµÄ¹¤×÷Á÷ÐèÊÖ¶¯Ì滻аæ½Úµã¡£
+* Ìí¼ÓInnerGlow, InnerShadow, MotionBlur½Úµã¡£
+* ËùÓÐÒÑÍê³ÉµÄ½ÚµãÖØÐÂÃüÃû£¬½Úµã·ÖΪ4×飺LayerStyle, LayerMask, LayerUtility, LayerFilter¡£ÒòÎªÖØÐÂÃüÃû£¬°üº¬¾É°æ½ÚµãµÄ¹¤×÷Á÷ÐèÊÖ¶¯Ì滻аæ½Úµã¡£
+* OuterGlow½ÚµãÐ޸ģ¬Ôö¼ÓÁÁ¶È¡¢µÆ¹âÑÕÉ«¡¢»Ô¹âÑÕɫѡÏî¡£
* Ìí¼ÓMaskInvert½Úµã¡£
* Ìí¼ÓStroke½Úµã¡£
* Ìí¼ÓMaskPreview½Úµã¡£
@@ -14,13 +17,12 @@ ComfyUI
* Ìí¼ÓOuterGlow½Úµã¡£
* Ê׸ö½ÚµãDropShadowÌá½»¡£
-## ½Úµã˵Ã÷£º
+# LayerStyle
### DropShadow:
Éú³ÉÒõÓ°¡£

-
½ÚµãÑ¡Ïî˵Ã÷£º

* background_image1: ±³¾°Í¼Ïñ¡£
@@ -35,10 +37,6 @@ ComfyUI
* blur£ºÒõÓ°Ä£ºý³Ì¶È¡£
* shadow_color4: ÒõÓ°ÑÕÉ«¡£
-
-Êä³ö£º
-* image
-
### OuterGlow£º
Éú³ÉÍâ·¢¹â¡£

@@ -57,10 +55,6 @@ ComfyUI
* light_color4: ·¢¹âÖÐÐÄÑÕÉ«¡£
* glow_colo4: »Ô¹âÍâΧÑÕÉ«¡£
-
-Êä³ö£º
-* image
-
### Stroke£º
Éú³ÉÃè±ß¡£

@@ -73,15 +67,28 @@ ComfyUI
* invert_mask: ÊÇ·ñ·´×ªÕÚÕÖ¡£
* blend_mode3: Ãè±ßµÄ»ìºÏģʽ¡£
* opacity: ²»Í¸Ã÷¶È¡£
-* inner_stroke*: Ãè±ßÏòÄÚÊÕËõ·ù¶È¡£
-* outer_stroke*£ºÃè±ßÏòÍâÀ©ÕÅ·ù¶È¡£
+* stroke_grow: Ãè±ßÀ©ÕÅ/ÊÕËõ·ù¶È£¬ÕýÖµÊÇÀ©ÕÅ£¬¸ºÖµÊÇÊÕËõ¡£
+* stroke_width£ºÃè±ß¿í¶È¡£
* stroke_color4: Ãè±ßÑÕÉ«¡£
-*Ãè±ßµÄ¿í¶ÈµÈÓÚÊÕËõÖµ¼ÓÉÏÀ©ÕÅÖµ¡£Á½¸öÖµ·Ö¿ªÉèÖÃÄܸü·½±ãµÄµ÷Õû±ß¿ò·¶Î§¡£
+
+#### ½ÚµãÑ¡Ïî×¢½â£º
+1 image¡¢maskºÍbackground_image(Èç¹ûÓÐÊäÈë)ÕâÈýÏî±ØÐëÊÇÏàͬµÄ³ß´ç¡£
+2 mask²»ÊDZØÐëµÄÊäÈëÏĬÈÏʹÓÃimageµÄalphaͨµÀ£¬Èç¹ûimageÊäÈë²»°üº¬alphaͨµÀ½«×Ô¶¯´´½¨Õû¸öͼÏñµÄalphaͨµÀ¡£Èç¹ûÊäÈëmask£¬Ô±¾µÄalphaͨµÀ½«±»mask¸²¸Ç¡£
+3: »ìºÏģʽ°üÀ¨normal¡¢multply¡¢screen¡¢add¡¢subtract¡¢difference¡¢darkerºÍlighter¡£
+4: ÑÕɫʹÓÃ16½øÖÆRGB×Ö·û´®¸ñʽÃèÊö£¬ÀýÈç '#FA3D86'¡£
+
+# LayerMask
+
+### MaskPreview:
+Ô¤ÀÀmask
+
+
+### MaskInvert:
+mask·´×ª
-Êä³ö£º
-* image
+# LayerUtility
### ImageBlend£º
ÓÃÓںϳÉͼ²ã£¬Ìṩ¶àÖÖ»ìºÏģʽ¹©Ñ¡Ôñ£¬¿ÉÉèÖÃ͸Ã÷¶È¡£
@@ -96,10 +103,6 @@ ComfyUI
* blend_mode3: ͼ²ã»ìºÏģʽ¡£
* opacity: ²»Í¸Ã÷¶È¡£
-
-Êä³ö£º
-* image
-
### ImageOpacity:
µ÷ÕûͼÏñ²»Í¸Ã÷¶È¡£

@@ -110,28 +113,6 @@ ComfyUI
* invert_mask: ÊÇ·ñ·´×ªÕÚÕÖ¡£
* opacity: ²»Í¸Ã÷¶È¡£
-Êä³ö£º
-* image(RGBA)
-* mask
-
-### MaskPreview:
-Ô¤ÀÀmask
-
-
-ÊäÈ룺
-* mask
-
-### MaskInvert:
-mask·´×ª
-
-
-ÊäÈ룺
-* mask
-
-Êä³ö£º
-* mask
-
-
### ColorPicker:
ÔÚÉ«°åÉÏѡȡÑÕÉ«²¢Êä³ö¡£
¸Ä×Ô[mtb nodes](https://github.com/melMass/comfy_mtb)µÄweb extensions¡£
@@ -143,13 +124,15 @@ mask
Êä³ö£º
* string
+# LayerUtility
+### MotionBlur:
+Ô˶¯Ä£ºý¡£
+
+½ÚµãÑ¡Ïî˵Ã÷£º
+* angle: Ä£ºý½Ç¶È¡£
+* blur: Ä£ºý´óС¡£
-### ½ÚµãÑ¡Ïî×¢½â£º
-1 image¡¢maskºÍbackground_image(Èç¹ûÓÐÊäÈë)ÕâÈýÏî±ØÐëÊÇÏàͬµÄ³ß´ç¡£
-2 mask²»ÊDZØÐëµÄÊäÈëÏĬÈÏʹÓÃimageµÄalphaͨµÀ£¬Èç¹ûimageÊäÈë²»°üº¬alphaͨµÀ½«×Ô¶¯´´½¨Õû¸öͼÏñµÄalphaͨµÀ¡£Èç¹ûÊäÈëmask£¬Ô±¾µÄalphaͨµÀ½«±»mask¸²¸Ç¡£
-3: »ìºÏģʽ°üÀ¨normal¡¢multply¡¢screen¡¢add¡¢subtract¡¢difference¡¢darkerºÍlighter¡£
-4: ÑÕɫʹÓÃ16½øÖÆRGB×Ö·û´®¸ñʽÃèÊö£¬ÀýÈç '#FA3D86'¡£
## ʹÓÃʾÀý£º
@@ -157,13 +140,9 @@ mask
## ÒÔϹ¤×÷Ôڼƻ®ÁбíÖÐ
-* Inner Shadow
-* Inner Glow
-* Texture
* Color Overlay
* Gradient Overlay
-*
## °²×°·½·¨£º
* ÔÚCompyUI²å¼þĿ¼(ÀýÈç¡°CompyUI\custom_nodes\¡±)Öдò¿ªcmd´°¿Ú£¬¼üÈë```git clone https://github.com/chflame163/ComfyUI_LayerStyle.git```°²×°¡£»òÕßÏÂÔØ½âѹzipÎļþ£¬½«µÃµ½µÄÎļþ¼Ð¸´ÖƵ½ ComfyUI\custom_nodes\
diff --git a/image/color_picker.png b/image/color_picker.png
index af1530c..6bade89 100644
Binary files a/image/color_picker.png and b/image/color_picker.png differ
diff --git a/image/drop_shadow_example.png b/image/drop_shadow_example.png
index 5756603..4c64938 100644
Binary files a/image/drop_shadow_example.png and b/image/drop_shadow_example.png differ
diff --git a/image/image_blend_example.png b/image/image_blend_example.png
index 4340488..519e77e 100644
Binary files a/image/image_blend_example.png and b/image/image_blend_example.png differ
diff --git a/image/image_blend_node.png b/image/image_blend_node.png
index bc77c2d..04da7eb 100644
Binary files a/image/image_blend_node.png and b/image/image_blend_node.png differ
diff --git a/image/image_opacity_example.png b/image/image_opacity_example.png
index d9e30f9..29994b0 100644
Binary files a/image/image_opacity_example.png and b/image/image_opacity_example.png differ
diff --git a/image/inner_glow_example.png b/image/inner_glow_example.png
new file mode 100644
index 0000000..f7321c9
Binary files /dev/null and b/image/inner_glow_example.png differ
diff --git a/image/inner_shadow_example.png b/image/inner_shadow_example.png
new file mode 100644
index 0000000..dd9f2d3
Binary files /dev/null and b/image/inner_shadow_example.png differ
diff --git a/image/mask_invert.png b/image/mask_invert.png
index 3469ed1..923b3a8 100644
Binary files a/image/mask_invert.png and b/image/mask_invert.png differ
diff --git a/image/motion_blur_example.png b/image/motion_blur_example.png
new file mode 100644
index 0000000..b98dead
Binary files /dev/null and b/image/motion_blur_example.png differ
diff --git a/image/outer_glow_example.png b/image/outer_glow_example.png
index 9fe2252..8907e6c 100644
Binary files a/image/outer_glow_example.png and b/image/outer_glow_example.png differ
diff --git a/image/stroke_example.png b/image/stroke_example.png
index b9e354b..775942f 100644
Binary files a/image/stroke_example.png and b/image/stroke_example.png differ
diff --git a/image/stroke_node.png b/image/stroke_node.png
index 58decdc..8d050d8 100644
Binary files a/image/stroke_node.png and b/image/stroke_node.png differ
diff --git a/image/title.png b/image/title.png
index 4bdaad7..8e3c36d 100644
Binary files a/image/title.png and b/image/title.png differ
diff --git a/py/color_picker.py b/py/color_picker.py
index 8755ff1..742d862 100644
--- a/py/color_picker.py
+++ b/py/color_picker.py
@@ -23,10 +23,10 @@ class ColorPicker:
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("value",)
FUNCTION = 'picker'
- CATEGORY = '😺dzNodes'
+ CATEGORY = '😺dzNodes/LayerUtility'
OUTPUT_NODE = True
- def picker(self, color, mode,):
+ def picker(self, color, mode):
ret = color
if ret == 'white':
ret = "#FFFFFF"
@@ -36,9 +36,9 @@ class ColorPicker:
NODE_CLASS_MAPPINGS = {
- "LayerStyle_ColorPicker": ColorPicker
+ "LayerUtility: ColorPicker": ColorPicker
}
NODE_DISPLAY_NAME_MAPPINGS = {
- "LayerStyle_ColorPicker": "LayerStyle: ColorPicker"
+ "LayerUtility: ColorPicker": "LayerUtility: ColorPicker"
}
\ No newline at end of file
diff --git a/py/drop_shadow.py b/py/drop_shadow.py
index 44af2d4..dc65e15 100644
--- a/py/drop_shadow.py
+++ b/py/drop_shadow.py
@@ -15,10 +15,10 @@ class DropShadow:
"invert_mask": ("BOOLEAN", {"default": True}), # �转mask
"blend_mode": (chop_mode,), # 混�模�
"opacity": ("INT", {"default": 50, "min": 0, "max": 100, "step": 1}), # �明度
- "distance_x": ("INT", {"default": 5, "min": -9999, "max": 9999, "step": 1}), # x_�移
- "distance_y": ("INT", {"default": 5, "min": -9999, "max": 9999, "step": 1}), # y_�移
- "grow": ("INT", {"default": 2, "min": -9999, "max": 9999, "step": 1}), # 扩å¼
- "blur": ("INT", {"default": 15, "min": 0, "max": 100, "step": 1}), # 模糊
+ "distance_x": ("INT", {"default": 25, "min": -9999, "max": 9999, "step": 1}), # x_�移
+ "distance_y": ("INT", {"default": 25, "min": -9999, "max": 9999, "step": 1}), # y_�移
+ "grow": ("INT", {"default": 6, "min": -9999, "max": 9999, "step": 1}), # 扩å¼
+ "blur": ("INT", {"default": 18, "min": 0, "max": 100, "step": 1}), # 模糊
"shadow_color": ("STRING", {"default": "#000000"}), # 背景颜色
},
"optional": {
@@ -26,20 +26,18 @@ class DropShadow:
}
}
- log('DropShadow Processing...')
- # RETURN_TYPES = ("IMAGE", "MASK",)
- # RETURN_NAMES = ("image", "shadow_mask",)
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("image",)
FUNCTION = 'drop_shadow'
- CATEGORY = '😺dzNodes'
+ CATEGORY = '😺dzNodes/LayerStyle'
OUTPUT_NODE = True
def drop_shadow(self, background_image, layer_image,
invert_mask, blend_mode, opacity, distance_x, distance_y,
grow, blur, shadow_color,
- layer_mask=None,
+ layer_mask=None
):
+
distance_x = -distance_x
distance_y = -distance_y
_canvas = tensor2pil(background_image).convert('RGB')
@@ -50,23 +48,18 @@ class DropShadow:
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) #æ‰©å¼ ï¼Œæ¨¡ç³Š
-
# ��阴影
shadow_color = Image.new("RGB", _layer.size, color=shadow_color)
alpha = tensor2pil(shadow_mask).convert('L')
_shadow = chop_image(_canvas, shadow_color, blend_mode, opacity)
_canvas.paste(_shadow, mask=alpha)
-
# ��layer
_canvas.paste(_layer, mask=_mask)
-
ret_image = _canvas
- # ret_mask = shadow_mask
- # return (pil2tensor(ret_image), ret_mask,)
+ log('DropShadow Processed.')
return (pil2tensor(ret_image),)
NODE_CLASS_MAPPINGS = {
diff --git a/py/image_blend.py b/py/image_blend.py
index 9c0fb87..6681602 100644
--- a/py/image_blend.py
+++ b/py/image_blend.py
@@ -24,15 +24,14 @@ class ImageBlend:
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("image",)
FUNCTION = 'image_blend'
- CATEGORY = '😺dzNodes'
+ CATEGORY = '😺dzNodes/LayerUtility'
OUTPUT_NODE = True
def image_blend(self, background_image, layer_image,
invert_mask, blend_mode, opacity,
- layer_mask=None,
+ layer_mask=None
):
- log('ImageBlend Processing...')
_canvas = tensor2pil(background_image).convert('RGB')
_layer = tensor2pil(layer_image).convert('RGB')
_mask = tensor2pil(layer_image).convert('RGBA').split()[-1]
@@ -40,18 +39,17 @@ class ImageBlend:
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
-
+ log('ImageBlend Processed.')
return (pil2tensor(ret_image),)
NODE_CLASS_MAPPINGS = {
- "LayerStyle_ImageBlend": ImageBlend
+ "LayerUtility: ImageBlend": ImageBlend
}
NODE_DISPLAY_NAME_MAPPINGS = {
- "LayerStyle_ImageBlend": "LayerStyle: ImageBlend"
+ "LayerUtility: ImageBlend": "LayerUtility: ImageBlend"
}
\ No newline at end of file
diff --git a/py/image_opacity.py b/py/image_opacity.py
index cb104c0..4b7f889 100644
--- a/py/image_opacity.py
+++ b/py/image_opacity.py
@@ -19,11 +19,10 @@ class ImageOpacity:
}
}
- log('ImageOpacity Processing...')
RETURN_TYPES = ("IMAGE", "MASK",)
RETURN_NAMES = ("image", "mask",)
FUNCTION = 'image_opacity'
- CATEGORY = '😺dzNodes'
+ CATEGORY = '😺dzNodes/LayerUtility'
OUTPUT_NODE = True
def image_opacity(self, image, opacity, invert_mask,
@@ -51,13 +50,13 @@ class ImageOpacity:
ret_image = Image.merge('RGBA', (R, G, B, ImageChops.invert(ret_mask)))
else:
ret_image = Image.merge('RGBA', (R, G, B, ret_mask))
-
+ log('ImageOpacity Processed.')
return (pil2tensor(ret_image), image2mask(ret_mask),)
NODE_CLASS_MAPPINGS = {
- "LayerStyle_ImageOpacity": ImageOpacity
+ "LayerUtility: ImageOpacity": ImageOpacity
}
NODE_DISPLAY_NAME_MAPPINGS = {
- "LayerStyle_ImageOpacity": "LayerStyle: ImageOpacity"
+ "LayerUtility: ImageOpacity": "LayerUtility: ImageOpacity"
}
\ No newline at end of file
diff --git a/py/imagefunc.py b/py/imagefunc.py
index 7140c4d..e4d8cdc 100644
--- a/py/imagefunc.py
+++ b/py/imagefunc.py
@@ -12,6 +12,8 @@ def log(message):
name = 'LayerStyle'
print(f"# 😺dzNodes: {name} -> {message}")
+'''Converter'''
+
def cv22pil(cv2_img:np.ndarray) -> Image:
cv2_img = cv2.cvtColor(cv2_img, cv2.COLOR_BGR2RGB)
return Image.fromarray(cv2_img)
@@ -54,9 +56,7 @@ def mask2image(mask:torch.Tensor) -> Image:
_image, Image.new("RGBA", _mask.size, color='black'), _mask)
return _image
-def mask_invert(mask:torch.Tensor) -> torch.Tensor:
- _image = mask2image(mask)
- return image2mask(ImageChops.invert(_image))
+'''Image Functions'''
def shift_image(image:Image, distance_x:int, distance_y:int) -> Image:
bkcolor = (0, 0, 0)
@@ -65,14 +65,13 @@ def shift_image(image:Image, distance_x:int, distance_y:int) -> Image:
ret_image = Image.new('RGB', size=(width, height), color=bkcolor)
for x in range(width):
for y in range(height):
- if x > -distance_x and y > -distance_y:
- if x + distance_x < width and y + distance_y < height:
+ if x > -distance_x and y > -distance_y: # 防æ¢å›žè½¬
+ if x + distance_x < width and y + distance_y < height: # 防æ¢è¶Šç•Œ
pixel = image.getpixel((x + distance_x, y + distance_y))
ret_image.putpixel((x, y), pixel)
return ret_image
def chop_image(background_image:Image, layer_image:Image, blend_mode:str, opacity:int) -> Image:
-
ret_image = background_image
if blend_mode == 'normal':
ret_image = layer_image
@@ -90,16 +89,43 @@ def chop_image(background_image:Image, layer_image:Image, blend_mode:str, opacit
ret_image = ImageChops.darker(background_image, layer_image)
if blend_mode == 'lighter':
ret_image = ImageChops.lighter(background_image, layer_image)
-
# opacity
if opacity == 0:
ret_image = background_image
elif opacity < 100:
alpha = 1.0 - float(opacity) / 100
ret_image = Image.blend(ret_image, background_image, alpha)
-
return ret_image
+def remove_background(image:Image, mask:Image, color:str) -> Image:
+ width = image.width
+ height = image.height
+ ret_image = Image.new('RGB', size=(width, height), color=color)
+ ret_image.paste(image, mask=mask)
+ return ret_image
+
+def motion_blur(image:Image, angle:int, blur:int) -> Image:
+ angle += 45
+ blur *= 5
+ image = np.array(pil2cv2(image))
+ M = cv2.getRotationMatrix2D((blur / 2, blur / 2), angle, 1)
+ motion_blur_kernel = np.diag(np.ones(blur))
+ motion_blur_kernel = cv2.warpAffine(motion_blur_kernel, M, (blur, blur))
+ motion_blur_kernel = motion_blur_kernel / blur
+ blurred = cv2.filter2D(image, -1, motion_blur_kernel)
+ # convert to uint8
+ cv2.normalize(blurred, blurred, 0, 255, cv2.NORM_MINMAX)
+ blurred = np.array(blurred, dtype=np.uint8)
+ ret_image = cv22pil(blurred)
+ return ret_image
+
+def direction_blur(image:Image, angle:int, blur:int, color:str) -> Image:
+
+ ret_image = image
+ return ret_image
+
+'''Mask Functions'''
+
def expand_mask(mask:torch.Tensor, grow:int, blur:int) -> torch.Tensor:
# grow
c = 0
@@ -122,54 +148,50 @@ def expand_mask(mask:torch.Tensor, grow:int, blur:int) -> torch.Tensor:
pil_image = tensor2pil(tensor.cpu().detach())
pil_image = pil_image.filter(ImageFilter.GaussianBlur(blur))
out[idx] = pil2tensor(pil_image)
-
ret_mask = torch.cat(out, dim=0)
return ret_mask
-def remove_background(image:Image, mask:Image, color:str) -> Image:
- width = image.width
- height = image.height
- ret_image = Image.new('RGB', size=(width, height), color=color)
- ret_image.paste(image, mask=mask)
- return ret_image
+def mask_invert(mask:torch.Tensor) -> torch.Tensor:
+ _image = mask2image(mask)
+ return image2mask(ImageChops.invert(_image))
-def subtract_mask(masks_a, masks_b):
+def subtract_mask(masks_a:torch.Tensor, masks_b:torch.Tensor) -> torch.Tensor:
return torch.clamp(masks_a - masks_b, 0, 255)
-def RGB_to_Hex(RGB):
- # _rgb = tuple(map(int, RGB[1:-1].split(',')))
- _rgb = RGB
+'''Color Functions'''
+
+def RGB_to_Hex(RGB) -> str:
color = '#'
- for i in _rgb:
+ for i in RGB:
num = int(i)
color += str(hex(num))[-2:].replace('x', '0').upper()
return color
-def Hex_to_RGB(inhex):
+def Hex_to_RGB(inhex) -> tuple:
rval = inhex[1:3]
gval = inhex[3:5]
bval = inhex[5:]
rgb = (int(rval, 16), int(gval, 16), int(bval, 16))
return tuple(rgb)
-def step_value(start_value, end_value, total_step, step):
- factor = step / total_step
- return int((end_value - start_value) * factor) + start_value
+'''Value Functions'''
-def step_color(start_color, end_color, total_step, step):
+def step_value(start_value, end_value, total_step, step) -> float: # 按当å‰�æ¥æ•°åœ¨æ€»æ¥æ•°ä¸çš„ä½�置返回比例值
+ factor = step / total_step
+ return (end_value - start_value) * factor + start_value
+
+def step_color(start_color, end_color, total_step, step): # 按当å‰�æ¥æ•°åœ¨æ€»æ¥æ•°ä¸çš„ä½�置返回比例颜色
if isinstance(start_color, str):
start_color = tuple(Hex_to_RGB(start_color))
-
if isinstance(end_color, str):
end_color = tuple(Hex_to_RGB(end_color))
-
start_R, start_G, start_B = start_color[0], start_color[1], start_color[2]
end_R, end_G, end_B = end_color[0], end_color[1], end_color[2]
- ret_color = (step_value(start_R, end_R, total_step, step),
- step_value(start_G, end_G, total_step, step),
- step_value(start_B, end_B, total_step, step),
+ ret_color = (int(step_value(start_R, end_R, total_step, step)),
+ int(step_value(start_G, end_G, total_step, step)),
+ int(step_value(start_B, end_B, total_step, step)),
)
if isinstance(start_color, str):
return RGB_to_Hex(ret_color)
else:
- return ret_color
\ No newline at end of file
+ return ret_color
diff --git a/py/inner_glow.py b/py/inner_glow.py
new file mode 100644
index 0000000..eee6107
--- /dev/null
+++ b/py/inner_glow.py
@@ -0,0 +1,75 @@
+from .imagefunc import *
+
+class InnerGlow:
+
+ def __init__(self):
+ pass
+
+ @classmethod
+ def INPUT_TYPES(self):
+ chop_mode = ['screen', 'add', 'lighter', 'normal', 'multply', 'subtract','difference','darker']
+ 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}), # �明度
+ "brightness": ("INT", {"default": 5, "min": 2, "max": 20, "step": 1}), # è¿ä»£
+ "glow_range": ("INT", {"default": 48, "min": -9999, "max": 9999, "step": 1}), # 扩å¼
+ "blur": ("INT", {"default": 25, "min": 0, "max": 9999, "step": 1}), # 扩å¼
+ "light_color": ("STRING", {"default": "#FFBF30"}), # å…‰æº�ä¸å¿ƒé¢œè‰²
+ "glow_color": ("STRING", {"default": "#FE0000"}), # 辉光外围颜色
+ },
+ "optional": {
+ "layer_mask": ("MASK",), #
+ }
+ }
+
+ RETURN_TYPES = ("IMAGE",)
+ RETURN_NAMES = ("image",)
+ FUNCTION = 'inner_glow'
+ CATEGORY = '😺dzNodes/LayerStyle'
+ OUTPUT_NODE = True
+
+ def inner_glow(self, background_image, layer_image,
+ invert_mask, blend_mode, opacity,
+ brightness, glow_range, blur, light_color, 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 layer_mask is not None:
+ if invert_mask:
+ layer_mask = 1 - layer_mask
+ _mask = mask2image(layer_mask).convert('L')
+
+ blur_factor = blur / 20.0
+ grow = glow_range
+ inner_mask = _mask
+ for x in range(brightness):
+ blur = int(grow * blur_factor)
+ _color = step_color(glow_color, light_color, brightness, x)
+ glow_mask = expand_mask(image2mask(inner_mask), -grow, blur) #æ‰©å¼ ï¼Œæ¨¡ç³Š
+ # ��glow
+ color_image = Image.new("RGB", _layer.size, color=_color)
+ alpha = tensor2pil(mask_invert(glow_mask)).convert('L')
+ _glow = chop_image(_layer, color_image, blend_mode, int(step_value(1, opacity, brightness, x)))
+ _layer.paste(_glow, mask=alpha)
+ grow = grow - int(glow_range/brightness)
+ # ��layer
+ _layer.paste(_canvas, mask=ImageChops.invert(_mask))
+ ret_image = _layer
+ log('InnerGLow Advance Processed.')
+ return (pil2tensor(ret_image),)
+
+NODE_CLASS_MAPPINGS = {
+ "LayerStyle: InnerGlow": InnerGlow
+}
+
+NODE_DISPLAY_NAME_MAPPINGS = {
+ "LayerStyle: InnerGlow": "LayerStyle: InnerGlow"
+}
\ No newline at end of file
diff --git a/py/inner_shadow.py b/py/inner_shadow.py
new file mode 100644
index 0000000..c60622a
--- /dev/null
+++ b/py/inner_shadow.py
@@ -0,0 +1,72 @@
+from .imagefunc import *
+
+class InnerShadow:
+
+ 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": 50, "min": 0, "max": 100, "step": 1}), # �明度
+ "distance_x": ("INT", {"default": 5, "min": -9999, "max": 9999, "step": 1}), # x_�移
+ "distance_y": ("INT", {"default": 5, "min": -9999, "max": 9999, "step": 1}), # y_�移
+ "grow": ("INT", {"default": 2, "min": -9999, "max": 9999, "step": 1}), # 扩å¼
+ "blur": ("INT", {"default": 15, "min": 0, "max": 100, "step": 1}), # 模糊
+ "shadow_color": ("STRING", {"default": "#000000"}), # 背景颜色
+ },
+ "optional": {
+ "layer_mask": ("MASK",), #
+ }
+ }
+
+
+ RETURN_TYPES = ("IMAGE",)
+ RETURN_NAMES = ("image",)
+ FUNCTION = 'inner_shadow'
+ CATEGORY = '😺dzNodes/LayerStyle'
+ OUTPUT_NODE = True
+
+ def inner_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
+ _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) #æ‰©å¼ ï¼Œæ¨¡ç³Š
+ # ��阴影
+ shadow_color = Image.new("RGB", _layer.size, color=shadow_color)
+ alpha = tensor2pil(shadow_mask).convert('L')
+ _shadow = chop_image(_layer, shadow_color, blend_mode, opacity)
+ _layer.paste(_shadow, mask=ImageChops.invert(alpha))
+ # ��layer
+ _canvas.paste(_layer, mask=_mask)
+ ret_image = _canvas
+ log('InnerShadow Processed.')
+ return (pil2tensor(ret_image),)
+
+NODE_CLASS_MAPPINGS = {
+ "LayerStyle: InnerShadow": InnerShadow
+}
+
+NODE_DISPLAY_NAME_MAPPINGS = {
+ "LayerStyle: InnerShadow": "LayerStyle: InnerShadow"
+}
\ No newline at end of file
diff --git a/py/mask_invert.py b/py/mask_invert.py
index c11a549..6868e61 100644
--- a/py/mask_invert.py
+++ b/py/mask_invert.py
@@ -18,17 +18,17 @@ class MaskInvert:
RETURN_TYPES = ("MASK",)
RETURN_NAMES = ("mask",)
FUNCTION = 'mask_invert'
- CATEGORY = '😺dzNodes'
+ CATEGORY = '😺dzNodes/LayerMask'
OUTPUT_NODE = True
- def mask_invert(self,mask,):
+ def mask_invert(self,mask):
return (mask_invert(mask),)
NODE_CLASS_MAPPINGS = {
- "LayerStyle_MaskInvert": MaskInvert
+ "LayerMask: MaskInvert": MaskInvert
}
NODE_DISPLAY_NAME_MAPPINGS = {
- "LayerStyle_MaskInvert": "LayerStyle: MaskInvert"
+ "LayerMask: MaskInvert": "LayerMask: MaskInvert"
}
\ No newline at end of file
diff --git a/py/mask_preview.py b/py/mask_preview.py
index 1462144..1d9a49d 100644
--- a/py/mask_preview.py
+++ b/py/mask_preview.py
@@ -17,16 +17,16 @@ class MaskPreview(SaveImage):
}
FUNCTION = "mask_preview"
- CATEGORY = '😺dzNodes'
+ CATEGORY = '😺dzNodes/LayerMask'
def mask_preview(self, mask):
preview = mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])).movedim(1, -1).expand(-1, -1, -1, 3)
return self.save_images(preview, "MaskPreview")
NODE_CLASS_MAPPINGS = {
- "LayerStyle_MaskPreview": MaskPreview
+ "LayerMask: MaskPreview": MaskPreview
}
NODE_DISPLAY_NAME_MAPPINGS = {
- "LayerStyle_MaskPreview": "LayerStyle: MaskPreview"
+ "LayerMask: MaskPreview": "LayerMask: MaskPreview"
}
\ No newline at end of file
diff --git a/py/motion_blur.py b/py/motion_blur.py
new file mode 100644
index 0000000..927a96c
--- /dev/null
+++ b/py/motion_blur.py
@@ -0,0 +1,40 @@
+from .imagefunc import *
+
+class MotionBlur:
+
+ def __init__(self):
+ pass
+
+ @classmethod
+ def INPUT_TYPES(self):
+
+ return {
+ "required": {
+ "image": ("IMAGE", ), #
+ "angle": ("INT", {"default": 0, "min": -90, "max": 90, "step": 1}), # 角度
+ "blur": ("INT", {"default": 20, "min": 1, "max": 999, "step": 1}), # 模糊
+ },
+ "optional": {
+ }
+ }
+
+ RETURN_TYPES = ("IMAGE",)
+ RETURN_NAMES = ("image",)
+ FUNCTION = 'motion_blur'
+ CATEGORY = '😺dzNodes/LayerFilter'
+ OUTPUT_NODE = True
+
+ def motion_blur(self, image, angle, blur):
+
+ _canvas = tensor2pil(image).convert('RGB')
+ ret_image = motion_blur(_canvas, angle, blur)
+ log('MotionBlur Processed.')
+ return (pil2tensor(ret_image),)
+
+NODE_CLASS_MAPPINGS = {
+ "LayerFilter: MotionBlur": MotionBlur
+}
+
+NODE_DISPLAY_NAME_MAPPINGS = {
+ "LayerFilter: MotionBlur": "LayerFilter: MotionBlur"
+}
\ No newline at end of file
diff --git a/py/outer_glow.py b/py/outer_glow.py
index c1f4e5a..aa0aa0e 100644
--- a/py/outer_glow.py
+++ b/py/outer_glow.py
@@ -29,16 +29,15 @@ class OuterGlow:
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("image",)
FUNCTION = 'outer_glow'
- CATEGORY = '😺dzNodes'
+ CATEGORY = '😺dzNodes/LayerStyle'
OUTPUT_NODE = True
def outer_glow(self, background_image, layer_image,
invert_mask, blend_mode, opacity,
brightness, glow_range, blur, light_color, glow_color,
- layer_mask=None,
+ layer_mask=None
):
- log('OuterGLow Advance Processing...')
_canvas = tensor2pil(background_image).convert('RGB')
_layer = tensor2pil(layer_image).convert('RGB')
_mask = tensor2pil(layer_image).convert('RGBA').split()[-1]
@@ -56,14 +55,13 @@ class OuterGlow:
# ��glow
color_image = Image.new("RGB", _layer.size, color=_color)
alpha = tensor2pil(glow_mask).convert('L')
- _glow = chop_image(_canvas, color_image, blend_mode, step_value(1, opacity, brightness, x))
+ _glow = chop_image(_canvas, color_image, blend_mode, int(step_value(1, opacity, brightness, x)))
_canvas.paste(_glow, mask=alpha)
grow = grow - int(glow_range/brightness)
-
# ��layer
_canvas.paste(_layer, mask=_mask)
ret_image = _canvas
-
+ log('OuterGLow Advance Processed.')
return (pil2tensor(ret_image),)
NODE_CLASS_MAPPINGS = {
diff --git a/py/stroke.py b/py/stroke.py
index b9c0aca..5c2e209 100644
--- a/py/stroke.py
+++ b/py/stroke.py
@@ -15,8 +15,8 @@ class Stroke:
"invert_mask": ("BOOLEAN", {"default": True}), # �转mask
"blend_mode": (chop_mode,), # 混�模�
"opacity": ("INT", {"default": 100, "min": 0, "max": 100, "step": 1}), # �明度
- "inner_stroke": ("INT", {"default": 4, "min": 0, "max": 9999, "step": 1}), # 收缩值
- "outer_stroke": ("INT", {"default": 4, "min": 0, "max": 9999, "step": 1}), # æ‰©å¼ å€¼
+ "stroke_grow": ("INT", {"default": 0, "min": -999, "max": 999, "step": 1}), # 收缩值
+ "stroke_width": ("INT", {"default": 8, "min": 0, "max": 999, "step": 1}), # æ‰©å¼ å€¼
"blur": ("INT", {"default": 0, "min": 0, "max": 100, "step": 1}), # 模糊
"stroke_color": ("STRING", {"default": "#FF0000"}), # �边颜色
},
@@ -28,16 +28,15 @@ class Stroke:
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("image",)
FUNCTION = 'stroke'
- CATEGORY = '😺dzNodes'
+ CATEGORY = '😺dzNodes/LayerStyle'
OUTPUT_NODE = True
def stroke(self, background_image, layer_image,
invert_mask, blend_mode, opacity,
- inner_stroke, outer_stroke, blur, stroke_color,
- layer_mask=None,
+ stroke_grow, stroke_width, blur, stroke_color,
+ layer_mask=None
):
- log('Stroke Processing...')
_canvas = tensor2pil(background_image).convert('RGB')
_layer = tensor2pil(layer_image).convert('RGB')
_mask = tensor2pil(layer_image).convert('RGBA').split()[-1]
@@ -46,7 +45,10 @@ class Stroke:
layer_mask = 1 - layer_mask
_mask = mask2image(layer_mask).convert('L')
- inner_mask = expand_mask(image2mask(_mask), -inner_stroke, blur)
+ grow_offset = int(stroke_width / 2)
+ inner_stroke = stroke_grow - grow_offset
+ outer_stroke = inner_stroke + stroke_width
+ inner_mask = expand_mask(image2mask(_mask), inner_stroke, blur)
outer_mask = expand_mask(image2mask(_mask), outer_stroke, blur)
strock_mask = subtract_mask(outer_mask, inner_mask)
color_image = Image.new('RGB', size=_layer.size, color=stroke_color)
@@ -54,12 +56,13 @@ class Stroke:
_canvas.paste(_layer, mask=_mask)
_canvas.paste(blend_image, mask=tensor2pil(strock_mask))
ret_image = _canvas
+ log('Stroke Processed.')
return (pil2tensor(ret_image),)
NODE_CLASS_MAPPINGS = {
- "LayerStyle_Stroke": Stroke
+ "LayerStyle: Stroke": Stroke
}
NODE_DISPLAY_NAME_MAPPINGS = {
- "LayerStyle_Stroke": "LayerStyle: Stroke"
+ "LayerStyle: Stroke": "LayerStyle: Stroke"
}
\ No newline at end of file
diff --git a/workflow/512x512bkgd.jpg b/workflow/512x512bkgd.jpg
index 0ffd73f..3003d5b 100644
Binary files a/workflow/512x512bkgd.jpg and b/workflow/512x512bkgd.jpg differ
diff --git a/workflow/drop_shadow_example.json b/workflow/drop_shadow_example.json
index 4ec4bd8..9becdfa 100644
--- a/workflow/drop_shadow_example.json
+++ b/workflow/drop_shadow_example.json
@@ -1,207 +1,206 @@
-{
- "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": [
- 180,
- -680
- ],
- "size": {
- "0": 315,
- "1": 314
- },
- "flags": {},
- "order": 0,
- "mode": 0,
- "outputs": [
- {
- "name": "IMAGE",
- "type": "IMAGE",
- "links": [
- 55
- ],
- "shape": 3,
- "slot_index": 0
- },
- {
- "name": "MASK",
- "type": "MASK",
- "links": [
- 56
- ],
- "shape": 3,
- "slot_index": 1
- }
- ],
- "properties": {
- "Node name for S&R": "LoadImage"
- },
- "widgets_values": [
- "512x512.png",
- "image"
- ]
- },
- {
- "id": 3,
- "type": "LoadImage",
- "pos": [
- -160,
- -680
- ],
- "size": {
- "0": 315,
- "1": 314
- },
- "flags": {},
- "order": 1,
- "mode": 0,
- "outputs": [
- {
- "name": "IMAGE",
- "type": "IMAGE",
- "links": [
- 54
- ],
- "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"
- ]
- }
- ],
- "links": [
- [
- 54,
- 3,
- 0,
- 22,
- 0,
- "IMAGE"
- ],
- [
- 55,
- 2,
- 0,
- 22,
- 1,
- "IMAGE"
- ],
- [
- 56,
- 2,
- 1,
- 22,
- 2,
- "MASK"
- ],
- [
- 58,
- 22,
- 0,
- 23,
- 0,
- "IMAGE"
- ]
- ],
- "groups": [],
- "config": {},
- "extra": {},
- "version": 0.4
+{
+ "last_node_id": 18,
+ "last_link_id": 35,
+ "nodes": [
+ {
+ "id": 4,
+ "type": "PreviewImage",
+ "pos": [
+ 1360,
+ 390
+ ],
+ "size": [
+ 310.00006103515625,
+ 308.33331298828125
+ ],
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 34
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "PreviewImage"
+ }
+ },
+ {
+ "id": 2,
+ "type": "LoadImage",
+ "pos": [
+ 310,
+ 390
+ ],
+ "size": {
+ "0": 315,
+ "1": 314
+ },
+ "flags": {},
+ "order": 0,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 32
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": null,
+ "shape": 3
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512bk.jpg",
+ "image"
+ ]
+ },
+ {
+ "id": 18,
+ "type": "LayerStyle_DropShadow",
+ "pos": [
+ 1013,
+ 414
+ ],
+ "size": {
+ "0": 315,
+ "1": 266
+ },
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "background_image",
+ "type": "IMAGE",
+ "link": 32
+ },
+ {
+ "name": "layer_image",
+ "type": "IMAGE",
+ "link": 33
+ },
+ {
+ "name": "layer_mask",
+ "type": "MASK",
+ "link": 35
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 34
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerStyle_DropShadow"
+ },
+ "widgets_values": [
+ true,
+ "normal",
+ 50,
+ 25,
+ 25,
+ 6,
+ 18,
+ "#000000"
+ ]
+ },
+ {
+ "id": 15,
+ "type": "LoadImage",
+ "pos": [
+ 660,
+ 399
+ ],
+ "size": {
+ "0": 315,
+ "1": 314
+ },
+ "flags": {},
+ "order": 1,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 33
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": [
+ 35
+ ],
+ "shape": 3,
+ "slot_index": 1
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512 (14).png",
+ "image"
+ ]
+ }
+ ],
+ "links": [
+ [
+ 32,
+ 2,
+ 0,
+ 18,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 33,
+ 15,
+ 0,
+ 18,
+ 1,
+ "IMAGE"
+ ],
+ [
+ 34,
+ 18,
+ 0,
+ 4,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 35,
+ 15,
+ 1,
+ 18,
+ 2,
+ "MASK"
+ ]
+ ],
+ "groups": [],
+ "config": {},
+ "extra": {},
+ "version": 0.4
}
\ No newline at end of file
diff --git a/workflow/image_blend_example.json b/workflow/image_blend_example.json
index f3fb892..34f1873 100644
--- a/workflow/image_blend_example.json
+++ b/workflow/image_blend_example.json
@@ -1,202 +1,426 @@
-{
- "last_node_id": 5,
- "last_link_id": 5,
- "nodes": [
- {
- "id": 1,
- "type": "LoadImage",
- "pos": [
- 327,
- 175
- ],
- "size": {
- "0": 315,
- "1": 314
- },
- "flags": {},
- "order": 0,
- "mode": 0,
- "outputs": [
- {
- "name": "IMAGE",
- "type": "IMAGE",
- "links": [
- 1
- ],
- "shape": 3,
- "slot_index": 0
- },
- {
- "name": "MASK",
- "type": "MASK",
- "links": null,
- "shape": 3
- }
- ],
- "properties": {
- "Node name for S&R": "LoadImage"
- },
- "widgets_values": [
- "512x512bkgd (3).jpg",
- "image"
- ]
- },
- {
- "id": 2,
- "type": "LoadImage",
- "pos": [
- 680,
- 176
- ],
- "size": {
- "0": 315,
- "1": 314
- },
- "flags": {},
- "order": 1,
- "mode": 0,
- "outputs": [
- {
- "name": "IMAGE",
- "type": "IMAGE",
- "links": [
- 2
- ],
- "shape": 3,
- "slot_index": 0
- },
- {
- "name": "MASK",
- "type": "MASK",
- "links": [
- 5
- ],
- "shape": 3,
- "slot_index": 1
- }
- ],
- "properties": {
- "Node name for S&R": "LoadImage"
- },
- "widgets_values": [
- "512x512 (5).png",
- "image"
- ]
- },
- {
- "id": 3,
- "type": "LayerStyle_ImageBlend",
- "pos": [
- 1041,
- 203
- ],
- "size": {
- "0": 315,
- "1": 146
- },
- "flags": {},
- "order": 2,
- "mode": 0,
- "inputs": [
- {
- "name": "background_image",
- "type": "IMAGE",
- "link": 1
- },
- {
- "name": "layer_image",
- "type": "IMAGE",
- "link": 2
- },
- {
- "name": "layer_mask",
- "type": "MASK",
- "link": 5
- }
- ],
- "outputs": [
- {
- "name": "image",
- "type": "IMAGE",
- "links": [
- 4
- ],
- "shape": 3,
- "slot_index": 0
- }
- ],
- "properties": {
- "Node name for S&R": "LayerStyle_ImageBlend"
- },
- "widgets_values": [
- true,
- "subtract",
- 50
- ]
- },
- {
- "id": 4,
- "type": "SaveImage",
- "pos": [
- 1401,
- 195
- ],
- "size": [
- 315,
- 270
- ],
- "flags": {},
- "order": 3,
- "mode": 0,
- "inputs": [
- {
- "name": "images",
- "type": "IMAGE",
- "link": 4
- }
- ],
- "properties": {},
- "widgets_values": [
- "ComfyUI"
- ]
- }
- ],
- "links": [
- [
- 1,
- 1,
- 0,
- 3,
- 0,
- "IMAGE"
- ],
- [
- 2,
- 2,
- 0,
- 3,
- 1,
- "IMAGE"
- ],
- [
- 4,
- 3,
- 0,
- 4,
- 0,
- "IMAGE"
- ],
- [
- 5,
- 2,
- 1,
- 3,
- 2,
- "MASK"
- ]
- ],
- "groups": [],
- "config": {},
- "extra": {},
- "version": 0.4
+{
+ "last_node_id": 10,
+ "last_link_id": 17,
+ "nodes": [
+ {
+ "id": 6,
+ "type": "LayerUtility: ImageBlend",
+ "pos": [
+ 1030,
+ 370
+ ],
+ "size": {
+ "0": 315,
+ "1": 146
+ },
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "background_image",
+ "type": "IMAGE",
+ "link": 6
+ },
+ {
+ "name": "layer_image",
+ "type": "IMAGE",
+ "link": 7
+ },
+ {
+ "name": "layer_mask",
+ "type": "MASK",
+ "link": 8
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 9
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerUtility: ImageBlend"
+ },
+ "widgets_values": [
+ true,
+ "subtract",
+ 31
+ ]
+ },
+ {
+ "id": 4,
+ "type": "SaveImage",
+ "pos": [
+ 1370,
+ 120
+ ],
+ "size": [
+ 282.3333740234375,
+ 289.66668701171875
+ ],
+ "flags": {},
+ "order": 5,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 9
+ }
+ ],
+ "properties": {},
+ "widgets_values": [
+ "ComfyUI"
+ ]
+ },
+ {
+ "id": 7,
+ "type": "LayerUtility: ImageBlend",
+ "pos": [
+ 1030,
+ 570
+ ],
+ "size": {
+ "0": 315,
+ "1": 146
+ },
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "background_image",
+ "type": "IMAGE",
+ "link": 10
+ },
+ {
+ "name": "layer_image",
+ "type": "IMAGE",
+ "link": 11
+ },
+ {
+ "name": "layer_mask",
+ "type": "MASK",
+ "link": 12
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 13
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerUtility: ImageBlend"
+ },
+ "widgets_values": [
+ true,
+ "lighter",
+ 100
+ ]
+ },
+ {
+ "id": 2,
+ "type": "LoadImage",
+ "pos": [
+ 670,
+ 370
+ ],
+ "size": {
+ "0": 315,
+ "1": 314
+ },
+ "flags": {},
+ "order": 0,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 7,
+ 11,
+ 15
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": [
+ 8,
+ 12,
+ 16
+ ],
+ "shape": 3,
+ "slot_index": 1
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512 (5).png",
+ "image"
+ ]
+ },
+ {
+ "id": 9,
+ "type": "LayerUtility: ImageBlend",
+ "pos": [
+ 1030,
+ 760
+ ],
+ "size": {
+ "0": 315,
+ "1": 146
+ },
+ "flags": {},
+ "order": 4,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "background_image",
+ "type": "IMAGE",
+ "link": 14
+ },
+ {
+ "name": "layer_image",
+ "type": "IMAGE",
+ "link": 15
+ },
+ {
+ "name": "layer_mask",
+ "type": "MASK",
+ "link": 16
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 17
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerUtility: ImageBlend"
+ },
+ "widgets_values": [
+ true,
+ "multply",
+ 68
+ ]
+ },
+ {
+ "id": 1,
+ "type": "LoadImage",
+ "pos": [
+ 320,
+ 370
+ ],
+ "size": {
+ "0": 315,
+ "1": 314
+ },
+ "flags": {},
+ "order": 1,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 6,
+ 10,
+ 14
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": null,
+ "shape": 3
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512bkgd (3).jpg",
+ "image"
+ ]
+ },
+ {
+ "id": 8,
+ "type": "SaveImage",
+ "pos": [
+ 1371,
+ 453
+ ],
+ "size": {
+ "0": 282.3333740234375,
+ "1": 289.66668701171875
+ },
+ "flags": {},
+ "order": 6,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 13
+ }
+ ],
+ "properties": {},
+ "widgets_values": [
+ "ComfyUI"
+ ]
+ },
+ {
+ "id": 10,
+ "type": "SaveImage",
+ "pos": [
+ 1370,
+ 786
+ ],
+ "size": {
+ "0": 282.3333740234375,
+ "1": 289.66668701171875
+ },
+ "flags": {},
+ "order": 7,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 17
+ }
+ ],
+ "properties": {},
+ "widgets_values": [
+ "ComfyUI"
+ ]
+ }
+ ],
+ "links": [
+ [
+ 6,
+ 1,
+ 0,
+ 6,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 7,
+ 2,
+ 0,
+ 6,
+ 1,
+ "IMAGE"
+ ],
+ [
+ 8,
+ 2,
+ 1,
+ 6,
+ 2,
+ "MASK"
+ ],
+ [
+ 9,
+ 6,
+ 0,
+ 4,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 10,
+ 1,
+ 0,
+ 7,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 11,
+ 2,
+ 0,
+ 7,
+ 1,
+ "IMAGE"
+ ],
+ [
+ 12,
+ 2,
+ 1,
+ 7,
+ 2,
+ "MASK"
+ ],
+ [
+ 13,
+ 7,
+ 0,
+ 8,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 14,
+ 1,
+ 0,
+ 9,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 15,
+ 2,
+ 0,
+ 9,
+ 1,
+ "IMAGE"
+ ],
+ [
+ 16,
+ 2,
+ 1,
+ 9,
+ 2,
+ "MASK"
+ ],
+ [
+ 17,
+ 9,
+ 0,
+ 10,
+ 0,
+ "IMAGE"
+ ]
+ ],
+ "groups": [],
+ "config": {},
+ "extra": {},
+ "version": 0.4
}
\ No newline at end of file
diff --git a/workflow/inner_glow_example.json b/workflow/inner_glow_example.json
new file mode 100644
index 0000000..3331eb9
--- /dev/null
+++ b/workflow/inner_glow_example.json
@@ -0,0 +1,206 @@
+{
+ "last_node_id": 16,
+ "last_link_id": 27,
+ "nodes": [
+ {
+ "id": 4,
+ "type": "PreviewImage",
+ "pos": [
+ 1360,
+ 390
+ ],
+ "size": [
+ 310.00006103515625,
+ 308.33331298828125
+ ],
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 27
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "PreviewImage"
+ }
+ },
+ {
+ "id": 2,
+ "type": "LoadImage",
+ "pos": [
+ 310,
+ 390
+ ],
+ "size": {
+ "0": 315,
+ "1": 314
+ },
+ "flags": {},
+ "order": 0,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 24
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": null,
+ "shape": 3
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512bk.jpg",
+ "image"
+ ]
+ },
+ {
+ "id": 15,
+ "type": "LoadImage",
+ "pos": [
+ 660,
+ 394
+ ],
+ "size": {
+ "0": 315,
+ "1": 314
+ },
+ "flags": {},
+ "order": 1,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 25
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": [
+ 26
+ ],
+ "shape": 3,
+ "slot_index": 1
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512 (14).png",
+ "image"
+ ]
+ },
+ {
+ "id": 16,
+ "type": "LayerStyle: InnerGlow",
+ "pos": [
+ 1013,
+ 419
+ ],
+ "size": {
+ "0": 315,
+ "1": 266
+ },
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "background_image",
+ "type": "IMAGE",
+ "link": 24
+ },
+ {
+ "name": "layer_image",
+ "type": "IMAGE",
+ "link": 25
+ },
+ {
+ "name": "layer_mask",
+ "type": "MASK",
+ "link": 26
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 27
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerStyle: InnerGlow"
+ },
+ "widgets_values": [
+ true,
+ "screen",
+ 100,
+ 12,
+ 26,
+ 12,
+ "#FFBF30",
+ "#FE0000"
+ ]
+ }
+ ],
+ "links": [
+ [
+ 24,
+ 2,
+ 0,
+ 16,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 25,
+ 15,
+ 0,
+ 16,
+ 1,
+ "IMAGE"
+ ],
+ [
+ 26,
+ 15,
+ 1,
+ 16,
+ 2,
+ "MASK"
+ ],
+ [
+ 27,
+ 16,
+ 0,
+ 4,
+ 0,
+ "IMAGE"
+ ]
+ ],
+ "groups": [],
+ "config": {},
+ "extra": {},
+ "version": 0.4
+}
\ No newline at end of file
diff --git a/workflow/inner_shadow_example.json b/workflow/inner_shadow_example.json
new file mode 100644
index 0000000..0e8ac9f
--- /dev/null
+++ b/workflow/inner_shadow_example.json
@@ -0,0 +1,206 @@
+{
+ "last_node_id": 19,
+ "last_link_id": 39,
+ "nodes": [
+ {
+ "id": 4,
+ "type": "PreviewImage",
+ "pos": [
+ 1360,
+ 390
+ ],
+ "size": [
+ 310.00006103515625,
+ 308.33331298828125
+ ],
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 39
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "PreviewImage"
+ }
+ },
+ {
+ "id": 2,
+ "type": "LoadImage",
+ "pos": [
+ 310,
+ 390
+ ],
+ "size": {
+ "0": 315,
+ "1": 314
+ },
+ "flags": {},
+ "order": 0,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 36
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": null,
+ "shape": 3
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512bk.jpg",
+ "image"
+ ]
+ },
+ {
+ "id": 15,
+ "type": "LoadImage",
+ "pos": [
+ 660,
+ 399
+ ],
+ "size": {
+ "0": 315,
+ "1": 314
+ },
+ "flags": {},
+ "order": 1,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 37
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": [
+ 38
+ ],
+ "shape": 3,
+ "slot_index": 1
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512 (14).png",
+ "image"
+ ]
+ },
+ {
+ "id": 19,
+ "type": "LayerStyle: InnerShadow",
+ "pos": [
+ 1014,
+ 417
+ ],
+ "size": {
+ "0": 315,
+ "1": 266
+ },
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "background_image",
+ "type": "IMAGE",
+ "link": 36
+ },
+ {
+ "name": "layer_image",
+ "type": "IMAGE",
+ "link": 37
+ },
+ {
+ "name": "layer_mask",
+ "type": "MASK",
+ "link": 38
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 39
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerStyle: InnerShadow"
+ },
+ "widgets_values": [
+ true,
+ "normal",
+ 100,
+ 5,
+ 5,
+ 2,
+ 15,
+ "#000000"
+ ]
+ }
+ ],
+ "links": [
+ [
+ 36,
+ 2,
+ 0,
+ 19,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 37,
+ 15,
+ 0,
+ 19,
+ 1,
+ "IMAGE"
+ ],
+ [
+ 38,
+ 15,
+ 1,
+ 19,
+ 2,
+ "MASK"
+ ],
+ [
+ 39,
+ 19,
+ 0,
+ 4,
+ 0,
+ "IMAGE"
+ ]
+ ],
+ "groups": [],
+ "config": {},
+ "extra": {},
+ "version": 0.4
+}
\ No newline at end of file
diff --git a/workflow/outer_glow_example.json b/workflow/outer_glow_example.json
index 1911830..ce9d226 100644
--- a/workflow/outer_glow_example.json
+++ b/workflow/outer_glow_example.json
@@ -1,16 +1,41 @@
{
- "last_node_id": 5,
- "last_link_id": 4,
+ "last_node_id": 20,
+ "last_link_id": 43,
"nodes": [
{
- "id": 1,
+ "id": 4,
+ "type": "PreviewImage",
+ "pos": [
+ 1360,
+ 390
+ ],
+ "size": [
+ 310.00006103515625,
+ 308.33331298828125
+ ],
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 43
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "PreviewImage"
+ }
+ },
+ {
+ "id": 2,
"type": "LoadImage",
"pos": [
- 279,
- 378
+ 310,
+ 390
],
"size": {
- "0": 279.00006103515625,
+ "0": 315,
"1": 314
},
"flags": {},
@@ -21,8 +46,7 @@
"name": "IMAGE",
"type": "IMAGE",
"links": [
- 1,
- 2
+ 40
],
"shape": 3,
"slot_index": 0
@@ -38,120 +62,81 @@
"Node name for S&R": "LoadImage"
},
"widgets_values": [
- "D04QPvc (7).jpg",
+ "512x512bk.jpg",
"image"
]
},
{
- "id": 2,
- "type": "Image Remove Background Rembg (mtb)",
+ "id": 15,
+ "type": "LoadImage",
"pos": [
- 597,
- 405
+ 660,
+ 399
],
"size": {
- "0": 294,
- "1": 230
+ "0": 315,
+ "1": 314
},
"flags": {},
- "order": 2,
+ "order": 1,
"mode": 0,
- "inputs": [
- {
- "name": "image",
- "type": "IMAGE",
- "link": 1
- }
- ],
"outputs": [
{
- "name": "Image (rgba)",
+ "name": "IMAGE",
"type": "IMAGE",
"links": [
- 3
+ 41
],
"shape": 3,
"slot_index": 0
},
{
- "name": "Mask",
+ "name": "MASK",
"type": "MASK",
- "links": null,
- "shape": 3
- },
- {
- "name": "Image",
- "type": "IMAGE",
- "links": null,
- "shape": 3
+ "links": [
+ 42
+ ],
+ "shape": 3,
+ "slot_index": 1
}
],
"properties": {
- "Node name for S&R": "Image Remove Background Rembg (mtb)"
+ "Node name for S&R": "LoadImage"
},
"widgets_values": [
- false,
- 240,
- 10,
- 10,
- false,
- "#000000"
+ "512x512 (14).png",
+ "image"
]
},
{
- "id": 4,
- "type": "PreviewImage",
- "pos": [
- 1284,
- 380
- ],
- "size": {
- "0": 434.666748046875,
- "1": 290.66668701171875
- },
- "flags": {},
- "order": 4,
- "mode": 0,
- "inputs": [
- {
- "name": "images",
- "type": "IMAGE",
- "link": 4
- }
- ],
- "properties": {
- "Node name for S&R": "PreviewImage"
- }
- },
- {
- "id": 3,
+ "id": 20,
"type": "LayerStyle_OuterGlow",
"pos": [
- 925,
- 381
+ 1012,
+ 423
],
"size": {
"0": 315,
"1": 266
},
"flags": {},
- "order": 3,
+ "order": 2,
"mode": 0,
"inputs": [
{
"name": "background_image",
"type": "IMAGE",
- "link": 2
+ "link": 40
},
{
"name": "layer_image",
"type": "IMAGE",
- "link": 3
+ "link": 41
},
{
"name": "layer_mask",
"type": "MASK",
- "link": null
+ "link": 42
}
],
"outputs": [
@@ -159,7 +144,7 @@
"name": "image",
"type": "IMAGE",
"links": [
- 4
+ 43
],
"shape": 3,
"slot_index": 0
@@ -178,89 +163,36 @@
"#FFBF30",
"#FE0000"
]
- },
- {
- "id": 5,
- "type": "LayerStyle_OuterGlow",
- "pos": [
- 2165.2059106060115,
- 401.76576118268605
- ],
- "size": {
- "0": 315,
- "1": 266
- },
- "flags": {},
- "order": 1,
- "mode": 0,
- "inputs": [
- {
- "name": "background_image",
- "type": "IMAGE",
- "link": null
- },
- {
- "name": "layer_image",
- "type": "IMAGE",
- "link": null
- },
- {
- "name": "layer_mask",
- "type": "MASK",
- "link": null
- }
- ],
- "outputs": [
- {
- "name": "image",
- "type": "IMAGE",
- "links": null,
- "shape": 3
- }
- ],
- "properties": {
- "Node name for S&R": "LayerStyle_OuterGlow"
- },
- "widgets_values": [
- true,
- "screen",
- 100,
- 5,
- 48,
- 25,
- "#FFBF30",
- "#FE0000"
- ]
}
],
"links": [
[
- 1,
- 1,
- 0,
+ 40,
2,
0,
+ 20,
+ 0,
"IMAGE"
],
[
- 2,
- 1,
+ 41,
+ 15,
0,
- 3,
- 0,
- "IMAGE"
- ],
- [
- 3,
- 2,
- 0,
- 3,
+ 20,
1,
"IMAGE"
],
[
- 4,
- 3,
+ 42,
+ 15,
+ 1,
+ 20,
+ 2,
+ "MASK"
+ ],
+ [
+ 43,
+ 20,
0,
4,
0,
diff --git a/workflow/stroke_example.json b/workflow/stroke_example.json
index 00da33e..2c3af9e 100644
--- a/workflow/stroke_example.json
+++ b/workflow/stroke_example.json
@@ -1,68 +1,38 @@
{
- "last_node_id": 15,
- "last_link_id": 18,
+ "last_node_id": 21,
+ "last_link_id": 47,
"nodes": [
{
- "id": 1,
- "type": "LayerStyle_Stroke",
+ "id": 4,
+ "type": "PreviewImage",
"pos": [
- 758,
- 309
+ 1360,
+ 390
+ ],
+ "size": [
+ 310.00006103515625,
+ 308.33331298828125
],
- "size": {
- "0": 315,
- "1": 242
- },
"flags": {},
- "order": 2,
+ "order": 3,
"mode": 0,
"inputs": [
{
- "name": "background_image",
+ "name": "images",
"type": "IMAGE",
- "link": 16
- },
- {
- "name": "layer_image",
- "type": "IMAGE",
- "link": 10
- },
- {
- "name": "layer_mask",
- "type": "MASK",
- "link": 3
- }
- ],
- "outputs": [
- {
- "name": "image",
- "type": "IMAGE",
- "links": [
- 4
- ],
- "shape": 3,
- "slot_index": 0
+ "link": 47
}
],
"properties": {
- "Node name for S&R": "LayerStyle_Stroke"
- },
- "widgets_values": [
- true,
- "normal",
- 100,
- 8,
- 2,
- 0,
- "#DB43A2"
- ]
+ "Node name for S&R": "PreviewImage"
+ }
},
{
- "id": 3,
+ "id": 2,
"type": "LoadImage",
"pos": [
- 413,
- 284
+ 310,
+ 390
],
"size": {
"0": 315,
@@ -76,49 +46,7 @@
"name": "IMAGE",
"type": "IMAGE",
"links": [
- 10
- ],
- "shape": 3,
- "slot_index": 0
- },
- {
- "name": "MASK",
- "type": "MASK",
- "links": [
- 3
- ],
- "shape": 3,
- "slot_index": 1
- }
- ],
- "properties": {
- "Node name for S&R": "LoadImage"
- },
- "widgets_values": [
- "512x512 (10).png",
- "image"
- ]
- },
- {
- "id": 2,
- "type": "LoadImage",
- "pos": [
- 59,
- 279
- ],
- "size": {
- "0": 315,
- "1": 314
- },
- "flags": {},
- "order": 1,
- "mode": 0,
- "outputs": [
- {
- "name": "IMAGE",
- "type": "IMAGE",
- "links": [
- 16
+ 44
],
"shape": 3,
"slot_index": 0
@@ -134,68 +62,140 @@
"Node name for S&R": "LoadImage"
},
"widgets_values": [
- "512x512bkgd (7).jpg",
+ "512x512bk.jpg",
"image"
]
},
{
- "id": 4,
- "type": "PreviewImage",
+ "id": 15,
+ "type": "LoadImage",
"pos": [
- 1105,
- 285
+ 660,
+ 399
],
"size": {
- "0": 299.7062683105469,
- "1": 311.1947937011719
+ "0": 315,
+ "1": 314
},
"flags": {},
- "order": 3,
+ "order": 1,
"mode": 0,
- "inputs": [
+ "outputs": [
{
- "name": "images",
+ "name": "IMAGE",
"type": "IMAGE",
- "link": 4
+ "links": [
+ 45
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": [
+ 46
+ ],
+ "shape": 3,
+ "slot_index": 1
}
],
"properties": {
- "Node name for S&R": "PreviewImage"
- }
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "512x512 (14).png",
+ "image"
+ ]
+ },
+ {
+ "id": 21,
+ "type": "LayerStyle: Stroke",
+ "pos": [
+ 1016,
+ 434
+ ],
+ "size": {
+ "0": 315,
+ "1": 242
+ },
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "background_image",
+ "type": "IMAGE",
+ "link": 44
+ },
+ {
+ "name": "layer_image",
+ "type": "IMAGE",
+ "link": 45
+ },
+ {
+ "name": "layer_mask",
+ "type": "MASK",
+ "link": 46
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 47
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerStyle: Stroke"
+ },
+ "widgets_values": [
+ true,
+ "normal",
+ 100,
+ 0,
+ 8,
+ 0,
+ "#FF0088"
+ ]
}
],
"links": [
[
- 3,
- 3,
+ 44,
+ 2,
+ 0,
+ 21,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 45,
+ 15,
+ 0,
+ 21,
1,
+ "IMAGE"
+ ],
+ [
+ 46,
+ 15,
1,
+ 21,
2,
"MASK"
],
[
- 4,
- 1,
+ 47,
+ 21,
0,
4,
0,
"IMAGE"
- ],
- [
- 10,
- 3,
- 0,
- 1,
- 1,
- "IMAGE"
- ],
- [
- 16,
- 2,
- 0,
- 1,
- 0,
- "IMAGE"
]
],
"groups": [],