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