From 7b3c4f06077b0c4794bb253addbd6cabf5d89755 Mon Sep 17 00:00:00 2001 From: "Lex Darlog (DRL)" <3897975+Lex-DRL@users.noreply.github.com> Date: Mon, 14 Jul 2025 17:56:28 +0500 Subject: [PATCH] `BestResolutionPrimUpStrategy` --- __init__.py | 2 ++ enums.py | 17 +++++++--- nodes_prims.py | 91 +++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 86 insertions(+), 24 deletions(-) diff --git a/__init__.py b/__init__.py index 7cf92ef..33c2e81 100644 --- a/__init__.py +++ b/__init__.py @@ -15,6 +15,7 @@ NODE_CLASS_MAPPINGS: _t.Dict[str, type] = { "BestResolutionSimple": BestResolutionSimple, "BestResolutionPrimResPriority": BestResolutionPrimResPriority, + "BestResolutionPrimUpStrategy": BestResolutionPrimUpStrategy, } NODE_DISPLAY_NAME_MAPPINGS: _t.Dict[str, str] = { "BestResolutionFromArea": "Best-Res (area)", @@ -23,6 +24,7 @@ NODE_DISPLAY_NAME_MAPPINGS: _t.Dict[str, str] = { "BestResolutionSimple": "Best-Res (simple)", "BestResolutionPrimResPriority": "Priority (Best-Res)", + "BestResolutionPrimUpStrategy": "Upscale Strategy (Best-Res)", } __all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"] diff --git a/enums.py b/enums.py index 99b4871..79e0550 100644 --- a/enums.py +++ b/enums.py @@ -11,11 +11,20 @@ except ImportError: from comfy.comfy_types.node_typing import StrEnum as _StrEnum -class RoundingPriority(_StrEnum): +class __BaseEnum(_StrEnum): + @classmethod + def all_values(cls) -> _t.Tuple[str, ...]: + return tuple(x.value for x in cls) + + +class RoundingPriority(__BaseEnum): DESIRED = 'desired' ORIGINAL = 'original' UPSCALED = 'upscaled' - @classmethod - def all_values(cls) -> _t.Tuple[str, ...]: - return tuple(x.value for x in cls) + +class UpscaleTweakStrategy(__BaseEnum): + PAD = 'pad' + CROP = 'crop' + NEAREST = 'nearest' + EXACT_UPSCALE = 'exact-upscale' diff --git a/nodes_prims.py b/nodes_prims.py index dc8e90a..67a09be 100644 --- a/nodes_prims.py +++ b/nodes_prims.py @@ -16,17 +16,6 @@ from .enums import * _res_priority_data_type = RoundingPriority.all_values() _res_priority_data_type_set = set(_res_priority_data_type) - -# _priority_in_type = (_IO.BOOLEAN, { -# 'default': True, 'label_on': 'upscaled', 'label_off': 'original', -# 'tooltip': ( -# "Which of the resolutions is more important to be as close to the desired as possible:\n\n" -# "When ON, the rounded with/height are first calculated for the UPSCALED resolution - and " -# "only then the original ones are back-tracked from them.\n" -# "When OFF, they're first calculated for the ORIGINAL resolution - and " -# "the upscaled ones are tracked forward from them." -# ) -# }) _res_priority_in_type = ( _res_priority_data_type, { @@ -41,13 +30,12 @@ _res_priority_in_type = ( "initial size as much as possible.\n\n" "• upscaled - vice versa: first, the rounded upscaled resolution is calculated; then, the initial one " "back-tracked from it." - ) + ), } ) - -_input_types_prim_priority = _deepfreeze({ +_input_types_res_priority = _deepfreeze({ 'required': { - 'priority': _res_priority_in_type + 'priority': _res_priority_in_type, }, # 'hidden': { # 'unique_id': 'UNIQUE_ID', @@ -56,6 +44,12 @@ _input_types_prim_priority = _deepfreeze({ }) +def _res_priority_verify(priority: _t.Union[RoundingPriority, str]) -> str: + if priority not in _res_priority_data_type_set: + raise ValueError(f"Invalid value for resolution priority: {priority!r}\nExpected one of: {_res_priority_data_type!r}") + return str(priority) + + class BestResolutionPrimResPriority: """ 'priority' selector for "Best Resolution" upscale-nodes. @@ -73,7 +67,7 @@ class BestResolutionPrimResPriority: @classmethod def INPUT_TYPES(cls): - return _input_types_prim_priority + return _input_types_res_priority def main( self, priority: _t.Union[RoundingPriority, str], @@ -82,8 +76,65 @@ class BestResolutionPrimResPriority: ): return (_res_priority_verify(priority), ) +# ---------------------------------------------------------- -def _res_priority_verify(priority: _t.Union[RoundingPriority, str]) -> str: - if priority not in _res_priority_data_type_set: - raise ValueError(f"Invalid value for resolution priority: {priority!r}\nExpected one of: {_res_priority_data_type!r}") - return str(priority) +_up_strategy_data_type = UpscaleTweakStrategy.all_values() +_up_strategy_data_type_set = set(_up_strategy_data_type) +_up_strategy_in_type = ( + _up_strategy_data_type, + { + 'default': UpscaleTweakStrategy.PAD.value, + 'tooltip': ( + "If the upscaled resolution can't be achieved by uniform scaling of the initial-res, " + "how to tweak the image to get there:\n\n" + "• pad - upscale the image to fit it into the desired frame on one side, " + "then add missing pixels on the other one for outpaint.\n" + "• crop - upscale the image to fill the entire frame, then crop extra pixels on one side.\n" + "• nearest - automatically choose one of the above, to crop/pad the least number of pixels.\n" + "• exact-upscale - follow the provided upscale-value precisely. This is the only option that uses it. " + "Also, it's the only one that might require both outpainting and crop." + ), + } +) +_input_types_up_strategy = _deepfreeze({ + 'required': { + 'strategy': _up_strategy_in_type, + }, + # 'hidden': { + # 'unique_id': 'UNIQUE_ID', + # }, + # 'optional': {}, +}) + + +def _up_strategy_verify(strategy: _t.Union[RoundingPriority, str]) -> str: + if strategy not in _up_strategy_data_type_set: + raise ValueError(f"Invalid value for upscale strategy: {strategy!r}\nExpected one of: {_up_strategy_data_type!r}") + return str(strategy) + + +class BestResolutionPrimUpStrategy: + """ + 'strategy' selector for "Upscale Tweaks" node in "Best Resolution" pack. + """ + NODE_NAME = 'BestResolutionPrimUpStrategy' + CATEGORY = _meta.category + DESCRIPTION = _cleandoc(__doc__) + + OUTPUT_NODE = False + + FUNCTION = 'main' + RETURN_TYPES = (_up_strategy_data_type, ) + RETURN_NAMES = ('strategy', ) + # OUTPUT_TOOLTIPS = ('', ) + + @classmethod + def INPUT_TYPES(cls): + return _input_types_up_strategy + + def main( + self, strategy: _t.Union[RoundingPriority, str], + # show: bool, + # unique_id: str = None + ): + return (_up_strategy_verify(strategy), )