/*
* 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 .
*/
#ifndef LIBPLACEBO_FILTER_KERNELS_H_
#define LIBPLACEBO_FILTER_KERNELS_H_
#include
#include
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_IN(v6.303) 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;
// Deprecated aliases of pl_filter_function_cubic (see the table above)
PL_DEPRECATED_IN(v6.341) PL_API extern const struct pl_filter_function pl_filter_function_bicubic;
PL_DEPRECATED_IN(v6.341) PL_API extern const struct pl_filter_function pl_filter_function_bcspline;
PL_DEPRECATED_IN(v6.341) PL_API extern const struct pl_filter_function pl_filter_function_catmull_rom;
PL_DEPRECATED_IN(v6.341) PL_API extern const struct pl_filter_function pl_filter_function_mitchell;
PL_DEPRECATED_IN(v6.341) PL_API extern const struct pl_filter_function pl_filter_function_robidoux;
PL_DEPRECATED_IN(v6.341) PL_API extern const struct pl_filter_function pl_filter_function_robidouxsharp;
// 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
PL_DEPRECATED_IN(v6.316) float filter_scale; // 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
PL_DEPRECATED_IN(v6.336) float radius_cutoff; // 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_