use image::{ImageBuffer, Rgba};
use std::path::Path;
#[derive(Debug, Clone, Default)]
pub struct ScreenshotOptions {
pub transparent_background: bool,
}
pub fn save_image(
filename: &str,
data: &[u8],
width: u32,
height: u32,
) -> Result<(), ScreenshotError> {
let path = Path::new(filename);
let extension = path
.extension()
.and_then(|e| e.to_str())
.map(str::to_lowercase)
.unwrap_or_default();
let mut rgba_data = data.to_vec();
for chunk in rgba_data.chunks_exact_mut(4) {
chunk.swap(0, 2); }
let img: ImageBuffer<Rgba<u8>, Vec<u8>> =
ImageBuffer::from_raw(width, height, rgba_data).ok_or(ScreenshotError::InvalidImageData)?;
match extension.as_str() {
"png" => {
img.save_with_format(path, image::ImageFormat::Png)?;
}
"jpg" | "jpeg" => {
let rgb_img = image::DynamicImage::ImageRgba8(img).to_rgb8();
rgb_img.save_with_format(path, image::ImageFormat::Jpeg)?;
}
_ => {
return Err(ScreenshotError::UnsupportedFormat(extension));
}
}
Ok(())
}
pub fn save_to_buffer(data: &[u8], width: u32, height: u32) -> Result<Vec<u8>, ScreenshotError> {
let mut rgba_data = data.to_vec();
for chunk in rgba_data.chunks_exact_mut(4) {
chunk.swap(0, 2); }
let img: ImageBuffer<Rgba<u8>, Vec<u8>> =
ImageBuffer::from_raw(width, height, rgba_data).ok_or(ScreenshotError::InvalidImageData)?;
let mut buffer = std::io::Cursor::new(Vec::new());
img.write_to(&mut buffer, image::ImageFormat::Png)?;
Ok(buffer.into_inner())
}
#[derive(Debug, thiserror::Error)]
pub enum ScreenshotError {
#[error("Failed to save image: {0}")]
IoError(#[from] std::io::Error),
#[error("Image encoding error: {0}")]
ImageError(#[from] image::ImageError),
#[error("Unsupported image format: {0}")]
UnsupportedFormat(String),
#[error("Invalid image data")]
InvalidImageData,
#[error("GPU buffer mapping failed")]
BufferMapFailed,
}