summaryrefslogtreecommitdiffstats
path: root/src/include/libplacebo/filters.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/libplacebo/filters.h')
-rw-r--r--src/include/libplacebo/filters.h415
1 files changed, 415 insertions, 0 deletions
diff --git a/src/include/libplacebo/filters.h b/src/include/libplacebo/filters.h
new file mode 100644
index 0000000..a95649d
--- /dev/null
+++ b/src/include/libplacebo/filters.h
@@ -0,0 +1,415 @@
+/*
+ * This file is part of libplacebo.
+ *
+ * libplacebo is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * libplacebo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIBPLACEBO_FILTER_KERNELS_H_
+#define LIBPLACEBO_FILTER_KERNELS_H_
+
+#include <stdbool.h>
+#include <libplacebo/log.h>
+
+PL_API_BEGIN
+
+#define PL_FILTER_MAX_PARAMS 2
+
+// Invocation parameters for a given kernel
+struct pl_filter_ctx {
+ float radius;
+ float params[PL_FILTER_MAX_PARAMS];
+};
+
+// Represents a single filter function, i.e. kernel or windowing function.
+struct pl_filter_function {
+ // The cosmetic name associated with this filter function.
+ const char *name;
+
+ // The radius of the filter function. For resizable filters, this gives
+ // the radius needed to represent a single filter lobe (tap).
+ float radius;
+
+ // If true, the filter function is resizable (see pl_filter_config.radius)
+ bool resizable;
+
+ // If true, the filter function is tunable (see pl_filter_config.params)
+ bool tunable[PL_FILTER_MAX_PARAMS];
+
+ // If the relevant parameter is tunable, this contains the default values.
+ float params[PL_FILTER_MAX_PARAMS];
+
+ // The underlying filter function itself: Computes the weight as a function
+ // of the offset. All filter functions must be normalized such that x=0 is
+ // the center point, and in particular weight(0) = 1.0. The functions may
+ // be undefined for values of x outside [0, radius].
+ double (*weight)(const struct pl_filter_ctx *f, double x);
+
+ // If true, this filter represents an opaque placeholder for a more
+ // sophisticated filter function which does not fit into the pl_filter
+ // framework. `weight()` will always return 0.0.
+ bool opaque;
+};
+
+// Deprecated function, merely checks a->weight == b->weight
+PL_DEPRECATED PL_API bool
+pl_filter_function_eq(const struct pl_filter_function *a,
+ const struct pl_filter_function *b);
+
+// Box filter: Entirely 1.0 within the radius, entirely 0.0 outside of it.
+// This is also sometimes called a Dirichlet window
+PL_API extern const struct pl_filter_function pl_filter_function_box;
+
+// Triangle filter: Linear transitions from 1.0 at x=0 to 0.0 at x=radius.
+// This is also sometimes called a Bartlett window.
+PL_API extern const struct pl_filter_function pl_filter_function_triangle;
+
+// Cosine filter: Ordinary cosine function, single lobe.
+PL_API extern const struct pl_filter_function pl_filter_function_cosine;
+
+// Hann function: Cosine filter named after Julius von Hann. Also commonly
+// mislabeled as a "Hanning" function, due to its similarly to the Hamming
+// function.
+PL_API extern const struct pl_filter_function pl_filter_function_hann;
+
+// Hamming function: Cosine filter named after Richard Hamming.
+PL_API extern const struct pl_filter_function pl_filter_function_hamming;
+
+// Welch filter: Polynomial function consisting of a single parabolic section.
+PL_API extern const struct pl_filter_function pl_filter_function_welch;
+
+// Kaiser filter: Approximation of the DPSS window using Bessel functions.
+// Also sometimes called a Kaiser-Bessel window.
+// Parameter [0]: Shape (alpha). Determines the trade-off between the main lobe
+// and the side lobes.
+PL_API extern const struct pl_filter_function pl_filter_function_kaiser;
+
+// Blackman filter: Cosine filter named after Ralph Beebe Blackman.
+// Parameter [0]: Scale (alpha). Influences the shape. The defaults result in
+// zeros at the third and fourth sidelobes.
+PL_API extern const struct pl_filter_function pl_filter_function_blackman;
+
+// Bohman filter: 2nd order Cosine filter.
+PL_API extern const struct pl_filter_function pl_filter_function_bohman;
+
+// Gaussian function: Similar to the Gaussian distribution, this defines a
+// bell curve function.
+// Parameter [0]: Scale (t), increasing makes the result blurrier.
+PL_API extern const struct pl_filter_function pl_filter_function_gaussian;
+
+// Quadratic function: 2nd order approximation of the gaussian function. Also
+// sometimes called a "quadric" window.
+PL_API extern const struct pl_filter_function pl_filter_function_quadratic;
+
+// Sinc function: Widely used for both kernels and windows, sinc(x) = sin(x)/x.
+PL_API extern const struct pl_filter_function pl_filter_function_sinc;
+
+// Jinc function: Similar to sinc, but extended to the 2D domain. Widely
+// used as the kernel of polar (EWA) filters. Also sometimes called a Sombrero
+// function.
+PL_API extern const struct pl_filter_function pl_filter_function_jinc;
+
+// Sphinx function: Similar to sinc and jinx, but extended to the 3D domain.
+// The name is derived from "spherical" sinc. Can be used to filter 3D signals
+// in theory.
+PL_API extern const struct pl_filter_function pl_filter_function_sphinx;
+
+// B/C-tunable Spline function: This is a family of commonly used spline
+// functions with two tunable parameters. Does not need to be windowed.
+// Parameter [0]: "B"
+// Parameter [1]: "C"
+// Some popular variants of this function are:
+// B = 1.0, C = 0.0: "base" Cubic (blurry)
+// B = 0.0, C = 0.0: Hermite filter (blocky)
+// B = 0.0, C = 0.5: Catmull-Rom filter (sharp)
+// B = 1/3, C = 1/3: Mitchell-Netravali filter (soft, doesn't ring)
+// B ≈ 0.37, C ≈ 0.31: Robidoux filter (used by ImageMagick)
+// B ≈ 0.26, C ≈ 0.37: RobidouxSharp filter (sharper variant of Robidoux)
+PL_API extern const struct pl_filter_function pl_filter_function_cubic;
+PL_API extern const struct pl_filter_function pl_filter_function_hermite;
+#define pl_filter_function_bicubic pl_filter_function_cubic
+#define pl_filter_function_bcspline pl_filter_function_cubic
+
+// Cubic splines with 2/3/4 taps. Referred to as "spline16", "spline36", and
+// "spline64" mainly for historical reasons, based on the number of pixels in
+// their window when using them as 2D orthogonal filters. Do not need to be
+// windowed.
+PL_API extern const struct pl_filter_function pl_filter_function_spline16;
+PL_API extern const struct pl_filter_function pl_filter_function_spline36;
+PL_API extern const struct pl_filter_function pl_filter_function_spline64;
+
+// Special filter function for the built-in oversampling algorithm. This is an
+// opaque filter with no meaningful representation. though it has one tunable
+// parameter controlling the threshold at which to switch back to ordinary
+// nearest neighbour sampling. (See `pl_shader_sample_oversample`)
+PL_API extern const struct pl_filter_function pl_filter_function_oversample;
+
+// A list of built-in filter functions, terminated by NULL
+//
+// Note: May contain extra aliases for the above functions.
+PL_API extern const struct pl_filter_function * const pl_filter_functions[];
+PL_API extern const int pl_num_filter_functions; // excluding trailing NULL
+
+// Find the filter function with the given name, or NULL on failure.
+PL_API const struct pl_filter_function *pl_find_filter_function(const char *name);
+
+// Backwards compatibility with the older configuration API. Redundant with
+// `pl_filter_function.name`. May be formally deprecated in the future.
+
+struct pl_filter_function_preset {
+ const char *name;
+ const struct pl_filter_function *function;
+};
+
+// A list of built-in filter function presets, terminated by {0}
+PL_API extern const struct pl_filter_function_preset pl_filter_function_presets[];
+PL_API extern const int pl_num_filter_function_presets; // excluding trailing {0}
+
+// Find the filter function preset with the given name, or NULL on failure.
+PL_API const struct pl_filter_function_preset *pl_find_filter_function_preset(const char *name);
+
+// Different usage domains for a filter
+enum pl_filter_usage {
+ PL_FILTER_UPSCALING = (1 << 0),
+ PL_FILTER_DOWNSCALING = (1 << 1),
+ PL_FILTER_FRAME_MIXING = (1 << 2),
+
+ PL_FILTER_SCALING = PL_FILTER_UPSCALING | PL_FILTER_DOWNSCALING,
+ PL_FILTER_ALL = PL_FILTER_SCALING | PL_FILTER_FRAME_MIXING,
+};
+
+// Represents a tuned combination of filter functions, plus parameters
+struct pl_filter_config {
+ // The cosmetic name associated with this filter config. Optional for
+ // user-provided configs, but always set by built-in configurations.
+ const char *name;
+
+ // Longer / friendly name. Always set for built-in configurations,
+ // except for names which are merely aliases of other filters.
+ const char *description;
+
+ // Allowed and recommended usage domains (respectively)
+ //
+ // When it is desired to maintain a simpler user interface, it may be
+ // recommended to include only scalers whose recommended usage domains
+ // includes the relevant context in which it will be used.
+ enum pl_filter_usage allowed;
+ enum pl_filter_usage recommended;
+
+ // The kernel function and (optionally) windowing function.
+ const struct pl_filter_function *kernel;
+ const struct pl_filter_function *window;
+
+ // The radius. Ignored if !kernel->resizable. Optional, defaults to
+ // kernel->radius if unset.
+ float radius;
+
+ // Parameters for the respective filter function. Ignored if not tunable.
+ float params[PL_FILTER_MAX_PARAMS];
+ float wparams[PL_FILTER_MAX_PARAMS];
+
+ // Represents a clamping coefficient for negative weights. A value of 0.0
+ // (the default) represents no clamping. A value of 1.0 represents full
+ // clamping, i.e. all negative weights will be clamped to 0. Values in
+ // between will be linearly scaled.
+ float clamp;
+
+ // Additional blur coefficient. This effectively stretches the kernel,
+ // without changing the effective radius of the filter radius. Setting this
+ // to a value of 0.0 is equivalent to disabling it. Values significantly
+ // below 1.0 may seriously degrade the visual output, and should be used
+ // with care.
+ float blur;
+
+ // Additional taper coefficient. This essentially flattens the function's
+ // center. The values within [-taper, taper] will return 1.0, with the
+ // actual function being squished into the remainder of [taper, radius].
+ // Defaults to 0.0.
+ float taper;
+
+ // If true, this filter is intended to be used as a polar/2D filter (EWA)
+ // instead of a separable/1D filter. Does not affect the actual sampling,
+ // but provides information about how the results are to be interpreted.
+ bool polar;
+
+ // Antiringing strength. A value of 0.0 disables antiringing, and a value
+ // of 1.0 enables full-strength antiringing. Defaults to 0.0 if
+ // unspecified.
+ //
+ // Note: This is only included in `pl_filter_config` for convenience. Does
+ // not affect the actual filter sampling, but provides information to the
+ // downstream consumer of the `pl_filter`.
+ float antiring;
+};
+
+PL_API bool pl_filter_config_eq(const struct pl_filter_config *a,
+ const struct pl_filter_config *b);
+
+// Samples a given filter configuration at a given x coordinate, while
+// respecting all parameters of the configuration.
+PL_API double pl_filter_sample(const struct pl_filter_config *c, double x);
+
+// A list of built-in filter configurations. Since they are just combinations
+// of the above filter functions, they are not described in much further
+// detail.
+PL_API extern const struct pl_filter_config pl_filter_spline16; // 2 taps
+PL_API extern const struct pl_filter_config pl_filter_spline36; // 3 taps
+PL_API extern const struct pl_filter_config pl_filter_spline64; // 4 taps
+PL_API extern const struct pl_filter_config pl_filter_nearest;
+PL_API extern const struct pl_filter_config pl_filter_box;
+PL_API extern const struct pl_filter_config pl_filter_bilinear;
+PL_API extern const struct pl_filter_config pl_filter_gaussian;
+// Sinc family (all configured to 3 taps):
+PL_API extern const struct pl_filter_config pl_filter_sinc; // unwindowed
+PL_API extern const struct pl_filter_config pl_filter_lanczos; // sinc-sinc
+PL_API extern const struct pl_filter_config pl_filter_ginseng; // sinc-jinc
+PL_API extern const struct pl_filter_config pl_filter_ewa_jinc; // unwindowed
+PL_API extern const struct pl_filter_config pl_filter_ewa_lanczos; // jinc-jinc
+PL_API extern const struct pl_filter_config pl_filter_ewa_lanczossharp;
+PL_API extern const struct pl_filter_config pl_filter_ewa_lanczos4sharpest;
+PL_API extern const struct pl_filter_config pl_filter_ewa_ginseng; // jinc-sinc
+PL_API extern const struct pl_filter_config pl_filter_ewa_hann; // jinc-hann
+// Spline family
+PL_API extern const struct pl_filter_config pl_filter_bicubic;
+PL_API extern const struct pl_filter_config pl_filter_hermite;
+PL_API extern const struct pl_filter_config pl_filter_catmull_rom;
+PL_API extern const struct pl_filter_config pl_filter_mitchell;
+PL_API extern const struct pl_filter_config pl_filter_mitchell_clamp; // clamp = 1.0
+PL_API extern const struct pl_filter_config pl_filter_robidoux;
+PL_API extern const struct pl_filter_config pl_filter_robidouxsharp;
+PL_API extern const struct pl_filter_config pl_filter_ewa_robidoux;
+PL_API extern const struct pl_filter_config pl_filter_ewa_robidouxsharp;
+// Special/opaque filters
+PL_API extern const struct pl_filter_config pl_filter_oversample;
+
+// Backwards compatibility
+#define pl_filter_triangle pl_filter_bilinear
+#define pl_oversample_frame_mixer pl_filter_oversample
+
+// A list of built-in filter configs, terminated by NULL
+PL_API extern const struct pl_filter_config * const pl_filter_configs[];
+PL_API extern const int pl_num_filter_configs; // excluding trailing NULL
+
+// Find the filter config with the given name, or NULL on failure.
+// `usage` restricts the valid usage (based on `pl_filter_config.allowed`).
+PL_API const struct pl_filter_config *
+pl_find_filter_config(const char *name, enum pl_filter_usage usage);
+
+// Backward compatibility with the previous filter configuration API. Redundant
+// with pl_filter_config.name/description. May be deprecated in the future.
+struct pl_filter_preset {
+ const char *name;
+ const struct pl_filter_config *filter;
+
+ // Longer / friendly name, or NULL for aliases
+ const char *description;
+};
+
+// A list of built-in filter presets, terminated by {0}
+PL_API extern const struct pl_filter_preset pl_filter_presets[];
+PL_API extern const int pl_num_filter_presets; // excluding trailing {0}
+
+// Find the filter preset with the given name, or NULL on failure.
+PL_API const struct pl_filter_preset *pl_find_filter_preset(const char *name);
+
+// Parameters for filter generation.
+struct pl_filter_params {
+ // The particular filter configuration to be sampled. config.kernel must
+ // be set to a valid pl_filter_function.
+ struct pl_filter_config config;
+
+ // The precision of the resulting LUT. A value of 64 should be fine for
+ // most practical purposes, but higher or lower values may be justified
+ // depending on the use case. This value must be set to something > 0.
+ int lut_entries;
+
+ // --- Polar filers only (config.polar)
+
+ // As a micro-optimization, all samples below this cutoff value will be
+ // ignored when updating the cutoff radius. Setting it to a value of 0.0
+ // disables this optimization.
+ float cutoff;
+
+ // --- Separable filters only (!config.polar)
+
+ // Indicates the maximum row size that is supported by the calling code, or
+ // 0 for no limit.
+ int max_row_size;
+
+ // Indicates the row stride alignment. For some use cases (e.g. uploading
+ // the weights as a texture), there are certain alignment requirements for
+ // each row. The chosen row_size will always be a multiple of this value.
+ // Specifying 0 indicates no alignment requirements.
+ int row_stride_align;
+
+ // --- Deprecated options
+ float filter_scale PL_DEPRECATED; // no effect, use `config.blur` instead
+};
+
+#define pl_filter_params(...) (&(struct pl_filter_params) { __VA_ARGS__ })
+
+// Represents an initialized instance of a particular filter, with a
+// precomputed LUT. The interpretation of the LUT depends on the type of the
+// filter (polar or separable).
+typedef const struct pl_filter_t {
+ // Deep copy of the parameters, for convenience.
+ struct pl_filter_params params;
+
+ // Contains the true radius of the computed filter. This may be
+ // smaller than the configured radius depending on the exact filter
+ // parameters used. Mainly relevant for polar filters, since
+ // it affects the value range of *weights.
+ float radius;
+
+ // Radius of the first zero crossing (main lobe size).
+ float radius_zero;
+
+ // The computed look-up table (LUT). For polar filters, this is interpreted
+ // as a 1D array with dimensions [lut_entries] containing the raw filter
+ // samples on the scale [0, radius]. For separable (non-polar) filters,
+ // this is interpreted as a 2D array with dimensions
+ // [lut_entries][row_stride]. The inner rows contain the `row_size` samples
+ // to convolve with the corresponding input pixels. The outer coordinate is
+ // used to very the fractional offset (phase). So for example, if the
+ // sample position to reconstruct is directly aligned with the source
+ // texels, you would use the values from weights[0]. If the sample position
+ // to reconstruct is exactly half-way between two source texels (180° out
+ // of phase), you would use the values from weights[lut_entries/2].
+ const float *weights;
+
+ // --- separable filters only (!params.config.polar)
+
+ // The number of source texels to convolve over for each row. This value
+ // will never exceed the given `max_row_size`. If the filter ends up
+ // cut off because of this, the bool `insufficient` will be set to true.
+ int row_size;
+ bool insufficient;
+
+ // The separation (in *weights) between each row of the filter. Always
+ // a multiple of params.row_stride_align.
+ int row_stride;
+
+ // --- deprecated / removed fields
+ float radius_cutoff PL_DEPRECATED; // identical to `radius`
+} *pl_filter;
+
+// Generate (compute) a filter instance based on a given filter configuration.
+// The resulting pl_filter must be freed with `pl_filter_free` when no longer
+// needed. Returns NULL if filter generation fails due to invalid parameters
+// (i.e. missing a required parameter).
+PL_API pl_filter pl_filter_generate(pl_log log, const struct pl_filter_params *params);
+PL_API void pl_filter_free(pl_filter *filter);
+
+PL_API_END
+
+#endif // LIBPLACEBO_FILTER_KERNELS_H_