80 lines
2.7 KiB
Python
80 lines
2.7 KiB
Python
# encoding: utf-8
|
|
"""
|
|
Internal enums: option choices, shared between nodes.
|
|
"""
|
|
|
|
try:
|
|
from enum import StrEnum as _StrEnum
|
|
except ImportError:
|
|
from comfy.comfy_types.node_typing import StrEnum as _StrEnum
|
|
|
|
|
|
class __BaseEnum(_StrEnum):
|
|
@classmethod
|
|
def all_values(cls) -> tuple[str, ...]:
|
|
return tuple(x.value for x in cls)
|
|
|
|
@classmethod
|
|
def validate(cls, value) -> str:
|
|
raise NotImplementedError
|
|
|
|
|
|
class RoundingPriority(__BaseEnum):
|
|
"""
|
|
Defines what resolution to prioritize, as well as which order to perform rounding in:
|
|
|
|
|
|
• 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.
|
|
• 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.
|
|
• upscaled - vice versa: first, the rounded upscaled resolution is calculated;
|
|
then, the initial one back-tracked from it.
|
|
"""
|
|
DESIRED = 'desired'
|
|
ORIGINAL = 'original'
|
|
UPSCALED = 'upscaled'
|
|
|
|
@classmethod
|
|
def validate(cls, value) -> str:
|
|
if value not in _res_priority_values_set:
|
|
raise ValueError(f"Invalid value for resolution priority: {value!r}\nExpected one of: {_res_priority_values!r}")
|
|
return str(value)
|
|
|
|
|
|
_res_priority_values = RoundingPriority.all_values()
|
|
_res_priority_values_set = set(RoundingPriority.all_values())
|
|
|
|
|
|
class UpscaledCropPadStrategy(__BaseEnum):
|
|
"""
|
|
If the upscaled resolution can't be achieved by uniform scaling of the initial-res,
|
|
how to tweak the image to get there:
|
|
|
|
|
|
• pad only - upscale the image to fit it into the desired frame on one side,
|
|
then add missing pixels on the other one for outpaint.
|
|
• crop only - upscale the image to fill the entire frame, then crop extra pixels on one side.
|
|
• nearest - automatically choose one of the above, to crop/pad the least number of pixels (by area).
|
|
• 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.
|
|
|
|
In case when both are required, the output values assume this order: upscale -> crop -> pad.
|
|
"""
|
|
PAD = 'pad only'
|
|
CROP = 'crop only'
|
|
NEAREST = 'nearest'
|
|
EXACT_UPSCALE = 'exact-upscale'
|
|
|
|
@classmethod
|
|
def validate(cls, value) -> str:
|
|
if value not in _up_strategy_values_set:
|
|
raise ValueError(f"Invalid value for upscale strategy: {value!r}\nExpected one of: {_up_strategy_values!r}")
|
|
return str(value)
|
|
|
|
|
|
_up_strategy_values = UpscaledCropPadStrategy.all_values()
|
|
_up_strategy_values_set = set(UpscaledCropPadStrategy.all_values())
|