1 /* 2 * This file is part of libplacebo. 3 * 4 * libplacebo is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * libplacebo is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef LIBPLACEBO_FILTER_KERNELS_H_ 19 #define LIBPLACEBO_FILTER_KERNELS_H_ 20 21 #include <stdbool.h> 22 #include <libplacebo/log.h> 23 24 PL_API_BEGIN 25 26 #define PL_FILTER_MAX_PARAMS 2 27 28 // Represents a single filter function, i.e. kernel or windowing function. 29 // To invoke a filter with a different configuration than the default, you can 30 // make a copy of this struct and modify the non-const fields before passing it 31 // to pl_filter_initialize. 32 struct pl_filter_function { 33 // These bools indicate whether or not `radius` and `params` may be 34 // modified by the user. 35 bool resizable; 36 bool tunable[PL_FILTER_MAX_PARAMS]; 37 38 // The underlying filter function itself: Computes the weight as a function 39 // of the offset. All filter functions must be normalized such that x=0 is 40 // the center point, and in particular weight(0) = 1.0. The functions may 41 // be undefined for values of x outside [0, radius]. 42 double (*weight)(const struct pl_filter_function *k, double x); 43 44 // This field may be used to adjust the function's radius. Defaults to the 45 // the radius needed to represent a single filter lobe (tap). If the 46 // function is not resizable, this field must not be modified - otherwise 47 // the result of filter evaluation is undefined. 48 float radius; 49 50 // These fields may be used to adjust the function. Defaults to the 51 // function's preferred defaults. if the relevant setting is not tunable, 52 // they are ignored entirely. 53 float params[PL_FILTER_MAX_PARAMS]; 54 }; 55 56 bool pl_filter_function_eq(const struct pl_filter_function *a, 57 const struct pl_filter_function *b); 58 59 // Box filter: Entirely 1.0 within the radius, entirely 0.0 outside of it. 60 // This is also sometimes called a Dirichlet window 61 extern const struct pl_filter_function pl_filter_function_box; 62 63 // Triangle filter: Linear transitions from 1.0 at x=0 to 0.0 at x=radius. 64 // This is also sometimes called a Bartlett window. 65 extern const struct pl_filter_function pl_filter_function_triangle; 66 67 // Cosine filter: Ordinary cosine function, single lobe. 68 extern const struct pl_filter_function pl_filter_function_cosine; 69 70 // Hann function: Cosine filter named after Julius von Hann. Also commonly 71 // mislabeled as a "Hanning" function, due to its similarly to the Hamming 72 // function. 73 extern const struct pl_filter_function pl_filter_function_hann; 74 75 // Hamming function: Cosine filter named after Richard Hamming. 76 extern const struct pl_filter_function pl_filter_function_hamming; 77 78 // Welch filter: Polynomial function consisting of a single parabolic section. 79 extern const struct pl_filter_function pl_filter_function_welch; 80 81 // Kaiser filter: Approximation of the DPSS window using Bessel functions. 82 // Also sometimes called a Kaiser-Bessel window. 83 // Parameter [0]: Shape (alpha). Determines the trade-off between the main lobe 84 // and the side lobes. 85 extern const struct pl_filter_function pl_filter_function_kaiser; 86 87 // Blackman filter: Cosine filter named after Ralph Beebe Blackman. 88 // Parameter [0]: Scale (alpha). Influences the shape. The defaults result in 89 // zeros at the third and fourth sidelobes. 90 extern const struct pl_filter_function pl_filter_function_blackman; 91 92 // Bohman filter: 2nd order Cosine filter. 93 extern const struct pl_filter_function pl_filter_function_bohman; 94 95 // Gaussian function: Similar to the Gaussian distribution, this defines a 96 // bell curve function. 97 // Parameter [0]: Scale (t), increasing makes the result blurrier. 98 extern const struct pl_filter_function pl_filter_function_gaussian; 99 100 // Quadratic function: 2nd order approximation of the gaussian function. Also 101 // sometimes called a "quadric" window. 102 extern const struct pl_filter_function pl_filter_function_quadratic; 103 104 // Sinc function: Widely used for both kernels and windows, sinc(x) = sin(x)/x. 105 extern const struct pl_filter_function pl_filter_function_sinc; 106 107 // Jinc function: Similar to sinc, but extended to the 2D domain. Widely 108 // used as the kernel of polar (EWA) filters. Also sometimes called a Sombrero 109 // function. 110 extern const struct pl_filter_function pl_filter_function_jinc; 111 112 // Sphinx function: Similar to sinc and jinx, but extended to the 3D domain. 113 // The name is derived from "spherical" sinc. Can be used to filter 3D signals 114 // in theory. 115 extern const struct pl_filter_function pl_filter_function_sphinx; 116 117 // B/C-tunable Spline function: This is a family of commonly used spline 118 // functions with two tunable parameters. Does not need to be windowed. 119 // Parameter [0]: "B" 120 // Parameter [1]: "C" 121 // Due to its populariy, this function is available in several variants. 122 // B = 0.0, C = 0.0: "base" bcspline, AKA Hermite spline (blocky) 123 // B = 0.0, C = 0.5: Catmull-Rom filter (sharp) 124 // B = 1/3, C = 1/3: Mitchell-Netravali filter (soft, doesn't ring) 125 // B ≈ 0.37, C ≈ 0.31: Robidoux filter (used by ImageMagick) 126 // B ≈ 0.26, C ≈ 0.37: RobidouxSharp filter. (sharper variant of Robidoux) 127 extern const struct pl_filter_function pl_filter_function_bcspline; 128 extern const struct pl_filter_function pl_filter_function_catmull_rom; 129 extern const struct pl_filter_function pl_filter_function_mitchell; 130 extern const struct pl_filter_function pl_filter_function_robidoux; 131 extern const struct pl_filter_function pl_filter_function_robidouxsharp; 132 133 // Bicubic function: Very smooth and free of ringing, but very blurry. Does not 134 // need to be windowed. 135 extern const struct pl_filter_function pl_filter_function_bicubic; 136 137 // Piecewise approximations of the Lanczos filter function (sinc-windowed 138 // sinc). Referred to as "spline16", "spline36" and "spline64" mainly for 139 // historical reasons, based on their fixed radii of 2, 3 and 4 (respectively). 140 // These do not need to be windowed. 141 extern const struct pl_filter_function pl_filter_function_spline16; 142 extern const struct pl_filter_function pl_filter_function_spline36; 143 extern const struct pl_filter_function pl_filter_function_spline64; 144 145 struct pl_filter_function_preset { 146 const char *name; 147 const struct pl_filter_function *function; 148 }; 149 150 // A list of built-in filter function presets, terminated by {0} 151 extern const struct pl_filter_function_preset pl_filter_function_presets[]; 152 extern const int pl_num_filter_function_presets; // excluding trailing {0} 153 154 // Find the filter function preset with the given name, or NULL on failure. 155 const struct pl_filter_function_preset *pl_find_filter_function_preset(const char *name); 156 157 // Backwards compatibility 158 #define pl_named_filter_function pl_filter_function_preset 159 #define pl_named_filter_functions pl_filter_function_presets 160 #define pl_find_named_filter_function pl_find_filter_function_preset 161 162 // Represents a particular configuration/combination of filter functions to 163 // form a filter. 164 struct pl_filter_config { 165 const struct pl_filter_function *kernel; // The kernel function 166 const struct pl_filter_function *window; // The windowing function. Optional 167 168 // Represents a clamping coefficient for negative weights. A value of 0.0 169 // (the default) represents no clamping. A value of 1.0 represents full 170 // clamping, i.e. all negative weights will be clamped to 0. Values in 171 // between will be linearly scaled. 172 float clamp; 173 174 // Additional blur coefficient. This effectively stretches the kernel, 175 // without changing the effective radius of the filter radius. Setting this 176 // to a value of 0.0 is equivalent to disabling it. Values significantly 177 // below 1.0 may seriously degrade the visual output, and should be used 178 // with care. 179 float blur; 180 181 // Additional taper coefficient. This essentially flattens the function's 182 // center. The values within [-taper, taper] will return 1.0, with the 183 // actual function being squished into the remainder of [taper, radius]. 184 // Defaults to 0.0. 185 float taper; 186 187 // If true, this filter is intended to be used as a polar/2D filter (EWA) 188 // instead of a separable/1D filter. Does not affect the actual sampling, 189 // but provides information about how the results are to be interpreted. 190 bool polar; 191 }; 192 193 bool pl_filter_config_eq(const struct pl_filter_config *a, 194 const struct pl_filter_config *b); 195 196 // Samples a given filter configuration at a given x coordinate, while 197 // respecting all parameters of the configuration. 198 double pl_filter_sample(const struct pl_filter_config *c, double x); 199 200 // A list of built-in filter configurations. Since they are just combinations 201 // of the above filter functions, they are not described in much further 202 // detail. 203 extern const struct pl_filter_config pl_filter_spline16; // 2 taps 204 extern const struct pl_filter_config pl_filter_spline36; // 3 taps 205 extern const struct pl_filter_config pl_filter_spline64; // 4 taps 206 extern const struct pl_filter_config pl_filter_nearest; // AKA box 207 extern const struct pl_filter_config pl_filter_bilinear; // AKA triangle 208 extern const struct pl_filter_config pl_filter_gaussian; 209 // Sinc family (all configured to 3 taps): 210 extern const struct pl_filter_config pl_filter_sinc; // unwindowed, 211 extern const struct pl_filter_config pl_filter_lanczos; // sinc-sinc 212 extern const struct pl_filter_config pl_filter_ginseng; // sinc-jinc 213 extern const struct pl_filter_config pl_filter_ewa_jinc; // unwindowed 214 extern const struct pl_filter_config pl_filter_ewa_lanczos; // jinc-jinc 215 extern const struct pl_filter_config pl_filter_ewa_ginseng; // jinc-sinc 216 extern const struct pl_filter_config pl_filter_ewa_hann; // jinc-hann 217 extern const struct pl_filter_config pl_filter_haasnsoft PL_DEPRECATED; 218 // Spline family 219 extern const struct pl_filter_config pl_filter_bicubic; 220 extern const struct pl_filter_config pl_filter_catmull_rom; 221 extern const struct pl_filter_config pl_filter_mitchell; 222 extern const struct pl_filter_config pl_filter_mitchell_clamp; // clamp = 1.0 223 extern const struct pl_filter_config pl_filter_robidoux; 224 extern const struct pl_filter_config pl_filter_robidouxsharp; 225 extern const struct pl_filter_config pl_filter_ewa_robidoux; 226 extern const struct pl_filter_config pl_filter_ewa_robidouxsharp; 227 228 // Backwards compatibility 229 #define pl_filter_box pl_filter_nearest 230 #define pl_filter_triangle pl_filter_bilinear 231 232 struct pl_filter_preset { 233 const char *name; 234 const struct pl_filter_config *filter; 235 236 // Longer / friendly name, or NULL for aliases 237 const char *description; 238 }; 239 240 // A list of built-in filter presets, terminated by {0} 241 extern const struct pl_filter_preset pl_filter_presets[]; 242 extern const int pl_num_filter_presets; // excluding trailing {0} 243 244 // Find the filter preset with the given name, or NULL on failure. 245 const struct pl_filter_preset *pl_find_filter_preset(const char *name); 246 247 // Backwards compatibility 248 #define pl_named_filter_config pl_filter_preset 249 #define pl_named_filters pl_filter_presets 250 #define pl_find_named_filter pl_find_filter_preset 251 252 // Parameters for filter generation. 253 struct pl_filter_params { 254 // The particular filter configuration to be sampled. config.kernel must 255 // be set to a valid pl_filter_function. 256 struct pl_filter_config config; 257 258 // The precision of the resulting LUT. A value of 64 should be fine for 259 // most practical purposes, but higher or lower values may be justified 260 // depending on the use case. This value must be set to something > 0. 261 int lut_entries; 262 263 // When set to values above 1.0, the filter will be computed at a size 264 // larger than the radius would otherwise require, in order to prevent 265 // aliasing when downscaling. In practice, this should be set to the 266 // inverse of the scaling ratio, i.e. src_size / dst_size. 267 float filter_scale; 268 269 // --- polar filers only (config.polar) 270 271 // As a micro-optimization, all samples below this cutoff value will be 272 // ignored when updating the cutoff radius. Setting it to a value of 0.0 273 // disables this optimization. 274 float cutoff; 275 276 // --- separable filters only (!config.polar) 277 278 // Indicates the maximum row size that is supported by the calling code, or 279 // 0 for no limit. 280 int max_row_size; 281 282 // Indicates the row stride alignment. For some use cases (e.g. uploading 283 // the weights as a texture), there are certain alignment requirements for 284 // each row. The chosen row_size will always be a multiple of this value. 285 // Specifying 0 indicates no alignment requirements. 286 int row_stride_align; 287 }; 288 289 // Represents an initialized instance of a particular filter, with a 290 // precomputed LUT. The interpretation of the LUT depends on the type of the 291 // filter (polar or separable). 292 typedef const PL_STRUCT(pl_filter) { 293 // Deep copy of the parameters, for convenience. 294 struct pl_filter_params params; 295 296 // Contains the true radius of the computed filter. This may be 297 // larger than `config.kernel->radius` depending on the `scale` passed to 298 // pl_filter_generate. This is only relevant for polar filters, where it 299 // affects the value range of *weights. 300 float radius; 301 302 // The computed look-up table (LUT). For polar filters, this is interpreted 303 // as a 1D array with dimensions [lut_entries] containing the raw filter 304 // samples on the scale [0, radius]. For separable (non-polar) filters, 305 // this is interpreted as a 2D array with dimensions 306 // [lut_entries][row_stride]. The inner rows contain the `row_size` samples 307 // to convolve with the corresponding input pixels. The outer coordinate is 308 // used to very the fractional offset (phase). So for example, if the 309 // sample position to reconstruct is directly aligned with the source 310 // texels, you would use the values from weights[0]. If the sample position 311 // to reconstruct is exactly half-way between two source texels (180° out 312 // of phase), you would use the values from weights[lut_entries/2]. 313 const float *weights; 314 315 // --- polar filters only (params.config.polar) 316 317 // Contains the effective cut-off radius for this filter. Samples outside 318 // of this cutoff radius may be discarded. Computed based on the `cutoff` 319 // value specified at filter generation. Only relevant for polar filters 320 // since skipping samples outside of the radius can be a significant 321 // performance gain for EWA sampling. 322 float radius_cutoff; 323 324 // --- separable filters only (!params.config.polar) 325 326 // The number of source texels to convolve over for each row. This value 327 // will never exceed the given `max_row_size`. If the filter ends up 328 // cut off because of this, the bool `insufficient` will be set to true. 329 int row_size; 330 bool insufficient; 331 332 // The separation (in *weights) between each row of the filter. Always 333 // a multiple of params.row_stride_align. 334 int row_stride; 335 } *pl_filter; 336 337 // Generate (compute) a filter instance based on a given filter configuration. 338 // The resulting pl_filter must be freed with `pl_filter_free` when no longer 339 // needed. Returns NULL if filter generation fails due to invalid parameters 340 // (i.e. missing a required parameter). 341 pl_filter pl_filter_generate(pl_log log, const struct pl_filter_params *params); 342 void pl_filter_free(pl_filter *filter); 343 344 PL_API_END 345 346 #endif // LIBPLACEBO_FILTER_KERNELS_H_ 347