1#[cfg(feature = "background_image")]
2use edge_detection::Detection;
3
4use crate::types::point::Point;
5use crate::types::rect::Rect;
6
7#[cfg(feature = "background_image")]
8use image::{DynamicImage, GenericImageView, GrayImage, Rgba};
9
10pub type Dimensions = Rect<usize>;
14
15impl Dimensions {
16 pub fn from_wh(width: usize, height: usize) -> Self {
20 Rect {
21 min: Point::default(),
22 max: Point {
23 x: width,
24 y: height,
25 },
26 }
27 }
28}
29
30#[cfg(feature = "background_image")]
31pub(crate) fn canny_algorithm(image: &GrayImage, sigma: f32) -> Detection {
32 let det = edge_detection::canny(image.clone(), sigma, 0.3, 0.05);
33
34 det.as_image().save("canny.png").expect("save failed");
35
36 det
37}
38
39#[cfg(feature = "background_image")]
40pub(crate) fn average_color_for_rect(
41 image: &DynamicImage,
42 rect: &Rect<u32>,
43 default: Rgba<u8>,
44) -> Rgba<u8> {
45 if rect.max.x > image.width() || rect.max.y > image.height() {
46 return default;
47 }
48 let colors: Vec<[u8; 4]> = (rect.min.x..rect.max.x)
49 .flat_map(|x| {
50 (rect.min.y..rect.max.y)
51 .map(|y| image.get_pixel(x, y).0)
52 .collect::<Vec<[u8; 4]>>()
53 })
54 .collect();
55
56 if !colors.is_empty() {
57 let summed_red: usize =
58 (colors.iter().map(|c| c[0] as usize).sum::<usize>()) / colors.len();
59 let summed_green: usize =
60 colors.iter().map(|c| c[1] as usize).sum::<usize>() / colors.len();
61 let summed_blue: usize = colors.iter().map(|c| c[2] as usize).sum::<usize>() / colors.len();
62 let summed_alpha: usize =
63 colors.iter().map(|c| c[3] as usize).sum::<usize>() / colors.len();
64
65 Rgba([
66 summed_red as u8,
67 summed_green as u8,
68 summed_blue as u8,
69 summed_alpha as u8,
70 ])
71 } else {
72 default
73 }
74}
75
76#[cfg(feature = "background_image")]
77pub(crate) fn color_to_rgb_string(rgba: &Rgba<u8>) -> String {
78 format!("rgb({}, {}, {})", rgba.0[0], rgba.0[1], rgba.0[2],)
79}