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