1use crate::{error, util};
4use crate::error::ImgProcResult;
5use crate::image::{Image, BaseImage};
6
7pub fn erode(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
10 error::check_grayscale(input)?;
11
12 let (width, height) = input.info().wh();
13 let size = 2 * radius + 1;
14 let max_sum = (size * size * 255) as f32;
15 let table = util::generate_summed_area_table(&input.clone().into());
16 let mut output = Image::blank(input.info());
17
18 for y in 0..height {
19 for x in 0..width {
20 let mut x_top = x;
21 let mut x_bot = x;
22 let mut y_top = y;
23 let mut y_bot = y;
24
25 if x >= radius {
26 x_top -= radius;
27 }
28 if x < width - radius {
29 x_bot += radius;
30 }
31 if y >= radius {
32 y_top -= radius;
33 }
34 if y < height - radius {
35 y_bot += radius;
36 }
37
38 if (util::rectangular_intensity_sum(&table, x_top, y_top, x_bot, y_bot)[0] - max_sum).abs() < f32::EPSILON {
39 output.set_pixel(x, y, &[255]);
40 }
41 }
42 }
43
44 Ok(output)
45}
46
47pub fn dilate(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
50 error::check_grayscale(input)?;
51
52 let (width, height) = input.info().wh();
53 let table = util::generate_summed_area_table(&input.clone().into());
54 let mut output = Image::blank(input.info());
55
56 for y in 0..height {
57 for x in 0..width {
58 let mut x_top = x;
59 let mut x_bot = x;
60 let mut y_top = y;
61 let mut y_bot = y;
62
63 if x >= radius {
64 x_top -= radius;
65 }
66 if x < width - radius {
67 x_bot += radius;
68 }
69 if y >= radius {
70 y_top -= radius;
71 }
72 if y < height - radius {
73 y_bot += radius;
74 }
75
76 if util::rectangular_intensity_sum(&table, x_top, y_top, x_bot, y_bot)[0] >= 255.0 {
77 output.set_pixel(x, y, &[255]);
78 }
79 }
80 }
81
82 Ok(output)
83}
84
85pub fn majority(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
88 error::check_grayscale(input)?;
89
90 let (width, height) = input.info().wh();
91 let table = util::generate_summed_area_table(&input.clone().into());
92 let mut output = Image::blank(input.info());
93
94 for y in 0..height {
95 for x in 0..width {
96 let mut x_top = x;
97 let mut x_bot = x;
98 let mut y_top = y;
99 let mut y_bot = y;
100
101 if x >= radius {
102 x_top -= radius;
103 }
104 if x < width - radius {
105 x_bot += radius;
106 }
107 if y >= radius {
108 y_top -= radius;
109 }
110 if y < height - radius {
111 y_bot += radius;
112 }
113
114 if util::rectangular_intensity_sum(&table, x_top, y_top, x_bot, y_bot)[0] >= 255.0 {
115 output.set_pixel(x, y, &[255]);
116 }
117 }
118 }
119
120 Ok(output)
121}
122
123pub fn open(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
125 Ok(dilate(&erode(input, radius)?, radius)?)
126}
127
128pub fn close(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
130 Ok(erode(&dilate(input, radius)?, radius)?)
131}
132
133#[allow(unused_parens)]
135pub fn gradient(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
136 error::check_grayscale(input)?;
137
138 let (width, height) = input.info().wh();
139 let size = 2 * radius + 1;
140 let max_sum = (size * size * 255) as f32;
141 let table = util::generate_summed_area_table(&input.clone().into());
142 let mut output = Image::blank(input.info());
143
144 for y in 0..height {
145 for x in 0..width {
146 let mut x_top = x;
147 let mut x_bot = x;
148 let mut y_top = y;
149 let mut y_bot = y;
150
151 if x >= radius {
152 x_top -= radius;
153 }
154 if x < width - radius {
155 x_bot += radius;
156 }
157 if y >= radius {
158 y_top -= radius;
159 }
160 if y < height - radius {
161 y_bot += radius;
162 }
163
164 let sum = util::rectangular_intensity_sum(&table, x_top, y_top, x_bot, y_bot)[0];
165 let erode = ((sum - max_sum).abs() < f32::EPSILON);
166 let dilate = (sum >= 255.0);
167
168 if erode ^ dilate {
169 output.set_pixel(x, y, &[255]);
170 }
171 }
172 }
173
174 Ok(output)
175}