diff --git a/vskernels/kernels/abstract.py b/vskernels/kernels/abstract.py index fddaa6e..4f62e9b 100644 --- a/vskernels/kernels/abstract.py +++ b/vskernels/kernels/abstract.py @@ -19,6 +19,18 @@ ] +def _default_kernel_radius(cls, self) -> int: + if hasattr(self, '_static_kernel_radius'): + return ceil(self._static_kernel_radius) + + try: + return super(cls, self).kernel_radius + except AttributeError: + ... + + raise NotImplementedError + + class BaseScaler: @staticmethod def from_param( @@ -120,6 +132,10 @@ def multi( return self.scale(clip, dst_width, dst_height, shift, **kwargs) + @inject_self.property + def kernel_radius(self) -> int: + return _default_kernel_radius(__class__, self) + class Descaler(vs_object): @inject_self.cached @@ -165,6 +181,10 @@ def ensure_obj( ) -> Descaler: return BaseScaler.ensure_obj(cls, Descaler, descaler, UnknownDescalerError, [], func_except) # type: ignore + @inject_self.property + def kernel_radius(self) -> int: + return _default_kernel_radius(__class__, self) + class Resampler(vs_object): @inject_self.cached @@ -186,6 +206,10 @@ def ensure_obj( ) -> Resampler: return BaseScaler.ensure_obj(cls, Resampler, resampler, UnknownDescalerError, [], func_except) # type: ignore + @inject_self.property + def kernel_radius(self) -> int: + return _default_kernel_radius(__class__, self) + class Kernel(Scaler, Descaler, Resampler): """ diff --git a/vskernels/kernels/bicubic.py b/vskernels/kernels/bicubic.py index 99de42b..1508c78 100644 --- a/vskernels/kernels/bicubic.py +++ b/vskernels/kernels/bicubic.py @@ -3,7 +3,7 @@ from math import acos, asinh, cos, sqrt from typing import TYPE_CHECKING, Any -from vstools import CustomValueError, core, vs +from vstools import CustomValueError, core, vs, inject_self from .complex import ComplexKernel @@ -68,6 +68,12 @@ def get_params_args( return args | dict(b=self.b, c=self.c) return args | dict(filter_param_a=self.b, filter_param_b=self.c) + @inject_self.property + def kernel_radius(self) -> int: + if (self.b, self.c) == (0, 0): + return 1 + return 2 + class BSpline(Bicubic): """Bicubic b=1, c=0""" @@ -265,3 +271,7 @@ def _get_bc_args(self) -> tuple[float, float]: autoc = (self.target - self.b) / 2 return autob, autoc + + @inject_self.property + def kernel_radius(self) -> int: + return Bicubic(*self._get_bc_args()).kernel_radius diff --git a/vskernels/kernels/fmtconv.py b/vskernels/kernels/fmtconv.py index c549d11..b81c424 100644 --- a/vskernels/kernels/fmtconv.py +++ b/vskernels/kernels/fmtconv.py @@ -1,12 +1,13 @@ from __future__ import annotations +from math import ceil from typing import Any, Callable, overload from vstools import VideoFormatT, VSFunction, core, inject_self, vs from .abstract import Resampler -from .complex import ComplexScaler from .bicubic import Bicubic +from .complex import ComplexScaler __all__ = [ 'FmtConv' @@ -167,3 +168,12 @@ def _shift(shift_top: float | list[float] = 0.0, shift_left: float | list[float] shifts_left = shifts_left[:n_planes] return _shift(shifts_top, shifts_left) + + @inject_self.property + def kernel_radius(self) -> int: + taps_hv = self.kwargs.get('taps_h', self.kwargs.get('taps_v', None)) + + if taps_hv is None: + taps_hv = self.taps + + return ceil(taps_hv) diff --git a/vskernels/kernels/placebo.py b/vskernels/kernels/placebo.py index f779c92..67dcfc1 100644 --- a/vskernels/kernels/placebo.py +++ b/vskernels/kernels/placebo.py @@ -1,5 +1,6 @@ from __future__ import annotations +from math import ceil from typing import TYPE_CHECKING, Any from vstools import Transfer, TransferT, core, inject_self, vs @@ -82,3 +83,15 @@ def get_params_args( antiring=self.antiring, cutoff=self.cutoff, lut_entries=self.lut_entries, trc=curve.value_libplacebo ) + + @inject_self.property + def kernel_radius(self) -> int: + from .bicubic import Bicubic + + if self.taps: + return ceil(self.taps) + + if self.b or self.c: + return Bicubic(self.b, self.c).kernel_radius + + return 2 diff --git a/vskernels/kernels/resize.py b/vskernels/kernels/resize.py index f1e553f..cb40a49 100644 --- a/vskernels/kernels/resize.py +++ b/vskernels/kernels/resize.py @@ -1,8 +1,9 @@ from __future__ import annotations +from math import ceil from typing import Any -from vstools import core, vs +from vstools import core, vs, inject_self from .zimg import ZimgComplexKernel @@ -17,6 +18,7 @@ class Point(ZimgComplexKernel): """Built-in point resizer.""" scale_function = resample_function = descale_function = core.lazy.resize.Point + _static_kernel_radius = 1 class Bilinear(ZimgComplexKernel): @@ -24,6 +26,7 @@ class Bilinear(ZimgComplexKernel): scale_function = resample_function = core.lazy.resize.Bilinear descale_function = core.lazy.descale.Debilinear + _static_kernel_radius = 1 class Lanczos(ZimgComplexKernel): @@ -51,3 +54,7 @@ def get_params_args( if is_descale: return args | dict(taps=self.taps) return args | dict(filter_param_a=self.taps) + + @inject_self.property + def kernel_radius(self) -> int: + return ceil(self.taps) diff --git a/vskernels/kernels/spline.py b/vskernels/kernels/spline.py index fa61db9..280edb8 100644 --- a/vskernels/kernels/spline.py +++ b/vskernels/kernels/spline.py @@ -4,8 +4,8 @@ from vstools import core -from .zimg import ZimgComplexKernel from .fmtconv import FmtConv +from .zimg import ZimgComplexKernel __all__ = [ 'Spline', @@ -35,6 +35,7 @@ class Spline16(ZimgComplexKernel): scale_function = resample_function = core.lazy.resize.Spline16 descale_function = core.lazy.descale.Despline16 + _static_kernel_radius = 2 class Spline36(ZimgComplexKernel): @@ -48,6 +49,7 @@ class Spline36(ZimgComplexKernel): scale_function = resample_function = core.lazy.resize.Spline36 descale_function = core.lazy.descale.Despline36 + _static_kernel_radius = 3 class Spline64(ZimgComplexKernel): @@ -61,3 +63,4 @@ class Spline64(ZimgComplexKernel): scale_function = resample_function = core.lazy.resize.Spline64 descale_function = core.lazy.descale.Despline64 + _static_kernel_radius = 4 diff --git a/vskernels/kernels/various.py b/vskernels/kernels/various.py index 59fb9ed..d64064c 100644 --- a/vskernels/kernels/various.py +++ b/vskernels/kernels/various.py @@ -107,7 +107,9 @@ def __init__(self, b: float = 0.0, c: float = 0.5, radius: int | None = None, ** radius = kwargs.pop('taps', radius) if radius is None: - radius = 1 if (b, c) == (0, 0) else 2 + from .bicubic import Bicubic + + radius = Bicubic(b, c).kernel_radius super().__init__(radius, b, c, **kwargs)