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