diff --git a/README.md b/README.md index a5b5161..b305b8a 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# XYPlot: Comfy plugin +# ImagesGrid: Comfy plugin -![Image](./workflows/xy_plot_mini.png) -[Workflows](./workflows/xy_plot_mini.json) -![Image](./workflows/xy_plot_base.png) -[Workflows](./workflows/xy_plot_base.json) +![Image](./workflows/mini.png) +[Workflows](./workflows/mini.json) +![Image](./workflows/base.png) +[Workflows](./workflows/base.json) ## How to use @@ -13,11 +13,11 @@ ``` cd custom_nodes # From comfy path -git clone https://github.com/LEv145/XY-plot-comfy-plugin XYPlot +git clone https://github.com/LEv145/images-grid-comfy-plugin ImagesGrid ``` ### Update ``` -cd custom_nodes/XYPlot +cd custom_nodes/ImagesGrid git pull ``` diff --git a/__init__.py b/__init__.py index 5815486..d84184d 100644 --- a/__init__.py +++ b/__init__.py @@ -1,7 +1,9 @@ -from .src import LatentCombineNode, XYPlotNode +from .src import LatentCombineNode, ImagesGridByColumnsNode, ImagesGridByRowsNode, ImageCombineNode NODE_CLASS_MAPPINGS = { - "XYPlot": XYPlotNode, "LatentCombine": LatentCombineNode, + "ImagesGridByColumns": ImagesGridByColumnsNode, + "ImagesGridByRows": ImagesGridByRowsNode, + "ImageCombine": ImageCombineNode, } diff --git a/src/__init__.py b/src/__init__.py index b3ad20d..dbab28c 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,2 +1,3 @@ -from .nodes.xy_plot import XYPlotNode +from .nodes.images_grid import ImagesGridByColumnsNode, ImagesGridByRowsNode from .nodes.latent_combine import LatentCombineNode +from .nodes.image_combine import ImageCombineNode diff --git a/src/base.py b/src/base.py index de60d1a..c06dc3f 100644 --- a/src/base.py +++ b/src/base.py @@ -1,16 +1,9 @@ import typing as t -from dataclasses import dataclass -class BasePlotNode(): - CATEGORY: str = "XYPlot" +class BaseNode(): + CATEGORY: str = "ImagesGrid" FUNCTION: str = "execute" -@dataclass -class KSamplerXYPlotInput(): - setting: str - value: int - - Image = t.Any diff --git a/src/nodes/image_combine.py b/src/nodes/image_combine.py new file mode 100644 index 0000000..ce7fde0 --- /dev/null +++ b/src/nodes/image_combine.py @@ -0,0 +1,32 @@ +import typing as t + +import torch + +from ..base import BaseNode, Image + + +class ImageCombineNode(BaseNode): + RETURN_TYPES: t.Tuple[str] = ("IMAGE",) + + @classmethod + def INPUT_TYPES(cls) -> t.Dict[str, t.Any]: + return { + "required": { + "image_1": ("IMAGE",), + "image_2": ("IMAGE",), + }, + } + + def execute( + self, + image_1: Image, + image_2: Image, + ) -> t.Tuple[Image]: + print(image_1.size()) + print(image_2.size()) + print(image_1) + + result = torch.cat((image_1, image_2), 0) + print(result.size()) + + return (result,) diff --git a/src/nodes/images_grid.py b/src/nodes/images_grid.py new file mode 100644 index 0000000..aae0184 --- /dev/null +++ b/src/nodes/images_grid.py @@ -0,0 +1,48 @@ +import typing as t + +from ..base import BaseNode, Image +from ..utils import ( + tensor_to_pillow, + pillow_to_tensor, + create_image_grid_by_columns, + create_image_grid_by_rows, +) + + +class BaseImagesGridNode(BaseNode): + RETURN_TYPES: t.Tuple[str] = ("IMAGE",) + + @classmethod + def _create_input_types(cls, coordinate_name: str) -> t.Dict[str, t.Any]: + return { + "required": { + "images": ("IMAGE",), + "gap": ("INT", {"default": 0, "min": 0}), + coordinate_name: ("INT", {"default": 1, "min": 1}), + } + } + + def _create_execute(self, images, function, function_kw) -> t.Tuple[Image]: + pillow_images = [tensor_to_pillow(i) for i in images] + pillow_grid = function(images=pillow_images, **function_kw) + tensor_grid = pillow_to_tensor(pillow_grid) + + return (tensor_grid,) + + +class ImagesGridByColumnsNode(BaseImagesGridNode): + @classmethod + def INPUT_TYPES(cls) -> t.Dict[str, t.Any]: + return cls._create_input_types("max_columns") + + def execute(self, images: Image, **kw) -> tuple[Image]: + return self._create_execute(images, create_image_grid_by_columns, kw) + + +class ImagesGridByRowsNode(BaseImagesGridNode): + @classmethod + def INPUT_TYPES(cls) -> t.Dict[str, t.Any]: + return cls._create_input_types("max_rows") + + def execute(self, images: Image, **kw) -> tuple[Image]: + return self._create_execute(images, create_image_grid_by_rows, kw) diff --git a/src/nodes/latent_combine.py b/src/nodes/latent_combine.py index 6172cb2..96e0259 100644 --- a/src/nodes/latent_combine.py +++ b/src/nodes/latent_combine.py @@ -2,10 +2,10 @@ import typing as t import torch -from ..base import BasePlotNode, Image +from ..base import BaseNode, Image -class LatentCombineNode(BasePlotNode): +class LatentCombineNode(BaseNode): RETURN_TYPES: t.Tuple[str] = ("LATENT",) @classmethod @@ -22,8 +22,6 @@ class LatentCombineNode(BasePlotNode): latent_1: t.Dict[str, t.Any], latent_2: t.Dict[str, t.Any], ) -> t.Tuple[t.Dict[str, t.Any]]: - latent_1_samples = latent_1["samples"] - latent_2_samples = latent_2["samples"] - samples = torch.cat((latent_1_samples, latent_2_samples), 0) + samples = torch.cat((latent_1["samples"], latent_2["samples"]), 0) return ({"samples": samples},) diff --git a/src/nodes/xy_plot.py b/src/nodes/xy_plot.py deleted file mode 100644 index f63cc00..0000000 --- a/src/nodes/xy_plot.py +++ /dev/null @@ -1,30 +0,0 @@ -import typing as t - -from ..base import BasePlotNode, Image -from ..utils import tensor_to_pillow, pillow_to_tensor, create_image_grid - - -class XYPlotNode(BasePlotNode): - RETURN_TYPES: t.Tuple[str] = ("IMAGE",) - - @classmethod - def INPUT_TYPES(cls) -> t.Dict[str, t.Any]: - return { - "required": { - "images": ("IMAGE",), - "gap": ("INT", {"default": 0, "min": 0}), - "ncol": ("INT", {"default": 1, "min": 1}), - }, - } - - def execute( - self, - images: Image, - ncol: int, - gap: int - ) -> tuple[Image]: - pillow_images = [tensor_to_pillow(i) for i in images] - pillow_grid = create_image_grid(pillow_images, ncol=ncol, gap=gap) - tensor_grid = pillow_to_tensor(pillow_grid) - - return (tensor_grid,) diff --git a/src/utils.py b/src/utils.py index 5e4bae0..9f8e223 100644 --- a/src/utils.py +++ b/src/utils.py @@ -13,27 +13,41 @@ def pillow_to_tensor(image): return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0) -def create_image_grid(images: t.List[Image.Image], gap: int, ncol: int): - # Calculate the number of rows needed based on the number of images and columns - nrow = (len(images) + ncol - 1) // ncol +def create_image_grid_by_columns( + images: t.List[Image.Image], + gap: int, + max_columns: int, +) -> Image.Image: + max_rows = (len(images) + max_columns - 1) // max_columns + return create_image_grid(images=images, gap=gap, max_columns=max_columns, max_rows=max_rows) - # Get the size of the first image to use as a template for the grid + +def create_image_grid_by_rows( + images: t.List[Image.Image], + gap: int, + max_rows: int, +) -> Image.Image: + max_columns = (len(images) + max_rows - 1) // max_rows + return create_image_grid(images=images, gap=gap, max_columns=max_columns, max_rows=max_rows) + + +def create_image_grid( + images: t.List[Image.Image], + gap: int, + max_columns: int, + max_rows: int, +) -> Image.Image: size = images[0].size - # Calculate the total size of the grid with gaps - width = size[0] * ncol + gap * (ncol - 1) - height = size[1] * nrow + gap * (nrow - 1) + width = size[0] * max_columns + (max_columns - 1) * gap + height = size[1] * max_rows + (max_rows - 1) * gap - # Create a new image for the grid grid_image = Image.new("RGB", (width, height), color="white") - # Iterate over each image and paste it into the grid for i, image in enumerate(images): - # Calculate the position of the image in the grid - x = (i % ncol) * (size[0] + gap) - y = (i // ncol) * (size[1] + gap) + x = (i % max_columns) * (size[0] + gap) + y = (i // max_columns) * (size[1] + gap) - # Paste the image into the grid grid_image.paste(image, (x, y)) return grid_image diff --git a/workflows/xy_plot_base.json b/workflows/base.json similarity index 69% rename from workflows/xy_plot_base.json rename to workflows/base.json index f2aca6e..7a26018 100644 --- a/workflows/xy_plot_base.json +++ b/workflows/base.json @@ -1,148 +1,7 @@ { - "last_node_id": 40, - "last_link_id": 72, + "last_node_id": 61, + "last_link_id": 102, "nodes": [ - { - "id": 15, - "type": "PreviewImage", - "pos": [ - 1435, - 325 - ], - "size": { - "0": 363.55511474609375, - "1": 290.6986999511719 - }, - "flags": {}, - "order": 20, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 20 - } - ], - "properties": { - "Node name for S&R": "PreviewImage" - } - }, - { - "id": 32, - "type": "VAEDecode", - "pos": [ - 188.6033769999996, - 306.84141700000043 - ], - "size": { - "0": 210, - "1": 46 - }, - "flags": {}, - "order": 11, - "mode": 0, - "inputs": [ - { - "name": "samples", - "type": "LATENT", - "link": 49 - }, - { - "name": "vae", - "type": "VAE", - "link": 64 - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 51 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "VAEDecode" - } - }, - { - "id": 34, - "type": "VAEDecode", - "pos": [ - 190.6033769999996, - 397.8414170000003 - ], - "size": { - "0": 210, - "1": 46 - }, - "flags": {}, - "order": 12, - "mode": 0, - "inputs": [ - { - "name": "samples", - "type": "LATENT", - "link": 50 - }, - { - "name": "vae", - "type": "VAE", - "link": 65 - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 53 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "VAEDecode" - } - }, - { - "id": 11, - "type": "ImageSetArea", - "pos": [ - 435, - 376 - ], - "size": { - "0": 216.59999084472656, - "1": 26 - }, - "flags": {}, - "order": 15, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 53, - "slot_index": 0 - } - ], - "outputs": [ - { - "name": "IMAGES", - "type": "IMAGES", - "links": [ - 13 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "ImageSetArea" - } - }, { "id": 25, "type": "CLIPTextEncode", @@ -223,94 +82,6 @@ "(worst quality, low quality:1.4), monochrome, zombie" ] }, - { - "id": 37, - "type": "VAEDecode", - "pos": [ - 195.60337699999963, - 489.8414170000004 - ], - "size": { - "0": 210, - "1": 46 - }, - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [ - { - "name": "samples", - "type": "LATENT", - "link": 58 - }, - { - "name": "vae", - "type": "VAE", - "link": 66 - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 59 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "VAEDecode" - } - }, - { - "id": 24, - "type": "CheckpointLoaderSimple", - "pos": [ - -1129.3966229999999, - 302.84141700000043 - ], - "size": { - "0": 315, - "1": 98 - }, - "flags": {}, - "order": 0, - "mode": 0, - "outputs": [ - { - "name": "MODEL", - "type": "MODEL", - "links": [ - 69 - ], - "slot_index": 0 - }, - { - "name": "CLIP", - "type": "CLIP", - "links": [ - 35, - 36 - ], - "slot_index": 1 - }, - { - "name": "VAE", - "type": "VAE", - "links": [ - 63 - ], - "slot_index": 2 - } - ], - "properties": { - "Node name for S&R": "CheckpointLoaderSimple" - }, - "widgets_values": [ - "Counterfeit-v2_5.safetensors" - ] - }, { "id": 28, "type": "Reroute", @@ -373,7 +144,7 @@ "name": "", "type": "VAE", "links": [ - 67 + 77 ], "slot_index": 0 } @@ -384,117 +155,160 @@ } }, { - "id": 29, + "id": 24, + "type": "CheckpointLoaderSimple", + "pos": [ + -1129.3966229999999, + 302.84141700000043 + ], + "size": { + "0": 315, + "1": 98 + }, + "flags": {}, + "order": 0, + "mode": 0, + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 69 + ], + "slot_index": 0 + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 35, + 36 + ], + "slot_index": 1 + }, + { + "name": "VAE", + "type": "VAE", + "links": [ + 63 + ], + "slot_index": 2 + } + ], + "properties": { + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "Counterfeit-v2_5.safetensors" + ] + }, + { + "id": 40, "type": "Reroute", "pos": [ - -361.39662299999907, - 113.84141700000015 + 407, + 80 ], "size": [ 75, 26 ], "flags": {}, + "order": 8, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": 77, + "slot_index": 0 + } + ], + "outputs": [ + { + "name": "VAE", + "type": "VAE", + "links": [ + 76 + ], + "slot_index": 0 + } + ], + "properties": { + "showOutputText": true, + "horizontal": false + } + }, + { + "id": 43, + "type": "VAEDecode", + "pos": [ + 528, + 441 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 88 + }, + { + "name": "vae", + "type": "VAE", + "link": 76 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 94 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEDecode" + } + }, + { + "id": 38, + "type": "EmptyLatentImage", + "pos": [ + -646, + 808 + ], + "size": [ + 315, + 106 + ], + "flags": {}, "order": 6, "mode": 0, "inputs": [ { - "name": "", - "type": "*", - "link": 44, - "slot_index": 0 - } - ], - "outputs": [ - { - "name": "", - "type": "MODEL", - "links": [ - 70, - 71, - 72 - ], - "slot_index": 0 - } - ], - "properties": { - "showOutputText": false, - "horizontal": false - } - }, - { - "id": 40, - "type": "Reroute", - "pos": [ - 64.60337700000011, - 78.84141700000006 - ], - "size": [ - 75, - 26 - ], - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [ - { - "name": "", - "type": "*", - "link": 67, - "slot_index": 0 - } - ], - "outputs": [ - { - "name": "", - "type": "VAE", - "links": [ - 64, - 65, - 66 - ], - "slot_index": 0 - } - ], - "properties": { - "showOutputText": false, - "horizontal": false - } - }, - { - "id": 27, - "type": "KSampler", - "pos": [ - -213.39662300000015, - 303.84141700000043 - ], - "size": { - "0": 315, - "1": 262 - }, - "flags": {}, - "order": 8, - "mode": 0, - "inputs": [ - { - "name": "model", - "type": "MODEL", - "link": 70 - }, - { - "name": "positive", - "type": "CONDITIONING", - "link": 41 - }, - { - "name": "negative", - "type": "CONDITIONING", - "link": 40 - }, - { - "name": "latent_image", - "type": "LATENT", - "link": 62 + "name": "batch_size", + "type": "INT", + "link": 100, + "widget": { + "name": "batch_size", + "config": [ + "INT", + { + "default": 1, + "min": 1, + "max": 64 + } + ] + } } ], "outputs": [ @@ -502,37 +316,37 @@ "name": "LATENT", "type": "LATENT", "links": [ - 49 + 60, + 61, + 62 ], "slot_index": 0 } ], "properties": { - "Node name for S&R": "KSampler" + "Node name for S&R": "EmptyLatentImage" }, "widgets_values": [ - 1, - false, - 20, - 8, - "dpmpp_sde", - "karras", - 1 + 512, + 512, + 4 ] }, { "id": 31, "type": "KSampler", "pos": [ - -216.3966230000001, - 606.8414170000007 + -213, + 598 ], "size": { "0": 315, "1": 262 }, - "flags": {}, - "order": 9, + "flags": { + "collapsed": false + }, + "order": 10, "mode": 0, "inputs": [ { @@ -561,7 +375,7 @@ "name": "LATENT", "type": "LATENT", "links": [ - 50 + 74 ], "slot_index": 0 } @@ -580,226 +394,63 @@ ] }, { - "id": 38, - "type": "EmptyLatentImage", + "id": 27, + "type": "KSampler", "pos": [ - -647.3966230000001, - 808.8414170000001 + -210, + 293 ], "size": { "0": 315, - "1": 106 + "1": 262 }, - "flags": {}, - "order": 1, + "flags": { + "collapsed": false + }, + "order": 9, "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 70 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 41 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 40 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 62 + } + ], "outputs": [ { "name": "LATENT", "type": "LATENT", "links": [ - 60, - 61, - 62 + 73 ], "slot_index": 0 } ], "properties": { - "Node name for S&R": "EmptyLatentImage" + "Node name for S&R": "KSampler" }, "widgets_values": [ - 512, - 512, - 1 - ] - }, - { - "id": 18, - "type": "ImageSetArea", - "pos": [ - 434, - 441 - ], - "size": { - "0": 216.59999084472656, - "1": 26 - }, - "flags": {}, - "order": 16, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 59 - } - ], - "outputs": [ - { - "name": "IMAGES", - "type": "IMAGES", - "links": [ - 22 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "ImageSetArea" - } - }, - { - "id": 10, - "type": "ImageSetArea", - "pos": [ - 437, - 307 - ], - "size": { - "0": 216.59999084472656, - "1": 26 - }, - "flags": {}, - "order": 14, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 51 - } - ], - "outputs": [ - { - "name": "IMAGES", - "type": "IMAGES", - "links": [ - 12 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "ImageSetArea" - } - }, - { - "id": 12, - "type": "FloatImageCombine", - "pos": [ - 711, - 301 - ], - "size": { - "0": 317.4000244140625, - "1": 46 - }, - "flags": {}, - "order": 17, - "mode": 0, - "inputs": [ - { - "name": "float_image_1", - "type": "IMAGES", - "link": 12 - }, - { - "name": "float_image_2", - "type": "IMAGES", - "link": 13 - } - ], - "outputs": [ - { - "name": "IMAGES", - "type": "IMAGES", - "links": [ - 32 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "FloatImageCombine" - } - }, - { - "id": 19, - "type": "FloatImageCombine", - "pos": [ - 712, - 387 - ], - "size": { - "0": 317.4000244140625, - "1": 46 - }, - "flags": {}, - "order": 18, - "mode": 0, - "inputs": [ - { - "name": "float_image_1", - "type": "IMAGES", - "link": 32 - }, - { - "name": "float_image_2", - "type": "IMAGES", - "link": 22 - } - ], - "outputs": [ - { - "name": "IMAGES", - "type": "IMAGES", - "links": [ - 24 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "FloatImageCombine" - } - }, - { - "id": 17, - "type": "XYPlot", - "pos": [ - 1075, - 326 - ], - "size": { - "0": 315, - "1": 82 - }, - "flags": {}, - "order": 19, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGES", - "link": 24 - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 20 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "XYPlot" - }, - "widgets_values": [ - 10, + 1, + false, + 20, + 8, + "dpmpp_sde", + "karras", 1 ] }, @@ -807,15 +458,18 @@ "id": 36, "type": "KSampler", "pos": [ - -214, - 915 + -211, + 898 ], "size": { "0": 315, "1": 262 }, - "flags": {}, - "order": 10, + "flags": { + "collapsed": false, + "pinned": true + }, + "order": 11, "mode": 0, "inputs": [ { @@ -844,7 +498,7 @@ "name": "LATENT", "type": "LATENT", "links": [ - 58 + 79 ], "slot_index": 0 } @@ -861,57 +515,263 @@ "karras", 1 ] + }, + { + "id": 29, + "type": "Reroute", + "pos": [ + -360, + 117 + ], + "size": [ + 82, + 26 + ], + "flags": { + "pinned": true + }, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": 44, + "slot_index": 0 + } + ], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 70, + 71, + 72 + ], + "slot_index": 0 + } + ], + "properties": { + "showOutputText": true, + "horizontal": false + } + }, + { + "id": 56, + "type": "ImagesGridByColumns", + "pos": [ + 849, + 450 + ], + "size": [ + 315, + 82 + ], + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 94 + }, + { + "name": "max_columns", + "type": "INT", + "link": 102, + "widget": { + "name": "max_columns", + "config": [ + "INT", + { + "default": 1, + "min": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 95 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ImagesGridByColumns" + }, + "widgets_values": [ + 0, + 4 + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 15, + "type": "PreviewImage", + "pos": [ + 1267, + 450 + ], + "size": { + "0": 601.5753173828125, + "1": 479.24884033203125 + }, + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 95 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 42, + "type": "LatentCombine", + "pos": [ + 266, + 446 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "latent_1", + "type": "LATENT", + "link": 73, + "slot_index": 0 + }, + { + "name": "latent_2", + "type": "LATENT", + "link": 74, + "slot_index": 1 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 80 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "LatentCombine" + }, + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 59, + "type": "PrimitiveNode", + "pos": [ + -1081, + 1086 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": { + "collapsed": false + }, + "order": 1, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 100, + 102 + ], + "slot_index": 0, + "widget": { + "name": "max_columns", + "config": [ + "INT", + { + "default": 1, + "min": 1 + } + ] + } + } + ], + "title": "Y items count", + "properties": {}, + "widgets_values": [ + 4, + false + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 44, + "type": "LatentCombine", + "pos": [ + 265, + 530 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "latent_1", + "type": "LATENT", + "link": 80 + }, + { + "name": "latent_2", + "type": "LATENT", + "link": 79 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 88 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "LatentCombine" + }, + "color": "#322", + "bgcolor": "#533" } ], "links": [ - [ - 12, - 10, - 0, - 12, - 0, - "IMAGES" - ], - [ - 13, - 11, - 0, - 12, - 1, - "IMAGES" - ], - [ - 20, - 17, - 0, - 15, - 0, - "IMAGE" - ], - [ - 22, - 18, - 0, - 19, - 1, - "IMAGES" - ], - [ - 24, - 19, - 0, - 17, - 0, - "IMAGES" - ], - [ - 32, - 12, - 0, - 19, - 0, - "IMAGES" - ], [ 35, 24, @@ -968,38 +828,6 @@ 1, "CONDITIONING" ], - [ - 49, - 27, - 0, - 32, - 0, - "LATENT" - ], - [ - 50, - 31, - 0, - 34, - 0, - "LATENT" - ], - [ - 51, - 32, - 0, - 10, - 0, - "IMAGE" - ], - [ - 53, - 34, - 0, - 11, - 0, - "IMAGE" - ], [ 54, 25, @@ -1016,22 +844,6 @@ 2, "CONDITIONING" ], - [ - 58, - 36, - 0, - 37, - 0, - "LATENT" - ], - [ - 59, - 37, - 0, - 18, - 0, - "IMAGE" - ], [ 60, 38, @@ -1064,38 +876,6 @@ 0, "*" ], - [ - 64, - 40, - 0, - 32, - 1, - "VAE" - ], - [ - 65, - 40, - 0, - 34, - 1, - "VAE" - ], - [ - 66, - 40, - 0, - 37, - 1, - "VAE" - ], - [ - 67, - 39, - 0, - 40, - 0, - "*" - ], [ 69, 24, @@ -1127,10 +907,98 @@ 36, 0, "MODEL" + ], + [ + 73, + 27, + 0, + 42, + 0, + "LATENT" + ], + [ + 74, + 31, + 0, + 42, + 1, + "LATENT" + ], + [ + 76, + 40, + 0, + 43, + 1, + "VAE" + ], + [ + 77, + 39, + 0, + 40, + 0, + "*" + ], + [ + 79, + 36, + 0, + 44, + 1, + "LATENT" + ], + [ + 80, + 42, + 0, + 44, + 0, + "LATENT" + ], + [ + 88, + 44, + 0, + 43, + 0, + "LATENT" + ], + [ + 94, + 43, + 0, + 56, + 0, + "IMAGE" + ], + [ + 95, + 56, + 0, + 15, + 0, + "IMAGE" + ], + [ + 100, + 59, + 0, + 38, + 0, + "INT" + ], + [ + 102, + 59, + 0, + 56, + 1, + "INT" ] ], "groups": [], "config": {}, "extra": {}, "version": 0.4 -} +} \ No newline at end of file diff --git a/workflows/base.png b/workflows/base.png new file mode 100644 index 0000000..7f43905 Binary files /dev/null and b/workflows/base.png differ diff --git a/workflows/xy_plot_mini.json b/workflows/mini.json similarity index 53% rename from workflows/xy_plot_mini.json rename to workflows/mini.json index 9d12f01..ff752a9 100644 --- a/workflows/xy_plot_mini.json +++ b/workflows/mini.json @@ -1,218 +1,7 @@ { - "last_node_id": 44, - "last_link_id": 75, + "last_node_id": 56, + "last_link_id": 97, "nodes": [ - { - "id": 15, - "type": "PreviewImage", - "pos": [ - 1435, - 325 - ], - "size": { - "0": 363.55511474609375, - "1": 290.6986999511719 - }, - "flags": {}, - "order": 9, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 20 - } - ], - "properties": { - "Node name for S&R": "PreviewImage" - } - }, - { - "id": 10, - "type": "ImageSetArea", - "pos": [ - 437, - 307 - ], - "size": { - "0": 216.59999084472656, - "1": 26 - }, - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 73 - } - ], - "outputs": [ - { - "name": "IMAGES", - "type": "IMAGES", - "links": [ - 12 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "ImageSetArea" - } - }, - { - "id": 12, - "type": "FloatImageCombine", - "pos": [ - 711, - 301 - ], - "size": { - "0": 317.4000244140625, - "1": 46 - }, - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [ - { - "name": "float_image_1", - "type": "IMAGES", - "link": 12 - }, - { - "name": "float_image_2", - "type": "IMAGES", - "link": 13 - } - ], - "outputs": [ - { - "name": "IMAGES", - "type": "IMAGES", - "links": [ - 32 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "FloatImageCombine" - } - }, - { - "id": 19, - "type": "FloatImageCombine", - "pos": [ - 712, - 387 - ], - "size": { - "0": 317.4000244140625, - "1": 46 - }, - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [ - { - "name": "float_image_1", - "type": "IMAGES", - "link": 32 - }, - { - "name": "float_image_2", - "type": "IMAGES", - "link": 22 - } - ], - "outputs": [ - { - "name": "IMAGES", - "type": "IMAGES", - "links": [ - 24 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "FloatImageCombine" - } - }, - { - "id": 11, - "type": "ImageSetArea", - "pos": [ - 441, - 372 - ], - "size": { - "0": 216.59999084472656, - "1": 26 - }, - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 74, - "slot_index": 0 - } - ], - "outputs": [ - { - "name": "IMAGES", - "type": "IMAGES", - "links": [ - 13 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "ImageSetArea" - } - }, - { - "id": 18, - "type": "ImageSetArea", - "pos": [ - 439, - 439 - ], - "size": { - "0": 216.59999084472656, - "1": 26 - }, - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 75 - } - ], - "outputs": [ - { - "name": "IMAGES", - "type": "IMAGES", - "links": [ - 22 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "ImageSetArea" - } - }, { "id": 41, "type": "LoadImage", @@ -232,7 +21,7 @@ "name": "IMAGE", "type": "IMAGE", "links": [ - 73 + 90 ], "slot_index": 0 }, @@ -250,6 +39,43 @@ "image" ] }, + { + "id": 42, + "type": "LoadImage", + "pos": [ + 69, + 449 + ], + "size": { + "0": 315, + "1": 102 + }, + "flags": {}, + "order": 1, + "mode": 0, + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 91 + ], + "slot_index": 0 + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "ComfyUI_00153_.png", + "image" + ] + }, { "id": 43, "type": "LoadImage", @@ -269,7 +95,7 @@ "name": "IMAGE", "type": "IMAGE", "links": [ - 75 + 94 ], "slot_index": 0 }, @@ -288,24 +114,134 @@ ] }, { - "id": 17, - "type": "XYPlot", + "id": 54, + "type": "ImageCombine", "pos": [ - 1075, - 326 + 460, + 350 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "image_1", + "type": "IMAGE", + "link": 90 + }, + { + "name": "image_2", + "type": "IMAGE", + "link": 91 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 93 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ImageCombine" + }, + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 55, + "type": "ImageCombine", + "pos": [ + 460, + 440 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "image_1", + "type": "IMAGE", + "link": 93 + }, + { + "name": "image_2", + "type": "IMAGE", + "link": 94 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 95 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ImageCombine" + }, + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 56, + "type": "PreviewImage", + "pos": [ + 1059, + 350 + ], + "size": [ + 428.921914672851, + 507.1954368591306 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 97 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 53, + "type": "ImagesGridByColumns", + "pos": [ + 700, + 350 ], "size": { "0": 315, "1": 82 }, "flags": {}, - "order": 8, + "order": 5, "mode": 0, "inputs": [ { "name": "images", - "type": "IMAGES", - "link": 24 + "type": "IMAGE", + "link": 95, + "slot_index": 0 } ], "outputs": [ @@ -313,127 +249,68 @@ "name": "IMAGE", "type": "IMAGE", "links": [ - 20 + 97 ], "slot_index": 0 } ], "properties": { - "Node name for S&R": "XYPlot" + "Node name for S&R": "ImagesGridByColumns" }, "widgets_values": [ - 10, + 5, 2 - ] - }, - { - "id": 42, - "type": "LoadImage", - "pos": [ - 69, - 449 ], - "size": { - "0": 315, - "1": 102 - }, - "flags": {}, - "order": 1, - "mode": 0, - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 74 - ], - "slot_index": 0 - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "properties": { - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "ComfyUI_00153_.png", - "image" - ] + "color": "#322", + "bgcolor": "#533" } ], "links": [ [ - 12, - 10, - 0, - 12, - 0, - "IMAGES" - ], - [ - 13, - 11, - 0, - 12, - 1, - "IMAGES" - ], - [ - 20, - 17, - 0, - 15, - 0, - "IMAGE" - ], - [ - 22, - 18, - 0, - 19, - 1, - "IMAGES" - ], - [ - 24, - 19, - 0, - 17, - 0, - "IMAGES" - ], - [ - 32, - 12, - 0, - 19, - 0, - "IMAGES" - ], - [ - 73, + 90, 41, 0, - 10, + 54, 0, "IMAGE" ], [ - 74, + 91, 42, 0, - 11, + 54, + 1, + "IMAGE" + ], + [ + 93, + 54, + 0, + 55, 0, "IMAGE" ], [ - 75, + 94, 43, 0, - 18, + 55, + 1, + "IMAGE" + ], + [ + 95, + 55, + 0, + 53, + 0, + "IMAGE" + ], + [ + 97, + 53, + 0, + 56, 0, "IMAGE" ] @@ -442,4 +319,4 @@ "config": {}, "extra": {}, "version": 0.4 -} +} \ No newline at end of file diff --git a/workflows/mini.png b/workflows/mini.png new file mode 100644 index 0000000..02355b6 Binary files /dev/null and b/workflows/mini.png differ diff --git a/workflows/xy_plot_base.png b/workflows/xy_plot_base.png deleted file mode 100644 index efc6398..0000000 Binary files a/workflows/xy_plot_base.png and /dev/null differ diff --git a/workflows/xy_plot_mini.png b/workflows/xy_plot_mini.png deleted file mode 100644 index 2832dff..0000000 Binary files a/workflows/xy_plot_mini.png and /dev/null differ