diff --git a/src/image_provider.rs b/src/image_provider.rs new file mode 100644 index 0000000..d42ea08 --- /dev/null +++ b/src/image_provider.rs @@ -0,0 +1,73 @@ +use crate::dimensions::{calculate_resize_dimensions, Dimensions}; +use image::ImageReader; +use macroquad::texture::Texture2D; +use std::path::PathBuf; +use walkdir::WalkDir; + +pub struct ImageProvider { + path: PathBuf, + directory_it: Box>>, + texture: Option, + screen_dimension: Dimensions, +} + +impl ImageProvider { + pub fn new(screen_dimension: Dimensions, path: PathBuf) -> Self { + Self { + directory_it: Box::new(WalkDir::new(&path).max_open(8).into_iter()), + texture: None, + screen_dimension, + path, + } + } + + pub fn load_next_image(&mut self) -> anyhow::Result<()> { + let path = self.get_next_image_path()?; + let image = ImageReader::open(path)?.decode()?; + + let image_dim = Dimensions::new(image.width(), image.height()); + let new_dim = calculate_resize_dimensions(self.screen_dimension, image_dim); + + let image = image.resize( + new_dim.width, + new_dim.height, + image::imageops::FilterType::Lanczos3, + ); + + self.texture = Some(Texture2D::from_rgba8( + image.width().try_into()?, + image.height().try_into()?, + &image.into_rgba8(), + )); + + Ok(()) + } + + pub fn get_current_texture(&self) -> anyhow::Result<&Texture2D> { + self.texture + .as_ref() + .ok_or_else(|| anyhow::anyhow!("No image loaded")) + } + + fn get_next_image_path(&mut self) -> anyhow::Result { + loop { + match self.directory_it.next() { + Some(Ok(entry)) => { + if entry.file_type().is_file() + && entry + .path() + .extension() + .is_some_and(|ext| ext == "jpg" || ext == "jpeg" || ext == "png") + { + return Ok(entry.path().to_path_buf()); + } + } + Some(Err(e)) => return Err(e.into()), + None => { + // Reset the iterator when we reach the end + self.directory_it = Box::new(WalkDir::new(&self.path).max_open(8).into_iter()); + } + } + } + } +}