Updates to naming and force div 16

Made naming more consistent and added a toggle to force divisible by 16.
This commit is contained in:
boobkake22
2026-03-04 22:20:51 -08:00
parent f96b88ecec
commit ff5bd508e4
5 changed files with 78 additions and 14 deletions
+6 -4
View File
@@ -1,4 +1,4 @@
# ComfyUI Wan Resolutions
# ComfyUI WanResolutions
ComfyUI custom node that outputs `width` and `height` presets for Wan 2.2 video generation.
@@ -7,6 +7,7 @@ ComfyUI custom node that outputs `width` and `height` presets for Wan 2.2 video
- Lets you choose an `aspect_ratio` and resolution quality tier
- Outputs `INT` values: `width`, `height`
- Optional `IMAGE` input auto-matches the closest supported aspect ratio as an override
- Optional `round_to_16` snaps output to dimensions divisible by 16 while staying close to the target ratio
- Keeps equivalent quality tier when you switch aspect ratios in the UI
Supported aspect ratios:
@@ -34,10 +35,11 @@ Restart ComfyUI after installing.
## Usage
1. Add the `Wan Resolution` node.
1. Add the `WanResolutions` node.
2. Pick `aspect_ratio` and `resolution`.
3. Optional: connect an `IMAGE` input to auto-select the nearest aspect ratio.
4. Connect `width` and `height` outputs to your downstream nodes.
3. Optional: enable `round_to_16` for dimensions divisible by 16.
4. Optional: connect an `IMAGE` input to auto-select the nearest aspect ratio.
5. Connect `width` and `height` outputs to your downstream nodes.
## License
+3 -3
View File
@@ -1,11 +1,11 @@
from .wan_resolution import WanResolution
from .wanresolutions import WanResolutions
NODE_CLASS_MAPPINGS = {
"WanResolution": WanResolution,
"WanResolutions": WanResolutions,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"WanResolution": "Wan Resolution",
"WanResolutions": "WanResolutions",
}
# Any .js files in this directory will be loaded by the frontend
@@ -115,9 +115,9 @@ function tierIndexForValue(aspectRatio, value) {
}
app.registerExtension({
name: "wan_resolution.dynamic_resolution_list",
name: "wanresolutions.dynamic_resolution_list",
async nodeCreated(node) {
if (node.comfyClass !== "WanResolution") return;
if (node.comfyClass !== "WanResolutions") return;
const aspectWidget = node.widgets?.find((w) => w.name === "aspect_ratio");
const resWidget = node.widgets?.find((w) => w.name === "resolution");
+3 -3
View File
@@ -1,6 +1,6 @@
[project]
name = "comfyui-wan-resolutions"
description = "ComfyUI custom node for selecting WAN resolution presets by aspect ratio."
name = "comfyui-wanresolutions"
description = "ComfyUI custom node for selecting Wan resolution presets by aspect ratio."
authors = [
{ name = "boobkake22", email = "boobkake22@gmail.com" }
]
@@ -16,5 +16,5 @@ Repository = "https://github.com/boobkake22/ComfyUI-WanResolutions"
[tool.comfy]
PublisherId = "boobkake22"
DisplayName = "Wan Resolutions"
DisplayName = "WanResolutions"
Icon = ""
+64 -2
View File
@@ -2,11 +2,12 @@ import re
from typing import Dict, List, Optional, Tuple
class WanResolution:
class WanResolutions:
"""
WAN Resolution
WanResolutions
- Choose aspect ratio and quality tier.
- Optional IMAGE input can auto-select the closest aspect ratio.
- Optional round_to_16 can snap output dimensions to multiples of 16.
- Outputs width,height as INT.
"""
@@ -124,6 +125,7 @@ class WanResolution:
"required": {
"aspect_ratio": (aspect_choices, {"default": default_ar}),
"resolution": (all_resolution_choices, {"default": default_res}),
"round_to_16": ("BOOLEAN", {"default": False}),
},
"optional": {
"image": ("IMAGE",),
@@ -166,6 +168,63 @@ class WanResolution:
w, h, _ = rows[0]
return w, h
@staticmethod
def _round_to_multiple(value: float, multiple: int) -> int:
if multiple <= 0:
return int(round(value))
return max(multiple, int(round(float(value) / float(multiple))) * multiple)
@classmethod
def _round_resolution_preserve_aspect(
cls,
width: int,
height: int,
multiple: int = 16,
) -> Tuple[int, int]:
"""
Snap dimensions to a required multiple while keeping aspect ratio as close
as possible to the requested width/height.
"""
if width <= 0 or height <= 0:
return (
cls._round_to_multiple(max(1, width), multiple),
cls._round_to_multiple(max(1, height), multiple),
)
target_ratio = float(width) / float(height)
target_area = width * height
base_w = cls._round_to_multiple(width, multiple)
base_h = cls._round_to_multiple(height, multiple)
width_candidates = {max(multiple, base_w + (step * multiple)) for step in range(-3, 4)}
height_candidates = {max(multiple, base_h + (step * multiple)) for step in range(-3, 4)}
candidates = set()
# Generate options by preserving ratio from width and from height.
for w in width_candidates:
h = cls._round_to_multiple(float(w) / target_ratio, multiple)
candidates.add((w, h))
for h in height_candidates:
w = cls._round_to_multiple(float(h) * target_ratio, multiple)
candidates.add((w, h))
# Add a small local grid around the nearest rounded size.
for w in width_candidates:
for h in height_candidates:
candidates.add((w, h))
best_w, best_h = min(
candidates,
key=lambda wh: (
abs((float(wh[0]) / float(wh[1])) - target_ratio),
abs(wh[0] - width) + abs(wh[1] - height),
abs((wh[0] * wh[1]) - target_area),
),
)
return int(best_w), int(best_h)
@staticmethod
def _parse_aspect_ratio_value(aspect_ratio: str) -> Optional[float]:
m = re.match(r"^\s*(\d+)\s*:\s*(\d+)\s*$", aspect_ratio or "")
@@ -234,6 +293,7 @@ class WanResolution:
aspect_ratio: str,
resolution: str,
image=None,
round_to_16: bool = False,
):
resolved_aspect = aspect_ratio
image_dims = self._image_dimensions(image)
@@ -242,4 +302,6 @@ class WanResolution:
resolved_aspect = self._best_aspect_ratio(image_w, image_h)
w, h = self._parse_resolution(resolved_aspect, resolution)
if round_to_16:
w, h = self._round_resolution_preserve_aspect(w, h, multiple=16)
return (int(w), int(h))