1use crate::errors::AutoGuiError;
7#[cfg(not(feature = "lite"))]
8use image::{
9 error::LimitError, DynamicImage, GrayImage, ImageBuffer, Luma, Pixel, Primitive, Rgb, Rgba,
10};
11#[cfg(not(feature = "lite"))]
12use rustfft::{num_complex::Complex, num_traits::ToPrimitive};
13
14#[cfg(not(feature = "lite"))]
15pub fn load_image_bw(location: &str) -> Result<ImageBuffer<Luma<u8>, Vec<u8>>, AutoGuiError> {
18 let img = image::ImageReader::open(location)?;
19
20 let img = img.decode()?;
21
22 let gray_image: ImageBuffer<Luma<u8>, Vec<u8>> = img.to_luma8();
23 Ok(gray_image)
24}
25#[cfg(not(feature = "lite"))]
26pub fn load_image_rgba(location: &str) -> Result<ImageBuffer<Rgba<u8>, Vec<u8>>, AutoGuiError> {
29 let img = image::ImageReader::open(location)?;
30 let img = img.decode()?;
31 Ok(img.to_rgba8()) }
33#[cfg(not(feature = "lite"))]
34pub fn check_imagebuffer_color_scheme<P, T>(
35 image: &ImageBuffer<P, Vec<T>>,
36) -> Result<u32, AutoGuiError>
37where
38 P: Pixel<Subpixel = T> + 'static,
39 T: Primitive + ToPrimitive + 'static,
40{
41 let buff_len = image.as_raw().len() as u32;
42 let (img_w, img_h) = image.dimensions();
43 if (img_w * img_h) == 0 {
44 let err = "Error: The buffer provided is empty and has no size".to_string();
45 return Err(AutoGuiError::ImgError(err));
46 }
47 Ok(buff_len / (img_w * img_h))
48}
49#[cfg(not(feature = "lite"))]
50pub fn convert_t_imgbuffer_to_luma<P, T>(
51 image: &ImageBuffer<P, Vec<T>>,
52 color_scheme: u32,
53) -> Result<ImageBuffer<Luma<u8>, Vec<u8>>, AutoGuiError>
54where
55 P: Pixel<Subpixel = T> + 'static,
56 T: Primitive + ToPrimitive + 'static,
57{
58 let (img_w, img_h) = image.dimensions();
59 match color_scheme {
60 1 => {
61 let raw_img: Result<Vec<u8>, AutoGuiError> = image
64 .as_raw()
65 .iter()
66 .map(|x| {
67 x.to_u8().ok_or(AutoGuiError::ImgError(
68 "Pixel conversion to raw failed".to_string(),
69 ))
70 })
71 .collect();
72
73 ImageBuffer::<Luma<u8>, Vec<u8>>::from_raw(img_w, img_h, raw_img?).ok_or(
74 AutoGuiError::ImgError("failed to convert to Luma".to_string()),
75 )
76 }
77 3 => {
78 let raw_img: Result<Vec<u8>, AutoGuiError> = image
80 .as_raw()
81 .iter()
82 .map(|x| {
83 x.to_u8().ok_or(AutoGuiError::ImgError(
84 "Pixel conversion to raw failed".to_string(),
85 ))
86 })
87 .collect();
88 let rgb_img = ImageBuffer::<Rgb<u8>, Vec<u8>>::from_raw(img_w, img_h, raw_img?).ok_or(
89 AutoGuiError::ImgError("Failed conversion to RGB".to_string()),
90 )?;
91 Ok(DynamicImage::ImageRgb8(rgb_img).to_luma8())
92 }
93 4 => {
94 let raw_img: Result<Vec<u8>, AutoGuiError> = image
96 .as_raw()
97 .iter()
98 .map(|x| {
99 x.to_u8().ok_or(AutoGuiError::ImgError(
100 "Pixel conversion to raw failed".to_string(),
101 ))
102 })
103 .collect();
104 let rgba_img = ImageBuffer::<Rgba<u8>, Vec<u8>>::from_raw(img_w, img_h, raw_img?)
105 .ok_or(AutoGuiError::ImgError(
106 "Failed conversion to RGBA".to_string(),
107 ))?;
108 Ok(DynamicImage::ImageRgba8(rgba_img).to_luma8())
109 }
110 _ => Err(AutoGuiError::ImgError(
111 "Unknown image format. Load works only for Rgb/Rgba/Luma(BW) formats".to_string(),
112 )),
113 }
114}
115#[cfg(not(feature = "lite"))]
116pub fn convert_rgba_to_bw(
118 image: ImageBuffer<Rgba<u8>, Vec<u8>>,
119) -> Result<ImageBuffer<Luma<u8>, Vec<u8>>, AutoGuiError> {
120 let (img_w, img_h) = image.dimensions();
121 let raw_img: Result<Vec<u8>, AutoGuiError> = image
122 .as_raw()
123 .iter()
124 .map(|x| {
125 x.to_u8().ok_or(AutoGuiError::ImgError(
126 "Pixel conversion to raw failed".to_string(),
127 ))
128 })
129 .collect();
130 let rgba_img = ImageBuffer::<Rgba<u8>, Vec<u8>>::from_raw(img_w, img_h, raw_img?).ok_or(
131 AutoGuiError::ImgError("Failed to convert to RGBA".to_string()),
132 )?;
133 Ok(DynamicImage::ImageRgba8(rgba_img).to_luma8())
134}
135#[cfg(not(feature = "lite"))]
136pub fn convert_rgba_to_bw_old(
138 image: ImageBuffer<Rgba<u8>, Vec<u8>>,
139) -> Result<ImageBuffer<Luma<u8>, Vec<u8>>, AutoGuiError> {
140 let mut grayscale_data: Vec<u8> = Vec::with_capacity(image.len());
141 let image_width = image.width();
142 let image_height = image.height();
143 for chunk in image.chunks_exact(4) {
144 let r = chunk[2] as u32;
145 let g = chunk[1] as u32;
146 let b = chunk[0] as u32;
147 let gray_value = ((r * 30 + g * 59 + b * 11) / 100) as u8;
149 grayscale_data.push(gray_value);
150 }
151 GrayImage::from_raw(image_width, image_height, grayscale_data).ok_or(AutoGuiError::ImgError(
152 "Failed to convert to grayscale".to_string(),
153 ))
154}
155
156#[cfg(not(feature = "lite"))]
157pub fn cut_screen_region<T>(
161 x: u32,
162 y: u32,
163 width: u32,
164 height: u32,
165 screen_image: &ImageBuffer<T, Vec<u8>>,
166) -> ImageBuffer<T, Vec<u8>>
167where
168 T: Pixel<Subpixel = u8> + 'static,
169{
170 assert!(x + width <= screen_image.width());
171 assert!(y + height <= screen_image.height());
172
173 let mut sub_image: ImageBuffer<T, Vec<u8>> = ImageBuffer::new(width, height);
174
175 for y_sub in 0..height {
177 for x_sub in 0..width {
178 let pixel = screen_image.get_pixel(x + x_sub, y + y_sub);
179 sub_image.put_pixel(x_sub, y_sub, *pixel);
180 }
181 }
182 sub_image
183}
184
185#[cfg(not(feature = "lite"))]
186pub fn imagebuffer_to_vec<T: Copy + Primitive + 'static>(
188 image: &ImageBuffer<Luma<T>, Vec<T>>,
189) -> Vec<Vec<T>> {
190 let (width, height) = image.dimensions();
191 let zero_pixel = image.get_pixel(0, 0)[0];
192 let mut vec: Vec<Vec<T>> = vec![vec![zero_pixel; width as usize]; height as usize];
193
194 for y in 0..height {
195 for x in 0..width {
196 vec[y as usize][x as usize] = image.get_pixel(x, y)[0];
197 }
198 }
199 vec
200}