Files
2026-04-07 07:06:35 +03:00

146 lines
4.3 KiB
Python

from math import gcd
ASPECT_RATIO_PRESETS = {
"1:1": (1, 1),
"16:9": (16, 9),
"9:16": (9, 16),
"4:3": (4, 3),
"3:4": (3, 4),
"3:2": (3, 2),
"2:3": (2, 3),
"21:9": (21, 9),
"9:21": (9, 21),
"5:4": (5, 4),
"4:5": (4, 5),
"Custom": None,
}
def normalize_ratio(width, height):
width = max(1, int(width))
height = max(1, int(height))
divisor = gcd(width, height)
return width // divisor, height // divisor
def round_to_multiple(value, multiple):
return max(multiple, int(round(value / multiple)) * multiple)
def calculate_exact_resolution(ratio_width, ratio_height, multiple, size_step):
ratio_width, ratio_height = normalize_ratio(ratio_width, ratio_height)
multiple = max(1, int(multiple))
size_step = max(1, int(size_step))
base_width = multiple * ratio_width * size_step
base_height = multiple * ratio_height * size_step
return (
base_width,
base_height,
base_width * 2,
base_height * 2,
base_width * 4,
base_height * 4,
)
def calculate_approx_resolution(ratio_width, ratio_height, multiple, size_step):
ratio_width, ratio_height = normalize_ratio(ratio_width, ratio_height)
multiple = max(1, int(multiple))
size_step = max(1, int(size_step))
base_side = multiple * size_step
if ratio_width == ratio_height:
base_width = base_side
base_height = base_side
elif ratio_width > ratio_height:
base_width = base_side
base_height = round_to_multiple(base_width * ratio_height / ratio_width, multiple)
else:
base_height = base_side
base_width = round_to_multiple(base_height * ratio_width / ratio_height, multiple)
upscale_2x_width = base_width * 2
upscale_2x_height = base_height * 2
upscale_4x_width = base_width * 4
upscale_4x_height = base_height * 4
return (
base_width,
base_height,
upscale_2x_width,
upscale_2x_height,
upscale_4x_width,
upscale_4x_height,
)
class LTXResolutionHelperNode:
CATEGORY = "LTX/Helpers"
FUNCTION = "get_resolutions"
RETURN_TYPES = ("INT", "INT", "STRING")
RETURN_NAMES = ("base_width", "base_height", "summary")
DESCRIPTION = (
"Calculates a base resolution aligned to a chosen multiple "
"and shows the resulting sizes after two sequential 2x upscales."
)
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"aspect_ratio": (list(ASPECT_RATIO_PRESETS.keys()), {"default": "1:1"}),
"ratio_mode": (["Exact Ratio", "Approximate Max Side"], {"default": "Exact Ratio"}),
"custom_ratio_width": ("INT", {"default": 16, "min": 1, "max": 999, "step": 1}),
"custom_ratio_height": ("INT", {"default": 9, "min": 1, "max": 999, "step": 1}),
"multiple": ("INT", {"default": 32, "min": 1, "max": 512, "step": 1}),
"size_step": ("INT", {"default": 10, "min": 1, "max": 50, "step": 1}),
}
}
def get_resolutions(
self,
aspect_ratio,
ratio_mode,
custom_ratio_width,
custom_ratio_height,
multiple,
size_step,
):
if aspect_ratio == "Custom":
ratio_width, ratio_height = normalize_ratio(custom_ratio_width, custom_ratio_height)
else:
ratio_width, ratio_height = ASPECT_RATIO_PRESETS[aspect_ratio]
calculator = calculate_exact_resolution if ratio_mode == "Exact Ratio" else calculate_approx_resolution
(
base_width,
base_height,
upscale_2x_width,
upscale_2x_height,
upscale_4x_width,
upscale_4x_height,
) = calculator(ratio_width, ratio_height, multiple, size_step)
summary = (
f"mode {ratio_mode} | "
f"ratio {ratio_width}:{ratio_height} | "
f"base {base_width}x{base_height} | "
f"2x {upscale_2x_width}x{upscale_2x_height} | "
f"4x {upscale_4x_width}x{upscale_4x_height}"
)
return (base_width, base_height, summary)
NODE_CLASS_MAPPINGS = {
"LTXResolutionHelperNode": LTXResolutionHelperNode,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"LTXResolutionHelperNode": "LTX Resolution Helper",
}
WEB_DIRECTORY = "./js"