Skip to content

Commit

Permalink
Move Complex* to complex submodule
Browse files Browse the repository at this point in the history
  • Loading branch information
Setsugennoao committed Oct 15, 2023
1 parent ef49503 commit 5440e7f
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 150 deletions.
3 changes: 1 addition & 2 deletions vskernels/kernels/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from __future__ import annotations

from . import docs # noqa: F401
from .abstract import * # noqa: F401, F403
from .bicubic import * # noqa: F401, F403
from .complex import * # noqa: F401, F403
from .fmtconv import * # noqa: F401, F403
from .impulse import * # noqa: F401, F403
from .placebo import * # noqa: F401, F403
Expand Down
147 changes: 3 additions & 144 deletions vskernels/kernels/abstract.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from __future__ import annotations

from math import ceil
from typing import TYPE_CHECKING, Any, Sequence, Union, cast, overload
from typing import Any, Sequence, Union, cast, overload

from vstools import (
CustomValueError, FuncExceptT, GenericVSFunction, HoldsVideoFormatT, KwargsT, Matrix, MatrixT, Resolution, Sar, T,
CustomValueError, FuncExceptT, GenericVSFunction, HoldsVideoFormatT, Matrix, MatrixT, T,
VideoFormatT, check_variable_resolution, core, get_subclasses, get_video_format, inject_self, vs, vs_object
)

Expand All @@ -14,12 +14,7 @@
'Scaler', 'ScalerT',
'Descaler', 'DescalerT',
'Resampler', 'ResamplerT',
'Kernel', 'KernelT',

'ComplexScaler',
'ComplexKernel',

'LinearScaler'
'Kernel', 'KernelT'
]


Expand Down Expand Up @@ -353,143 +348,7 @@ def ensure_obj(
)


class _BaseLinearOperation:
orig_kwargs = {}

def __init__(self, **kwargs: Any) -> None:
self.orig_kwargs = kwargs
self.kwargs = {k: v for k, v in kwargs.items() if k not in ('linear', 'sigmoid')}

@staticmethod
def _linear_op(op_name: str) -> Any:
def func(
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
*, linear: bool = False, sigmoid: bool | tuple[float, float] = False, **kwargs: Any
) -> vs.VideoNode:
from ..util import LinearLight

has_custom_op = hasattr(self, f'_linear_{op_name}')
operation = getattr(self, f'_linear_{op_name}') if has_custom_op else super().scale
sigmoid = self.orig_kwargs.get('sigmoid', sigmoid)
linear = self.orig_kwargs.get('linear', False) or linear or not not sigmoid

if not linear and not has_custom_op:
return operation(clip, width, height, shift, **kwargs)

with LinearLight(clip, linear, sigmoid, self) as ll:
ll.linear = operation(ll.linear, width, height, shift, **kwargs)

return ll.out

return func


class LinearScaler(_BaseLinearOperation, Scaler):
if TYPE_CHECKING:
@inject_self.cached
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
*, linear: bool = False, sigmoid: bool | tuple[float, float] = False, **kwargs: Any
) -> vs.VideoNode:
...
else:
scale = _BaseLinearOperation._linear_op('scale')


class LinearDescaler(_BaseLinearOperation, Descaler):
if TYPE_CHECKING:
@inject_self.cached
def descale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
*, linear: bool = False, sigmoid: bool | tuple[float, float] = False, **kwargs: Any
) -> vs.VideoNode:
...
else:
descale = _BaseLinearOperation._linear_op('descale')


class _KeepArScaler(Scaler):
def _handle_crop_resize_kwargs( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
**kwargs: Any
) -> tuple[KwargsT, tuple[float, float], Sar]:
kwargs.setdefault('src_top', kwargs.pop('sy', shift[0]))
kwargs.setdefault('src_left', kwargs.pop('sx', shift[1]))
kwargs.setdefault('src_width', kwargs.pop('sw', clip.width))
kwargs.setdefault('src_height', kwargs.pop('sh', clip.height))

src_res = Resolution(kwargs['src_width'], kwargs['src_height'])
out_res = Resolution(width, height)

sar = Sar.from_clip(clip)

if sar.numerator != sar.denominator:
sar_f = sar.numerator / sar.denominator

if sar_f > 1:
out_res = Resolution(out_res.width / sar_f, out_res.height)
else:
out_res = Resolution(out_res.width, out_res.height * sar_f)

sar = Sar(1, 1)

src_dar, out_dar = src_res.width / src_res.height, out_res.width / out_res.height

if src_dar != out_dar:
if src_dar > out_dar:
src_res, out_res = src_res.transpose(), out_res.transpose()
src_shift, src_window = 'src_left', 'src_width'
else:
src_shift, src_window = 'src_top', 'src_height'

fix_scale = src_res.width / out_res.width
fix_crop = src_res.height - (out_res.height * fix_scale)
fix_shift = fix_crop / 2

kwargs[src_shift] = kwargs.get(src_shift, 0) + fix_shift
kwargs[src_window] = kwargs[src_window] - fix_crop

out_shift = (kwargs.pop('src_top'), kwargs.pop('src_left'))

return kwargs, out_shift, sar

@inject_self.cached
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
*, keep_ar: bool = False, **kwargs: Any
) -> vs.VideoNode:
if keep_ar:
kwargs, shift, sar = self._handle_crop_resize_kwargs(clip, width, height, shift, **kwargs)

kwargs = self.get_scale_args(clip, shift, width, height, **kwargs)

clip = self.scale_function(clip, **kwargs)

if keep_ar:
clip = sar.apply(clip)

return clip


class ComplexScaler(LinearScaler, _KeepArScaler):
if TYPE_CHECKING:
@inject_self.cached
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
*, keep_ar: bool = False, linear: bool = False, sigmoid: bool | tuple[float, float] = False,
**kwargs: Any
) -> vs.VideoNode:
...


class ComplexKernel(Kernel, LinearDescaler, ComplexScaler):
...


ScalerT = Union[str, type[Scaler], Scaler]
DescalerT = Union[str, type[Descaler], Descaler]
ResamplerT = Union[str, type[Resampler], Resampler]
KernelT = Union[str, type[Kernel], Kernel]

ComplexScalerT = Union[str, type[ComplexScaler], ComplexScaler]
ComplexKernelT = Union[str, type[ComplexKernel], ComplexKernel]
3 changes: 2 additions & 1 deletion vskernels/kernels/bicubic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

from vstools import CustomValueError, core, vs

from .abstract import ComplexKernel, Kernel
from .abstract import Kernel
from .complex import ComplexKernel

__all__ = [
'Bicubic',
Expand Down
153 changes: 153 additions & 0 deletions vskernels/kernels/complex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
from __future__ import annotations

from typing import TYPE_CHECKING, Any, Union

from vstools import KwargsT, Resolution, Sar, inject_self, vs

from .abstract import Descaler, Kernel, Scaler

__all__ = [
'LinearScaler', 'LinearDescaler',

'KeepArScaler',

'ComplexScaler', 'ComplexScalerT',
'ComplexKernel', 'ComplexKernelT'
]


class _BaseLinearOperation:
orig_kwargs = {}

def __init__(self, **kwargs: Any) -> None:
self.orig_kwargs = kwargs
self.kwargs = {k: v for k, v in kwargs.items() if k not in ('linear', 'sigmoid')}

@staticmethod
def _linear_op(op_name: str) -> Any:
def func(
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
*, linear: bool = False, sigmoid: bool | tuple[float, float] = False, **kwargs: Any
) -> vs.VideoNode:
from ..util import LinearLight

has_custom_op = hasattr(self, f'_linear_{op_name}')
operation = getattr(self, f'_linear_{op_name}') if has_custom_op else super().scale # type: ignore
sigmoid = self.orig_kwargs.get('sigmoid', sigmoid)
linear = self.orig_kwargs.get('linear', False) or linear or not not sigmoid

if not linear and not has_custom_op:
return operation(clip, width, height, shift, **kwargs)

with LinearLight(clip, linear, sigmoid, self) as ll:
ll.linear = operation(ll.linear, width, height, shift, **kwargs)

return ll.out

return func


class LinearScaler(_BaseLinearOperation, Scaler):
if TYPE_CHECKING:
@inject_self.cached
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
*, linear: bool = False, sigmoid: bool | tuple[float, float] = False, **kwargs: Any
) -> vs.VideoNode:
...
else:
scale = _BaseLinearOperation._linear_op('scale')


class LinearDescaler(_BaseLinearOperation, Descaler):
if TYPE_CHECKING:
@inject_self.cached
def descale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
*, linear: bool = False, sigmoid: bool | tuple[float, float] = False, **kwargs: Any
) -> vs.VideoNode:
...
else:
descale = _BaseLinearOperation._linear_op('descale')


class KeepArScaler(Scaler):
def _handle_crop_resize_kwargs( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
**kwargs: Any
) -> tuple[KwargsT, tuple[float, float], Sar]:
kwargs.setdefault('src_top', kwargs.pop('sy', shift[0]))
kwargs.setdefault('src_left', kwargs.pop('sx', shift[1]))
kwargs.setdefault('src_width', kwargs.pop('sw', clip.width))
kwargs.setdefault('src_height', kwargs.pop('sh', clip.height))

src_res = Resolution(kwargs['src_width'], kwargs['src_height'])
out_res = Resolution(width, height)

sar = Sar.from_clip(clip)

if sar.numerator != sar.denominator:
sar_f = sar.numerator / sar.denominator

if sar_f > 1:
out_res = Resolution(out_res.width / sar_f, out_res.height)
else:
out_res = Resolution(out_res.width, out_res.height * sar_f)

sar = Sar(1, 1)

src_dar, out_dar = src_res.width / src_res.height, out_res.width / out_res.height

if src_dar != out_dar:
if src_dar > out_dar:
src_res, out_res = src_res.transpose(), out_res.transpose()
src_shift, src_window = 'src_left', 'src_width'
else:
src_shift, src_window = 'src_top', 'src_height'

fix_scale = src_res.width / out_res.width
fix_crop = src_res.height - (out_res.height * fix_scale)
fix_shift = fix_crop / 2

kwargs[src_shift] = kwargs.get(src_shift, 0) + fix_shift
kwargs[src_window] = kwargs[src_window] - fix_crop

out_shift = (kwargs.pop('src_top'), kwargs.pop('src_left'))

return kwargs, out_shift, sar

@inject_self.cached
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
*, keep_ar: bool = False, **kwargs: Any
) -> vs.VideoNode:
if keep_ar:
kwargs, shift, sar = self._handle_crop_resize_kwargs(clip, width, height, shift, **kwargs)

kwargs = self.get_scale_args(clip, shift, width, height, **kwargs)

clip = self.scale_function(clip, **kwargs)

if keep_ar:
clip = sar.apply(clip)

return clip


class ComplexScaler(LinearScaler, KeepArScaler):
if TYPE_CHECKING:
@inject_self.cached
def scale( # type: ignore[override]
self, clip: vs.VideoNode, width: int, height: int, shift: tuple[float, float] = (0, 0),
*, keep_ar: bool = False, linear: bool = False, sigmoid: bool | tuple[float, float] = False,
**kwargs: Any
) -> vs.VideoNode:
...


class ComplexKernel(Kernel, LinearDescaler, ComplexScaler):
...


ComplexScalerT = Union[str, type[ComplexScaler], ComplexScaler]
ComplexKernelT = Union[str, type[ComplexKernel], ComplexKernel]
2 changes: 1 addition & 1 deletion vskernels/kernels/fmtconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from vstools import VideoFormatT, VSFunction, core, inject_self, vs

from .abstract import ComplexScaler
from .complex import ComplexScaler
from .bicubic import Bicubic

__all__ = [
Expand Down
2 changes: 1 addition & 1 deletion vskernels/kernels/resize.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from vstools import core, vs

from .abstract import ComplexKernel
from .complex import ComplexKernel

__all__ = [
'Point',
Expand Down
2 changes: 1 addition & 1 deletion vskernels/kernels/spline.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from vstools import core

from .abstract import ComplexKernel
from .complex import ComplexKernel
from .fmtconv import FmtConv

__all__ = [
Expand Down

0 comments on commit 5440e7f

Please sign in to comment.