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(
35 rgba: impl Into<Bytes>,
36 size: Size<u32>,
37 scale_factor: f32,
38 ) -> Self {
39 Self {
40 rgba: rgba.into(),
41 size,
42 scale_factor,
43 }
44 }
45
46 pub fn crop(&self, region: Rectangle<u32>) -> Result<Self, CropError> {
49 if region.width == 0 || region.height == 0 {
50 return Err(CropError::Zero);
51 }
52
53 if region.x + region.width > self.size.width
54 || region.y + region.height > self.size.height
55 {
56 return Err(CropError::OutOfBounds);
57 }
58
59 const PIXEL_SIZE: usize = 4;
61
62 let bytes_per_row = self.size.width as usize * PIXEL_SIZE;
63 let row_range = region.y as usize..(region.y + region.height) as usize;
64 let column_range = region.x as usize * PIXEL_SIZE
65 ..(region.x + region.width) as usize * PIXEL_SIZE;
66
67 let chopped = self.rgba.chunks(bytes_per_row).enumerate().fold(
68 vec![],
69 |mut acc, (row, bytes)| {
70 if row_range.contains(&row) {
71 acc.extend(&bytes[column_range.clone()]);
72 }
73
74 acc
75 },
76 );
77
78 Ok(Self {
79 rgba: Bytes::from(chopped),
80 size: Size::new(region.width, region.height),
81 scale_factor: self.scale_factor,
82 })
83 }
84}
85
86impl AsRef<[u8]> for Screenshot {
87 fn as_ref(&self) -> &[u8] {
88 &self.rgba
89 }
90}
91
92impl From<Screenshot> for Bytes {
93 fn from(screenshot: Screenshot) -> Self {
94 screenshot.rgba
95 }
96}
97
98#[derive(Debug, thiserror::Error)]
99pub enum CropError {
101 #[error("The cropped region is out of bounds.")]
102 OutOfBounds,
104 #[error("The cropped region is not visible.")]
105 Zero,
107}