iced_core/window/
screenshot.rs1use crate::{Bytes, Rectangle, Size};
3
4use std::fmt::{Debug, Formatter};
5
6#[derive(Clone)]
10pub struct Screenshot {
11 pub rgba: Bytes,
13 pub size: Size<u32>,
15 pub scale_factor: f32,
18}
19
20impl Debug for Screenshot {
21 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
22 write!(
23 f,
24 "Screenshot: {{ \n bytes: {}\n scale: {}\n size: {:?} }}",
25 self.rgba.len(),
26 self.scale_factor,
27 self.size
28 )
29 }
30}
31
32impl Screenshot {
33 pub fn new(rgba: impl Into<Bytes>, size: Size<u32>, scale_factor: f32) -> Self {
35 Self {
36 rgba: rgba.into(),
37 size,
38 scale_factor,
39 }
40 }
41
42 pub fn crop(&self, region: Rectangle<u32>) -> Result<Self, CropError> {
45 if region.width == 0 || region.height == 0 {
46 return Err(CropError::Zero);
47 }
48
49 if region.x + region.width > self.size.width || region.y + region.height > self.size.height
50 {
51 return Err(CropError::OutOfBounds);
52 }
53
54 const PIXEL_SIZE: usize = 4;
56
57 let bytes_per_row = self.size.width as usize * PIXEL_SIZE;
58 let row_range = region.y as usize..(region.y + region.height) as usize;
59 let column_range =
60 region.x as usize * PIXEL_SIZE..(region.x + region.width) as usize * PIXEL_SIZE;
61
62 let chopped =
63 self.rgba
64 .chunks(bytes_per_row)
65 .enumerate()
66 .fold(vec![], |mut acc, (row, bytes)| {
67 if row_range.contains(&row) {
68 acc.extend(&bytes[column_range.clone()]);
69 }
70
71 acc
72 });
73
74 Ok(Self {
75 rgba: Bytes::from(chopped),
76 size: Size::new(region.width, region.height),
77 scale_factor: self.scale_factor,
78 })
79 }
80}
81
82impl AsRef<[u8]> for Screenshot {
83 fn as_ref(&self) -> &[u8] {
84 &self.rgba
85 }
86}
87
88impl From<Screenshot> for Bytes {
89 fn from(screenshot: Screenshot) -> Self {
90 screenshot.rgba
91 }
92}
93
94#[derive(Debug, thiserror::Error)]
95pub enum CropError {
97 #[error("The cropped region is out of bounds.")]
98 OutOfBounds,
100 #[error("The cropped region is not visible.")]
101 Zero,
103}