use crate::SubtileError;
use image::{EncodableLayout, Pixel, PixelWithColorType};
use std::{
borrow::Borrow,
fs::create_dir_all,
io,
ops::Deref,
path::{Path, PathBuf},
};
use thiserror::Error;
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum DumpError {
#[error("could not create path for dump images '{}'", path.display())]
Folder {
path: PathBuf,
source: io::Error,
},
#[error("could not write image dump file '{}'", filename.display())]
DumpImage {
filename: PathBuf,
source: image::ImageError,
},
}
#[profiling::function]
pub fn dump_images<'a, Iter, Img, P, Container>(
path: &str,
images: Iter,
) -> Result<(), SubtileError>
where
P: Pixel + PixelWithColorType + 'a,
[P::Subpixel]: EncodableLayout,
Container: Deref<Target = [P::Subpixel]> + 'a,
Img: Borrow<image::ImageBuffer<P, Container>>,
Iter: IntoIterator<Item = Img>,
{
let folder_path = PathBuf::from(path);
if !folder_path.is_dir() {
create_dir_all(folder_path.as_path()).map_err(|source| DumpError::Folder {
path: folder_path.clone(),
source,
})?;
}
images
.into_iter()
.enumerate()
.try_for_each(move |(i, img)| {
let filepath = folder_path.clone().join(format!("{i:06}.png"));
dump_image(&filepath, img.borrow()).map_err(|source| DumpError::DumpImage {
filename: filepath,
source,
})
})?;
Ok(())
}
#[profiling::function]
fn dump_image<P, Pix, Container>(
filename: P,
image: &image::ImageBuffer<Pix, Container>, ) -> Result<(), image::ImageError>
where
P: AsRef<Path>,
Pix: Pixel + PixelWithColorType,
[Pix::Subpixel]: EncodableLayout,
Container: Deref<Target = [Pix::Subpixel]>,
{
image.save(filename)
}