diff --git a/__init__.py b/__init__.py index 5296e16..073d019 100644 --- a/__init__.py +++ b/__init__.py @@ -8,7 +8,7 @@ from .nodes.Aspect_Ratio_and_Tile_size_calculator import NODE_CLASS_MAPPINGS as from .nodes.blipimagecaptioning import NODE_CLASS_MAPPINGS as BLIP_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as BLIP_DISPLAY_MAPPINGS from .nodes.BooleanToggleNode import NODE_CLASS_MAPPINGS as TOGGLE_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as TOGGLE_DISPLAY_MAPPINGS from .nodes.concatenate_and_test_if_empty import NODE_CLASS_MAPPINGS as CONCAT_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as CONCAT_DISPLAY_MAPPINGS -from .nodes.ImageBasicNode import NODE_CLASS_MAPPINGS as BASIC_MAPPINGS +from .nodes.ImageBasicNode import NODE_CLASS_MAPPINGS as BASIC_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as BASIC_DISPLAY_MAPPINGS # Combine all Node Mappings NODE_CLASS_MAPPINGS = {} @@ -30,12 +30,13 @@ NODE_CLASS_MAPPINGS.update(CONCAT_MAPPINGS) NODE_DISPLAY_NAME_MAPPINGS.update(CONCAT_DISPLAY_MAPPINGS) NODE_CLASS_MAPPINGS.update(BASIC_MAPPINGS) +NODE_DISPLAY_NAME_MAPPINGS.update(BASIC_DISPLAY_MAPPINGS) # Exportiere alle Node-Mappings für ComfyUI __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] # Metadaten -__version__ = "1.0.0" +__version__ = "1.0.5" __author__ = "Skycoder" __description__ = "A collection of useful custom nodes for ComfyUI workflows" __license__ = "MIT" diff --git a/nodes/ImageBasicNode.py b/nodes/ImageBasicNode.py index 3ee24e1..0c76584 100644 --- a/nodes/ImageBasicNode.py +++ b/nodes/ImageBasicNode.py @@ -1,6 +1,7 @@ from PIL import Image import numpy as np import torch +import math class ImageBasicNode: @classmethod @@ -8,17 +9,21 @@ class ImageBasicNode: return { "required": { "image": ("IMAGE",), # ComfyUI-internes Bildobjekt - "operation": (["no operation", "resize", "grayscale"],), # Auswahlfunktion + "resize": ("BOOLEAN", {"default": False}), + "grayscale": ("BOOLEAN", {"default": False}), "keep_aspect_ratio": ("BOOLEAN", {"default": True}), + "resize_mode": (["by_dimensions", "by_megapixel"], {"default": "by_megapixel"}), }, "optional": { + "target_megapixel": ("FLOAT", {"default": 1.0, "step":0.1, "min": 0.1}), "new_width": ("INT", {"default": 256, "min": 1, "max": 4096}), "new_height": ("INT", {"default": 256, "min": 1, "max": 4096}), + "divisible_by": ([1, 2, 4, 8, 16, 32, 64], {"default": 1}), } } RETURN_TYPES = ("INT", "INT", "FLOAT", "STRING", "STRING", "IMAGE") - RETURN_NAMES = ("width", "height", "ratio", "mode", "format", "output_image") + RETURN_NAMES = ("width", "height", "ratio", "aspect_type", "aspect_ratio_common", "output_image") FUNCTION = "process_image" CATEGORY = "Beispiele/Bild" @@ -44,46 +49,70 @@ class ImageBasicNode: avg = int(0.299 * R + 0.587 * G + 0.114 * B) px[x,y] = (avg, avg, avg) #print(value) - return + return image - def correctDimensions(self, width, height, ratio): - if ratio > width / height: - o_width = int(width) - o_height = int(width / ratio) - elif ratio <= width / height: - o_width = int(height * ratio) - o_height = int(height) + def correctDimensions(self, width, height, ratio, target_megapixel): + target_pixel = target_megapixel * 1000000 + o_height = int(math.sqrt(target_pixel/ratio)) + o_width = int(ratio * o_height) return (o_width, o_height) - def process_image(self, image, operation, keep_aspect_ratio, new_width=None, new_height=None): + def process_image(self, image, resize, grayscale, keep_aspect_ratio, resize_mode="by_megapixel", target_megapixel=1.0, new_width=None, new_height=None, divisible_by=1): # ComfyUI gibt ein numpy-Array zurück, PIL braucht das als Image pil_image = self.tensor2pil(image) - + round_to = int(divisible_by) width, height = pil_image.size ratio = width / height output_image = pil_image # Default - if operation == "resize" and new_width and new_height: - if keep_aspect_ratio: - new_width, new_height = self.correctDimensions(new_width, new_height, ratio) + if resize: + if resize_mode == "by_megapixel" and target_megapixel: + new_width, new_height = self.correctDimensions(width, height, ratio, target_megapixel) + + elif resize_mode == "by_dimensions" and new_width and new_height: + if keep_aspect_ratio: + if new_width / new_height > ratio: + new_width = int(new_height * ratio) + else: + new_height = int(new_width / ratio) + + else: + new_width, new_height = 256, 256 + if keep_aspect_ratio: + if new_width / new_height > ratio: + new_width = int(new_height * ratio) + else: + new_height = int(new_width / ratio) + + # Apply user-selected rounding + new_width = max(round_to, round(new_width / round_to) * round_to) + new_height = max(round_to, round(new_height / round_to) * round_to) - output_image = pil_image.resize((new_width, new_height)) + output_image = pil_image.resize((new_width, new_height), Image.Resampling.LANCZOS) width, height = output_image.size - # (Wenn nicht resized wird, bleibt Bild wie es ist) - - elif operation == "grayscale": - self.bwimage(output_image) + + # grayscale if checkbox is set + if grayscale: + output_image = self.bwimage(output_image) ratio = width / height - mode = output_image.mode - form = output_image.format + + gcd = math.gcd(width, height) + gcd_w = width // gcd + gcd_h = height // gcd + aspect_ratio_common = f"{gcd_w}:{gcd_h}" + aspect_type = "landscape" if ratio > 1 else "portrait" if ratio < 1 else "square" + # Für ComfyUI zurück in Tensor wandeln img_tensor = self.pil2tensor(output_image) - return (width, height, ratio, mode, form, img_tensor) + return (width, height, ratio, aspect_type, aspect_ratio_common, img_tensor) NODE_CLASS_MAPPINGS = { "ImageBasicNode": ImageBasicNode, } +NODE_DISPLAY_NAME_MAPPINGS = { + "ImageBasicNode": "Image Advanced Resize", +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index b604c34..f801b3e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "comfyui-skycoder-tools" -version = "1.0.4" +version = "1.0.5" description = "A collection of useful custom nodes for ComfyUI workflows" authors = [ {name = "Skycoder182", email = "skycoder@example.com"}