Merge branch 'dev': v1.1.1
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# V1.1.1
|
||||
|
||||
- This `CHANGELOG.md` file.
|
||||
- Prim-node rename (class and internal name, too): `Upscale Strategy (Best-Res)` -> `Crop-Pad Strategy (Best-Res)`
|
||||
- Inputs/outputs for upscale-related nodes are renamed to be more intuitive.
|
||||
- `Best-Res (area+scale)`: change (restore) the value returned by `upscale` output.
|
||||
- Upscale-related nodes: change some defaults.
|
||||
|
||||
⚠️ Active `TODO:`
|
||||
- Add `upscale` versions for `simple` and `ratio` nodes, too.
|
||||
- Add options for `crop/pad` node - to determine the order of [crop/pad] -> upscale -> [crop/pad].
|
||||
|
||||
# V1.1.0
|
||||
|
||||
The minimally-complete version (full workflow coverage for my own use-case).
|
||||
- Significant internal refactor.
|
||||
- New group/category name: `Best Resolution`
|
||||
- New nodes:
|
||||
- `Best-Res (area+scale)`
|
||||
- `Upscaled Crop/Pad (Best-Res)`
|
||||
- New primitive nodes:
|
||||
- `Priority (Best-Res)`
|
||||
- `Upscale Strategy (Best-Res)`
|
||||
|
||||
# v1.0.0
|
||||
|
||||
The MVP. Contains nodes:
|
||||
- `Best-Res (simple)`
|
||||
- `Best-Res (ratio)`
|
||||
- `Best-Res (area+scale)`
|
||||
|
||||
`TODO: supporting utility nodes (primitives for combo-selectors, calculators for post-upscale res-tweaks with pad/crop).`
|
||||
@@ -7,7 +7,9 @@
|
||||
A small modular pack — 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.
|
||||
- ... and for (the essential) pixel-step.
|
||||
|
||||
[🔄 Updates ChangeLog](CHANGELOG.md)
|
||||
|
||||

|
||||
|
||||
@@ -43,6 +45,14 @@ All you need to know is a size (one side) of square images the model was trained
|
||||
- match the total resolution (i.e., image area, number of pixels) as close to the training one as possible,
|
||||
- ... while still respecting aspect ratio, image orientation and step size.
|
||||
|
||||
### Advanced: Upscale support (aka "HD-fix")
|
||||
|
||||

|
||||
|
||||
`Best-Res` nodes have a special version _(currently, only `area` node has one)_, which also account for very first upscale aka HD-fix - to ensure the upscaled resolution is also divisible by the step value.
|
||||
|
||||
Additionally, they're accompanied by utility node to also auto-detect any necessary cropping/padding (for out-paint) to perform on the upscaled image before second KSampler (the "HD-fix" itself).
|
||||
|
||||
## Tooltips
|
||||
|
||||
Each parameter is self-documented in the shortest possible, yet exhaustive detail - just hover mouse over it. If you're new to Comfy and Stable Diffusion, this might be especially helpful.
|
||||
|
||||
+2
-2
@@ -15,8 +15,8 @@ NODE_CLASS_MAPPINGS: _t.Dict[str, type] = {
|
||||
"BestResolutionFromAspectRatio": BestResolutionFromAspectRatio,
|
||||
"BestResolutionSimple": BestResolutionSimple,
|
||||
|
||||
"BestResolutionPrimCropPadStrategy": BestResolutionPrimCropPadStrategy,
|
||||
"BestResolutionPrimResPriority": BestResolutionPrimResPriority,
|
||||
"BestResolutionPrimUpStrategy": BestResolutionPrimUpStrategy,
|
||||
|
||||
"BestResolutionUpscaledCropPad": BestResolutionUpscaledCropPad,
|
||||
}
|
||||
@@ -26,8 +26,8 @@ NODE_DISPLAY_NAME_MAPPINGS: _t.Dict[str, str] = {
|
||||
"BestResolutionFromAspectRatio": "Best-Res (ratio)",
|
||||
"BestResolutionSimple": "Best-Res (simple)",
|
||||
|
||||
"BestResolutionPrimCropPadStrategy": "Crop-Pad Strategy (Best-Res)",
|
||||
"BestResolutionPrimResPriority": "Priority (Best-Res)",
|
||||
"BestResolutionPrimUpStrategy": "Upscale Strategy (Best-Res)",
|
||||
|
||||
"BestResolutionUpscaledCropPad": "Upscaled Crop/Pad (Best-Res)",
|
||||
}
|
||||
|
||||
@@ -179,56 +179,58 @@ def simple_result_from_approx_wh(
|
||||
return result
|
||||
|
||||
|
||||
def _need_post_resize(width: int, height: int, up_width: int, up_height: int):
|
||||
def _need_post_resize(width: int, height: int, hd_width: int, hd_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_x: float = float(hd_width) / width
|
||||
real_upscale_y: float = float(hd_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
|
||||
round_pos_int(real_upscale_avg * width) != hd_width or
|
||||
round_pos_int(real_upscale_avg * height) != hd_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,
|
||||
priority: _t.Union[RoundingPriority, str], upscale: float, hd_step:int,
|
||||
show: bool = True,
|
||||
unique_id: str = None, target_square_size: _t_number = None
|
||||
) -> ResultUpscaled:
|
||||
"""Primary part of the main func for nodes with upscaling - when desired initial-width/height are already calculated."""
|
||||
upscale = max(float(upscale), 1.0)
|
||||
up_width_f: float = upscale * width_f
|
||||
up_height_f: float = upscale * height_f
|
||||
hd_width_f: float = upscale * width_f
|
||||
hd_height_f: float = upscale * height_f
|
||||
width_f = float(width_f)
|
||||
|
||||
step = number_to_int(step)
|
||||
up_step = number_to_int(up_step)
|
||||
hd_step = number_to_int(hd_step)
|
||||
|
||||
if priority == RoundingPriority.DESIRED:
|
||||
width, n_steps_x, height, n_steps_y = round_width_and_height_closest_to_the_ratio(width_f, height_f, step)
|
||||
up_width, up_steps_x, up_height, up_steps_y = round_width_and_height_closest_to_the_ratio(
|
||||
up_width_f, up_height_f, up_step
|
||||
hd_width, hd_steps_x, hd_height, hd_steps_y = round_width_and_height_closest_to_the_ratio(
|
||||
hd_width_f, hd_height_f, hd_step
|
||||
)
|
||||
elif priority == RoundingPriority.ORIGINAL:
|
||||
width, n_steps_x, height, n_steps_y = round_width_and_height_closest_to_the_ratio(width_f, height_f, step)
|
||||
up_width, up_steps_x, up_height, up_steps_y = round_width_and_height_closest_to_the_ratio(
|
||||
upscale * width, upscale * height, up_step
|
||||
hd_width, hd_steps_x, hd_height, hd_steps_y = round_width_and_height_closest_to_the_ratio(
|
||||
upscale * width, upscale * height, hd_step
|
||||
)
|
||||
else:
|
||||
up_width, up_steps_x, up_height, up_steps_y = round_width_and_height_closest_to_the_ratio(
|
||||
up_width_f, up_height_f, up_step
|
||||
hd_width, hd_steps_x, hd_height, hd_steps_y = round_width_and_height_closest_to_the_ratio(
|
||||
hd_width_f, hd_height_f, hd_step
|
||||
)
|
||||
width, n_steps_x, height, n_steps_y = round_width_and_height_closest_to_the_ratio(
|
||||
float(up_width) / upscale, float(up_height) / upscale, step
|
||||
float(hd_width) / upscale, float(hd_height) / upscale, step
|
||||
)
|
||||
|
||||
result = ResultUpscaled(upscale, width, height, up_width, up_height)
|
||||
needs_resize, real_upscale_avg, real_upscale_x, real_upscale_y = _need_post_resize(width, height, hd_width, hd_height)
|
||||
|
||||
result = ResultUpscaled(upscale if needs_resize else real_upscale_avg, width, height, hd_width, hd_height)
|
||||
|
||||
if not unique_id:
|
||||
return result
|
||||
@@ -240,21 +242,19 @@ def upscale_result_from_approx_wh(
|
||||
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))
|
||||
('🔲 ', hd_width_f, hd_height_f, hd_step, hd_width, hd_steps_x, hd_height, hd_steps_y, _sqrt(hd_width_f * hd_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')
|
||||
))
|
||||
|
||||
needs_resize, real_upscale_avg, real_upscale_x, real_upscale_y = _need_post_resize(width, height, up_width, up_height)
|
||||
|
||||
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_avg:.3f} ---\n"
|
||||
else f"\n--- x{real_upscale_avg:.3f}✅ ---\n"
|
||||
)
|
||||
text = separator_line.join(report_parts)
|
||||
|
||||
|
||||
+29
-29
@@ -19,10 +19,10 @@ class _CropPadInput:
|
||||
"""
|
||||
upscale: float
|
||||
|
||||
orig_w: int
|
||||
orig_h: int
|
||||
up_w: int
|
||||
up_h: int
|
||||
init_w: int
|
||||
init_h: int
|
||||
hd_w: int
|
||||
hd_h: int
|
||||
|
||||
strategy: str
|
||||
align_x: float
|
||||
@@ -36,14 +36,14 @@ def _upscaled_crop_xy_offset(extra_w: int, extra_h: int, align_x: float, align_y
|
||||
|
||||
|
||||
def _upscaled_crop(_in: _CropPadInput, real_upscale: float) -> ResultUpscaledCropPad:
|
||||
raw_upscaled_w = _round_pos_int(real_upscale * _in.orig_w)
|
||||
raw_upscaled_h = _round_pos_int(real_upscale * _in.orig_h)
|
||||
extra_w = max(raw_upscaled_w - _in.up_w, 0)
|
||||
extra_h = max(raw_upscaled_h - _in.up_h, 0)
|
||||
raw_upscaled_w = _round_pos_int(real_upscale * _in.init_w)
|
||||
raw_upscaled_h = _round_pos_int(real_upscale * _in.init_h)
|
||||
extra_w = max(raw_upscaled_w - _in.hd_w, 0)
|
||||
extra_h = max(raw_upscaled_h - _in.hd_h, 0)
|
||||
crop_x_offset, crop_y_offset = _upscaled_crop_xy_offset(extra_w, extra_h, _in.align_x, _in.align_y)
|
||||
return ResultUpscaledCropPad(
|
||||
real_upscale,
|
||||
True, _in.up_w, _in.up_h, crop_x_offset, crop_y_offset,
|
||||
True, _in.hd_w, _in.hd_h, crop_x_offset, crop_y_offset,
|
||||
False, 0, 0, 0, 0,
|
||||
)
|
||||
|
||||
@@ -57,10 +57,10 @@ def _upscaled_pad_side_values(extra_w: int, extra_h: int, align_x: float, align_
|
||||
|
||||
|
||||
def _upscaled_pad(_in: _CropPadInput, real_upscale: float) -> ResultUpscaledCropPad:
|
||||
raw_upscaled_w = _round_pos_int(real_upscale * _in.orig_w)
|
||||
raw_upscaled_h = _round_pos_int(real_upscale * _in.orig_h)
|
||||
pad_w = max(_in.up_w - raw_upscaled_w, 0)
|
||||
pad_h = max(_in.up_h - raw_upscaled_h, 0)
|
||||
raw_upscaled_w = _round_pos_int(real_upscale * _in.init_w)
|
||||
raw_upscaled_h = _round_pos_int(real_upscale * _in.init_h)
|
||||
pad_w = max(_in.hd_w - raw_upscaled_w, 0)
|
||||
pad_h = max(_in.hd_h - raw_upscaled_h, 0)
|
||||
return ResultUpscaledCropPad(
|
||||
real_upscale,
|
||||
False, raw_upscaled_w, raw_upscaled_h, 0, 0,
|
||||
@@ -70,8 +70,8 @@ def _upscaled_pad(_in: _CropPadInput, real_upscale: float) -> ResultUpscaledCrop
|
||||
|
||||
def _upscaled_crop_delta_pixels(_in: _CropPadInput, result: ResultUpscaledCropPad) -> int:
|
||||
"""Calculate the area of total cropped patch for crop-only mode."""
|
||||
raw_upscaled_w = _round_pos_int(result.upscale * _in.orig_w)
|
||||
raw_upscaled_h = _round_pos_int(result.upscale * _in.orig_h)
|
||||
raw_upscaled_w = _round_pos_int(result.upscale * _in.init_w)
|
||||
raw_upscaled_h = _round_pos_int(result.upscale * _in.init_h)
|
||||
cropped_w = min(result.crop_width, raw_upscaled_w)
|
||||
cropped_h = min(result.crop_height, raw_upscaled_h)
|
||||
return abs(raw_upscaled_w * raw_upscaled_h - cropped_w * cropped_h)
|
||||
@@ -79,8 +79,8 @@ def _upscaled_crop_delta_pixels(_in: _CropPadInput, result: ResultUpscaledCropPa
|
||||
|
||||
def _upscaled_pad_delta_pixels(_in: _CropPadInput, result: ResultUpscaledCropPad) -> int:
|
||||
"""Calculate the area of total out-painted patch for pad-only mode."""
|
||||
raw_upscaled_w = _round_pos_int(result.upscale * _in.orig_w)
|
||||
raw_upscaled_h = _round_pos_int(result.upscale * _in.orig_h)
|
||||
raw_upscaled_w = _round_pos_int(result.upscale * _in.init_w)
|
||||
raw_upscaled_h = _round_pos_int(result.upscale * _in.init_h)
|
||||
padded_w = raw_upscaled_w + max(result.pad_left, 0) + max(result.pad_right, 0)
|
||||
padded_h = raw_upscaled_h + max(result.pad_top, 0) + max(result.pad_bottom, 0)
|
||||
return abs(padded_w * padded_h - raw_upscaled_w * raw_upscaled_h)
|
||||
@@ -88,11 +88,11 @@ def _upscaled_pad_delta_pixels(_in: _CropPadInput, result: ResultUpscaledCropPad
|
||||
|
||||
def _upscaled_crop_pad(_in: _CropPadInput) -> ResultUpscaledCropPad:
|
||||
"""The actual function for "Upscaled Crop/Pad" node - extracted to wrap it with displaying the message."""
|
||||
needs_resize, real_upscale_avg, real_upscale_x, real_upscale_y = _need_post_resize(_in.orig_w, _in.orig_h, _in.up_w, _in.up_h)
|
||||
needs_resize, real_upscale_avg, real_upscale_x, real_upscale_y = _need_post_resize(_in.init_w, _in.init_h, _in.hd_w, _in.hd_h)
|
||||
if not needs_resize:
|
||||
return ResultUpscaledCropPad(
|
||||
real_upscale_avg,
|
||||
False, _in.up_w, _in.up_h, 0, 0,
|
||||
False, _in.hd_w, _in.hd_h, 0, 0,
|
||||
False, 0, 0, 0, 0,
|
||||
)
|
||||
|
||||
@@ -117,19 +117,19 @@ def _upscaled_crop_pad(_in: _CropPadInput) -> ResultUpscaledCropPad:
|
||||
assert _in.strategy == UpscaledCropPadStrategy.EXACT_UPSCALE
|
||||
|
||||
upscale = _in.upscale
|
||||
raw_upscaled_w = _round_pos_int(upscale * _in.orig_w)
|
||||
raw_upscaled_h = _round_pos_int(upscale * _in.orig_h)
|
||||
raw_upscaled_w = _round_pos_int(upscale * _in.init_w)
|
||||
raw_upscaled_h = _round_pos_int(upscale * _in.init_h)
|
||||
# We're in the most complex case. These ^ can be both below and above the target up-res.
|
||||
# So, we need to follow the whole upscale->crop->pad chain: we'll just get zeroes where there will be nothing to do.
|
||||
|
||||
cropped_w = min(_in.up_w, raw_upscaled_w)
|
||||
cropped_h = min(_in.up_h, raw_upscaled_h)
|
||||
cropped_w = min(_in.hd_w, raw_upscaled_w)
|
||||
cropped_h = min(_in.hd_h, raw_upscaled_h)
|
||||
crop_extra_w = raw_upscaled_w - cropped_w
|
||||
crop_extra_h = raw_upscaled_h - cropped_h
|
||||
crop_x_offset, crop_y_offset = _upscaled_crop_xy_offset(crop_extra_w, crop_extra_h, _in.align_x, _in.align_y)
|
||||
|
||||
pad_extra_w = _in.up_w - cropped_w
|
||||
pad_extra_h = _in.up_h - cropped_h
|
||||
pad_extra_w = _in.hd_w - cropped_w
|
||||
pad_extra_h = _in.hd_h - cropped_h
|
||||
pad_side_values = _upscaled_pad_side_values(pad_extra_w, pad_extra_h, _in.align_x, _in.align_y)
|
||||
return ResultUpscaledCropPad(
|
||||
upscale,
|
||||
@@ -140,7 +140,7 @@ def _upscaled_crop_pad(_in: _CropPadInput) -> ResultUpscaledCropPad:
|
||||
|
||||
def upscaled_crop_pad(
|
||||
upscale: float,
|
||||
orig_w: int, orig_h: int, up_w: int, up_h: int,
|
||||
init_w: int, init_h: int, hd_w: int, hd_h: int,
|
||||
strategy: str,
|
||||
align_x: float, align_y: float,
|
||||
show: bool = True,
|
||||
@@ -153,7 +153,7 @@ def upscaled_crop_pad(
|
||||
# noinspection PyArgumentList
|
||||
result = _upscaled_crop_pad(_CropPadInput(
|
||||
upscale,
|
||||
orig_w, orig_h, up_w, up_h,
|
||||
init_w, init_h, hd_w, hd_h,
|
||||
strategy,
|
||||
align_x, align_y,
|
||||
))
|
||||
@@ -173,8 +173,8 @@ def upscaled_crop_pad(
|
||||
text_parts: _t.List[str] = [f"x{result.upscale:.3f}", ]
|
||||
|
||||
if result.do_crop:
|
||||
crop_r = up_w - (result.crop_x_origin + result.crop_width)
|
||||
crop_b = up_h - (result.crop_y_origin + result.crop_height)
|
||||
crop_r = hd_w - (result.crop_x_origin + result.crop_width)
|
||||
crop_b = hd_h - (result.crop_y_origin + result.crop_height)
|
||||
text_parts.append(f"Crop:\nL {result.crop_x_origin}, R {crop_r}, B {crop_b}, T {result.crop_y_origin}")
|
||||
|
||||
if result.do_padding:
|
||||
|
||||
@@ -42,16 +42,16 @@ class UpscaledCropPadStrategy(__BaseEnum):
|
||||
how to tweak the image to get there:
|
||||
|
||||
|
||||
• pad - upscale the image to fit it into the desired frame on one side,
|
||||
• 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 - upscale the image to fill the entire frame, then crop extra pixels on one side.
|
||||
• 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'
|
||||
CROP = 'crop'
|
||||
PAD = 'pad only'
|
||||
CROP = 'crop only'
|
||||
NEAREST = 'nearest'
|
||||
EXACT_UPSCALE = 'exact-upscale'
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 520 KiB |
+6
-6
@@ -50,10 +50,10 @@ _input_types_crop_pad = _deepfreeze({
|
||||
'upscale': (_IO.FLOAT, dict(_upscale_in_type[1], **{
|
||||
'tooltip': f"Only used when {UpscaledCropPadStrategy.EXACT_UPSCALE!r} strategy selected."
|
||||
})),
|
||||
'orig_w': (_IO.INT, dict(_type_dict_res, **{'tooltip': _return_ttips_upscale['orig_w']})),
|
||||
'orig_h': (_IO.INT, dict(_type_dict_res, **{'tooltip': _return_ttips_upscale['orig_h']})),
|
||||
'up_w': (_IO.INT, dict(_type_dict_res, **{'tooltip': _return_ttips_upscale['up_w']})),
|
||||
'up_h': (_IO.INT, dict(_type_dict_res, **{'tooltip': _return_ttips_upscale['up_h']})),
|
||||
'init_width': (_IO.INT, dict(_type_dict_res, **{'tooltip': _return_ttips_upscale['init_width']})),
|
||||
'init_height': (_IO.INT, dict(_type_dict_res, **{'tooltip': _return_ttips_upscale['init_height']})),
|
||||
'HD_width': (_IO.INT, dict(_type_dict_res, **{'tooltip': _return_ttips_upscale['HD_width'], 'default': 1536})),
|
||||
'HD_height': (_IO.INT, dict(_type_dict_res, **{'tooltip': _return_ttips_upscale['HD_height'], 'default': 1536})),
|
||||
'strategy': _up_strategy_in_type,
|
||||
'align_x': (_IO.FLOAT, dict(_rel_pos_in_type[1], **{
|
||||
'tooltip': (
|
||||
@@ -103,7 +103,7 @@ class BestResolutionUpscaledCropPad:
|
||||
def main(
|
||||
self,
|
||||
upscale: float,
|
||||
orig_w: int, orig_h: int, up_w: int, up_h: int,
|
||||
init_width: int, init_height: int, HD_width: int, HD_height: int,
|
||||
strategy: _t.Union[UpscaledCropPadStrategy, str],
|
||||
align_x: float, align_y: float,
|
||||
# show: bool,
|
||||
@@ -111,7 +111,7 @@ class BestResolutionUpscaledCropPad:
|
||||
):
|
||||
return _upscaled_crop_pad(
|
||||
upscale,
|
||||
orig_w, orig_h, up_w, up_h,
|
||||
init_width, init_height, HD_width, HD_height,
|
||||
_up_strategy_verify(strategy),
|
||||
align_x, align_y,
|
||||
# show,
|
||||
|
||||
+4
-4
@@ -23,7 +23,7 @@ _res_priority_data_type_set = set(_res_priority_data_type)
|
||||
_res_priority_in_type = (
|
||||
_res_priority_data_type,
|
||||
{
|
||||
'default': RoundingPriority.DESIRED.value,
|
||||
'default': RoundingPriority.ORIGINAL,
|
||||
'tooltip': _format_object_docstring(RoundingPriority),
|
||||
}
|
||||
)
|
||||
@@ -77,7 +77,7 @@ _up_strategy_data_type_set = set(_up_strategy_data_type)
|
||||
_up_strategy_in_type = (
|
||||
_up_strategy_data_type,
|
||||
{
|
||||
'default': UpscaledCropPadStrategy.EXACT_UPSCALE.value,
|
||||
'default': UpscaledCropPadStrategy.PAD,
|
||||
'tooltip': _format_object_docstring(UpscaledCropPadStrategy),
|
||||
}
|
||||
)
|
||||
@@ -98,11 +98,11 @@ def _up_strategy_verify(strategy: _t.Union[RoundingPriority, str]) -> str:
|
||||
return str(strategy)
|
||||
|
||||
|
||||
class BestResolutionPrimUpStrategy:
|
||||
class BestResolutionPrimCropPadStrategy:
|
||||
"""
|
||||
'strategy' selector for "Upscaled Crop/Pad" node in "Best Resolution" pack.
|
||||
"""
|
||||
NODE_NAME = 'BestResolutionPrimUpStrategy'
|
||||
NODE_NAME = 'BestResolutionPrimCropPadStrategy'
|
||||
CATEGORY = _meta.category
|
||||
DESCRIPTION = _format_docstring(_cleandoc(__doc__))
|
||||
|
||||
|
||||
+18
-9
@@ -32,18 +32,27 @@ from .slot_types import (
|
||||
|
||||
_return_types_upscale = (_IO.FLOAT, _IO.INT, _IO.INT, _IO.INT, _IO.INT)
|
||||
_return_ttips_upscale = _frozendict({
|
||||
'upscale': "Simply outputs the same upscale-value you've set on the node.",
|
||||
'orig_w': "Width for original/initial image",
|
||||
'orig_h': "Height for original/initial image",
|
||||
'up_w': "Width for the (main) upscaled image",
|
||||
'up_h': "Height for the (main) upscaled image",
|
||||
'upscale': (
|
||||
"If the HD resolution can be achieved by uniformly scaling the initial one "
|
||||
"(there is \"✅\" and not \"⚠️\" in the upscale-line of the status message), "
|
||||
"outputs this precise upscale-value (might be different from the one originally set on the node itself).\n\n"
|
||||
"Otherwise, outputs the original upscale-value intact.\n"
|
||||
"In this case, you shouldn't use it directly and instead should pass it "
|
||||
"to the \"Upscaled Crop/Pad (Best-Res)\" node and use the upscale-output from it.\n\n"
|
||||
"In both cases, it won't hurt to use the \"Upscaled Crop/Pad (Best-Res)\" node and just rely "
|
||||
"on it's `do_crop` and `do_padding` toggle-outputs."
|
||||
),
|
||||
'init_width': "Width for original/initial image",
|
||||
'init_height': "Height for original/initial image",
|
||||
'HD_width': "Width for the (main/upscaled) HD-image",
|
||||
'HD_height': "Height for the (main/upscaled) HD-image",
|
||||
})
|
||||
|
||||
__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.",
|
||||
'HD_step': (_IO.INT, dict(_type_dict_step_upscale1, **{
|
||||
'tooltip': "Same as the main `step`, but for the upscaled resolution.\n144 = 8 * 2 * 3 * 3",
|
||||
})),
|
||||
}
|
||||
|
||||
@@ -94,7 +103,7 @@ class BestResolutionFromAreaUpscale:
|
||||
|
||||
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,
|
||||
priority: _t.Union[RoundingPriority, str], upscale: float, HD_step:int,
|
||||
# show: bool,
|
||||
unique_id: str = None
|
||||
):
|
||||
@@ -102,7 +111,7 @@ class BestResolutionFromAreaUpscale:
|
||||
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,
|
||||
_res_priority_verify(priority), upscale, HD_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.1.0"
|
||||
version = "1.1.1"
|
||||
authors = [
|
||||
{name = "Lex Darlog"}
|
||||
]
|
||||
|
||||
+4
-4
@@ -15,10 +15,10 @@ class ResultSimple(_t.NamedTuple):
|
||||
class ResultUpscaled(_t.NamedTuple):
|
||||
"""Returned NamedTuple for nodes with upscaling."""
|
||||
upscale: float
|
||||
orig_width: int
|
||||
orig_height: int
|
||||
up_width: int
|
||||
up_height: int
|
||||
init_width: int
|
||||
init_height: int
|
||||
hd_width: int
|
||||
hd_height: int
|
||||
|
||||
|
||||
class ResultUpscaledCropPad(_t.NamedTuple):
|
||||
|
||||
+3
-2
@@ -23,8 +23,8 @@ def number_type_dict(default: int = 512, min: int = 1, max: int = _sys.maxsize,
|
||||
|
||||
|
||||
type_dict_res = number_type_dict(1024)
|
||||
type_dict_step_init = number_type_dict(48)
|
||||
type_dict_step_upscale1 = number_type_dict(128)
|
||||
type_dict_step_init = number_type_dict(8*2*3)
|
||||
type_dict_step_upscale1 = number_type_dict(8*2*3*3)
|
||||
|
||||
upscale_in_type = (_IO.FLOAT, {
|
||||
'default': 1.5, 'min': 1.0, 'max': _sys.float_info.max, 'step': 0.25, 'round': 0.001,
|
||||
@@ -32,4 +32,5 @@ upscale_in_type = (_IO.FLOAT, {
|
||||
})
|
||||
rel_pos_in_type = (_IO.FLOAT, {
|
||||
'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.125, 'round': 0.0001,
|
||||
# 'display': 'slider', # Cosmetic only: display as 'number' or 'slider'
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user