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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
pub fn rotate_90_clockwise(height: usize, width: usize, vector: Vec<u8>) -> Vec<u8> {
let (new_width, _new_height) = (height, width);
let mut output_image = vec![0; vector.len()];
for y in 0..height {
for x in 0..width {
let (new_x, new_y) = (new_width - 1 - y, x);
let input_pixel = y * width + x;
let output_pixel = new_y * new_width + new_x;
for z in 0..3 {
output_image[output_pixel * 3 + z] = vector[input_pixel * 3 + z];
}
}
}
output_image
}
pub fn rotate_90_counterclockwise(height: usize, width: usize, vector: Vec<u8>) -> Vec<u8> {
let (new_width, _new_height) = (height, width);
let mut output_image = vec![0; vector.len()];
for y in 0..height {
for x in 0..width {
let (new_x, new_y) = (y, _new_height - 1 - x);
let input_pixel = y * width + x;
let output_pixel = new_y * new_width + new_x;
for z in 0..3 {
output_image[output_pixel * 3 + z] = vector[input_pixel * 3 + z];
}
}
}
output_image
}
pub fn horz_gauss_blur<const N: usize>(
height: usize,
width: usize,
middle: usize,
kernel: [usize; N],
raw: &[u8],
) -> Vec<u8> {
assert_eq!(height * width * 3, raw.len());
let horz_vec: Vec<_> = raw
.chunks(width * 3)
.enumerate()
.map(|(_y, buffer)| {
let a = buffer[..middle * 3]
.chunks(3)
.map(|value| [value[0], value[1], value[2]]);
let b = (middle..(width - middle - 1)).map(move |x| {
let mut adding_red = 0;
let mut adding_green = 0;
let mut adding_blue = 0;
unsafe {
for (index, z) in kernel.iter().enumerate() {
let offset = (middle + x - index) * 3;
adding_red += *buffer.get_unchecked(offset) as usize * *z;
adding_green += *buffer.get_unchecked(offset + 1) as usize * *z;
adding_blue += *buffer.get_unchecked(offset + 2) as usize * *z;
}
}
adding_red /= 256;
adding_green /= 256;
adding_blue /= 256;
[adding_red as u8, adding_green as u8, adding_blue as u8]
});
let c = buffer[(width - middle - 1) * 3..]
.chunks(3)
.map(|value| [value[0], value[1], value[2]]);
a.chain(b).chain(c)
})
.flatten()
.flatten()
.collect();
horz_vec
}
pub fn blur<const N: usize>(
height: usize,
width: usize,
kernel: [usize; N],
raw: Vec<u8>,
) -> (Vec<u8>, usize, usize) {
let middle = kernel.len() / 2;
let raw = horz_gauss_blur(height, width, middle, kernel, &raw);
let raw = rotate_90_clockwise(height, width, raw);
let (width, height) = (height, width);
let raw = horz_gauss_blur(height, width, middle, kernel, &raw);
let raw = rotate_90_counterclockwise(height, width, raw);
let (width, height) = (height, width);
(raw, width, height)
}