diff --git a/README.md b/README.md index 9fe4b42..c78bf96 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,8 @@ This repository offers various extension nodes for ComfyUI. Nodes here have diff * The color value can only be in the form of a hex code like #FFFF00 or a decimal number. * Image Util - * `Load Images From Dir (Inspire)`: This is almost same as `LoadImagesFromDirectory` of [ComfyUI-Advanced-Controlnet](https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet). This is just a modified version. Just note that this node forcibly normalizes the size of the loaded image to match the size of the first image, even if they are not the same size, to create a batch image. + * `Load Image Batch From Dir (Inspire)`: This is almost same as `LoadImagesFromDirectory` of [ComfyUI-Advanced-Controlnet](https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet). This is just a modified version. Just note that this node forcibly normalizes the size of the loaded image to match the size of the first image, even if they are not the same size, to create a batch image. + * `Load Image List From Dir (Inspire)`: This is almost same as `Load Image Batch From Dir (Inspire)`. However, note that this node loads data in a list format, not as a batch, so it returns images at their original size without normalizing the size. * `Load Image (Inspire)`: This node is similar to LoadImage, but the loaded image information is stored in the workflow. The image itself is stored in the workflow, making it easier to reproduce image generation on other computers. * KSampler Progress - In KSampler, the sampling process generates latent batches. By using `Video Combine` node from [ComfyUI-VideoHelperSuite](https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite), you can create a video from the progress. diff --git a/__init__.py b/__init__.py index 43e938d..985e3f3 100644 --- a/__init__.py +++ b/__init__.py @@ -7,7 +7,7 @@ import importlib -print(f"### Loading: ComfyUI-Inspire-Pack (V0.36)") +print(f"### Loading: ComfyUI-Inspire-Pack (V0.37)") node_list = [ "lora_block_weight", diff --git a/image_util.py b/image_util.py index 22ca927..e1ee513 100644 --- a/image_util.py +++ b/image_util.py @@ -8,7 +8,7 @@ import folder_paths import base64 from io import BytesIO -class LoadImagesFromDir: +class LoadImagesFromDirBatch: @classmethod def INPUT_TYPES(s): return { @@ -81,6 +81,75 @@ class LoadImagesFromDir: return (image1, len(images)) +class LoadImagesFromDirList: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "directory": ("STRING", {"default": ""}), + }, + "optional": { + "image_load_cap": ("INT", {"default": 0, "min": 0, "step": 1}), + "start_index": ("INT", {"default": 0, "min": 0, "step": 1}), + } + } + + RETURN_TYPES = ("IMAGE", "MASK") + OUTPUT_IS_LIST = (True, True) + + FUNCTION = "load_images" + + CATEGORY = "image" + + def load_images(self, directory: str, image_load_cap: int = 0, start_index: int = 0): + if not os.path.isdir(directory): + raise FileNotFoundError(f"Directory '{directory} cannot be found.'") + dir_files = os.listdir(directory) + if len(dir_files) == 0: + raise FileNotFoundError(f"No files in directory '{directory}'.") + + # Filter files by extension + valid_extensions = ['.jpg', '.jpeg', '.png', '.webp'] + dir_files = [f for f in dir_files if any(f.lower().endswith(ext) for ext in valid_extensions)] + + dir_files = sorted(dir_files) + dir_files = [os.path.join(directory, x) for x in dir_files] + + # start at start_index + dir_files = dir_files[start_index:] + + images = [] + masks = [] + + limit_images = False + if image_load_cap > 0: + limit_images = True + image_count = 0 + + for image_path in dir_files: + if os.path.isdir(image_path) and os.path.ex: + continue + if limit_images and image_count >= image_load_cap: + break + i = Image.open(image_path) + i = ImageOps.exif_transpose(i) + image = i.convert("RGB") + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + + if 'A' in i.getbands(): + mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0 + mask = 1. - torch.from_numpy(mask) + else: + mask = torch.zeros((64, 64), dtype=torch.float32, device="cpu") + + images.append(image) + masks.append(mask) + image_count += 1 + + return images, masks + + class LoadImageInspire: @classmethod def INPUT_TYPES(s): @@ -113,10 +182,12 @@ class LoadImageInspire: NODE_CLASS_MAPPINGS = { - "LoadImagesFromDir //Inspire": LoadImagesFromDir, + "LoadImagesFromDir //Inspire": LoadImagesFromDirBatch, + "LoadImageListFromDir //Inspire": LoadImagesFromDirList, "LoadImage //Inspire": LoadImageInspire, } NODE_DISPLAY_NAME_MAPPINGS = { - "LoadImagesFromDir //Inspire": "Load Images From Dir (Inspire)", + "LoadImagesFromDir //Inspire": "Load Image Batch From Dir (Inspire)", + "LoadImageListFromDir //Inspire": "Load Image List From Dir (Inspire)", "LoadImage //Inspire": "LoadImage (Inspire)", }