From 57b31cb79ab5661712ec30c73b3f8513090020fd Mon Sep 17 00:00:00 2001 From: sgt0 <140186177+sgt0@users.noreply.github.com> Date: Sun, 24 Nov 2024 18:40:59 +0000 Subject: [PATCH] Use noncustom kernel when possible `descale.Decustom` init is slow and AFAICT it's only being used for symmetry with `resize2.Custom`, which itself was introduced to enable setting `blur` (am I missing something else?). If that's the case, then everything is being made slower just for the (probably) few cases of blur usage. This hurts the native-res plugin especially. With this change, things work like so: 1. If descaling, always use `descale.Debicubic`/`descale.Debilinear`. They support `blur` so there should be no need for custom kernels. 2. If scaling/resampling, use `resize2.Bicubic`/`resize2.Bilinear` if `blur` is not set to the default of 1.0. This isn't here to speed anything up, rather it just seems like a good idea to use the plugin's available filters when possible instead of custom ones. 3. Otherwise, use the slower custom kernels since blur is needed and not provided by the plugin. With this, native-res execution (height [502, 999], step size 1, Catrom) goes from ~3 minutes to ~30 seconds. --- vskernels/kernels/bicubic.py | 22 +++++++++++++++++++--- vskernels/kernels/complex.py | 9 ++++++++- vskernels/kernels/custom.py | 22 ++++++++++++++++++++-- vskernels/kernels/spline.py | 8 +++++++- vskernels/kernels/various.py | 11 +++++++++-- 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/vskernels/kernels/bicubic.py b/vskernels/kernels/bicubic.py index ef84702..05c6a28 100644 --- a/vskernels/kernels/bicubic.py +++ b/vskernels/kernels/bicubic.py @@ -1,9 +1,9 @@ from __future__ import annotations from math import sqrt -from typing import Any +from typing import Any, override -from vstools import CustomValueError, inject_self +from vstools import CustomValueError, core, inject_self, vs from .complex import CustomComplexKernel from .helpers import bic_vals, poly3 @@ -36,12 +36,16 @@ class Bicubic(CustomComplexKernel): :param c: C-param for bicubic kernel """ + descale_function = core.lazy.descale.Debicubic # type: ignore[assignment] + _no_blur_scale_function = core.lazy.resize2.Bicubic + def __init__(self, b: float = 0, c: float = 1 / 2, **kwargs: Any) -> None: self.b = b self.c = c super().__init__(**kwargs) @inject_self.cached + @override def kernel(self, *, x: float) -> float: x, b, c = abs(x), self.b, self.c @@ -54,11 +58,23 @@ def kernel(self, *, x: float) -> float: return 0.0 @inject_self.cached.property - def kernel_radius(self) -> int: # type: ignore + @override + def kernel_radius(self) -> int: # type: ignore[override] if (self.b, self.c) == (0, 0): return 1 return 2 + @override + def get_params_args( + self, is_descale: bool, clip: vs.VideoNode, width: int | None = None, height: int | None = None, **kwargs: Any + ) -> dict[str, Any]: + args = super().get_params_args(is_descale, clip, width, height, **kwargs) + return ( + args | {"b": self.b, "c": self.c} + if is_descale + else args | {"filter_param_a": self.b, "filter_param_b": self.c} + ) + class BSpline(Bicubic): """Bicubic b=1, c=0""" diff --git a/vskernels/kernels/complex.py b/vskernels/kernels/complex.py index 1c59b62..af37e0f 100644 --- a/vskernels/kernels/complex.py +++ b/vskernels/kernels/complex.py @@ -1,7 +1,7 @@ from __future__ import annotations from math import ceil -from typing import TYPE_CHECKING, Any, SupportsFloat, TypeVar, Union, cast +from typing import TYPE_CHECKING, Any, SupportsFloat, TypeVar, Union, cast, override from stgpytools import inject_kwargs_params from vstools import ( @@ -261,6 +261,13 @@ def __init__(self, taps: float, **kwargs: Any) -> None: def kernel_radius(self) -> int: # type: ignore return ceil(self.taps) + @override + def get_params_args( + self, is_descale: bool, clip: vs.VideoNode, width: int | None = None, height: int | None = None, **kwargs: Any + ) -> dict[str, Any]: + args = super().get_params_args(is_descale, clip, width, height, **kwargs) + return args | {'taps': self.taps} if is_descale else args | {'filter_param_a': self.taps} + ComplexScalerT = Union[str, type[ComplexScaler], ComplexScaler] ComplexKernelT = Union[str, type[ComplexKernel], ComplexKernel] diff --git a/vskernels/kernels/custom.py b/vskernels/kernels/custom.py index 7fafe69..be922b8 100644 --- a/vskernels/kernels/custom.py +++ b/vskernels/kernels/custom.py @@ -2,8 +2,8 @@ from stgpytools import CustomValueError, KwargsT, inject_self from inspect import Signature -from vstools import vs, core -from typing import Any, Protocol +from vstools import GenericVSFunction, vs, core +from typing import Any, Protocol, override from .abstract import Kernel from typing import TypeVar @@ -20,6 +20,13 @@ def __call__(self, *, x: float) -> float: class CustomKernel(Kernel): + _no_blur_scale_function: GenericVSFunction | None = None + """ + Optional scale function that will be used when scaling without blur. This is + useful for cases where this function is more performant than the custom + kernel. + """ + def kernel(self, *, x: float) -> float: raise NotImplementedError @@ -37,14 +44,25 @@ def kernel(*, x: float) -> float: return self.kernel, support @inject_self + @override def scale_function( # type: ignore[override] self, clip: vs.VideoNode, width: int | None = None, height: int | None = None, *args: Any, **kwargs: Any ) -> vs.VideoNode: + # If a no-blur scale function is defined and the default blur is being + # used, then remove the parameter and use the given scale function. + if self._no_blur_scale_function and kwargs.get("blur", 1.0) == 1.0: + kwargs.pop("blur", None) + return self._no_blur_scale_function(clip, width, height, *args, **kwargs) + + # Otherwise, fall back to the slower custom kernel implementation. + kernel, support = self._modify_kernel_func(kwargs) clean_kwargs = { k: v for k, v in kwargs.items() if k not in Signature.from_callable(self._modify_kernel_func).parameters.keys() + # Remove params that won't be recognized by `resize2.Custom`. + and k not in ('filter_param_a', 'filter_param_b') } return core.resize2.Custom(clip, kernel, int(support), width, height, *args, **clean_kwargs) diff --git a/vskernels/kernels/spline.py b/vskernels/kernels/spline.py index 8a160c2..94dbf17 100644 --- a/vskernels/kernels/spline.py +++ b/vskernels/kernels/spline.py @@ -3,7 +3,7 @@ from math import comb from typing import Any -from vstools import inject_self +from vstools import core, inject_self from .complex import CustomComplexTapsKernel from .helpers import poly3 @@ -106,6 +106,8 @@ def __init__(self, **kwargs: Any) -> None: class Spline16(NaturalSpline): """Spline16 resizer.""" + descale_function = core.lazy.descale.Despline16 + _no_blur_scale_function = core.lazy.resize2.Spline16 _static_kernel_radius = 2 _static_coeffs = [ @@ -117,6 +119,8 @@ class Spline16(NaturalSpline): class Spline36(NaturalSpline): """Spline36 resizer.""" + descale_function = core.lazy.descale.Despline36 + _no_blur_scale_function = core.lazy.resize2.Spline36 _static_kernel_radius = 3 _static_coeffs = [ @@ -129,6 +133,8 @@ class Spline36(NaturalSpline): class Spline64(NaturalSpline): """Spline64 resizer.""" + descale_function = core.lazy.descale.Despline64 + _no_blur_scale_function = core.lazy.resize2.Spline64 _static_kernel_radius = 4 _static_coeffs = [ diff --git a/vskernels/kernels/various.py b/vskernels/kernels/various.py index 237ce03..92193f9 100644 --- a/vskernels/kernels/various.py +++ b/vskernels/kernels/various.py @@ -1,9 +1,9 @@ from __future__ import annotations from math import cos, exp, log, pi, sqrt -from typing import Any +from typing import Any, override -from vstools import inject_self +from vstools import core, inject_self, vs from .complex import CustomComplexKernel, CustomComplexTapsKernel from .helpers import sinc @@ -62,9 +62,12 @@ def kernel(self, *, x: float) -> float: class Bilinear(CustomComplexKernel): """Bilinear resizer.""" + descale_function = core.lazy.descale.Debilinear # type: ignore[assignment] + _no_blur_scale_function = core.lazy.resize2.Bilinear _static_kernel_radius = 1 @inject_self.cached + @override def kernel(self, *, x: float) -> float: return max(1.0 - abs(x), 0.0) @@ -76,10 +79,14 @@ class Lanczos(CustomComplexTapsKernel): :param taps: taps param for lanczos kernel """ + descale_function = core.lazy.descale.Delanczos # type: ignore[assignment] + _no_blur_scale_function = core.lazy.resize2.Lanczos + def __init__(self, taps: float = 3, **kwargs: Any) -> None: super().__init__(taps, **kwargs) @inject_self.cached + @override def kernel(self, *, x: float) -> float: x, taps = abs(x), self.kernel_radius