use crate::{Error, ScreenInfo, sys};
use std::path::Path;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
#[non_exhaustive]
pub enum ImageFormat {
#[default]
Png,
Avif,
Heif,
}
impl ImageFormat {
#[must_use]
pub const fn extension(&self) -> &'static str {
match self {
Self::Png => "png",
Self::Avif => "avif",
Self::Heif => "heic",
}
}
#[must_use]
pub const fn mime_type(&self) -> &'static str {
match self {
Self::Png => "image/png",
Self::Avif => "image/avif",
Self::Heif => "image/heic",
}
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct Screenshot {
data: Vec<u8>,
width: u32,
height: u32,
format: ImageFormat,
}
impl Screenshot {
#[cfg_attr(
target_arch = "wasm32",
expect(
dead_code,
reason = "browser screenshot capture is not exposed by the platform adapter"
)
)]
pub(crate) const fn new(data: Vec<u8>, width: u32, height: u32, format: ImageFormat) -> Self {
Self {
data,
width,
height,
format,
}
}
#[must_use]
pub fn data(&self) -> &[u8] {
&self.data
}
#[must_use]
pub fn into_data(self) -> Vec<u8> {
self.data
}
#[must_use]
pub const fn width(&self) -> u32 {
self.width
}
#[must_use]
pub const fn height(&self) -> u32 {
self.height
}
#[must_use]
pub const fn format(&self) -> ImageFormat {
self.format
}
pub fn save(&self, path: impl AsRef<Path>) -> Result<(), Error> {
std::fs::write(path, &self.data)?;
Ok(())
}
}
#[allow(clippy::missing_const_for_fn)] pub fn screenshot(display: &ScreenInfo, format: ImageFormat) -> Result<Screenshot, Error> {
sys::screenshot(display, format)
}
pub fn screenshot_primary(format: ImageFormat) -> Result<Screenshot, Error> {
let displays = crate::screens()?;
let primary = displays
.iter()
.find(|d| d.is_primary())
.or_else(|| displays.first())
.ok_or(Error::MonitorNotFound)?;
screenshot(primary, format)
}