Skip to content

Commit

Permalink
Make Scaler/Descaler scale/descale width/height parameters optional
Browse files Browse the repository at this point in the history
This is to allow 1x resampling with non-interpolatory kernels without manually specifying width/height #19
  • Loading branch information
Setsugennoao committed May 16, 2024
1 parent 9589a13 commit 4a3f65a
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 19 deletions.
15 changes: 12 additions & 3 deletions vskernels/kernels/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from vstools import (
CustomIndexError, CustomRuntimeError, CustomValueError, FieldBased, FuncExceptT, GenericVSFunction,
HoldsVideoFormatT, KwargsT, Matrix, MatrixT, PropEnum, T, VideoFormatT, check_correct_subsampling,
check_variable_resolution, core, depth, expect_bits, get_subclasses, get_video_format, inject_self, vs, vs_object
check_variable_resolution, core, depth, expect_bits, fallback, get_subclasses, get_video_format, inject_self, vs,
vs_object
)

from ..exceptions import UnknownDescalerError, UnknownKernelError, UnknownResamplerError, UnknownScalerError
Expand Down Expand Up @@ -175,6 +176,10 @@ def __init_subclass__(cls) -> None:
if mro:
raise CustomRuntimeError('You must implement kernel_radius when inheriting BaseScaler!', reason=cls)

@staticmethod
def _wh_norm(clip: vs.VideoNode, width: int | None = None, height: int | None = None) -> tuple[int, int]:
return (fallback(width, clip.width), fallback(height, clip.height))

@classmethod
def from_param(
cls: type[BaseScalerT], scaler: str | type[BaseScalerT] | BaseScalerT | None = None, /,
Expand Down Expand Up @@ -217,8 +222,10 @@ class Scaler(BaseScaler):
@inject_self.cached
@inject_kwargs_params
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift] = (0, 0), **kwargs: Any
self, clip: vs.VideoNode, width: int | None = None, height: int | None = None,
shift: tuple[TopShift, LeftShift] = (0, 0), **kwargs: Any
) -> vs.VideoNode:
width, height = Scaler._wh_norm(clip, width, height)
check_correct_subsampling(clip, width, height)
return self.scale_function(clip, **_norm_props_enums(self.get_scale_args(clip, shift, width, height, **kwargs)))

Expand Down Expand Up @@ -270,8 +277,10 @@ class Descaler(BaseScaler):
@inject_self.cached
@inject_kwargs_params
def descale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift] = (0, 0), **kwargs: Any
self, clip: vs.VideoNode, width: int | None, height: int | None, shift: tuple[TopShift, LeftShift] = (0, 0), **kwargs: Any
) -> vs.VideoNode:
width, height = self._wh_norm(clip, width, height)

check_correct_subsampling(clip, width, height)

field_based = FieldBased.from_param_or_video(kwargs.pop('field_based', None), clip)
Expand Down
20 changes: 14 additions & 6 deletions vskernels/kernels/complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ class _BaseLinearOperation:
def _linear_op(op_name: str) -> Any:
@inject_kwargs_params
def func(
self: _BaseLinearOperation, clip: vs.VideoNode, width: int, height: int,
self: _BaseLinearOperation, clip: vs.VideoNode, width: int | None = None, height: int | None = None,

shift: tuple[TopShift, LeftShift] = (0, 0), *,
linear: bool = False, sigmoid: bool | tuple[Slope, Center] = False, **kwargs: Any
) -> vs.VideoNode:
Expand Down Expand Up @@ -110,7 +111,8 @@ class LinearScaler(_BaseLinearOperation, Scaler):
@inject_self.cached
@inject_kwargs_params
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift] = (0, 0),
self, clip: vs.VideoNode, width: int | None = None, height: int | None = None,
shift: tuple[TopShift, LeftShift] = (0, 0),
*, linear: bool = False, sigmoid: bool | tuple[Slope, Center] = False, **kwargs: Any
) -> vs.VideoNode:
...
Expand All @@ -123,7 +125,8 @@ class LinearDescaler(_BaseLinearOperation, Descaler):
@inject_self.cached
@inject_kwargs_params
def descale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift] = (0, 0),
self, clip: vs.VideoNode, width: int | None = None, height: int | None = None,
shift: tuple[TopShift, LeftShift] = (0, 0),
*, linear: bool = False, sigmoid: bool | tuple[Slope, Center] = False, **kwargs: Any
) -> vs.VideoNode:
...
Expand Down Expand Up @@ -153,7 +156,7 @@ def _get_kwargs_keep_ar(
return kwargs

def _handle_crop_resize_kwargs( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift],
self, clip: vs.VideoNode, width: int | None, height: int | None, shift: tuple[TopShift, LeftShift],
sar: Sar | bool | float | None, dar: Dar | bool | float | None, **kwargs: Any
) -> tuple[KwargsT, tuple[TopShift, LeftShift], Sar | None]:
kwargs.setdefault('src_top', kwargs.pop('sy', shift[0]))
Expand Down Expand Up @@ -199,11 +202,14 @@ def _handle_crop_resize_kwargs( # type: ignore[override]
@inject_self.cached
@inject_kwargs_params
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift] = (0, 0), *,
self, clip: vs.VideoNode, width: int | None = None, height: int | None = None,
shift: tuple[TopShift, LeftShift] = (0, 0), *,
border_handling: BorderHandling = BorderHandling.MIRROR,
sar: Sar | float | bool | None = None, dar: Dar | float | bool | None = None, keep_ar: bool = False,
**kwargs: Any
) -> vs.VideoNode:
width, height = Scaler._wh_norm(clip, width, height)

check_correct_subsampling(clip, width, height)

const_size = 0 not in (clip.width, clip.height)
Expand Down Expand Up @@ -231,13 +237,15 @@ class ComplexScaler(LinearScaler, KeepArScaler):
@inject_self.cached
@inject_kwargs_params
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift] = (0, 0),
self, clip: vs.VideoNode, width: int | None = None, height: int | None = None,
shift: tuple[TopShift, LeftShift] = (0, 0),
*,
border_handling: BorderHandling = BorderHandling.MIRROR,
sar: Sar | bool | float | None = None, dar: Dar | bool | float | None = None, keep_ar: bool = False,
linear: bool = False, sigmoid: bool | tuple[Slope, Center] = False,
**kwargs: Any
) -> vs.VideoNode:
width, height = Scaler._wh_norm(clip, width, height)
return super().scale(
clip, width, height, shift, sar=sar, dar=dar, keep_ar=keep_ar,
linear=linear, sigmoid=sigmoid, border_handling=border_handling,
Expand Down
7 changes: 5 additions & 2 deletions vskernels/kernels/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ def __init__(self, b: float = 0, c: float = 1 / 2, **kwargs: Any) -> None:

@inject_self.cached
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0), **kwargs: Any
self, clip: vs.VideoNode, width: int | None = None, height: int | None = None,
shift: tuple[float, float] = (0, 0), **kwargs: Any
) -> vs.VideoNode:
"""
Perform a regular scaling operation.
Expand All @@ -34,14 +35,15 @@ def scale( # type: ignore[override]
:rtype: ``VideoNode``
"""
width, height = self._wh_norm(clip, width, height)
return core.resize.Bicubic(
clip, width, height, src_top=shift[0], src_left=shift[1],
filter_param_a=self.b, filter_param_b=self.c, **self.kwargs, **kwargs
)

@inject_self.cached
def descale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0), **kwargs: Any
self, clip: vs.VideoNode, width: int | None, height: int | None, shift: tuple[float, float] = (0, 0), **kwargs: Any
) -> vs.VideoNode:
"""
Perform a regular descaling operation.
Expand All @@ -54,6 +56,7 @@ def descale( # type: ignore[override]
:rtype: ``VideoNode``
"""
width, height = self._wh_norm(clip, width, height)
return depth(core.descale.Debicubic(
depth(clip, 32), width, height, b=self.b, c=self.c, src_top=shift[0], src_left=shift[1], **kwargs
), clip)
Expand Down
3 changes: 2 additions & 1 deletion vskernels/kernels/impulse.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ def __init__(self, impulse: Sequence[float], oversample: int = 8, taps: float =
@inject_self.cached
@inject_kwargs_params
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int,
self, clip: vs.VideoNode, width: int | None = None, height: int | None = None,
shift: tuple[TopShift, LeftShift] = (-0.125, -0.125), **kwargs: Any
) -> vs.VideoNode:
width, height = self._wh_norm(clip, width, height)
return super().scale(clip, width, height, shift, **kwargs)


Expand Down
7 changes: 4 additions & 3 deletions vskernels/kernels/placebo.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@ def __init__(
@inject_self.cached
@inject_kwargs_params
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift] = (0, 0),
*, linear: bool = True, sigmoid: bool | tuple[Slope, Center] = True, curve: TransferT | None = None,
**kwargs: Any
self, clip: vs.VideoNode, width: int | None = None, height: int | None = None,
shift: tuple[TopShift, LeftShift] = (0, 0), *,
linear: bool = True, sigmoid: bool | tuple[Slope, Center] = True, curve: TransferT | None = None, **kwargs: Any
) -> vs.VideoNode:
width, height = self._wh_norm(clip, width, height)
return super().scale(
clip, width, height, shift, linear=linear, sigmoid=sigmoid,
trc=Transfer.from_param_or_video(curve, clip).value_libplacebo
Expand Down
6 changes: 3 additions & 3 deletions vskernels/kernels/zimg.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from ..types import Center, LeftShift, Slope, TopShift
from .abstract import Descaler
from .complex import ComplexKernel, BorderHandling
from .complex import BorderHandling, ComplexKernel

__all__ = [
'ZimgDescaler',
Expand All @@ -20,7 +20,7 @@ class ZimgDescaler(Descaler):
@inject_self.cached
@inject_kwargs_params
def descale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift] = (0, 0),
self, clip: vs.VideoNode, width: int | None, height: int | None, shift: tuple[TopShift, LeftShift] = (0, 0),
*, blur: float = 1.0, border_handling: BorderHandling = BorderHandling.MIRROR, **kwargs: Any
) -> vs.VideoNode:
...
Expand All @@ -31,7 +31,7 @@ class ZimgComplexKernel(ComplexKernel, ZimgDescaler): # type: ignore
@inject_self.cached
@inject_kwargs_params
def descale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift] = (0, 0),
self, clip: vs.VideoNode, width: int | None, height: int | None, shift: tuple[TopShift, LeftShift] = (0, 0),
*, blur: float = 1.0, border_handling: BorderHandling, ignore_mask: vs.VideoNode | None = None,
linear: bool = False, sigmoid: bool | tuple[Slope, Center] = False, **kwargs: Any
) -> vs.VideoNode:
Expand Down
4 changes: 3 additions & 1 deletion vskernels/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,11 @@ class NoScaleBase(Scaler):
@inject_self.cached
@inject_kwargs_params
def scale( # type: ignore
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[TopShift, LeftShift] = (0, 0), **kwargs: Any
self, clip: vs.VideoNode, width: int | None = None, height: int | None = None,
shift: tuple[TopShift, LeftShift] = (0, 0), **kwargs: Any
) -> vs.VideoNode:
try:
width, height = Scaler._wh_norm(clip, width, height)
return super().scale(clip, clip.width, clip.height, shift, **kwargs) # type: ignore
except Exception:
return clip
Expand Down

0 comments on commit 4a3f65a

Please sign in to comment.