summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2016-10-26 16:32:57 +0200
committerwm4 <wm4@nowhere>2016-11-01 16:25:40 +0100
commit654721c27bc0b2ca5fe27a5932b42332c1674547 (patch)
treef44c259f491a145ff594978ac7b9fe4bc951df84
parent58383229756a8871fb312c0897914e45e5824fc1 (diff)
downloadmpv-654721c27bc0b2ca5fe27a5932b42332c1674547.tar.bz2
mpv-654721c27bc0b2ca5fe27a5932b42332c1674547.tar.xz
filter_kernels: add ability to taper kernels/windows
This allows us to define the tukey window (and other tapered windows). Also add a missing option definition for `wblur` while we're at it, to make testing out window-related stuff easier.
-rw-r--r--DOCS/man/options.rst19
-rw-r--r--video/out/filter_kernels.c49
-rw-r--r--video/out/filter_kernels.h1
-rw-r--r--video/out/opengl/video.c11
-rw-r--r--video/out/opengl/video.h1
5 files changed, 55 insertions, 26 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 45c0bca2f1..3fd3b62d85 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -3874,12 +3874,19 @@ The following video options are currently all specific to ``--vo=opengl`` and
never interpolate, thus behaving as if the regular nearest neighbour
algorithm was used. Defaults to 0.0.
-``--scale-blur=<value>``
- Kernel scaling factor (also known as a blur factor). Decreasing this makes
- the result sharper, increasing it makes it blurrier (default 0). If set to
- 0, the kernel's preferred blur factor is used. Note that setting this too
- low (eg. 0.5) leads to bad results. It's generally recommended to stick to
- values between 0.8 and 1.2.
+``--scale-blur=<value>``, ``--scale-wblur=<value>``
+ Kernel/window scaling factor (also known as a blur factor). Decreasing this
+ makes the result sharper, increasing it makes it blurrier (default 0). If
+ set to 0, the kernel's preferred blur factor is used. Note that setting
+ this too low (eg. 0.5) leads to bad results. It's generally recommended to
+ stick to values between 0.8 and 1.2.
+
+``--scale-taper=<value>``, ``--scale-wtaper=<value>``
+ Kernel/window taper factor. Increasing this flattens the filter function.
+ Value range is 0 to 1. A value of 0 (the default) means no flattening, a
+ value of 1 makes the filter completely flat (equivalent to a box function).
+ Values in between mean that some portion will be flat and the actual filter
+ function will be squeezed into the space in between.
``--scale-radius=<value>``
Set radius for tunable filters, must be a float number between 0.5 and
diff --git a/video/out/filter_kernels.c b/video/out/filter_kernels.c
index fe5265c70c..c5a12295f7 100644
--- a/video/out/filter_kernels.c
+++ b/video/out/filter_kernels.c
@@ -92,34 +92,45 @@ bool mp_init_filter(struct filter_kernel *filter, const int *sizes,
}
}
-// Sample from the blurred, windowed kernel. Note: The window is always
-// stretched to the true radius, regardless of the filter blur/scale.
-static double sample_filter(struct filter_kernel *filter,
- struct filter_window *window, double x)
+// Sample from a blurred and tapered window
+static double sample_window(struct filter_window *kernel, double x)
{
- double bk = filter->f.blur > 0.0 ? filter->f.blur : 1.0;
- double bw = window->blur > 0.0 ? window->blur : 1.0;
- double c = fabs(x) / (filter->inv_scale * bk);
- double w = window->weight ? window->weight(window, x/bw * window->radius
- / filter->f.radius)
- : 1.0;
- double v = c < filter->f.radius ? w * filter->f.weight(&filter->f, c) : 0.0;
- return filter->clamp ? fmax(0.0, fmin(1.0, v)) : v;
+ if (!kernel->weight)
+ return 1.0;
+
+ // All windows are symmetric, this makes life easier
+ x = fabs(x);
+ if (x >= kernel->radius)
+ return 0.0;
+
+ // Stretch and taper the window size as needed
+ x = kernel->blur > 0.0 ? x / kernel->blur : x;
+ x = x <= kernel->taper ? 0.0 : (x - kernel->taper) / (1 - kernel->taper);
+
+ return kernel->weight(kernel, x);
+}
+
+// Evaluate a filter's kernel and window at a given absolute position
+static double sample_filter(struct filter_kernel *filter, double x)
+{
+ // The window is always stretched to the entire kernel
+ double w = sample_window(&filter->w, x / filter->f.radius * filter->w.radius);
+ double k = sample_window(&filter->f, x / filter->inv_scale);
+ return filter->clamp ? fmax(0.0, fmin(1.0, w * k)) : w * k;
}
// Calculate the 1D filtering kernel for N sample points.
// N = number of samples, which is filter->size
// The weights will be stored in out_w[0] to out_w[N - 1]
// f = x0 - abs(x0), subpixel position in the range [0,1) or [0,1].
-static void mp_compute_weights(struct filter_kernel *filter,
- struct filter_window *window,
- double f, float *out_w)
+static void mp_compute_weights(struct filter_kernel *filter, double f,
+ float *out_w)
{
assert(filter->size > 0);
double sum = 0;
for (int n = 0; n < filter->size; n++) {
double x = f - (n - filter->size / 2 + 1);
- double w = sample_filter(filter, window, x);
+ double w = sample_filter(filter, x);
out_w[n] = w;
sum += w;
}
@@ -138,17 +149,16 @@ static void mp_compute_weights(struct filter_kernel *filter,
// [0.5 / count, 1.0 - 0.5 / count].
void mp_compute_lut(struct filter_kernel *filter, int count, float *out_array)
{
- struct filter_window *window = &filter->w;
if (filter->polar) {
// Compute a 1D array indexed by radius
for (int x = 0; x < count; x++) {
double r = x * filter->f.radius / (count - 1);
- out_array[x] = sample_filter(filter, window, r);
+ out_array[x] = sample_filter(filter, r);
}
} else {
// Compute a 2D array indexed by subpixel position
for (int n = 0; n < count; n++) {
- mp_compute_weights(filter, window, n / (double)(count - 1),
+ mp_compute_weights(filter, n / (double)(count - 1),
out_array + filter->size * n);
}
}
@@ -321,6 +331,7 @@ const struct filter_window mp_filter_windows[] = {
{"triangle", 1, triangle},
{"bartlett", 1, triangle},
{"hanning", 1, hanning},
+ {"tukey", 1, hanning, .taper = 0.5},
{"hamming", 1, hamming},
{"quadric", 1.5, quadric},
{"welch", 1, welch},
diff --git a/video/out/filter_kernels.h b/video/out/filter_kernels.h
index 2354ef4d0c..fc90a1cdde 100644
--- a/video/out/filter_kernels.h
+++ b/video/out/filter_kernels.h
@@ -22,6 +22,7 @@ struct filter_window {
double params[2]; // User-defined custom filter parameters. Not used by
// all filters
double blur; // Blur coefficient (sharpens or widens the filter)
+ double taper; // Taper coefficient (flattens the filter's center)
};
struct filter_kernel {
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index 17468ab9a5..8afae2f062 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -340,7 +340,10 @@ static int validate_window_opt(struct mp_log *log, const m_option_t *opt,
OPT_FLOAT(n"-param1", scaler[i].kernel.params[0], 0), \
OPT_FLOAT(n"-param2", scaler[i].kernel.params[1], 0), \
OPT_FLOAT(n"-blur", scaler[i].kernel.blur, 0), \
+ OPT_FLOATRANGE(n"-taper", scaler[i].kernel.taper, 0, 0.0, 1.0), \
OPT_FLOAT(n"-wparam", scaler[i].window.params[0], 0), \
+ OPT_FLOAT(n"-wblur", scaler[i].window.blur, 0), \
+ OPT_FLOATRANGE(n"-wtaper", scaler[i].window.taper, 0, 0.0, 1.0), \
OPT_FLAG(n"-clamp", scaler[i].clamp, 0), \
OPT_FLOATRANGE(n"-radius", scaler[i].radius, 0, 0.5, 16.0), \
OPT_FLOATRANGE(n"-antiring", scaler[i].antiring, 0, 0.0, 1.0), \
@@ -1357,7 +1360,8 @@ static bool scaler_fun_eq(struct scaler_fun a, struct scaler_fun b)
return ((!a.name && !b.name) || strcmp(a.name, b.name) == 0) &&
double_seq(a.params[0], b.params[0]) &&
double_seq(a.params[1], b.params[1]) &&
- a.blur == b.blur;
+ a.blur == b.blur &&
+ a.taper == b.taper;
}
static bool scaler_conf_eq(struct scaler_config a, struct scaler_config b)
@@ -1418,6 +1422,11 @@ static void reinit_scaler(struct gl_video *p, struct scaler *scaler,
if (conf->window.blur > 0.0)
scaler->kernel->w.blur = conf->window.blur;
+ if (conf->kernel.taper > 0.0)
+ scaler->kernel->f.taper = conf->kernel.taper;
+ if (conf->window.taper > 0.0)
+ scaler->kernel->w.taper = conf->window.taper;
+
if (scaler->kernel->f.resizable && conf->radius > 0.0)
scaler->kernel->f.radius = conf->radius;
diff --git a/video/out/opengl/video.h b/video/out/opengl/video.h
index 5011af83d1..54b7022f27 100644
--- a/video/out/opengl/video.h
+++ b/video/out/opengl/video.h
@@ -35,6 +35,7 @@ struct scaler_fun {
char *name;
float params[2];
float blur;
+ float taper;
};
struct scaler_config {