use crate::signal::Blob;
use crate::config::{Config, Format};
use std::debug_assert_matches;
use std::fs::File;
use std::io::{self, Write};
use std::path::Path;
impl Blob<'_> {
pub fn dump<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
let path = path.as_ref();
eprintln!("dumping as `{}` at \"{}\"", self.config().format.as_str(), path.display());
let mut file = File::create_buffered(path)?;
match self.config().format {
Format::Png => {
Self::dump_png_frame(self.config(), self.data(), &mut file)?;
}
_ => {
unimplemented!();
}
}
Ok(())
}
fn dump_png_frame<W: ?Sized + Write>(config: &Config, data: &[u8], w: &mut W) -> io::Result<()> {
debug_assert_matches!(config.format, Format::Png);
let mut encoder = png::Encoder::new(w, config.width.into(), config.height.into());
let colour_type = match config.channel_count {
1 => png::ColorType::Grayscale,
2 => png::ColorType::GrayscaleAlpha,
3 => png::ColorType::Rgb,
4 => png::ColorType::Rgba,
count => {
unimplemented!("channel count of `{count}` is not supported for PNG");
}
};
let bit_depth = match config.sample_depth {
1 => png::BitDepth::Eight,
2 => png::BitDepth::Sixteen,
depth => {
unimplemented!("sampling depth of `{depth}B` is not supported for PNG");
}
};
encoder.set_color(colour_type);
encoder.set_depth(bit_depth);
let mut w = encoder.write_header()?;
w.write_image_data(data)?;
Ok(())
}
}