1#![allow(clippy::excessive_precision)]
30
31use crate::bartlett::{bartlett, bartlett_hann};
32use crate::bc_spline::{
33 b_spline, catmull_rom, hermite_spline, mitchell_netravalli, robidoux, robidoux_sharp,
34};
35use crate::bilinear::bilinear;
36use crate::blackman::blackman;
37use crate::bohman::bohman;
38use crate::cubic::{bicubic_spline, cubic_spline};
39use crate::gaussian::gaussian;
40use crate::hann::{hamming, hann, hanning};
41use crate::kaiser::kaiser;
42use crate::lagrange::{lagrange2, lagrange3};
43use crate::lanczos::{
44 lanczos2, lanczos2_jinc, lanczos3, lanczos3_jinc, lanczos4, lanczos4_jinc, lanczos6,
45 lanczos6_jinc,
46};
47use crate::math::gaussian::Exponential;
48use crate::math::kaiser::BesselI0;
49use crate::math::lanczos::{lanczos5, lanczos5_jinc};
50use crate::math::sinc::{Sinc, Trigonometry};
51use crate::quadric::quadric;
52use crate::sinc::sinc;
53use crate::sphinx::sphinx;
54use crate::spline_n::{spline16, spline36, spline64};
55use crate::welch::welch;
56use crate::{ConstPI, ConstSqrt2, Jinc};
57use num_traits::{AsPrimitive, Float, MulAdd, Signed};
58use std::ops::{AddAssign, MulAssign, Neg};
59
60#[inline(always)]
61pub(crate) fn box_weight<V: Copy + 'static>(_: V) -> V
62where
63 f32: AsPrimitive<V>,
64{
65 1f32.as_()
66}
67
68#[derive(Debug, Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq)]
69pub enum ResamplingFunction {
71 Bilinear,
72 Nearest,
73 Cubic,
74 #[default]
75 MitchellNetravalli,
76 CatmullRom,
77 Hermite,
78 BSpline,
79 Hann,
80 Bicubic,
81 Hamming,
82 Hanning,
83 EwaHanning,
84 Blackman,
85 EwaBlackman,
86 Welch,
87 Quadric,
88 EwaQuadric,
89 Gaussian,
90 Sphinx,
91 Bartlett,
92 Robidoux,
93 EwaRobidoux,
94 RobidouxSharp,
95 EwaRobidouxSharp,
96 Spline16,
97 Spline36,
98 Spline64,
99 Kaiser,
100 BartlettHann,
101 Box,
102 Bohman,
103 Lanczos2,
104 Lanczos3,
105 Lanczos4,
106 Lanczos5,
107 Lanczos6,
108 Lanczos2Jinc,
109 Lanczos3Jinc,
110 Lanczos4Jinc,
111 Lanczos5Jinc,
112 Lanczos6Jinc,
113 EwaLanczos3,
114 Ginseng,
115 EwaGinseng,
116 EwaLanczosSharp,
117 EwaLanczos4Sharpest,
118 EwaLanczosSoft,
119 HaasnSoft,
120 Lagrange2,
121 Lagrange3,
122 EwaMitchellNetravalli,
123 EwaCatmullRom,
124 Area,
126}
127
128impl From<u32> for ResamplingFunction {
129 fn from(value: u32) -> Self {
130 match value {
131 0 => ResamplingFunction::Bilinear,
132 1 => ResamplingFunction::Nearest,
133 2 => ResamplingFunction::Cubic,
134 3 => ResamplingFunction::MitchellNetravalli,
135 4 => ResamplingFunction::CatmullRom,
136 5 => ResamplingFunction::Hermite,
137 6 => ResamplingFunction::BSpline,
138 7 => ResamplingFunction::Hann,
139 8 => ResamplingFunction::Bicubic,
140 9 => ResamplingFunction::Hamming,
141 10 => ResamplingFunction::Hanning,
142 11 => ResamplingFunction::Blackman,
143 12 => ResamplingFunction::Welch,
144 13 => ResamplingFunction::Quadric,
145 14 => ResamplingFunction::Gaussian,
146 15 => ResamplingFunction::Sphinx,
147 16 => ResamplingFunction::Bartlett,
148 17 => ResamplingFunction::Robidoux,
149 18 => ResamplingFunction::RobidouxSharp,
150 19 => ResamplingFunction::Spline16,
151 20 => ResamplingFunction::Spline36,
152 21 => ResamplingFunction::Spline64,
153 22 => ResamplingFunction::Kaiser,
154 23 => ResamplingFunction::BartlettHann,
155 24 => ResamplingFunction::Box,
156 25 => ResamplingFunction::Bohman,
157 26 => ResamplingFunction::Lanczos2,
158 27 => ResamplingFunction::Lanczos3,
159 28 => ResamplingFunction::Lanczos4,
160 29 => ResamplingFunction::Lanczos2Jinc,
161 30 => ResamplingFunction::Lanczos3Jinc,
162 31 => ResamplingFunction::Lanczos4Jinc,
163 32 => ResamplingFunction::EwaHanning,
164 33 => ResamplingFunction::EwaRobidoux,
165 34 => ResamplingFunction::EwaBlackman,
166 35 => ResamplingFunction::EwaQuadric,
167 36 => ResamplingFunction::EwaRobidouxSharp,
168 37 => ResamplingFunction::EwaLanczos3,
169 38 => ResamplingFunction::Ginseng,
170 39 => ResamplingFunction::EwaGinseng,
171 40 => ResamplingFunction::EwaLanczosSharp,
172 41 => ResamplingFunction::EwaLanczos4Sharpest,
173 42 => ResamplingFunction::EwaLanczosSoft,
174 43 => ResamplingFunction::HaasnSoft,
175 44 => ResamplingFunction::Lagrange2,
176 45 => ResamplingFunction::Lagrange3,
177 46 => ResamplingFunction::Lanczos6,
178 47 => ResamplingFunction::Lanczos6Jinc,
179 48 => ResamplingFunction::Area,
180 49 => ResamplingFunction::Lanczos5,
181 50 => ResamplingFunction::Lanczos5Jinc,
182 51 => ResamplingFunction::EwaCatmullRom,
183 52 => ResamplingFunction::EwaMitchellNetravalli,
184 _ => ResamplingFunction::Bilinear,
185 }
186 }
187}
188
189#[derive(Debug, Copy, Clone)]
191pub(crate) struct ResamplingWindow<T> {
192 pub(crate) window: fn(T) -> T,
193 pub(crate) window_size: f32,
194 pub(crate) blur: f32,
195 pub(crate) taper: f32,
196}
197
198impl<T> ResamplingWindow<T> {
199 fn new(window: fn(T) -> T, window_size: f32, blur: f32, taper: f32) -> ResamplingWindow<T> {
200 ResamplingWindow {
201 window,
202 window_size,
203 blur,
204 taper,
205 }
206 }
207}
208
209#[derive(Debug, Copy, Clone)]
211pub(crate) struct ResamplingFilter<T> {
212 pub kernel: fn(T) -> T,
213 pub window: Option<ResamplingWindow<T>>,
214 pub min_kernel_size: f32,
215 pub is_ewa: bool,
216 pub is_resizable_kernel: bool,
217 pub is_area: bool,
218}
219
220impl<T> ResamplingFilter<T> {
221 fn new(kernel: fn(T) -> T, min_kernel_size: f32, is_ewa: bool) -> ResamplingFilter<T> {
222 ResamplingFilter {
223 kernel,
224 window: None,
225 min_kernel_size,
226 is_ewa,
227 is_resizable_kernel: true,
228 is_area: false,
229 }
230 }
231
232 fn new_with_window(
233 kernel: fn(T) -> T,
234 window: ResamplingWindow<T>,
235 min_kernel_size: f32,
236 is_ewa: bool,
237 ) -> ResamplingFilter<T> {
238 ResamplingFilter::<T> {
239 kernel,
240 window: Some(window),
241 min_kernel_size,
242 is_ewa,
243 is_resizable_kernel: true,
244 is_area: false,
245 }
246 }
247
248 fn new_with_fixed_kernel(
249 kernel: fn(T) -> T,
250 min_kernel_size: f32,
251 is_ewa: bool,
252 ) -> ResamplingFilter<T> {
253 ResamplingFilter::<T> {
254 kernel,
255 window: None,
256 min_kernel_size,
257 is_ewa,
258 is_resizable_kernel: false,
259 is_area: false,
260 }
261 }
262
263 fn new_with_area(kernel: fn(T) -> T, min_kernel_size: f32) -> ResamplingFilter<T> {
264 ResamplingFilter {
265 kernel,
266 window: None,
267 min_kernel_size,
268 is_ewa: false,
269 is_resizable_kernel: true,
270 is_area: true,
271 }
272 }
273}
274
275const JINC_R3: f32 = 3.2383154841662362f32;
276const JINC_R4: f32 = 4.2410628637960699f32;
277
278impl ResamplingFunction {
279 pub(crate) fn get_resampling_filter<T>(&self) -> ResamplingFilter<T>
280 where
281 T: Copy
282 + Neg
283 + Signed
284 + Float
285 + 'static
286 + ConstPI
287 + MulAssign<T>
288 + AddAssign<T>
289 + AsPrimitive<f64>
290 + AsPrimitive<usize>
291 + Jinc<T>
292 + ConstSqrt2
293 + Trigonometry
294 + Exponential
295 + Sinc
296 + BesselI0
297 + MulAdd<Output = T>,
298 f32: AsPrimitive<T>,
299 f64: AsPrimitive<T>,
300 usize: AsPrimitive<T>,
301 {
302 match self {
303 ResamplingFunction::Bilinear => ResamplingFilter::new(bilinear, 1f32, false),
304 ResamplingFunction::Nearest => {
305 ResamplingFilter::new(bilinear, 1f32, false)
307 }
308 ResamplingFunction::Cubic => ResamplingFilter::new(cubic_spline, 2f32, false),
309 ResamplingFunction::MitchellNetravalli => {
310 ResamplingFilter::new(mitchell_netravalli, 2f32, false)
311 }
312 ResamplingFunction::CatmullRom => ResamplingFilter::new(catmull_rom, 2f32, false),
313 ResamplingFunction::Lanczos2 => ResamplingFilter::new(lanczos2, 2f32, false),
314 ResamplingFunction::Lanczos3 => ResamplingFilter::new(lanczos3, 3f32, false),
315 ResamplingFunction::Lanczos4 => ResamplingFilter::new(lanczos4, 4f32, false),
316 ResamplingFunction::Lanczos5 => ResamplingFilter::new(lanczos5, 5f32, false),
317 ResamplingFunction::Hermite => ResamplingFilter::new(hermite_spline, 2f32, false),
318 ResamplingFunction::BSpline => ResamplingFilter::new(b_spline, 2f32, false),
319 ResamplingFunction::Hann => ResamplingFilter::new(hann, 3f32, false),
320 ResamplingFunction::Bicubic => ResamplingFilter::new(bicubic_spline, 2f32, false),
321 ResamplingFunction::Hamming => ResamplingFilter::new(hamming, 1f32, false),
322 ResamplingFunction::Hanning => ResamplingFilter::new(hanning, 2f32, false),
323 ResamplingFunction::EwaHanning => ResamplingFilter::new_with_window(
324 T::jinc,
325 ResamplingWindow::new(hanning, 2f32, 0f32, 0f32),
326 1f32,
327 true,
328 ),
329 ResamplingFunction::Welch => ResamplingFilter::new(welch, 2f32, false),
330 ResamplingFunction::Quadric => ResamplingFilter::new(quadric, 2f32, false),
331 ResamplingFunction::EwaQuadric => ResamplingFilter::new(quadric, 2f32, true),
332 ResamplingFunction::Gaussian => ResamplingFilter::new(gaussian, 2f32, false),
333 ResamplingFunction::Sphinx => ResamplingFilter::new(sphinx, 2f32, false),
334 ResamplingFunction::Bartlett => ResamplingFilter::new(bartlett, 1f32, false),
335 ResamplingFunction::Robidoux => ResamplingFilter::new(robidoux, 2f32, false),
336 ResamplingFunction::EwaRobidoux => ResamplingFilter::new(robidoux, 2f32, true),
337 ResamplingFunction::RobidouxSharp => ResamplingFilter::new(robidoux_sharp, 2f32, false),
338 ResamplingFunction::EwaRobidouxSharp => {
339 ResamplingFilter::new(robidoux_sharp, 2f32, true)
340 }
341 ResamplingFunction::Spline16 => {
342 ResamplingFilter::new_with_fixed_kernel(spline16, 2f32, false)
343 }
344 ResamplingFunction::Spline36 => {
345 ResamplingFilter::new_with_fixed_kernel(spline36, 4f32, false)
346 }
347 ResamplingFunction::Spline64 => {
348 ResamplingFilter::new_with_fixed_kernel(spline64, 6f32, false)
349 }
350 ResamplingFunction::Kaiser => ResamplingFilter::new(kaiser, 2f32, false),
351 ResamplingFunction::BartlettHann => ResamplingFilter::new(bartlett_hann, 2f32, false),
352 ResamplingFunction::Box => ResamplingFilter::new(box_weight, 2f32, false),
353 ResamplingFunction::Area => ResamplingFilter::new_with_area(box_weight, 2f32),
354 ResamplingFunction::Bohman => ResamplingFilter::new(bohman, 2f32, false),
355 ResamplingFunction::Lanczos2Jinc => ResamplingFilter::new(lanczos2_jinc, 2f32, false),
356 ResamplingFunction::Lanczos3Jinc => ResamplingFilter::new(lanczos3_jinc, 3f32, false),
357 ResamplingFunction::EwaLanczos3 => ResamplingFilter::new(lanczos3, 3f32, true),
358 ResamplingFunction::Lanczos4Jinc => ResamplingFilter::new(lanczos4_jinc, 4f32, false),
359 ResamplingFunction::Lanczos5Jinc => ResamplingFilter::new(lanczos5_jinc, 5f32, false),
360 ResamplingFunction::Blackman => ResamplingFilter::new(blackman, 2f32, false),
361 ResamplingFunction::EwaBlackman => ResamplingFilter::new(blackman, 2f32, true),
362 ResamplingFunction::Ginseng => ResamplingFilter::new_with_window(
363 sinc,
364 ResamplingWindow::new(T::jinc, 3f32, 1f32, 0f32),
365 3f32,
366 false,
367 ),
368 ResamplingFunction::EwaGinseng => ResamplingFilter::new_with_window(
369 sinc,
370 ResamplingWindow::new(T::jinc, JINC_R3, 1f32, 0f32),
371 3f32,
372 true,
373 ),
374 ResamplingFunction::EwaLanczosSharp => ResamplingFilter::new_with_window(
375 T::jinc,
376 ResamplingWindow::new(T::jinc, JINC_R3, 0.9812505837223707f32, 0f32),
377 3f32,
378 true,
379 ),
380 ResamplingFunction::EwaLanczos4Sharpest => ResamplingFilter::new_with_window(
381 T::jinc,
382 ResamplingWindow::new(T::jinc, JINC_R4, 0.8845120932605005f32, 0f32),
383 4f32,
384 true,
385 ),
386 ResamplingFunction::EwaLanczosSoft => ResamplingFilter::new_with_window(
387 T::jinc,
388 ResamplingWindow::new(T::jinc, JINC_R3, 1.0164667662867047f32, 0f32),
389 3f32,
390 true,
391 ),
392 ResamplingFunction::HaasnSoft => ResamplingFilter::new_with_window(
393 T::jinc,
394 ResamplingWindow::new(hanning, 3f32, 1.11f32, 0f32),
395 3f32,
396 false,
397 ),
398 ResamplingFunction::Lagrange2 => ResamplingFilter::new(lagrange2, 2f32, false),
399 ResamplingFunction::Lagrange3 => ResamplingFilter::new(lagrange3, 3f32, false),
400 ResamplingFunction::Lanczos6Jinc => ResamplingFilter::new(lanczos6_jinc, 6f32, false),
401 ResamplingFunction::Lanczos6 => ResamplingFilter::new(lanczos6, 6f32, false),
402 ResamplingFunction::EwaMitchellNetravalli => {
403 ResamplingFilter::new(mitchell_netravalli, 2f32, true)
404 }
405 ResamplingFunction::EwaCatmullRom => ResamplingFilter::new(catmull_rom, 2f32, true),
406 }
407 }
408}