1use image::{Rgba, RgbaImage};
2use imageproc::{
3 drawing::{draw_filled_rect_mut, draw_line_segment_mut, draw_text_mut},
4 rect::Rect,
5};
6use rusttype::{Font, Scale};
7use screenshots::Screen;
8use std::error::Error;
9
10pub fn get_screen_size() -> Result<(u32, u32), &'static str> {
11 match Screen::all() {
12 Ok(screens) => match screens.get(0) {
13 Some(screen) => {
14 let width = screen.display_info.width;
15 let height = screen.display_info.height;
16 Ok((width, height))
17 }
18 None => Err("No screens found"),
19 },
20 Err(_) => Err("Failed to get screen information"),
21 }
22}
23
24pub fn capture_screen_with_cursor(file_path: &str) -> Result<(), String> {
25 let screens = Screen::all().map_err(|e| format!("Failed to get screens: {}", e))?;
26
27 let screen = screens.get(0).ok_or("No screens found")?;
28 let screenshot = screen
29 .capture()
30 .map_err(|e| format!("Failed to capture screen: {}", e))?;
31
32 screenshot
33 .save(file_path)
34 .map_err(|e| format!("Failed to save screenshot: {}", e))
35}
36
37pub fn add_grid_to_image(
38 original_image_path: &str,
39 new_image_path: &str,
40 grid_interval: i32,
41) -> Result<(), Box<dyn Error>> {
42 let image = image::open(original_image_path)?;
43
44 let image = image.into_rgba8();
45 let (width, height) = image.dimensions();
46 let mut draw = image;
47
48 let font_size = (grid_interval / 10) as u32;
49 let bg_width = (font_size as f32 * 6.5) as u32;
50 let bg_height = (font_size as f32 * 1.2) as u32;
51
52 for x in (grid_interval as u32..width).step_by(grid_interval as usize) {
54 for y in (grid_interval as u32..height).step_by(grid_interval as usize) {
55 draw_line_segment_mut(
56 &mut draw,
57 (x as f32, 0.0),
58 (x as f32, height as f32),
59 Rgba([0, 0, 255, 255]),
60 );
61
62 let x_percent = ((x as f32 / width as f32) * 100.0).round() as u32;
63 let y_percent = ((y as f32 / height as f32) * 100.0).round() as u32;
64 draw_label_with_background(
65 (x - bg_width / 2, y - bg_height / 2),
66 &format!("X={}%,Y={}%", x_percent, y_percent),
67 &mut draw,
68 bg_width,
69 bg_height,
70 font_size,
71 )?;
72 }
73 }
74
75 for y in (grid_interval as u32..height).step_by(grid_interval as usize) {
77 draw_line_segment_mut(
78 &mut draw,
79 (0.0, y as f32),
80 (width as f32, y as f32),
81 Rgba([0, 0, 255, 255]),
82 );
83 }
84
85 draw.save(new_image_path)?;
87
88 Ok(())
89}
90
91fn draw_label_with_background(
92 position: (u32, u32),
93 text: &str,
94 draw: &mut RgbaImage,
95 bg_width: u32,
96 bg_height: u32,
97 font_size: u32,
98) -> Result<(), String> {
99 let scale = Scale {
100 x: font_size as f32,
101 y: font_size as f32,
102 };
103
104 let font_data = include_bytes!("font/DejaVuSans.ttf") as &[u8];
105 let font =
106 Font::try_from_vec(font_data.to_vec()).ok_or_else(|| "Failed to load font".to_string())?;
107
108 let rect = Rect::at(position.0 as i32, position.1 as i32).of_size(bg_width, bg_height);
109 draw_filled_rect_mut(draw, rect, Rgba([255, 255, 255, 255]));
110
111 let x_position = position.0;
112 let y_position = position.1 + bg_height / 8;
113 draw_text_mut(
114 draw,
115 Rgba([0, 0, 0, 255]),
116 x_position as i32,
117 y_position as i32,
118 scale,
119 &font,
120 text,
121 );
122
123 Ok(())
124}