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(crate) fn filter_lut(&self) -> Option<&'a ImageFilterLut> {
68 self.filter
69 }
70
71 pub fn filter_dx_int(&self) -> u32 {
72 self.dx_int
73 }
74
75 pub fn filter_dy_int(&self) -> u32 {
76 self.dy_int
77 }
78
79 pub fn filter_dx_dbl(&self) -> f64 {
80 self.dx_dbl
81 }
82
83 pub fn filter_dy_dbl(&self) -> f64 {
84 self.dy_dbl
85 }
86
87 pub fn set_filter_offset(&mut self, dx: f64, dy: f64) {
92 self.dx_dbl = dx;
93 self.dy_dbl = dy;
94 self.dx_int = uround(dx * IMAGE_SUBPIXEL_SCALE as f64);
95 self.dy_int = uround(dy * IMAGE_SUBPIXEL_SCALE as f64);
96 }
97
98 pub fn set_filter_offset_uniform(&mut self, d: f64) {
100 self.set_filter_offset(d, d);
101 }
102
103 pub fn set_filter(&mut self, filter: &'a ImageFilterLut) {
105 self.filter = Some(filter);
106 }
107
108 pub fn prepare(&self) {
110 }
112}
113
114pub struct SpanImageResampleAffine<'a> {
125 base: SpanImageFilterBase<'a, SpanInterpolatorLinear<TransAffine>>,
126 scale_limit: f64,
127 blur_x: f64,
128 blur_y: f64,
129 rx: i32,
130 ry: i32,
131 rx_inv: i32,
132 ry_inv: i32,
133}
134
135impl<'a> SpanImageResampleAffine<'a> {
136 pub fn new(
138 interpolator: &'a mut SpanInterpolatorLinear<TransAffine>,
139 filter: &'a ImageFilterLut,
140 ) -> Self {
141 Self {
142 base: SpanImageFilterBase::new(interpolator, Some(filter)),
143 scale_limit: 200.0,
144 blur_x: 1.0,
145 blur_y: 1.0,
146 rx: 0,
147 ry: 0,
148 rx_inv: 0,
149 ry_inv: 0,
150 }
151 }
152
153 pub fn base(&self) -> &SpanImageFilterBase<'a, SpanInterpolatorLinear<TransAffine>> {
154 &self.base
155 }
156
157 pub fn base_mut(
158 &mut self,
159 ) -> &mut SpanImageFilterBase<'a, SpanInterpolatorLinear<TransAffine>> {
160 &mut self.base
161 }
162
163 pub fn scale_limit(&self) -> u32 {
164 uround(self.scale_limit)
165 }
166
167 pub fn set_scale_limit(&mut self, v: i32) {
168 self.scale_limit = v as f64;
169 }
170
171 pub fn blur_x(&self) -> f64 {
172 self.blur_x
173 }
174
175 pub fn blur_y(&self) -> f64 {
176 self.blur_y
177 }
178
179 pub fn set_blur_x(&mut self, v: f64) {
180 self.blur_x = v;
181 }
182
183 pub fn set_blur_y(&mut self, v: f64) {
184 self.blur_y = v;
185 }
186
187 pub fn set_blur(&mut self, v: f64) {
188 self.blur_x = v;
189 self.blur_y = v;
190 }
191
192 pub fn rx(&self) -> i32 {
193 self.rx
194 }
195
196 pub fn ry(&self) -> i32 {
197 self.ry
198 }
199
200 pub fn rx_inv(&self) -> i32 {
201 self.rx_inv
202 }
203
204 pub fn ry_inv(&self) -> i32 {
205 self.ry_inv
206 }
207
208 pub fn prepare(&mut self) {
212 let (mut scale_x, mut scale_y) = self.base.interpolator.transformer().scaling_abs();
213
214 let scale_xy = scale_x * scale_y;
215 if scale_xy > self.scale_limit {
216 scale_x = scale_x * self.scale_limit / scale_xy;
217 scale_y = scale_y * self.scale_limit / scale_xy;
218 }
219
220 if scale_x < 1.0 {
221 scale_x = 1.0;
222 }
223 if scale_y < 1.0 {
224 scale_y = 1.0;
225 }
226
227 if scale_x > self.scale_limit {
228 scale_x = self.scale_limit;
229 }
230 if scale_y > self.scale_limit {
231 scale_y = self.scale_limit;
232 }
233
234 scale_x *= self.blur_x;
235 scale_y *= self.blur_y;
236
237 if scale_x < 1.0 {
238 scale_x = 1.0;
239 }
240 if scale_y < 1.0 {
241 scale_y = 1.0;
242 }
243
244 self.rx = uround(scale_x * IMAGE_SUBPIXEL_SCALE as f64) as i32;
245 self.rx_inv = uround(1.0 / scale_x * IMAGE_SUBPIXEL_SCALE as f64) as i32;
246
247 self.ry = uround(scale_y * IMAGE_SUBPIXEL_SCALE as f64) as i32;
248 self.ry_inv = uround(1.0 / scale_y * IMAGE_SUBPIXEL_SCALE as f64) as i32;
249 }
250}
251
252pub struct SpanImageResample<'a, I> {
264 base: SpanImageFilterBase<'a, I>,
265 scale_limit: i32,
266 blur_x: i32,
267 blur_y: i32,
268}
269
270impl<'a, I> SpanImageResample<'a, I> {
271 pub fn new(interpolator: &'a mut I, filter: &'a ImageFilterLut) -> Self {
273 Self {
274 base: SpanImageFilterBase::new(interpolator, Some(filter)),
275 scale_limit: 20,
276 blur_x: IMAGE_SUBPIXEL_SCALE as i32,
277 blur_y: IMAGE_SUBPIXEL_SCALE as i32,
278 }
279 }
280
281 pub fn base(&self) -> &SpanImageFilterBase<'a, I> {
282 &self.base
283 }
284
285 pub fn base_mut(&mut self) -> &mut SpanImageFilterBase<'a, I> {
286 &mut self.base
287 }
288
289 pub fn scale_limit(&self) -> i32 {
290 self.scale_limit
291 }
292
293 pub fn set_scale_limit(&mut self, v: i32) {
294 self.scale_limit = v;
295 }
296
297 pub fn blur_x(&self) -> f64 {
298 self.blur_x as f64 / IMAGE_SUBPIXEL_SCALE as f64
299 }
300
301 pub fn blur_y(&self) -> f64 {
302 self.blur_y as f64 / IMAGE_SUBPIXEL_SCALE as f64
303 }
304
305 pub fn set_blur_x(&mut self, v: f64) {
306 self.blur_x = uround(v * IMAGE_SUBPIXEL_SCALE as f64) as i32;
307 }
308
309 pub fn set_blur_y(&mut self, v: f64) {
310 self.blur_y = uround(v * IMAGE_SUBPIXEL_SCALE as f64) as i32;
311 }
312
313 pub fn set_blur(&mut self, v: f64) {
314 let iv = uround(v * IMAGE_SUBPIXEL_SCALE as f64) as i32;
315 self.blur_x = iv;
316 self.blur_y = iv;
317 }
318
319 #[inline]
323 pub fn adjust_scale(&self, rx: &mut i32, ry: &mut i32) {
324 let subpixel = IMAGE_SUBPIXEL_SCALE as i32;
325 if *rx < subpixel {
326 *rx = subpixel;
327 }
328 if *ry < subpixel {
329 *ry = subpixel;
330 }
331 if *rx > subpixel * self.scale_limit {
332 *rx = subpixel * self.scale_limit;
333 }
334 if *ry > subpixel * self.scale_limit {
335 *ry = subpixel * self.scale_limit;
336 }
337 *rx = (*rx * self.blur_x) >> IMAGE_SUBPIXEL_SHIFT;
338 *ry = (*ry * self.blur_y) >> IMAGE_SUBPIXEL_SHIFT;
339 if *rx < subpixel {
340 *rx = subpixel;
341 }
342 if *ry < subpixel {
343 *ry = subpixel;
344 }
345 }
346}
347
348#[cfg(test)]
353mod tests {
354 use super::*;
355
356 #[test]
357 fn test_base_default_offsets() {
358 let trans = TransAffine::new();
359 let mut interp = SpanInterpolatorLinear::new(trans);
360 let base = SpanImageFilterBase::new(&mut interp, None);
361 assert_eq!(base.filter_dx_int(), IMAGE_SUBPIXEL_SCALE / 2);
362 assert_eq!(base.filter_dy_int(), IMAGE_SUBPIXEL_SCALE / 2);
363 assert_eq!(base.filter_dx_dbl(), 0.5);
364 assert_eq!(base.filter_dy_dbl(), 0.5);
365 }
366
367 #[test]
368 fn test_base_set_offset() {
369 let trans = TransAffine::new();
370 let mut interp = SpanInterpolatorLinear::new(trans);
371 let mut base = SpanImageFilterBase::new(&mut interp, None);
372 base.set_filter_offset(0.25, 0.75);
373 assert_eq!(base.filter_dx_dbl(), 0.25);
374 assert_eq!(base.filter_dy_dbl(), 0.75);
375 assert_eq!(base.filter_dx_int(), 64);
377 assert_eq!(base.filter_dy_int(), 192);
378 }
379
380 #[test]
381 fn test_base_set_offset_uniform() {
382 let trans = TransAffine::new();
383 let mut interp = SpanInterpolatorLinear::new(trans);
384 let mut base = SpanImageFilterBase::new(&mut interp, None);
385 base.set_filter_offset_uniform(0.0);
386 assert_eq!(base.filter_dx_int(), 0);
387 assert_eq!(base.filter_dy_int(), 0);
388 }
389
390 #[test]
391 fn test_base_filter_reference() {
392 let trans = TransAffine::new();
393 let mut interp = SpanInterpolatorLinear::new(trans);
394 let base = SpanImageFilterBase::new(&mut interp, None);
395 assert!(base.filter().is_none());
396 }
397
398 #[test]
399 fn test_base_with_filter() {
400 use crate::image_filters::ImageFilterBilinear;
401 let lut = ImageFilterLut::new_with_filter(&ImageFilterBilinear, true);
402 let trans = TransAffine::new();
403 let mut interp = SpanInterpolatorLinear::new(trans);
404 let base = SpanImageFilterBase::new(&mut interp, Some(&lut));
405 assert!(base.filter().is_some());
406 assert_eq!(base.filter().unwrap().radius(), 1.0);
407 }
408
409 #[test]
410 fn test_resample_affine_defaults() {
411 let trans = TransAffine::new();
412 let mut interp = SpanInterpolatorLinear::new(trans);
413 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
414 let r = SpanImageResampleAffine::new(&mut interp, &lut);
415 assert_eq!(r.scale_limit(), 200);
416 assert_eq!(r.blur_x(), 1.0);
417 assert_eq!(r.blur_y(), 1.0);
418 }
419
420 #[test]
421 fn test_resample_affine_prepare_identity() {
422 let trans = TransAffine::new();
423 let mut interp = SpanInterpolatorLinear::new(trans);
424 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
425 let mut r = SpanImageResampleAffine::new(&mut interp, &lut);
426 r.prepare();
427 assert_eq!(r.rx(), IMAGE_SUBPIXEL_SCALE as i32);
430 assert_eq!(r.ry(), IMAGE_SUBPIXEL_SCALE as i32);
431 assert_eq!(r.rx_inv(), IMAGE_SUBPIXEL_SCALE as i32);
433 assert_eq!(r.ry_inv(), IMAGE_SUBPIXEL_SCALE as i32);
434 }
435
436 #[test]
437 fn test_resample_affine_prepare_scaled() {
438 let trans = TransAffine::new_scaling(2.0, 3.0);
439 let mut interp = SpanInterpolatorLinear::new(trans);
440 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
441 let mut r = SpanImageResampleAffine::new(&mut interp, &lut);
442 r.prepare();
443 assert_eq!(r.rx(), 512);
446 assert_eq!(r.ry(), 768);
448 assert_eq!(r.rx_inv(), 128);
450 assert_eq!(r.ry_inv(), 85);
452 }
453
454 #[test]
455 fn test_resample_affine_blur() {
456 let trans = TransAffine::new();
457 let mut interp = SpanInterpolatorLinear::new(trans);
458 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
459 let mut r = SpanImageResampleAffine::new(&mut interp, &lut);
460 r.set_blur(2.0);
461 r.prepare();
462 assert_eq!(r.rx(), 512);
464 assert_eq!(r.ry(), 512);
465 }
466
467 #[test]
468 fn test_resample_generic_defaults() {
469 let trans = TransAffine::new();
470 let mut interp = SpanInterpolatorLinear::new(trans);
471 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
472 let r = SpanImageResample::new(&mut interp, &lut);
473 assert_eq!(r.scale_limit(), 20);
474 assert!((r.blur_x() - 1.0).abs() < 1e-10);
475 assert!((r.blur_y() - 1.0).abs() < 1e-10);
476 }
477
478 #[test]
479 fn test_resample_generic_adjust_scale_clamp_min() {
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 = 10; let mut ry = 10;
486 r.adjust_scale(&mut rx, &mut ry);
487 assert_eq!(rx, IMAGE_SUBPIXEL_SCALE as i32);
489 assert_eq!(ry, IMAGE_SUBPIXEL_SCALE as i32);
490 }
491
492 #[test]
493 fn test_resample_generic_adjust_scale_clamp_max() {
494 let trans = TransAffine::new();
495 let mut interp = SpanInterpolatorLinear::new(trans);
496 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
497 let r = SpanImageResample::new(&mut interp, &lut);
498 let mut rx = 100_000;
500 let mut ry = 100_000;
501 r.adjust_scale(&mut rx, &mut ry);
502 assert_eq!(rx, 5120);
504 assert_eq!(ry, 5120);
505 }
506
507 #[test]
508 fn test_resample_generic_adjust_scale_with_blur() {
509 let trans = TransAffine::new();
510 let mut interp = SpanInterpolatorLinear::new(trans);
511 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
512 let mut r = SpanImageResample::new(&mut interp, &lut);
513 r.set_blur(2.0); let mut rx = 256; let mut ry = 256;
516 r.adjust_scale(&mut rx, &mut ry);
517 assert_eq!(rx, 512);
519 assert_eq!(ry, 512);
520 }
521
522 #[test]
523 fn test_resample_generic_set_scale_limit() {
524 let trans = TransAffine::new();
525 let mut interp = SpanInterpolatorLinear::new(trans);
526 let lut = ImageFilterLut::new_with_filter(&crate::image_filters::ImageFilterBilinear, true);
527 let mut r = SpanImageResample::new(&mut interp, &lut);
528 r.set_scale_limit(50);
529 assert_eq!(r.scale_limit(), 50);
530 }
531}