#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum PixelFormat {
Argb32,
Bgra8,
Rgb565,
}
pub struct RgbaBuffer {
pub width: u32,
pub height: u32,
pub data: Vec<u8>,
}
impl RgbaBuffer {
pub fn has_content(&self) -> bool {
self.data.iter().any(|&b| b != 0)
}
pub fn save_png(&self, path: &std::path::Path) -> Result<(), crate::SoftRenderError> {
let file =
std::fs::File::create(path).map_err(|e| crate::SoftRenderError::Io(e.to_string()))?;
let buf_writer = std::io::BufWriter::new(file);
let mut encoder = png::Encoder::new(buf_writer, self.width, self.height);
encoder.set_color(png::ColorType::Rgba);
encoder.set_depth(png::BitDepth::Eight);
let mut writer = encoder
.write_header()
.map_err(|e| crate::SoftRenderError::Png(e.to_string()))?;
writer
.write_image_data(&self.data)
.map_err(|e| crate::SoftRenderError::Png(e.to_string()))
}
}
pub const HEADLESS_BG_COLOR: [u8; 4] = [26, 27, 38, 255];
pub fn render_headless_once(width: u32, height: u32) -> RgbaBuffer {
let bg = HEADLESS_BG_COLOR;
let data: Vec<u8> = (0..width * height)
.flat_map(|_| bg.iter().copied())
.collect();
RgbaBuffer {
width,
height,
data,
}
}
pub fn render_headless_scene<F>(width: u32, height: u32, draw_fn: F) -> RgbaBuffer
where
F: FnOnce(&mut crate::Canvas<'_>),
{
let bg = HEADLESS_BG_COLOR;
let mut fb =
crate::Framebuffer::with_fill(width, height, oxiui_core::Color(bg[0], bg[1], bg[2], bg[3]));
{
let mut canvas = crate::Canvas::new(&mut fb);
draw_fn(&mut canvas);
}
fb.to_rgba_buffer()
}