From bb67ea6878fb1d9d99a17edd3bdb16ce30c5f901 Mon Sep 17 00:00:00 2001 From: RyanOnTheInside <7623207+ryanontheinside@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:28:11 -0400 Subject: [PATCH] flex image horizontal to vertical --- __init__.py | 2 + node_configs/node_configs.py | 28 +++++++++ nodes/images/flex_images.py | 113 +++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- readme.md | 1 + 5 files changed, 145 insertions(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index f562581..e6f6d1e 100644 --- a/__init__.py +++ b/__init__.py @@ -210,6 +210,7 @@ from .nodes.images.flex_images import ( FlexImageTransform, FlexImageHueShift, FlexImageDepthWarp, + FlexImageHorizontalToVertical, ) from .nodes.video.flex_video import ( @@ -426,6 +427,7 @@ NODE_CLASS_MAPPINGS = { "FlexImageTransform": FlexImageTransform, "FlexImageHueShift": FlexImageHueShift, "FlexImageDepthWarp": FlexImageDepthWarp, + "FlexImageHorizontalToVertical":FlexImageHorizontalToVertical, #opacity xp # "FlexDepthBasedMaskOpacity": FlexDepthBasedMaskOpacity, # "DepthBasedMaskOpacity": DepthBasedMaskOpacity, diff --git a/node_configs/node_configs.py b/node_configs/node_configs.py index 32fa517..e7e19ac 100644 --- a/node_configs/node_configs.py +++ b/node_configs/node_configs.py @@ -1163,6 +1163,34 @@ Note: Extreme hue shifts may produce unexpected colors, especially for hues that """ }) +add_node_config("FlexImageHorizontalToVertical", { + "TOP_DESCRIPTION": "Converts horizontal images to vertical format with customizable background effects.", + "ADDITIONAL_INFO": """ +- Inherits base parameters from FlexImageBase: + - `images`: Input image sequence (IMAGE type) + - `feature`: Feature used to modulate the effect (FEATURE type) + - `strength`: Overall strength of the effect (0.0 to 1.0) + - `feature_threshold`: Minimum feature value to apply the effect (0.0 to 1.0) + +Additional Parameters: +- `blur_amount`: Amount of blur for background when using blur effect (0.1 to 100.0) +- `background_type`: Type of background effect to apply: + - "blur": Blurred version of original image + - "border": Solid color border + - "mirror": Mirrored version of the image + - "gradient": Gradient based on image colors + - "pixelate": Pixelated version of the image + - "waves": Wavy distortion effect +- `border_color`: Color of the border when using border background type ("black" or "white") +- `scale_factor`: Scale factor for the main image (0.1 to 2.0). Controls how large the original image appears in the vertical format. +- `effect_strength`: Intensity of the background effect (0.0 to 2.0) + +This node converts horizontal images to a vertical 16:9 format while maintaining aspect ratio. It's particularly useful for adapting landscape content for vertical video platforms like TikTok, Instagram Reels, or YouTube Shorts. + +The node only processes images that are wider than they are tall (horizontal). Vertical images pass through unchanged. +""" +}) + add_node_config("FlexImageContrast", { "TOP_DESCRIPTION": "Adjusts the contrast and brightness of the image, with an option to preserve luminosity.", "ADDITIONAL_INFO": """ diff --git a/nodes/images/flex_images.py b/nodes/images/flex_images.py index 012ab7a..a20f103 100644 --- a/nodes/images/flex_images.py +++ b/nodes/images/flex_images.py @@ -721,3 +721,116 @@ class FlexImageDepthWarp(FlexImageBase): else: print("Warning: No depth map provided.") return image + +class FlexImageHorizontalToVertical(FlexImageBase): + @classmethod + def INPUT_TYPES(cls): + base_inputs = super().INPUT_TYPES() + base_inputs["required"].update({ + "blur_amount": ("FLOAT", {"default": 30.0, "min": 0.1, "max": 100.0, "step": 0.1}), + "background_type": (["blur", "border", "mirror", "gradient", "pixelate", "waves"], {"default": "blur"}), + "border_color": (["black", "white"], {"default": "black"}), + "scale_factor": ("FLOAT", {"default": 1.0, "min": 0.1, "max": 2.0, "step": 0.01}), # Updated max to 2.0 + "effect_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.01}), + }) + return base_inputs + + @classmethod + def get_modifiable_params(cls): + return ["blur_amount", "scale_factor", "effect_strength", "None"] + + def apply_effect_internal(self, image: np.ndarray, blur_amount: float, background_type: str, + border_color: str, scale_factor: float, effect_strength: float, **kwargs) -> np.ndarray: + # Ensure parameters are within valid ranges after modulation + blur_amount = max(0.1, blur_amount) + scale_factor = np.clip(scale_factor, 0.1, 2.0) # Updated max to 2.0 + effect_strength = np.clip(effect_strength, 0.0, 2.0) + + h, w = image.shape[:2] + + # Only process if image is horizontal + if w <= h: + return image + + # Calculate new dimensions maintaining aspect ratio + new_h = h + new_w = int(h * 9/16) # Standard vertical aspect ratio (16:9 inverted) + + # Calculate scaling for the original image + scale = scale_factor * min(new_w / w, new_h / h) + scaled_w = int(w * scale) + scaled_h = int(h * scale) + + # Create base canvas + if border_color == "white": + result = np.ones((new_h, new_w, 3), dtype=np.float32) + else: # black + result = np.zeros((new_h, new_w, 3), dtype=np.float32) + + # Apply background effect + if background_type == "blur": + background = cv2.resize(image, (new_w, new_h)) + try: + background = cv2.GaussianBlur(background, (0, 0), blur_amount) + except cv2.error: + print(f"Warning: Blur failed with amount {blur_amount}, using minimum blur") + background = cv2.GaussianBlur(background, (0, 0), 0.1) + result = background + + elif background_type == "mirror": + # Create mirrored background + background = cv2.resize(image, (new_w, new_h)) + flipped = cv2.flip(background, 1) + alpha = np.linspace(0, 1, new_w) + alpha = np.tile(alpha, (new_h, 1)) + result = background * alpha[:,:,np.newaxis] + flipped * (1 - alpha[:,:,np.newaxis]) + + elif background_type == "gradient": + # Create gradient background using original image colors + resized = cv2.resize(image, (new_w, new_h)) + avg_color = np.mean(resized, axis=(0,1)) + gradient = np.linspace(0, 1, new_h)[:,np.newaxis] + gradient = np.tile(gradient, (1, new_w)) + for c in range(3): + result[:,:,c] = gradient * avg_color[c] * effect_strength + + elif background_type == "pixelate": + # Create heavily pixelated background + pixel_size = max(1, int(20 * effect_strength)) + small = cv2.resize(image, (new_w // pixel_size, new_h // pixel_size)) + result = cv2.resize(small, (new_w, new_h), interpolation=cv2.INTER_NEAREST) + + elif background_type == "waves": + # Create wavy background + background = cv2.resize(image, (new_w, new_h)) + y, x = np.mgrid[0:new_h, 0:new_w] + frequency = 0.05 * effect_strength + waves = np.sin(x * frequency) * 10 * effect_strength + for i in range(new_h): + shift = int(waves[i][0]) + result[i] = np.roll(background[i], shift, axis=0) + + # Scale original image + scaled_image = cv2.resize(image, (scaled_w, scaled_h)) + + # Calculate position to place scaled image + y_offset = (new_h - scaled_h) // 2 + x_offset = (new_w - scaled_w) // 2 + + # Compute regions for placement, handling possible cropping + y_start_img = max(0, -y_offset) + y_end_img = scaled_h - max(0, (y_offset + scaled_h) - new_h) + x_start_img = max(0, -x_offset) + x_end_img = scaled_w - max(0, (x_offset + scaled_w) - new_w) + + y_start_res = max(0, y_offset) + y_end_res = min(new_h, y_offset + scaled_h) + x_start_res = max(0, x_offset) + x_end_res = min(new_w, x_offset + scaled_w) + + # Place the valid region of the scaled image onto the result + result[y_start_res:y_end_res, x_start_res:x_end_res] = scaled_image[y_start_img:y_end_img, x_start_img:x_end_img] + + return np.clip(result, 0, 1) + + \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 0d9cc21..2260128 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui_ryanonyheinside" description = "Custom nodes introducing particle simulations, optical flow, audio manipulation & reactivity, and temporal masks" -version = "1.9.7" +version = "1.10.0" license = {file = "LICENSE"} dependencies = ["pygame","opencv-python==4.10.0","scipy","torchaudio", "pillow","librosa==0.10.2","pymunk==6.8.1","matplotlib","openunmix","mido"] diff --git a/readme.md b/readme.md index 241d516..a7c8925 100644 --- a/readme.md +++ b/readme.md @@ -38,6 +38,7 @@ *Examples showcasing various effects using particle emitters, vortices, and other node features* ##### 🆕 Recent Updates: +- 10/28/24 - **FlexImageHorizontalToVertical**: Converts horizontal images to vertical format with customizable background effects. - 10/23/24 - **Flex Images Now Feature Optional**: You no longer need to specify a feature to use Flex Image nodes. - 10/20/24 - **Audio Visualization Nodes**: Over 1 TRILLION ways to customize! - **FlexAudioVisualizerCircular**: Creates circular audio visualizations based on frequency or waveform data.