diff --git a/README.MD b/README.MD index bfdaf98..d59be1c 100644 --- a/README.MD +++ b/README.MD @@ -12,6 +12,7 @@ Nodes are divided into four groups according to their functions: LayerStyle, Lay [中文说明点这里](./README_CN.MD) ## Update +* Add [ExtendCanvas](#ExtendCanvas) node. * Add [ImageBlendAdvance](#ImageBlendAdvance) node. This node allows for the synthesis of background images and layers of different sizes, providing a more free synthesis experience. Add [PrintInfo](#PrintInfo) node as a workflow debugging aid. * Add [GradientOverlay](#GradientOverlay) and [ColorOverlay](#ColorOverlay) nodes. @@ -248,6 +249,20 @@ Node options: Output Type: * string +### ExtendCanvas +Extend the canvas +![image](image/extend_canvas_example.png) + +Node options: +![image](image/extend_canvas_node.png) +* invert_mask: Whether to reverse the mask. +* top: Top extension value. +* bottom: Bottom extension value. +* left: Left extension value. +* right: Right extension value. +* color; Color of canvas. + + ### PrintInfo ![image](image/print_info_node.png) Used to provide assistance for workflow debugging. When running, the properties of any object connected to this node will be printed to the console. @@ -301,7 +316,7 @@ LayerMask: * mask softedge LayerFilter: -* bulr +* blur * emboss * contour * findedge diff --git a/README_CN.MD b/README_CN.MD index b365e88..3d15b16 100644 --- a/README_CN.MD +++ b/README_CN.MD @@ -9,6 +9,7 @@ ComfyUI * [LayerFilter](#LayerFilter)½Úµã×éÌṩͼÏñЧ¹ûÂ˾µ¡£ ## ¸üÐÂ˵Ã÷ +* Ìí¼Ó[ExtendCanvas](#ExtendCanvas)½Úµã¡£ * Ìí¼Ó[ImageBlendAdvance](#ImageBlendAdvance)½Úµã¡£Õâ¸ö½ÚµãÔÊÐíºÏ³É³ß´ç²»Í¬µÄ±³¾°Í¼ºÍͼ²ã£¬ÌṩÁ˸ü¼Ó×ÔÓɵĺϳÉÌåÑé¡£ Ìí¼Ó[PrintInfo](#PrintInfo)½Úµã×÷Ϊ¹¤×÷Á÷µ÷ÊÔ¸¨Öú¹¤¾ß¡£ * Ìí¼Ó[GradientOverlay](#GradientOverlay),[ColorOverlay](#ColorOverlay)½Úµã¡£Ôö¼ÓÎÞЧmaskÊäÈëÅжϣ¬µ±ÊäÈëÎÞЧmaskʱ½«ÆäºöÂÔ¡£ @@ -245,6 +246,20 @@ mask Êä³ö: * string +### ExtendCanvas +À©Õ¹»­²¼¡£ +![image](image/extend_canvas_example.png) + +½ÚµãÑ¡Ïî˵Ã÷: +![image](image/extend_canvas_node.png) +* invert_mask: ÊÇ·ñ·´×ªÕÚÕÖ¡£ +* top: ¶¥²¿À©Õ¹Öµ¡£ +* bottom: µ×²¿À©Õ¹Öµ¡£ +* left: ×ó²àÀ©Õ¹Öµ¡£ +* right: ÓÒ²àÀ©Õ¹Öµ¡£ +* color; »­²¼ÑÕÉ« + + ### PrintInfo ![image](image/print_info_node.png) ÓÃÓÚ¸ø¹¤×÷Á÷µ÷ÊÔÌṩ¸¨Öú¡£µ±ÔËÐÐʱ£¬ÈκνÓÉÏÕâ¸ö½ÚµãµÄ¶ÔÏóµÄÊôÐÔ½«±»´òÓ¡µ½¿ØÖÆÌ¨¡£ @@ -294,7 +309,7 @@ LayerMask: * mask softedge LayerFilter: -* bulr +* blur * emboss * contour * findedge diff --git a/image/extend_canvas_example.png b/image/extend_canvas_example.png new file mode 100644 index 0000000..cc65b2e Binary files /dev/null and b/image/extend_canvas_example.png differ diff --git a/image/extend_canvas_node.png b/image/extend_canvas_node.png new file mode 100644 index 0000000..2dc01e5 Binary files /dev/null and b/image/extend_canvas_node.png differ diff --git a/py/color_picker.py b/py/color_picker.py index 742d862..4734b96 100644 --- a/py/color_picker.py +++ b/py/color_picker.py @@ -13,7 +13,7 @@ class ColorPicker: return { "required": { - "color": ("COLOR", {"default": "white"},), + "color": ("COLOR", {"default": "#FFFFFF"},), "mode": (mode_list,), # 输出模å¼� }, "optional": { diff --git a/py/extand_canvas.py b/py/extand_canvas.py new file mode 100644 index 0000000..73521a7 --- /dev/null +++ b/py/extand_canvas.py @@ -0,0 +1,62 @@ +from .imagefunc import * + +class ExtendCanvas: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + + return { + "required": { + "image": ("IMAGE", ), + "invert_mask": ("BOOLEAN", {"default": True}), # å��转mask + "top": ("INT", {"default": 0, "min": 0, "max": 99999, "step": 1}), + "bottom": ("INT", {"default": 0, "min": 0, "max": 99999, "step": 1}), + "left": ("INT", {"default": 0, "min": 0, "max": 99999, "step": 1}), + "right": ("INT", {"default": 0, "min": 0, "max": 99999, "step": 1}), + "color": ("COLOR", {"default": "#000000"},), + }, + "optional": { + "mask": ("MASK",), # + } + } + + RETURN_TYPES = ("IMAGE", "MASK",) + RETURN_NAMES = ("image", "mask") + FUNCTION = 'extend_canvas' + CATEGORY = '😺dzNodes/LayerUtility' + OUTPUT_NODE = True + + def extend_canvas(self, image, invert_mask, + top, bottom, left, right, color, + mask=None, + ): + + _image = tensor2pil(image).convert('RGB') + _mask = tensor2pil(image).convert('RGBA').split()[-1] + if mask is not None: + if invert_mask: + mask = 1 - mask + _mask = mask2image(mask).convert('L') + + width = _image.width + left + right + height = _image.height + top + bottom + _canvas = Image.new('RGB', (width, height), color) + _mask_canvas = Image.new('L', (width, height), "black") + + _canvas.paste(_image, box=(left,top)) + _mask_canvas.paste(_mask.convert('L'), box=(left, top)) + ret_image = _canvas + ret_mask = image2mask(_mask_canvas) + log('ExtendCanvas Processed.') + return (pil2tensor(ret_image), ret_mask,) + +NODE_CLASS_MAPPINGS = { + "LayerUtility: ExtendCanvas": ExtendCanvas +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "LayerUtility: ExtendCanvas": "LayerUtility: ExtendCanvas" +} \ No newline at end of file diff --git a/workflow/extend_canvas_example.json b/workflow/extend_canvas_example.json new file mode 100644 index 0000000..8de1f2f --- /dev/null +++ b/workflow/extend_canvas_example.json @@ -0,0 +1,194 @@ +{ + "last_node_id": 29, + "last_link_id": 62, + "nodes": [ + { + "id": 29, + "type": "LayerUtility: ExtendCanvas", + "pos": [ + 750, + 450 + ], + "size": { + "0": 218.39999389648438, + "1": 210 + }, + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 59 + }, + { + "name": "mask", + "type": "MASK", + "link": 60 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 61 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "mask", + "type": "MASK", + "links": [ + 62 + ], + "shape": 3, + "slot_index": 1 + } + ], + "properties": { + "Node name for S&R": "LayerUtility: ExtendCanvas" + }, + "widgets_values": [ + true, + 80, + 59, + 135, + 112, + "#8a0000" + ] + }, + { + "id": 28, + "type": "LayerMask: MaskPreview", + "pos": [ + 1080, + 590 + ], + "size": [ + 263.00006103515625, + 262.6666259765625 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 62 + } + ], + "properties": { + "Node name for S&R": "LayerMask: MaskPreview" + } + }, + { + "id": 26, + "type": "PreviewImage", + "pos": [ + 1080, + 290 + ], + "size": { + "0": 264.4000244140625, + "1": 246 + }, + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 61 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 23, + "type": "LoadImage", + "pos": [ + 380, + 450 + ], + "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": [ + 60 + ], + "shape": 3, + "slot_index": 1 + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "ComfyUI_00193_ (5).png", + "image" + ] + } + ], + "links": [ + [ + 59, + 23, + 0, + 29, + 0, + "IMAGE" + ], + [ + 60, + 23, + 1, + 29, + 1, + "MASK" + ], + [ + 61, + 29, + 0, + 26, + 0, + "IMAGE" + ], + [ + 62, + 29, + 1, + 28, + 0, + "MASK" + ] + ], + "groups": [], + "config": {}, + "extra": {}, + "version": 0.4 +} \ No newline at end of file