Merge pull request #2 from Meettya/feat/latent-scale-factor-config
Feat/latent scale factor config
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Karpich Dmitry
|
||||
Copyright (c) 2025-2026 Karpich Dmitry
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
## Image Fit Calculator
|
||||
|
||||
<img src="https://github.com/Meettya/ComfyUI-OneForOne-Demo/blob/b1f3ffa041d9b1f615553bb29ea2f74ded8b3b8b/examples/fit_calculator_node.jpg?raw=true" alt="Image Fit Calculator node" style="width: 50%; height: auto; display: block; margin-left: auto; margin-right: auto;">
|
||||
<img src="https://github.com/Meettya/ComfyUI-OneForOne-Demo/blob/cfc49d3046acfc5e6d8c1e68a2dc3662d2f36475/examples/fit_calculator_node.jpg?raw=true" alt="Image Fit Calculator node" style="width: 50%; height: auto; display: block; margin-left: auto; margin-right: auto;">
|
||||
|
||||
<br/>
|
||||
|
||||
The ComfyUI custom node **Image Fit Calculator** is designed to automatically calculate new image parameters based on a given latent and original image. Specifically, this node can perform calculations for resizing an image and provide data for paddings to control its placement within the latent space. Additionally, it includes settings that allow users to specify horizontal or vertical offsets as well as reduce the size of the image. This node performs only computational tasks, while actual operations on the image may be carried out by external nodes if they have the capability to use input data to manipulate the result.
|
||||
|
||||
<img src="https://github.com/Meettya/ComfyUI-OneForOne-Demo/blob/b1f3ffa041d9b1f615553bb29ea2f74ded8b3b8b/examples/fit_calculator.jpg?raw=true" alt="Image Fit Calculator example" style="display: block; margin-left: auto; margin-right: auto;">
|
||||
<img src="https://github.com/Meettya/ComfyUI-OneForOne-Demo/blob/cfc49d3046acfc5e6d8c1e68a2dc3662d2f36475/examples/fit_calculator.jpg?raw=true" alt="Image Fit Calculator example" style="display: block; margin-left: auto; margin-right: auto;">
|
||||
|
||||
In the provided workflow example, one can see how the ComfyUI node integrates with other components to streamline the process of image manipulation. This modular approach ensures flexibility and extensibility, enabling developers to easily incorporate new functionalities or optimize existing ones.
|
||||
|
||||

|
||||

|
||||
|
||||
If you encounter any bugs or have ideas for improving the ComfyUI node, feel free to create an issue or submit a pull request. Your contributions are highly appreciated and will help enhance this powerful tool for image processing automation.
|
||||
|
||||
|
||||
+51
-14
@@ -1,7 +1,15 @@
|
||||
from numpy import ndarray
|
||||
from typing import Union
|
||||
|
||||
from .util import get_sizes
|
||||
from .util import get_latent_size, get_image_size
|
||||
|
||||
SCALE_8X = "SD, Qwen (8x)"
|
||||
SCALE_16X = "Flux2 (16x)"
|
||||
SCALE_OPTIONS = [SCALE_8X, SCALE_16X]
|
||||
SCALE_FACTOR_MAP = {
|
||||
SCALE_8X: 8,
|
||||
SCALE_16X: 16,
|
||||
}
|
||||
|
||||
|
||||
class OFOImageFit:
|
||||
@@ -11,7 +19,11 @@ class OFOImageFit:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {"latent": ("LATENT",), "image": ("IMAGE",)},
|
||||
"required": {
|
||||
"latent": ("LATENT",),
|
||||
"image": ("IMAGE",),
|
||||
"latent_scale": (SCALE_OPTIONS, {"default": SCALE_8X}),
|
||||
},
|
||||
"optional": {
|
||||
"width_position": (
|
||||
"FLOAT",
|
||||
@@ -76,6 +88,7 @@ class OFOImageFit:
|
||||
self,
|
||||
latent: Union[dict, ndarray],
|
||||
image: ndarray,
|
||||
latent_scale: str,
|
||||
width_position: float = 0.5,
|
||||
height_position: float = 0.5,
|
||||
scale: float = 1.0,
|
||||
@@ -86,6 +99,7 @@ class OFOImageFit:
|
||||
Args:
|
||||
latent (np.ndarray or dict): Latent representation or dictionary containing latent samples.
|
||||
image (np.ndarray): Input image to be resized and padded.
|
||||
latent_scale (str): Latent scale factor option. "SD, Qwen (8x)" or "Flux2 (16x)".
|
||||
width_position (float, optional): Horizontal position where the image will be placed within the latent space. Defaults to 0.5.
|
||||
height_position (float, optional): Vertical position where the image will be placed within the latent space. Defaults to 0.5.
|
||||
scale (float, optional): Scaling factor applied to the image before resizing. Defaults to 1.0.
|
||||
@@ -93,24 +107,47 @@ class OFOImageFit:
|
||||
Returns:
|
||||
tuple: A tuple containing six integers representing the new width, height, top, right, bottom, and left padding values.
|
||||
"""
|
||||
# get sizes
|
||||
latent_height, latent_width = get_sizes(latent)
|
||||
image_height, image_width = get_sizes(image)
|
||||
scale_factor = SCALE_FACTOR_MAP[latent_scale]
|
||||
|
||||
# get minimum scale
|
||||
latent_height, latent_width = get_latent_size(latent, scale_factor)
|
||||
image_height, image_width = get_image_size(image)
|
||||
|
||||
# Compute base scaling (fit inside latent)
|
||||
scale_w = latent_width / image_width
|
||||
scale_h = latent_height / image_height
|
||||
min_scale = min(scale_w, scale_h) * scale
|
||||
|
||||
# scale image
|
||||
new_image_width = round(image_width * min_scale)
|
||||
new_image_height = round(image_height * min_scale)
|
||||
# Initial candidate dimensions (floored to avoid exceeding latent)
|
||||
raw_width = int(image_width * min_scale)
|
||||
raw_height = int(image_height * min_scale)
|
||||
|
||||
# calculate padding
|
||||
padding_left = round((latent_width - new_image_width) * width_position)
|
||||
padding_right = latent_width - new_image_width - padding_left
|
||||
padding_bottom = round((latent_height - new_image_height) * height_position)
|
||||
padding_top = latent_height - new_image_height - padding_bottom
|
||||
# Ensure raw dimensions do not exceed latent bounds (safety)
|
||||
raw_width = min(raw_width, latent_width)
|
||||
raw_height = min(raw_height, latent_height)
|
||||
|
||||
# ----- Adjust to multiples of 8 -----
|
||||
# We prefer rounding down to the nearest multiple of 8 (keep inside latent).
|
||||
# But we also need to ensure we don't lose too much size.
|
||||
# Let's find the largest multiple of 8 <= raw_width and <= raw_height.
|
||||
target_width = (raw_width // 8) * 8
|
||||
target_height = (raw_height // 8) * 8
|
||||
|
||||
# However, if the difference is too large (more than 7 pixels), we could try rounding up if still fits.
|
||||
# But to be safe and keep exact fit, we just round down.
|
||||
# If rounding down reduces size too much, the user can increase `scale`.
|
||||
new_image_width = target_width
|
||||
new_image_height = target_height
|
||||
|
||||
# ----- Recompute paddings based on final aligned sizes -----
|
||||
# Horizontal padding
|
||||
remaining_width = latent_width - new_image_width
|
||||
padding_left = int(remaining_width * width_position)
|
||||
padding_right = remaining_width - padding_left
|
||||
|
||||
# Vertical padding
|
||||
remaining_height = latent_height - new_image_height
|
||||
padding_top = int(remaining_height * height_position)
|
||||
padding_bottom = remaining_height - padding_top
|
||||
|
||||
return (
|
||||
new_image_width,
|
||||
|
||||
+9
-11
@@ -1,14 +1,12 @@
|
||||
from numpy import ndarray
|
||||
from typing import Union, Tuple
|
||||
|
||||
# latent to pixel scale factor
|
||||
SCALE = 8
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
def get_sizes(target: Union[dict, ndarray]) -> Tuple[int, int]:
|
||||
if isinstance(target, dict) and "samples" in target:
|
||||
# Latent height, width
|
||||
return (target["samples"].shape[2] * SCALE, target["samples"].shape[3] * SCALE)
|
||||
else:
|
||||
# Image height, width
|
||||
return (target.shape[1], target.shape[2])
|
||||
def get_latent_size(latent: dict, scale_factor: int = 8) -> Tuple[int, int]:
|
||||
"""Convert latent dimensions to pixel dimensions using scale factor."""
|
||||
return (latent["samples"].shape[2] * scale_factor, latent["samples"].shape[3] * scale_factor)
|
||||
|
||||
|
||||
def get_image_size(image: ndarray) -> Tuple[int, int]:
|
||||
"""Get image height and width from numpy array."""
|
||||
return (image.shape[1], image.shape[2])
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui-oneforone"
|
||||
description = "Node:Image Fit Calculator"
|
||||
version = "1.0.1"
|
||||
version = "2.0.1"
|
||||
license = {file = "LICENSE"}
|
||||
dependencies = ["numpy"]
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user