1use crate::basics::uround;
8use crate::image_filters::{ImageFilterLut, IMAGE_SUBPIXEL_SCALE, IMAGE_SUBPIXEL_SHIFT};
9use crate::span_interpolator_linear::SpanInterpolatorLinear;
10use crate::trans_affine::TransAffine;
11
12pub struct SpanImageFilterBase<'a, I> {
24 interpolator: &'a mut I,
25 filter: Option<&'a ImageFilterLut>,
26 dx_dbl: f64,
27 dy_dbl: f64,
28 dx_int: u32,
29 dy_int: u32,
30}
31
32impl<'a, I> SpanImageFilterBase<'a, I> {
33 pub fn new(interpolator: &'a mut I, filter: Option<&'a ImageFilterLut>) -> Self {
35 Self {
36 interpolator,
37 filter,
38 dx_dbl: 0.5,
39 dy_dbl: 0.5,
40 dx_int: IMAGE_SUBPIXEL_SCALE / 2,
41 dy_int: IMAGE_SUBPIXEL_SCALE / 2,
42 }
43 }
44
45 pub fn interpolator(&self) -> &I {
46 self.interpolator
47 }
48
49 pub fn interpolator_mut(&mut self) -> &mut I {
50 self.interpolator
51 }
52
53 pub fn filter(&self) -> Option<&ImageFilterLut> {
54 self.filter
55 }
56
57 pub fn filter_dx_int(&self) -> u32 {
58 self.dx_int
59 }
60
61 pub fn filter_dy_int(&self) -> u32 {
62 self.dy_int
63 }
64
65 pub fn filter_dx_dbl(&self) -> f64 {
66 self.dx_dbl
67 }
68
69 pub fn filter_dy_dbl(&self) -> f64 {
70 self.dy_dbl
71 }
72
73 pub fn set_filter_offset(&mut self, dx: f64, dy: f64) {
78 self.dx_dbl = dx;
79 self.dy_dbl = dy;
80 self.dx_int = uround(dx * IMAGE_SUBPIXEL_SCALE as f64);
81 self.dy_int = uround(dy * IMAGE_SUBPIXEL_SCALE as f64);
82 }
83
84 pub fn set_filter_offset_uniform(&mut self, d: f64) {
86 self.set_filter_offset(d, d);
87 }
88
89 pub fn set_filter(&mut self, filter: &'a ImageFilterLut) {
91 self.filter = Some(filter);
92 }
93
94 pub fn prepare(&self) {
96 }
98}
99
100pub struct SpanImageResampleAffine<'a> {
111 base: SpanImageFilterBase<'a, SpanInterpolatorLinear<TransAffine>>,
112 scale_limit: f64,
113 blur_x: f64,
114 blur_y: f64,
115 rx: i32,
116 ry: i32,
117 rx_inv: i32,
118 ry_inv: i32,
119}
120
121impl<'a> SpanImageResampleAffine<'a> {
122 pub fn new(
124 interpolator: &'a mut SpanInterpolatorLinear<TransAffine>,
125 filter: &'a ImageFilterLut,
126 ) -> Self {
127 Self {
128 base: SpanImageFilterBase::new(interpolator, Some(filter)),
129 scale_limit: 200.0,
130 blur_x: 1.0,
131 blur_y: 1.0,
132 rx: 0,
133 ry: 0,
134 rx_inv: 0,
135 ry_inv: 0,
136 }
137 }
138
139 pub fn base(&self) -> &SpanImageFilterBase<'a, SpanInterpolatorLinear<TransAffine>> {
140 &self.base
141 }
142
143 pub fn base_mut(
144 &mut self,
145 ) -> &mut SpanImageFilterBase<'a, SpanInterpolatorLinear<TransAffine>> {
146 &mut self.base
147 }
148
149 pub fn scale_limit(&self) -> u32 {
150 uround(self.scale_limit)
151 }
152
153 pub fn set_scale_limit(&mut self, v: i32) {
154 self.scale_limit = v as f64;
155 }
156
157 pub fn blur_x(&self) -> f64 {
158 self.blur_x
159 }
160
161 pub fn blur_y(&self) -> f64 {
162 self.blur_y
163 }
164
165 pub fn set_blur_x(&mut self, v: f64) {
166 self.blur_x = v;
167 }
168
169 pub fn set_blur_y(&mut self, v: f64) {
170 self.blur_y = v;
171 }
172
173 pub fn set_blur(&mut self, v: f64) {
174 self.blur_x = v;
175 self.blur_y = v;
176 }
177
178 pub fn rx(&self) -> i32 {
179 self.rx
180 }
181
182 pub fn ry(&self) -> i32 {
183 self.ry
184 }
185
186 pub fn rx_inv(&self) -> i32 {
187 self.rx_inv
188 }
189
190 pub fn ry_inv(&self) -> i32 {
191 self.ry_inv
192 }
193
194 pub fn prepare(&mut self) {
198 let (mut scale_x, mut scale_y) = self.base.interpolator.transformer().scaling_abs();
199
200 let scale_xy = scale_x * scale_y;
201 if scale_xy > self.scale_limit {
202 scale_x = scale_x * self.scale_limit / scale_xy;
203 scale_y = scale_y * self.scale_limit / scale_xy;
204 }
205
206 if scale_x < 1.0 {
207 scale_x = 1.0;
208 }
209 if scale_y < 1.0 {
210 scale_y = 1.0;
211 }
212
213 if scale_x > self.scale_limit {
214 scale_x = self.scale_limit;
215 }
216 if scale_y > self.scale_limit {
217 scale_y = self.scale_limit;
218 }
219
220 scale_x *= self.blur_x;
221 scale_y *= self.blur_y;
222
223 if scale_x < 1.0 {
224 scale_x = 1.0;
225 }
226 if scale_y < 1.0 {
227 scale_y = 1.0;
228 }
229
230 self.rx = uround(scale_x * IMAGE_SUBPIXEL_SCALE as f64) as i32;
231 self.rx_inv = uround(1.0 / scale_x * IMAGE_SUBPIXEL_SCALE as f64) as i32;
232
233 self.ry = uround(scale_y * IMAGE_SUBPIXEL_SCALE as f64) as i32;
234 self.ry_inv = uround(1.0 / scale_y * IMAGE_SUBPIXEL_SCALE as f64) as i32;
235 }
236}
237
238pub struct SpanImageResample<'a, I> {
250 base: SpanImageFilterBase<'a, I>,
251 scale_limit: i32,
252 blur_x: i32,
253 blur_y: i32,
254}
255
256impl<'a, I> SpanImageResample<'a, I> {
257 pub fn new(interpolator: &'a mut I, filter: &'a ImageFilterLut) -> Self {
259 Self {
260 base: SpanImageFilterBase::new(interpolator, Some(filter)),
261 scale_limit: 20,
262 blur_x: IMAGE_SUBPIXEL_SCALE as i32,
263 blur_y: IMAGE_SUBPIXEL_SCALE as i32,
264 }
265 }
266
267 pub fn base(&self) -> &SpanImageFilterBase<'a, I> {
268 &self.base
269 }
270
271 pub fn base_mut(&mut self) -> &mut SpanImageFilterBase<'a, I> {
272 &mut self.base
273 }
274
275 pub fn scale_limit(&self) -> i32 {
276 self.scale_limit
277 }
278
279 pub fn set_scale_limit(&mut self, v: i32) {
280 self.scale_limit = v;
281 }
282
283 pub fn blur_x(&self) -> f64 {
284 self.blur_x as f64 / IMAGE_SUBPIXEL_SCALE as f64
285 }
286
287 pub fn blur_y(&self) -> f64 {
288 self.blur_y as f64 / IMAGE_SUBPIXEL_SCALE as f64
289 }
290
291 pub fn set_blur_x(&mut self, v: f64) {
292 self.blur_x = uround(v * IMAGE_SUBPIXEL_SCALE as f64) as i32;
293 }
294
295 pub fn set_blur_y(&mut self, v: f64) {
296 self.blur_y = uround(v * IMAGE_SUBPIXEL_SCALE as f64) as i32;
297 }
298
299 pub fn set_blur(&mut self, v: f64) {
300 let iv = uround(v * IMAGE_SUBPIXEL_SCALE as f64) as i32;
301 self.blur_x = iv;
302 self.blur_y = iv;
303 }
304
305 #[inline]
309 pub fn adjust_scale(&self, rx: &mut i32, ry: &mut i32) {
310 let subpixel = IMAGE_SUBPIXEL_SCALE as i32;
311 if *rx < subpixel {
312 *rx = subpixel;
313 }
314 if *ry < subpixel {
315 *ry = subpixel;
316 }
317 if *rx > subpixel * self.scale_limit {
318 *rx = subpixel * self.scale_limit;
319 }
320 if *ry > subpixel * self.scale_limit {
321 *ry = subpixel * self.scale_limit;
322 }
323 *rx = (*rx * self.blur_x) >> IMAGE_SUBPIXEL_SHIFT;
324 *ry = (*ry * self.blur_y) >> IMAGE_SUBPIXEL_SHIFT;
325 if *rx < subpixel {
326 *rx = subpixel;
327 }
328 if *ry < subpixel {
329 *ry = subpixel;
330 }
331 }
332}
333
334#[cfg(test)]
339mod tests {
340 use super::*;
341
342 #[test]
343 fn test_base_default_offsets() {
344 let trans = TransAffine::new();
345 let mut interp = SpanInterpolatorLinear::new(trans);
346 let base = SpanImageFilterBase::new(&mut interp, None);
347 assert_eq!(base.filter_dx_int(), IMAGE_SUBPIXEL_SCALE / 2);
348 assert_eq!(base.filter_dy_int(), IMAGE_SUBPIXEL_SCALE / 2);
349 assert_eq!(base.filter_dx_dbl(), 0.5);
350 assert_eq!(base.filter_dy_dbl(), 0.5);
351 }
352
353 #[test]
354 fn test_base_set_offset() {
355 let trans = TransAffine::new();
356 let mut interp = SpanInterpolatorLinear::new(trans);
357 let mut base = SpanImageFilterBase::new(&mut interp, None);
358 base.set_filter_offset(0.25, 0.75);
359 assert_eq!(base.filter_dx_dbl(), 0.25);
360 assert_eq!(base.filter_dy_dbl(), 0.75);
361 assert_eq!(base.filter_dx_int(), 64);
363 assert_eq!(base.filter_dy_int(), 192);
364 }
365
366 #[test]
367 fn test_base_set_offset_uniform() {
368 let trans = TransAffine::new();
369 let mut interp = SpanInterpolatorLinear::new(trans);
370 let mut base = SpanImageFilterBase::new(&mut interp, None);
371 base.set_filter_offset_uniform(0.0);
372 assert_eq!(base.filter_dx_int(), 0);
373 assert_eq!(base.filter_dy_int(), 0);
374 }
375
376 #[test]
377 fn test_base_filter_reference() {
378 let trans = TransAffine::new();
379 let mut interp = SpanInterpolatorLinear::new(trans);
380 let base = SpanImageFilterBase::new(&mut interp, None);
381 assert!(base.filter().is_none());
382 }
383
384 #[test]
385 fn test_base_with_filter() {
386 use crate::image_filters::ImageFilterBilinear;
387 let lut = ImageFilterLut::new_with_filter(&ImageFilterBilinear, true);
388 let trans = TransAffine::new();
389 let mut interp = SpanInterpolatorLinear::new(trans);
390 let base = SpanImageFilterBase::new(&mut interp, Some(&lut));
391 assert!(base.filter().is_some());
392 assert_eq!(base.filter().unwrap().radius(), 1.0);
393 }
394
395 #[test]
396 fn test_resample_affine_defaults() {
397 let trans = TransAffine::new();
398 let mut interp = SpanInterpolatorLinear::new(trans);
399 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
400 let r = SpanImageResampleAffine::new(&mut interp, &lut);
401 assert_eq!(r.scale_limit(), 200);
402 assert_eq!(r.blur_x(), 1.0);
403 assert_eq!(r.blur_y(), 1.0);
404 }
405
406 #[test]
407 fn test_resample_affine_prepare_identity() {
408 let trans = TransAffine::new();
409 let mut interp = SpanInterpolatorLinear::new(trans);
410 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
411 let mut r = SpanImageResampleAffine::new(&mut interp, &lut);
412 r.prepare();
413 assert_eq!(r.rx(), IMAGE_SUBPIXEL_SCALE as i32);
416 assert_eq!(r.ry(), IMAGE_SUBPIXEL_SCALE as i32);
417 assert_eq!(r.rx_inv(), IMAGE_SUBPIXEL_SCALE as i32);
419 assert_eq!(r.ry_inv(), IMAGE_SUBPIXEL_SCALE as i32);
420 }
421
422 #[test]
423 fn test_resample_affine_prepare_scaled() {
424 let trans = TransAffine::new_scaling(2.0, 3.0);
425 let mut interp = SpanInterpolatorLinear::new(trans);
426 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
427 let mut r = SpanImageResampleAffine::new(&mut interp, &lut);
428 r.prepare();
429 assert_eq!(r.rx(), 512);
432 assert_eq!(r.ry(), 768);
434 assert_eq!(r.rx_inv(), 128);
436 assert_eq!(r.ry_inv(), 85);
438 }
439
440 #[test]
441 fn test_resample_affine_blur() {
442 let trans = TransAffine::new();
443 let mut interp = SpanInterpolatorLinear::new(trans);
444 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
445 let mut r = SpanImageResampleAffine::new(&mut interp, &lut);
446 r.set_blur(2.0);
447 r.prepare();
448 assert_eq!(r.rx(), 512);
450 assert_eq!(r.ry(), 512);
451 }
452
453 #[test]
454 fn test_resample_generic_defaults() {
455 let trans = TransAffine::new();
456 let mut interp = SpanInterpolatorLinear::new(trans);
457 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
458 let r = SpanImageResample::new(&mut interp, &lut);
459 assert_eq!(r.scale_limit(), 20);
460 assert!((r.blur_x() - 1.0).abs() < 1e-10);
461 assert!((r.blur_y() - 1.0).abs() < 1e-10);
462 }
463
464 #[test]
465 fn test_resample_generic_adjust_scale_clamp_min() {
466 let trans = TransAffine::new();
467 let mut interp = SpanInterpolatorLinear::new(trans);
468 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
469 let r = SpanImageResample::new(&mut interp, &lut);
470 let mut rx = 10; let mut ry = 10;
472 r.adjust_scale(&mut rx, &mut ry);
473 assert_eq!(rx, IMAGE_SUBPIXEL_SCALE as i32);
475 assert_eq!(ry, IMAGE_SUBPIXEL_SCALE as i32);
476 }
477
478 #[test]
479 fn test_resample_generic_adjust_scale_clamp_max() {
480 let trans = TransAffine::new();
481 let mut interp = SpanInterpolatorLinear::new(trans);
482 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
483 let r = SpanImageResample::new(&mut interp, &lut);
484 let mut rx = 100_000;
486 let mut ry = 100_000;
487 r.adjust_scale(&mut rx, &mut ry);
488 assert_eq!(rx, 5120);
490 assert_eq!(ry, 5120);
491 }
492
493 #[test]
494 fn test_resample_generic_adjust_scale_with_blur() {
495 let trans = TransAffine::new();
496 let mut interp = SpanInterpolatorLinear::new(trans);
497 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
498 let mut r = SpanImageResample::new(&mut interp, &lut);
499 r.set_blur(2.0); let mut rx = 256; let mut ry = 256;
502 r.adjust_scale(&mut rx, &mut ry);
503 assert_eq!(rx, 512);
505 assert_eq!(ry, 512);
506 }
507
508 #[test]
509 fn test_resample_generic_set_scale_limit() {
510 let trans = TransAffine::new();
511 let mut interp = SpanInterpolatorLinear::new(trans);
512 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
513 let mut r = SpanImageResample::new(&mut interp, &lut);
514 r.set_scale_limit(50);
515 assert_eq!(r.scale_limit(), 50);
516 }
517}