diff --git a/Mask.py b/Mask.py index 0a28ddf..2b7b852 100644 --- a/Mask.py +++ b/Mask.py @@ -663,4 +663,74 @@ class PngRectanglesToMaskList: return (masks[0], masks[1], masks[2], masks[3], masks[4], masks[5], masks[6], masks[7], masks[8], masks[9],) + +class CreateMaskWithCanvas: + ''' + Create a new mask on defined cavans + + Inputs: + C_Width - Width of cavans + C_Height - Height of cavans + X - The left point of new mask on cavans + Y - The top point of new mask on cavans + Width - Mask width + Height - Mask height + Intenisity - The intenisity of Mask, 1 for Soild. + Blur - The amount of Blur, 0 for Soild. + + Outputs: + mask - New mask with defined cavans + ''' + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "C_Width": ("INT", { "default": 512, "min": 8, "max": 4096, "step": 1, "display": "number" }), + "C_Height": ("INT", { "default": 512, "min": 8, "max": 4096, "step": 1, "display": "number" }), + "X": ("INT", { "default": 0, "min": 0, "max": 4096, "step": 1, "display": "number" }), + "Y": ("INT", { "default": 0, "min": 0, "max": 4096, "step": 1, "display": "number" }), + "Width": ("INT", { "default": 512, "min": 8, "max": 4096, "step": 1, "display": "number" }), + "Height": ("INT", { "default": 512, "min": 8, "max": 4096, "step": 1, "display": "number" }), + "Intenisity": ("FLOAT", { "default": 1.0, "min": 0.0, "max": 1.0, "step": 0.1, "display": "number" }), + "Blur": ("FLOAT", { "default": 0.0, "min": 0.0, "step": 0.5, "display": "number" }), + }, + } + + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('mask',) + FUNCTION = "CreateMaskWithCanvasEx" + CATEGORY = cat + + + def CreateMaskWithCanvasEx(self, C_Width, C_Height, X, Y, Width, Height, Intenisity, Blur): + destinationMask = torch.full((1,C_Height, C_Width), 0, dtype=torch.float32, device="cpu") + + output = destinationMask.reshape((-1, destinationMask.shape[-2], destinationMask.shape[-1])).clone() + + sourceMask = torch.full((1, Height, Width), Intenisity, dtype=torch.float32, device="cpu") + source = sourceMask.reshape((-1, sourceMask.shape[-2], sourceMask.shape[-1])) + + left, top = (X, Y) + right, bottom = (min(left + source.shape[-1], destinationMask.shape[-1]), min(top + source.shape[-2], destinationMask.shape[-2])) + visible_width, visible_height = (right - left, bottom - top,) + + source_portion = source[:, :visible_height, :visible_width] + destination_portion = destinationMask[:, top:bottom, left:right] + + output[:, top:bottom, left:right] = destination_portion + source_portion + mask = output + + if 0 < Blur: + size = int(6 * Blur +1) + if size % 2 == 0: + size+= 1 + + blurred = mask.unsqueeze(1) + blurred = T.GaussianBlur(size, Blur)(blurred) + blurred = blurred.squeeze(1) + mask = blurred + + return (mask,) + \ No newline at end of file diff --git a/README.md b/README.md index 3bee907..1e87efd 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,29 @@ Convert ranged `PngRectangles` to Mask with Mask `Intenisity` and `Blur` functio Example +------ +### Mira/Mask/Create Mask With Canvas +Create a new `mask` on defined `cavans`. +In case you need `merge` muliple `masks`, try search `MaskComposite` with `operation add`. + +| Inputs | Description | +| --- | --- | +| `C_Width` | Width of cavans. | +| `C_Height` | Height of cavans. | +| `X` | The left point of new mask on cavans. | +| `Y` | The top point of new mask on cavans. | +| `Width` | Mask width. | +| `Height` | Mask height. | +| `Intenisity` | `Intenisity` of Mask, set to `1.0` for solid Mask. | +| `Blur` | The intensity of blur around the edge of Mask, set to `0` for a solid edge. | + +| Outputs | Description | +| --- | --- | +| `mask` | New mask with defined cavans | + +Example + + ------ ### Mira/Util/Create Canvas Create Canvas information `Width` and `Height` for Latent with Landscape switch. There's an advanced version also controls `Batch` and `HiResMultiplier`. diff --git a/__init__.py b/__init__.py index b813fba..3fe4933 100644 --- a/__init__.py +++ b/__init__.py @@ -1,7 +1,7 @@ from .Multiplier import IntMultiplier, FloatMultiplier from .Numeral import NumeralToString, TwoFloats, FourFloats, SixFloats, EightFloats, StepsAndCfg, StepsAndCfgAndWH from .Util import CanvasCreatorAdvanced, CanvasCreatorSimple, CanvasCreatorBasic -from .Mask import CreateRegionalPNGMask, PngColorMasksToString, PngColorMasksToRGB, PngColorMasksToStringList, PngColorMasksToMaskList, PngRectanglesToMask, PngRectanglesToMaskList +from .Mask import CreateRegionalPNGMask, PngColorMasksToString, PngColorMasksToRGB, PngColorMasksToStringList, PngColorMasksToMaskList, PngRectanglesToMask, PngRectanglesToMaskList, CreateMaskWithCanvas from .Text import TextBox, TextWithBooleanSwitchAndCommonTextInput, TextCombinerSix, TextCombinerTwo from .Logic import SingleBooleanTrigger, TwoBooleanTrigger, FourBooleanTrigger, SixBooleanTrigger @@ -33,6 +33,7 @@ NODE_CLASS_MAPPINGS = { "PngColorMasksToMaskList" : PngColorMasksToMaskList, "PngRectanglesToMask" : PngRectanglesToMask, "PngRectanglesToMaskList" : PngRectanglesToMaskList, + "CreateMaskWithCanvas" : CreateMaskWithCanvas, "SingleBooleanTrigger" : SingleBooleanTrigger, "TwoBooleanTrigger" : TwoBooleanTrigger, @@ -68,6 +69,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "PngColorMasksToMaskList" : "PngColor Masks to Masks", "PngRectanglesToMask" : "PngRectangles to Mask", "PngRectanglesToMaskList" : "PngRectangles to Masks", + "CreateMaskWithCanvas" : "Create Mask With Canvas", "SingleBooleanTrigger" : "1 Bool", "TwoBooleanTrigger" : "2 Bool", diff --git a/examples/example_createmaskwithcavans.png b/examples/example_createmaskwithcavans.png new file mode 100644 index 0000000..8bb6908 Binary files /dev/null and b/examples/example_createmaskwithcavans.png differ