use std::path::Path;
use anyhow::Result;
use rayon::prelude::*;
pub struct RgbaImage {
width: usize,
height: usize,
data: Box<[u8]>,
}
impl RgbaImage {
pub fn new(width: usize, height: usize) -> Self {
Self {
width,
height,
data: vec![0; width * height * 4].into_boxed_slice(),
}
}
pub fn fill_pixels(&mut self, op: impl Fn(usize, usize) -> (u8, u8, u8, u8) + Sync) {
self.data
.par_chunks_mut(4)
.enumerate()
.for_each(|(index, pixel)| {
let x = index % self.width;
let y = index / self.width;
let (r, g, b, a) = op(x, y);
pixel[0] = r;
pixel[1] = g;
pixel[2] = b;
pixel[3] = a;
});
}
pub fn save_webp(&self, path: impl AsRef<Path>) -> Result<()> {
let encoded = webp_encoder::webp_encode_lossless_rgba(&self.data, self.width, self.height)?;
std::fs::write(path, encoded.webp_file())?;
Ok(())
}
}