https://github.com/irrational-encoding-wizardry/descale
VapourSynth plugin to undo upscaling
https://github.com/irrational-encoding-wizardry/descale
Last synced: 7 months ago
JSON representation
VapourSynth plugin to undo upscaling
- Host: GitHub
- URL: https://github.com/irrational-encoding-wizardry/descale
- Owner: Irrational-Encoding-Wizardry
- License: mit
- Created: 2017-05-02T21:00:46.000Z (almost 9 years ago)
- Default Branch: master
- Last Pushed: 2023-05-09T12:34:51.000Z (almost 3 years ago)
- Last Synced: 2025-04-21T13:54:09.776Z (11 months ago)
- Language: C
- Homepage:
- Size: 97.7 KB
- Stars: 73
- Watchers: 6
- Forks: 16
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Descale
Video/Image filter to undo upscaling.
Includes a VapourSynth and AviSynth+ plugin
## Usage
The VapourSynth plugin itself supports every constant input format. If the format is subsampled, left-aligned chroma planes are always assumed.
The included python wrapper, contrary to using the plugin directly, doesn't descale the chroma planes but scales them normally with `Spline36`.
```
descale.Debilinear(clip src, int width, int height, float src_left=0.0, float src_top=0.0, float src_width=width, float src_height=height, int border_handling=0, bool force=false, bool force_h=false, bool force_v=false, int opt=0)
descale.Debicubic(clip src, int width, int height, float b=0.0, float c=0.5, float src_left=0.0, float src_top=0.0, float src_width=width, float src_height=height, int border_handling=0, bool force=false, bool force_h=false, bool force_v=false, int opt=0)
descale.Delanczos(clip src, int width, int height, int taps=3, float src_left=0.0, float src_top=0.0, float src_width=width, float src_height=height, int border_handling=0, bool force=false, bool force_h=false, bool force_v=false, int opt=0)
descale.Despline16(clip src, int width, int height, float src_left=0.0, float src_top=0.0, float src_width=width, float src_height=height, int border_handling=0, bool force=false, bool force_h=false, bool force_v=false, int opt=0)
descale.Despline36(clip src, int width, int height, float src_left=0.0, float src_top=0.0, float src_width=width, float src_height=height, int border_handling=0, bool force=false, bool force_h=false, bool force_v=false, int opt=0)
descale.Despline64(clip src, int width, int height, float src_left=0.0, float src_top=0.0, float src_width=width, float src_height=height, int border_handling=0, bool force=false, bool force_h=false, bool force_v=false, int opt=0)
descale.Descale(clip src, int width, int height, str kernel, func custom_kernel, int taps=3, float b=0.0, float c=0.0, float src_left=0.0, float src_top=0.0, float src_width=width, float src_height=height, int border_handling=0, bool force=false, bool force_h=false, bool force_v=false, int opt=0)
```
The AviSynth+ plugin is used similarly, but without the `descale` namespace.
Custom kernels are only supported in the VapourSynth plugin.
### Custom kernels
```python
# Debilinear
core.descale.Descale(src, w, h, custom_kernel=lambda x: 1.0 - x, taps=1)
# Delanczos
import math
def sinc(x):
return 1.0 if x == 0 else math.sin(x * math.pi) / (x * math.pi)
taps = 3
core.descale.Descale(src, w, h, custom_kernel=lambda x: sinc(x) * sinc(x / taps), taps=taps)
# You can also use the python wrapper instead of calling the plugin functions directly
import descale
descale.Decustom(src, w, h, lambda x: 1.0 - x, taps=1)
```
## How does this work?
Resampling can be described as `A x = b`.
A is an n x m matrix with `m` being the input dimension and `n` the output dimension. `x` is the original vector with `m` elements, `b` is the vector after resampling with `n` elements. We want to solve this equation for `x`.
To do this, we extend the equation with the transpose of A: `A' A x = A' b`.
`A' A` is now a banded symmetrical m x m matrix and `A' b` is a vector with `m` elements.
This enables us to use LDLT decomposition on `A' A` to get `LD L' = A' A`. `LD` and `L` are both triangular matrices.
Then we solve `LD y = A' b` with forward substitution, and finally `L' x = y` with back substitution.
We now have the original vector `x`.
## Compilation
By default only the VapourSynth plugin is compiled.
To build the AviSynth+ plugin, add `-Dlibtype=avisynth` or `-Dlibtype=both` to the meson command below.
### Linux
```
$ meson build
$ ninja -C build
```
### Cross-compilation for Windows
```
$ meson build --cross-file cross-mingw-x86_64.txt
$ ninja -C build
```