WASasquatch / was-node-suite-comfyui

An extensive node suite for ComfyUI with over 210 new nodes
MIT License
1.15k stars 170 forks source link

Request: Add in an image passthrough node (example & reason provided) #292

Open aegis72 opened 10 months ago

aegis72 commented 10 months ago

I hacked the "Image Batch" node to remove extraneous inputs and assigned it the name "image Pass" The reason for this is because I am heavily using the "Everything Anywhere" nodes to pass things around my workflow without wires, except inside discrete modules. I ran into an issue though where I needed to use a single selector to select both a filetype (string) and an image, and I also wanted the user to only have to change one target name (gen_image, here) to connect to a different sampler's output for this "MegaSaver" node group.

image

I couldn't find any node that would just accept an image input and then pass it long, one to many style as shown here (that gen_image" link is virtual, not an actual wire), until I came across image batch. But I don't really need all the rest of the stuff that "Image Batch" does...I just needed it to accept that virtual image input and then pass the image through to the other nodes that do preprocessing to turn the saved image into different stuff (lineart, etc)

This works, but is basically just your "image batch" node, renamed, with the extra inputs removed. Would be great to have an optimized node for this purpose in the official release.

# IMAGE PassThrough (Aegis)

class WAS_Image_Pass:
    def __init__(self):
        pass

    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
            },
            "optional": {
                "images_a": ("IMAGE",),
                # "images_b": ("IMAGE",),
                # "images_c": ("IMAGE",),
                # Theoretically, an infinite number of image input parameters can be added.
            },
        }

    RETURN_TYPES = ("IMAGE",)
    RETURN_NAMES = ("image",)
    FUNCTION = "image_pass"
    CATEGORY = "WAS Suite/Image"

    def _check_image_dimensions(self, tensors, names):
        dimensions = [tensor.shape for tensor in tensors]
        if len(set(dimensions)) > 1:
            mismatched_indices = [i for i, dim in enumerate(dimensions) if dim[1:] != dimensions[0][1:]]
            mismatched_images = [names[i] for i in mismatched_indices]
            if mismatched_images:
                raise ValueError(f"WAS Image pass Warning: Input image dimensions do not match for images: {mismatched_images}")

    def image_pass(self, **kwargs):
        batched_tensors = [kwargs[key] for key in kwargs if kwargs[key] is not None]
        image_names = [key for key in kwargs if kwargs[key] is not None]

        if not batched_tensors:
            raise ValueError("At least one input image must be provided.")

        self._check_image_dimensions(batched_tensors, image_names)
        batched_tensors = torch.cat(batched_tensors, dim=0)
        return (batched_tensors,)