Skip to main content

manifold/
img.rs

1// Image I/O: decode JPEG/PNG to RGB8, encode PNG. Thin shim over image + png crates.
2
3use crate::codec::Dims;
4use crate::error::{Error, Result};
5use std::io::BufWriter;
6use std::path::Path;
7
8/// Loaded image: RGB8 pixels + dims.
9pub struct Image {
10    /// Width in pixels.
11    pub width: u32,
12    /// Height in pixels.
13    pub height: u32,
14    /// RGB8, row-major (w*h*3).
15    pub pixels: Vec<u8>, // RGB8, row-major
16}
17
18/// Load a JPEG/PNG file as RGB8 (exactness caveat: JPEG is lossy upstream).
19pub fn load(path: &Path) -> Result<Image> {
20    let img = image::open(path).map_err(|e| Error::ImageIo(e.to_string()))?;
21    let rgb = img.to_rgb8();
22    Ok(Image {
23        width: rgb.width(),
24        height: rgb.height(),
25        pixels: rgb.into_raw(),
26    })
27}
28
29/// Write PNG from RGB8.
30pub fn save_png(path: &Path, dims: Dims, pixels: &[u8]) -> Result<()> {
31    let f = std::fs::File::create(path)?;
32    let bw = BufWriter::new(f);
33    let mut enc = png::Encoder::new(bw, dims.width, dims.height);
34    enc.set_color(png::ColorType::Rgb);
35    enc.set_depth(png::BitDepth::Eight);
36    let mut writer = enc
37        .write_header()
38        .map_err(|e| Error::ImageIo(format!("png header: {e}")))?;
39    writer
40        .write_image_data(pixels)
41        .map_err(|e| Error::ImageIo(format!("png data: {e}")))?;
42    Ok(())
43}
44
45/// In-memory PNG encode for size benchmarks.
46pub fn encode_png(dims: Dims, pixels: &[u8]) -> Result<Vec<u8>> {
47    let mut buf = Vec::new();
48    {
49        let mut enc = png::Encoder::new(&mut buf, dims.width, dims.height);
50        enc.set_color(png::ColorType::Rgb);
51        enc.set_depth(png::BitDepth::Eight);
52        let mut writer = enc
53            .write_header()
54            .map_err(|e| Error::ImageIo(format!("png header: {e}")))?;
55        writer
56            .write_image_data(pixels)
57            .map_err(|e| Error::ImageIo(format!("png data: {e}")))?;
58    }
59    Ok(buf)
60}