Add support for loading GIF files directly

This commit is contained in:
timvisee
2023-12-30 14:15:23 +01:00
parent 46fd802c6b
commit 708cd2794f

View File

@@ -1,11 +1,13 @@
use image::codecs::gif::GifDecoder;
use rayon::prelude::*; use rayon::prelude::*;
use std::fs::File;
use std::path::Path; use std::path::Path;
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use crate::pix::canvas::Canvas; use crate::pix::canvas::Canvas;
use image::imageops::FilterType; use image::imageops::FilterType;
use image::DynamicImage; use image::{AnimationDecoder, DynamicImage};
/// A manager that manages all images to print. /// A manager that manages all images to print.
pub struct ImageManager { pub struct ImageManager {
@@ -34,7 +36,7 @@ impl ImageManager {
let image_manager = ImageManager::from( let image_manager = ImageManager::from(
paths paths
.par_iter() .par_iter()
.map(|path| load_image(path, size)) .flat_map(|path| load_image(path, size))
.collect(), .collect(),
); );
@@ -86,7 +88,7 @@ impl ImageManager {
} }
/// Load the image at the given path, and size it correctly /// Load the image at the given path, and size it correctly
fn load_image(path: &str, size: (u16, u16)) -> DynamicImage { fn load_image(path: &str, size: (u16, u16)) -> Vec<DynamicImage> {
// Create a path instance // Create a path instance
let path = Path::new(&path); let path = Path::new(&path);
@@ -95,9 +97,30 @@ fn load_image(path: &str, size: (u16, u16)) -> DynamicImage {
panic!("The given path does not exist or is not a file"); panic!("The given path does not exist or is not a file");
} }
// Load the image let extension = path
let image = image::open(path).unwrap(); .extension()
.and_then(|e| e.to_str())
.map(|e| e.to_lowercase());
// Resize the image to fit the screen // Load image(s)
image.resize_exact(size.0 as u32, size.1 as u32, FilterType::Gaussian) let images = match extension.as_deref() {
// Load all GIF frames
Some("gif") => GifDecoder::new(File::open(path).unwrap())
.expect("failed to decode GIF file")
.into_frames()
.collect_frames()
.expect("failed to parse GIF frames")
.into_iter()
.map(|frame| DynamicImage::ImageRgba8(frame.into_buffer()))
.collect(),
// Load single image
_ => vec![image::open(path).unwrap()],
};
// Resize images to fit the screen
images
.into_iter()
.map(|image| image.resize_exact(size.0 as u32, size.1 as u32, FilterType::Gaussian))
.collect()
} }