Files

239 lines
6.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Size preset definitions and calculation logic for the ComfyUI Auto Size plugin.
"""
from __future__ import annotations
# ============================================================================
# Model Specifications
# ============================================================================
MODEL_SPECS: dict[str, int] = {
"qwen-image": 28,
"illustrious": 32,
"z-image": 32,
"flux": 32,
}
DEFAULT_MODEL: str = "qwen-image"
# ============================================================================
# Fixed Size Presets
# ============================================================================
QWEN_SIZES: dict[str, tuple[int, int]] = {
"1:1": (1328, 1328),
"9:16": (928, 1664),
"16:9": (1664, 928),
"3:4": (1104, 1472),
"4:3": (1472, 1104),
"2:3": (1056, 1584),
"3:2": (1584, 1056),
}
ILLUSTRIOUS_SIZES: dict[str, tuple[int, int]] = {
"1:1": (1024, 1024),
"9:16": (768, 1344),
"16:9": (1344, 768),
"13:19": (832, 1216),
"19:13": (1216, 832),
"9:7": (1152, 896),
"7:9": (896, 1152),
"12:5": (1536, 640),
"5:12": (640, 1536),
"2:3": (1024, 1536),
"4:5": (896, 1120),
"5:4": (1120, 896),
"3:4": (864, 1152),
"4:3": (1152, 864),
}
Z_IMAGE_SIZES: dict[str, tuple[int, int]] = {
"1:1": (1280, 1280),
"9:16": (896, 1600),
"16:9": (1600, 896),
"7:9": (1120, 1440),
"9:7": (1440, 1120),
"3:4": (1104, 1472),
"4:3": (1472, 1104),
"2:3": (1024, 1536),
"3:2": (1536, 1024),
"9:21": (720, 1680),
"21:9": (1680, 720),
}
FLUX_SIZES: dict[str, tuple[int, int]] = {
"1:1": (1024, 1024),
"9:16": (720, 1280),
"16:9": (1280, 720),
"7:9": (896, 1152),
"9:7": (1152, 896),
"3:4": (864, 1152),
"4:3": (1152, 864),
"2:3": (832, 1248),
"3:2": (1248, 832),
"9:21": (576, 1344),
"21:9": (1344, 576),
}
FAV_SIZES: dict[str, tuple[int, int]] = {
"1:1": (1536, 1536),
"9:7": (1728, 1344),
"7:9": (1344, 1728),
"3:2": (1824, 1248),
"2:3": (1248, 1824),
"16:9": (2016, 1152),
"9:16": (1152, 2016),
}
# Combine for dropdown (labelled with size)
SIZE_LIST: list[str] = ["Full Custom (Use Inputs Below)"]
def add_to_list(prefix: str, sizes: dict[str, tuple[int, int]]) -> None:
"""
Populate the `SIZE_LIST` with human‑readable entries for a given size map.
"""
for ratio_label, (width, height) in sizes.items():
SIZE_LIST.append(f"{prefix} - {ratio_label} ({width}x{height})")
add_to_list("Qwen", QWEN_SIZES)
add_to_list("Illustrious", ILLUSTRIOUS_SIZES)
add_to_list("Z-Image", Z_IMAGE_SIZES)
add_to_list("Flux", FLUX_SIZES)
add_to_list("Fav", FAV_SIZES)
# ============================================================================
# Ratios
# ============================================================================
RATIOS: dict[str, float] = {
"1:1": 1.0,
"9:16": 9 / 16,
"16:9": 16 / 9,
"4:5": 4 / 5,
"5:4": 5 / 4,
"3:4": 3 / 4,
"4:3": 4 / 3,
"2:3": 2 / 3,
"3:2": 3 / 2,
"5:7": 5 / 7,
"7:5": 7 / 5,
"9:21": 9 / 21,
"21:9": 21 / 9,
"1:2": 1 / 2,
"2:1": 2 / 1,
}
# ============================================================================
# Lists for UI
# ============================================================================
MODEL_LIST: list[str] = list(MODEL_SPECS.keys())
RATIO_LIST: list[str] = [
"1:1",
"1:2",
"2:1",
"2:3",
"3:2",
"3:4",
"4:3",
"4:5",
"5:4",
"5:7",
"7:5",
"9:16",
"16:9",
"9:21",
"21:9",
]
# ============================================================================
# Method Constants
# ============================================================================
CROP_METHODS: list[str] = [
"Center Crop",
"Top-Left Crop",
"Bottom-Right Crop",
"Scale to Fit",
"Stretch to Fill",
]
SCALE_METHODS: list[str] = ["lanczos", "bilinear", "bicubic", "nearest"]
INTERPOLATION_MODES: dict[str, str] = {
"lanczos": "bicubic",
"bilinear": "bilinear",
"bicubic": "bicubic",
"nearest": "nearest",
}
# ============================================================================
# Calculation Logic
# ============================================================================
def resolve_resolution(
size_selection: str,
longer_side: int,
custom_ratio: str,
model: str,
) -> tuple[int, int]:
"""
Resolve final resolution based on priority:
1. Size selection (if not "Full Custom")
2. Custom calculation (longer side + ratio)
Args:
size_selection: The selected size string from defaults.
longer_side: The manual long side size.
custom_ratio: The manual aspect ratio.
model: The selected model (for strict alignment).
Returns:
(width, height) in pixels, snapped to the model's required multiple.
"""
# 1. Custom calculation (Primary if explicit value provided)
if longer_side > 0:
target_ratio = RATIOS.get(custom_ratio, 1.0)
multiple = MODEL_SPECS.get(model, 32)
if target_ratio > 1.0:
width = float(longer_side)
height = width / target_ratio
elif target_ratio < 1.0:
height = float(longer_side)
width = height * target_ratio
else:
width = float(longer_side)
height = float(longer_side)
final_width = round(width / multiple) * multiple
final_height = round(height / multiple) * multiple
final_width = max(final_width, multiple)
final_height = max(final_height, multiple)
return int(final_width), int(final_height)
# 2. Fixed "Size" selection (Fallback)
# data format example: "Qwen - 1:1 (1328x1328)"
if size_selection and "Full Custom" not in size_selection:
try:
# Extract "1328x1328" from inside parens
dim_part = size_selection.rsplit("(", 1)[-1].strip(")")
w_str, h_str = dim_part.split("x")
return int(w_str), int(h_str)
except (ValueError, IndexError):
pass
# 3. Default Fallback
return 1024, 1024