Merge branch 'dev': v1.0.1
This commit is contained in:
@@ -4,13 +4,16 @@
|
||||
|
||||
# `Best Resolution` nodes for ComfyUI
|
||||
|
||||
A small modular pack - QoL nodes for semi-automatic calculation of the best (most optimal) sampling resolution:
|
||||
- ... model-agnostic - i.e., compatible with **ANY** model (from now **or** the future),
|
||||
A small modular pack — QoL nodes for semi-automatic calculation of the best (most optimal) sampling resolution:
|
||||
- ... model-agnostic — i.e., compatible with **ANY** model (from now **or** the future),
|
||||
- ... accounting for upscale,
|
||||
- ... and for (the essential) pixel-step.
|
||||
|
||||

|
||||
|
||||
> [!IMPORTANT]
|
||||
> Nodes from this pack do **nothing** with actual images on their own — they only calculate the optimal **values** for the resolution.
|
||||
|
||||
Read any further only if you feel you need to.
|
||||
|
||||
## The purpose
|
||||
|
||||
+2
-1
@@ -2,7 +2,8 @@
|
||||
"""
|
||||
"""
|
||||
|
||||
from .nodes import *
|
||||
from .nodes_simple import *
|
||||
from .nodes_upscale import *
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"BestResolutionFromArea": BestResolutionFromArea,
|
||||
|
||||
@@ -92,6 +92,17 @@ def float_width_height_from_area(square_size: _t_number, landscape: bool, aspect
|
||||
return width_f, height_f
|
||||
|
||||
|
||||
def _show_text_on_node(text: str = None, unique_id: str = None):
|
||||
if not text:
|
||||
# TODO: Planned for the future - currently, there's no point removing the text since it's box is shown anyway
|
||||
# An odd workaround since `send_progress_text()` doesn't want to update text when '' passed
|
||||
text = '<span></span>'
|
||||
# print(f"{unique_id} text: {text!r}")
|
||||
|
||||
# Snatched from: https://github.com/comfyanonymous/ComfyUI/blob/27870ec3c30e56be9707d89a120eb7f0e2836be1/comfy_extras/nodes_images.py#L581-L582
|
||||
_PromptServer.instance.send_progress_text(text, unique_id)
|
||||
|
||||
|
||||
def _format_report_square_part(
|
||||
width_f: float, height_f: _t_number,
|
||||
width: int, height: int,
|
||||
@@ -161,16 +172,29 @@ def simple_result_from_approx_wh(
|
||||
text = (
|
||||
format_report_simple(width_f, height_f, step, width, n_steps_x, height, n_steps_y, target_square_size)
|
||||
if show
|
||||
# TODO: Planned for the future - currently, there's no point removing the text since it's box is shown anyway
|
||||
else '<span></span>' # An odd workaround since `send_progress_text()` doesn't want to update text when '' passed
|
||||
else None
|
||||
)
|
||||
# print(f"{unique_id} text: {text!r}")
|
||||
# Snatched from: https://github.com/comfyanonymous/ComfyUI/blob/27870ec3c30e56be9707d89a120eb7f0e2836be1/comfy_extras/nodes_images.py#L581-L582
|
||||
_PromptServer.instance.send_progress_text(text, unique_id)
|
||||
|
||||
_show_text_on_node(text, unique_id)
|
||||
return result
|
||||
|
||||
|
||||
def _need_post_resize(width: int, height: int, up_width: int, up_height: int):
|
||||
"""
|
||||
Detect whether the final init-res CAN NOT be uniformly scaled to the higher res,
|
||||
and thus would require cropping/out-painting.
|
||||
"""
|
||||
real_upscale_x: float = float(up_width) / width
|
||||
real_upscale_y: float = float(up_height) / height
|
||||
real_upscale_avg: float = (real_upscale_x + real_upscale_y) * 0.5
|
||||
|
||||
needs_resize: bool = (
|
||||
round_pos_int(real_upscale_avg * width) != up_width or
|
||||
round_pos_int(real_upscale_avg * height) != up_height
|
||||
)
|
||||
return needs_resize, real_upscale_avg, real_upscale_x, real_upscale_y
|
||||
|
||||
|
||||
|
||||
def upscale_result_from_approx_wh(
|
||||
width_f: float, height_f: _t_number, step: int,
|
||||
priority: _t.Union[RoundingPriority, str], upscale: float, up_step:int,
|
||||
@@ -204,41 +228,36 @@ def upscale_result_from_approx_wh(
|
||||
float(up_width) / upscale, float(up_height) / upscale, step
|
||||
)
|
||||
|
||||
result = (width, height, up_width, up_height)
|
||||
needs_resize, real_upscale_avg, real_upscale_x, real_upscale_y = _need_post_resize(width, height, up_width, up_height)
|
||||
out_upscale: float = upscale if needs_resize else real_upscale_avg
|
||||
|
||||
result = (width, height, out_upscale, up_width, up_height, needs_resize)
|
||||
|
||||
if not unique_id:
|
||||
return result
|
||||
|
||||
# TODO: Planned for the future - currently, there's no point removing the text since it's box is shown anyway
|
||||
text = '<span></span>' # An odd workaround since `send_progress_text()` doesn't want to update text when '' passed
|
||||
if show:
|
||||
reports: _t.List[str] = list()
|
||||
for prefix, w_f, h_f, s, w, n_x, h, n_y, trg_sq in [
|
||||
('◻️ ', width_f, height_f, step, width, n_steps_x, height, n_steps_y, target_square_size),
|
||||
('🔲 ', up_width_f, up_height_f, up_step, up_width, up_steps_x, up_height, up_steps_y, _sqrt(up_width_f * up_height_f))
|
||||
]:
|
||||
cur_report = format_report_simple(w_f, h_f, s, w, n_x, h, n_y, trg_sq)
|
||||
reports.append('\n'.join(
|
||||
f"{prefix}{x}" for x in cur_report.split('\n')
|
||||
))
|
||||
real_upscale_x = float(up_width) / width
|
||||
real_upscale_y = float(up_height) / height
|
||||
if not show:
|
||||
_show_text_on_node(None, unique_id)
|
||||
return result
|
||||
|
||||
# Pixel size relative to the upscaled image:
|
||||
up_half_pixel_x = 0.5 / up_width
|
||||
up_half_pixel_y = 0.5 / up_height
|
||||
# Threshold for upscale-multiplier to be considered the same res:
|
||||
almost_equal_rel_delta_x = real_upscale_x * up_half_pixel_x
|
||||
almost_equal_rel_delta_y = real_upscale_y * up_half_pixel_y
|
||||
almost_equal_rel_delta = max(almost_equal_rel_delta_x, almost_equal_rel_delta_y)
|
||||
if abs(real_upscale_x - real_upscale_y) < almost_equal_rel_delta:
|
||||
# The x/y delta between upscale multipliers is below a threshold to contribute even 1 pixel.
|
||||
# So, basically, the upscale is uniform:
|
||||
divider_line = f"\n--- x{real_upscale_x:.3f} ---\n"
|
||||
else:
|
||||
divider_line = f"\n--- ⚠️ x{real_upscale_x:.3f} / x{real_upscale_y:.3f} ---\n"
|
||||
text = divider_line.join(reports)
|
||||
# Snatched from: https://github.com/comfyanonymous/ComfyUI/blob/27870ec3c30e56be9707d89a120eb7f0e2836be1/comfy_extras/nodes_images.py#L581-L582
|
||||
_PromptServer.instance.send_progress_text(text, unique_id)
|
||||
report_parts: _t.List[str] = list()
|
||||
for prefix, w_f, h_f, s, w, n_x, h, n_y, trg_sq in [
|
||||
('◻️ ', width_f, height_f, step, width, n_steps_x, height, n_steps_y, target_square_size),
|
||||
('🔲 ', up_width_f, up_height_f, up_step, up_width, up_steps_x, up_height, up_steps_y, _sqrt(up_width_f * up_height_f))
|
||||
]:
|
||||
cur_report = format_report_simple(w_f, h_f, s, w, n_x, h, n_y, trg_sq)
|
||||
report_parts.append('\n'.join(
|
||||
f"{prefix}{x}" for x in cur_report.split('\n')
|
||||
))
|
||||
|
||||
separator_line: str = (
|
||||
# Real upscale factor in X and Y differ enough so we can't get the up-res from init-res with ANY uniform value:
|
||||
f"\n--- ⚠️ x{real_upscale_x:.3f} / x{real_upscale_y:.3f} ---\n"
|
||||
if needs_resize
|
||||
# The upscale is uniform:
|
||||
else f"\n--- x{real_upscale_x:.3f} ---\n"
|
||||
)
|
||||
text = separator_line.join(report_parts)
|
||||
|
||||
_show_text_on_node(text, unique_id)
|
||||
return result
|
||||
|
||||
@@ -5,7 +5,10 @@ Internal enums.
|
||||
|
||||
import typing as _t
|
||||
|
||||
from enum import StrEnum as _StrEnum
|
||||
try:
|
||||
from enum import StrEnum as _StrEnum
|
||||
except ImportError:
|
||||
from comfy.comfy_types.node_typing import StrEnum as _StrEnum
|
||||
|
||||
|
||||
class RoundingPriority(_StrEnum):
|
||||
|
||||
+17
-112
@@ -1,6 +1,6 @@
|
||||
# encoding: utf-8
|
||||
"""
|
||||
The actual nodes defined by the package.
|
||||
Simple (aka no-upscale) versions of nodes.
|
||||
"""
|
||||
|
||||
import typing as _t
|
||||
@@ -9,23 +9,27 @@ from inspect import cleandoc as _cleandoc
|
||||
from math import sqrt as _sqrt
|
||||
import sys as _sys
|
||||
|
||||
from frozendict import deepfreeze, frozendict
|
||||
from frozendict import deepfreeze as _deepfreeze
|
||||
|
||||
from comfy.comfy_types.node_typing import IO as _IO
|
||||
|
||||
from .node_types import *
|
||||
from .enums import *
|
||||
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,
|
||||
simple_result_from_approx_wh as _simple_result_from_approx_wh,
|
||||
upscale_result_from_approx_wh as _upscale_result_from_approx_wh
|
||||
simple_result_from_approx_wh as _simple_result_from_approx_wh
|
||||
)
|
||||
from .node_types import *
|
||||
|
||||
# ----------------------------------------------------------
|
||||
|
||||
# Tiny optimization by reusing the same immutable dict:
|
||||
_input_types_simple = deepfreeze({
|
||||
# _return_types_simple = (_IO.INT, _IO.INT, _IO.STRING)
|
||||
# _return_names_simple = ('width', 'height', 'report')
|
||||
_return_types_simple = (_IO.INT, _IO.INT)
|
||||
_return_names_simple = ('width', 'height')
|
||||
|
||||
# A tiny optimization by reusing the same immutable dict:
|
||||
_input_types_simple = _deepfreeze({
|
||||
'required': {
|
||||
'width': (_IO.INT, dict(type_dict_res, **{'tooltip': "Approximate width"})),
|
||||
'height': (_IO.INT, dict(type_dict_res, **{'tooltip': "Approximate height"})),
|
||||
@@ -51,11 +55,6 @@ _input_types_simple = deepfreeze({
|
||||
# 'optional': {},
|
||||
})
|
||||
|
||||
# _return_types_simple = (_IO.INT, _IO.INT, _IO.STRING)
|
||||
# _return_names_simple = ('width', 'height', 'report')
|
||||
_return_types_simple = (_IO.INT, _IO.INT)
|
||||
_return_names_simple = ('width', 'height')
|
||||
|
||||
|
||||
class BestResolutionSimple:
|
||||
"""
|
||||
@@ -70,7 +69,7 @@ class BestResolutionSimple:
|
||||
|
||||
FUNCTION = 'main'
|
||||
RETURN_TYPES = _return_types_simple
|
||||
# RETURN_TYPES_TOOLTIPS = {}
|
||||
# OUTPUT_TOOLTIPS = {}
|
||||
RETURN_NAMES = _return_names_simple
|
||||
|
||||
@classmethod
|
||||
@@ -88,6 +87,7 @@ class BestResolutionSimple:
|
||||
unique_id=unique_id, target_square_size=_sqrt(width * height)
|
||||
)
|
||||
|
||||
# ----------------------------------------------------------
|
||||
|
||||
_tooltip_aspect = (
|
||||
"Two aspects together define an aspect ratio (16:9, 4:3, etc).\n"
|
||||
@@ -95,7 +95,7 @@ _tooltip_aspect = (
|
||||
"The specified aspect ratio is APPROXIMATE: step parameter has priority over the exact image proportions."
|
||||
)
|
||||
|
||||
_input_types_orient = deepfreeze({
|
||||
_input_types_orient = _deepfreeze({
|
||||
'required': {
|
||||
'size': (_IO.INT, dict(type_dict_res, **{'tooltip': (
|
||||
"Approximate size of one of the image sides.\nWhich one - see the 'size_is_big' and 'landscape' toggles."
|
||||
@@ -173,8 +173,9 @@ class BestResolutionFromAspectRatio:
|
||||
unique_id=unique_id, target_square_size=_sqrt(width_f * height_f)
|
||||
)
|
||||
|
||||
# ----------------------------------------------------------
|
||||
|
||||
_input_types_area = deepfreeze({
|
||||
_input_types_area = _deepfreeze({
|
||||
'required': {
|
||||
'square_size': (_IO.INT, dict(type_dict_res, **{'tooltip': (
|
||||
"The total resolution of the image would be the same as of a square with this side.\n"
|
||||
@@ -237,99 +238,3 @@ class BestResolutionFromArea:
|
||||
# show,
|
||||
unique_id=unique_id, target_square_size=square_size
|
||||
)
|
||||
|
||||
|
||||
_return_types_upscale = (_IO.INT, _IO.INT, _IO.INT, _IO.INT)
|
||||
_return_ttips_upscale = frozendict({
|
||||
'orig_w': "Width for original image",
|
||||
'orig_h': "Height for original image",
|
||||
'up_w': "Width for upscaled image",
|
||||
'up_h': "Height for upscaled image"
|
||||
})
|
||||
_return_names_upscale = tuple(_return_ttips_upscale.keys())
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# __priority_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."
|
||||
# )
|
||||
# })
|
||||
__priority_type = (
|
||||
RoundingPriority.all_values(),
|
||||
{
|
||||
'default': RoundingPriority.DESIRED.value,
|
||||
'tooltip': (
|
||||
"Defines what resolution to prioritize, as well as which order to perform rounding in:\n\n"
|
||||
"• desired - first, approximate resolutions are calculated for both initial and upscaled size; "
|
||||
"then, both are rounded. In both cases, the rounded resolution is closest to the desired one, "
|
||||
"but aspect ratio might differ the most between sizes.\n\n"
|
||||
"• original - first, initial resolution is calculated and rounded; then, upscaled one is detected from it. "
|
||||
"Upscaled resolution might differ the most from the desired aspect ratio, but it follows the ratio from "
|
||||
"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."
|
||||
)
|
||||
}
|
||||
)
|
||||
__extra_inputs_for_upscale_only = {
|
||||
'priority': __priority_type,
|
||||
'upscale': (_IO.FLOAT, {
|
||||
'default': 1.5, 'min': 1.0, 'max': _sys.float_info.max, 'step': 0.25, 'round': 0.001,
|
||||
# 'tooltip': "", # TODO
|
||||
}),
|
||||
'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:
|
||||
NODE_NAME = 'BestResolutionFromAreaUpscale'
|
||||
CATEGORY = "utils/resolution"
|
||||
DESCRIPTION = _cleandoc(__doc__)
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
FUNCTION = 'main'
|
||||
RETURN_TYPES = _return_types_upscale
|
||||
RETURN_NAMES = _return_names_upscale
|
||||
RETURN_TYPES_TOOLTIPS = _return_ttips_upscale
|
||||
|
||||
@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,
|
||||
priority, upscale, up_step,
|
||||
# show,
|
||||
unique_id=unique_id, target_square_size=square_size
|
||||
)
|
||||
@@ -0,0 +1,141 @@
|
||||
# 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 .enums import *
|
||||
from .node_types import *
|
||||
from .nodes_simple import _input_types_area
|
||||
|
||||
# ----------------------------------------------------------
|
||||
|
||||
_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\")."
|
||||
),
|
||||
})
|
||||
|
||||
# __priority_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."
|
||||
# )
|
||||
# })
|
||||
__priority_type = (
|
||||
RoundingPriority.all_values(),
|
||||
{
|
||||
'default': RoundingPriority.DESIRED.value,
|
||||
'tooltip': (
|
||||
"Defines what resolution to prioritize, as well as which order to perform rounding in:\n\n"
|
||||
"• desired - first, approximate resolutions are calculated for both initial and upscaled size; "
|
||||
"then, both are rounded. In both cases, the rounded resolution is closest to the desired one, "
|
||||
"but aspect ratio might differ the most between sizes.\n\n"
|
||||
"• original - first, initial resolution is calculated and rounded; then, upscaled one is detected from it. "
|
||||
"Upscaled resolution might differ the most from the desired aspect ratio, but it follows the ratio from "
|
||||
"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."
|
||||
)
|
||||
}
|
||||
)
|
||||
__extra_inputs_for_upscale_only = {
|
||||
'priority': __priority_type,
|
||||
'upscale': (_IO.FLOAT, {
|
||||
'default': 1.5, 'min': 1.0, 'max': _sys.float_info.max, 'step': 0.25, 'round': 0.001,
|
||||
# 'tooltip': "", # TODO
|
||||
}),
|
||||
'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 = "utils/resolution"
|
||||
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,
|
||||
priority, upscale, up_step,
|
||||
# show,
|
||||
unique_id=unique_id, target_square_size=square_size
|
||||
)
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "best-resolution"
|
||||
description = "QoL nodes for semi-automatic calculation of the best (most optimal) sampling resolution \n• compatible with ANY model (from now or the future), \n• accounting for upscale \n• and pixel-step."
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
authors = [
|
||||
{name = "Lex Darlog"}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user