1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
pub trait Kernel<const SIZE: usize>
where
    Self: Copy + Send + Sync,
{
    fn values(&self) -> [[f32; SIZE]; SIZE];

    fn size(&self) -> usize;

    fn index(&self, index: [usize; 2]) -> f32 {
        if index[0] > self.size() || index[1] > self.size() {
            panic!("Index out of bounds");
        }

        self.values()[index[0]][index[1]]
    }

    fn compute_extended_index(
        &self,
        x: usize,
        y: usize,
        x_distance: isize,
        y_distance: isize,
        (max_y, max_x): (usize, usize),
    ) -> [usize; 2] {
        let kernel_size = self.size() as isize;
        let kernel_padding = kernel_size / 2;

        let mut x = x as isize + x_distance;
        let mut y = y as isize + y_distance;

        if x < 0 {
            x = -x;
        } else if x > max_x as isize - kernel_padding {
            let overshot_distance = x - max_x as isize + kernel_padding;
            x = max_x as isize - overshot_distance;
        }

        if y < 0 {
            y = -y;
        } else if y > max_y as isize - kernel_padding {
            let overshot_distance = y - max_y as isize + kernel_padding;
            y = max_y as isize - overshot_distance;
        }

        [y as usize, x as usize]
    }
}

#[derive(Copy, Clone)]
pub struct LinearInterpolationKernel;

impl Kernel<3> for LinearInterpolationKernel {
    fn values(&self) -> [[f32; 3]; 3] {
        [
            [1. / 16., 1. / 8., 1. / 16.],
            [1. / 8., 1. / 4., 1. / 8.],
            [1. / 16., 1. / 8., 1. / 16.],
        ]
    }

    fn size(&self) -> usize {
        3
    }
}

#[derive(Copy, Clone)]
pub struct LowScaleKernel;

impl Kernel<3> for LowScaleKernel {
    fn values(&self) -> [[f32; 3]; 3] {
        [
            [1. / 16., 1. / 8., 1. / 16.],
            [1. / 8., 10., 1. / 8.],
            [1. / 16., 1. / 8., 1. / 16.],
        ]
    }

    fn size(&self) -> usize {
        3
    }
}

#[derive(Copy, Clone)]
pub struct B3SplineKernel;

impl Kernel<5> for B3SplineKernel {
    fn values(&self) -> [[f32; 5]; 5] {
        [
            [1. / 256., 1. / 64., 3. / 128., 1. / 64., 1. / 256.],
            [1. / 64., 1. / 16., 3. / 32., 1. / 16., 1. / 64.],
            [3. / 128., 3. / 32., 9. / 64., 3. / 32., 3. / 128.],
            [1. / 64., 1. / 16., 3. / 32., 1. / 16., 1. / 64.],
            [1. / 256., 1. / 64., 3. / 128., 1. / 64., 1. / 256.],
        ]
    }

    fn size(&self) -> usize {
        5
    }
}