Files
pixelpwnr/src/image_manager.rs
2023-12-29 00:59:15 +01:00

106 lines
2.8 KiB
Rust

use rayon::prelude::*;
use std::path::Path;
use std::thread::sleep;
use std::time::Duration;
use image;
use image::imageops::FilterType;
use image::DynamicImage;
use pix::canvas::Canvas;
/// A manager that manages all images to print.
pub struct ImageManager {
images: Vec<DynamicImage>,
// Define whether the first image has been drawn
first: bool,
index: isize,
}
impl ImageManager {
/// Intantiate the image manager.
pub fn from(images: Vec<DynamicImage>) -> ImageManager {
ImageManager {
images,
first: false,
index: 0,
}
}
/// Instantiate the image manager, and load the images from the given paths.
pub fn load(paths: &[&str], size: (u16, u16)) -> ImageManager {
// Show a status message
println!("Load and process {} image(s)...", paths.len());
// Load the images from the paths
let image_manager = ImageManager::from(
paths
.par_iter()
.map(|path| load_image(path, size))
.collect(),
);
// TODO: process the image slices
// We succeeded
println!("All images have been loaded successfully");
image_manager
}
/// Tick the image
pub fn tick(&mut self, canvas: &mut Canvas) {
// Get the image index bound
let bound = self.images.len();
// Just return if the bound is one, as nothing should be updated
if self.first && bound == 1 {
return;
}
// Get the image to use
let image = &mut self.images[self.index as usize % bound];
// Update the image on the canvas
canvas.update_image(image);
// Increase the index
self.index += 1;
// We have rendered the first image
self.first = true;
}
/// Start working in the image manager.
///
/// This will start walking through all image frames,
/// and pushes each frame to all painters,
/// with the specified frames per second.
pub fn work(&mut self, canvas: &mut Canvas, fps: u32) {
loop {
// Tick to use the next image
self.tick(canvas);
// Sleep until we need to show the next image
sleep(Duration::from_millis((1000f32 / (fps as f32)) as u64));
}
}
}
/// Load the image at the given path, and size it correctly
fn load_image(path: &str, size: (u16, u16)) -> DynamicImage {
// Create a path instance
let path = Path::new(&path);
// Check whether the path exists
if !path.is_file() {
panic!("The given path does not exist or is not a file");
}
// Load the image
let image = image::open(path).unwrap();
// Resize the image to fit the screen
image.resize_exact(size.0 as u32, size.1 as u32, FilterType::Gaussian)
}