auto_pilot/
screen.rs

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    // Draw vertical lines and labels
53    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    // Draw horizontal lines
76    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    // Save the image
86    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}