Files
Lex-DRL-ComfyUI-BestResolution/nodes_upscale.py
T
2025-07-17 12:35:37 +05:00

117 lines
4.0 KiB
Python

# encoding: utf-8
"""
Advanced versions of nodes - with upscale.
"""
import typing as _t
from inspect import cleandoc as _cleandoc
import sys as _sys
from frozendict import deepfreeze as _deepfreeze, frozendict as _frozendict
from comfy.comfy_types.node_typing import IO as _IO
from ._funcs import (
aspect_ratios_sorted as _aspect_ratios_sorted,
number_to_int as _number_to_int,
float_width_height_from_area as _float_width_height_from_area,
upscale_result_from_approx_wh as _upscale_result_from_approx_wh
)
from . import _meta
from .enums import *
from .nodes_simple import _input_types_area
from .nodes_prims import _res_priority_in_type, _res_priority_verify
from .slot_types import (
type_dict_step_upscale1 as _type_dict_step_upscale1,
upscale_in_type as _upscale_in_type
)
# ----------------------------------------------------------
_return_types_upscale = (_IO.INT, _IO.INT, _IO.FLOAT, _IO.INT, _IO.INT, _IO.BOOLEAN)
_return_ttips_upscale = _frozendict({
'orig_w': "Width for original/initial image",
'orig_h': "Height for original/initial image",
'upscale': (
"If 'needs_resize' is FALSE, this would be the actual uniform value to scale your initial-res in order "
"to get the upscaled-res.\n"
"If 'needs_resize' is TRUE, this slot simply outputs the same upscale-value you've set on the node."
),
'up_w': "Width for the (main) upscaled image",
'up_h': "Height for the (main) upscaled image",
'needs_resize': (
"This will be FALSE if you can get the exact upscaled resolution by simply scaling the initial-res uniformly "
"(by the value output into 'upscale' slot).\n\n"
"Otherwise, it will be TRUE — indicating that you'll need to do some cropping/out-painting right AFTER "
"the actual upscale (increasing the resolution itself) but BEFORE post-upscale sampling (\"HD-fix\")."
),
})
__extra_inputs_for_upscale_only = {
'priority': _res_priority_in_type,
'upscale': _upscale_in_type,
'up_step': (_IO.INT, dict(_type_dict_step_upscale1, **{
'tooltip': "Same as the main `step`, but for the upscaled resolution.",
})),
}
_input_types_area_upscale = _deepfreeze({
'required': dict(
(k_v for k_v in _input_types_area['required'].items() if k_v[0] != 'show'),
**__extra_inputs_for_upscale_only,
# show=_input_types_area['required']['show'],
),
'hidden': {
'unique_id': 'UNIQUE_ID',
},
# 'optional': {},
})
class BestResolutionFromAreaUpscale:
"""
The most efficient way of selecting an optimal resolution:
image size selected indirectly - by the total desired resolution (area) + aspect ratio...
... PLUS, account for the immediate upscale right away.
Desired resolution (aka image area/megapixels/pixel count) is specified with a side of a square image. This isn't
accidental: most models disclose what image resolution they're trained on, and usually they're square:
- SD 1.5 - 512x512 pixels
- SDXL - 1024x1024 pixels
By simply providing this single number and setting your aspect ratio/orientation, you get the width and height to
produce the closest total resolution to the training set, while also respecting image proportions and step-rounding.
"""
NODE_NAME = 'BestResolutionFromAreaUpscale'
CATEGORY = _meta.category
DESCRIPTION = _cleandoc(__doc__)
OUTPUT_NODE = True
FUNCTION = 'main'
RETURN_TYPES = _return_types_upscale
RETURN_NAMES = tuple(_return_ttips_upscale.keys())
OUTPUT_TOOLTIPS = tuple(_return_ttips_upscale.values())
@classmethod
def INPUT_TYPES(cls):
return _input_types_area_upscale
def main(
self, square_size: int, step: int, landscape: bool, aspect_a: float, aspect_b: float,
priority: _t.Union[RoundingPriority, str], upscale: float, up_step:int,
# show: bool,
unique_id: str = None
):
square_size: int = _number_to_int(square_size)
width_f, height_f = _float_width_height_from_area(square_size, landscape, aspect_a, aspect_b)
return _upscale_result_from_approx_wh(
width_f, height_f, step,
_res_priority_verify(priority), upscale, up_step,
# show,
unique_id=unique_id, target_square_size=square_size
)