- Commit
- fc9009e6359bae934c6429aebd389846669d5b63
- Parent
- fe35f1247de21a19dac98f566076deb1de6ddce5
- Author
- Pablo <pablo-escobar@riseup.net>
- Date
Moved the code to render the thumbnails to the types module
Custum build of stapix for tikz.pablopie.xyz
Moved the code to render the thumbnails to the types module
2 files changed, 83 insertions, 78 deletions
Status | File Name | N° Changes | Insertions | Deletions |
Modified | src/main.rs | 82 | 4 | 78 |
Modified | src/types.rs | 79 | 79 | 0 |
diff --git a/src/main.rs b/src/main.rs @@ -1,5 +1,3 @@ -use image::io::Reader as ImageReader; -use image::DynamicImage; use std::env; use std::fs::{self, File}; use std::io::{self, Write}; @@ -21,14 +19,6 @@ const PAGE_TITLE: &str = "Pablo's Photo Gallery"; const AUTHOR: &str = "Pablo"; const LICENSE: &str = "GPLv3"; -/// WebP image quality -const IMAGE_QUALITY: f32 = 50.0; - -/// Target height of the thumbnails, depending on wether the image is vertical -/// or horizontal -const HORIZONTAL_THUMB_HEIGHT: u32 = 300; -const VERTICAL_THUMB_HEIGHT: u32 = 800; - fn main() -> io::Result<()> { let args: Vec<String> = env::args().collect(); @@ -93,8 +83,11 @@ fn render_gallery(pic_infos: Vec<PictureInfo>) -> io::Result<()> { } // TODO: Parallelize this + let mut thumb_path = PathBuf::new(); + thumb_path.push(TARGET_PATH); + thumb_path.push(THUMBS_PATH); for pic in &pic_infos { - render_thumbnail(pic)?; + pic.render_thumbnail(&thumb_path)?; } render_index(&pic_infos)?; @@ -210,73 +203,6 @@ fn render_pic_page(pic: &PictureInfo) -> io::Result<()> { writeln!(f, "</html>") } -fn render_thumbnail(pic: &PictureInfo) -> io::Result<()> { - let mut thumb_path = PathBuf::new(); - thumb_path.push(TARGET_PATH); - thumb_path.push(THUMBS_PATH); - thumb_path.push(pic.file_name.clone() + ".webp"); - - // Only try to render thumbnail in case the thumbnail file in the machine - // is older than the source file - if let (Ok(thumb_meta), Ok(img_meta)) = (fs::metadata(&thumb_path), fs::metadata(&pic.path)) { - if thumb_meta.modified()? > img_meta.modified()? { - // TODO: Report a warning to the user - return Ok(()); - } - } - - let mut thumb_file = match File::create(&thumb_path) { - Ok(f) => f, - Err(err) => { - eprintln!("ERROR: Couldn't open WebP thumbnail file {thumb_path:?}: {err}"); - exit(1); - } - }; - - let img_reader = match ImageReader::open(&pic.path) { - Ok(r) => r, - Err(err) => { - eprintln!( - "ERROR: Couldn't open file {path:?} to render WebP thumbnail: {err}", - path = pic.file_name - ); - exit(1); - } - }; - - let img = match img_reader.decode() { - Ok(img) => img, - Err(err) => { - eprintln!( - "ERROR: Failed to decode image file {name:?}: {err}", - name = pic.file_name - ); - exit(1); - } - }; - - let h = if img.width() > img.height() { - HORIZONTAL_THUMB_HEIGHT - } else { - VERTICAL_THUMB_HEIGHT - }; - let w = (h * img.width()) / img.height(); - - // We should make sure that the image is in the RGBA8 format so that - // the webp crate can encode it - let img = DynamicImage::from(img.thumbnail(w, h).into_rgba8()); - let mem = webp::Encoder::from_image(&img) - .expect("image should be in the RGBA8 format") - .encode(IMAGE_QUALITY); - - if let Err(err) = thumb_file.write_all(&mem) { - eprintln!("ERROR: Couldn't write WebP thumnail to file {thumb_path:?}: {err}"); - exit(1); - } - - Ok(()) -} - fn write_nav(f: &mut File) -> io::Result<()> { writeln!(f, "<header>")?; writeln!(f, "<nav>")?;
diff --git a/src/types.rs b/src/types.rs @@ -1,9 +1,22 @@ +use image::io::Reader as ImageReader; +use image::DynamicImage; use serde::{ de::{Deserializer, Error, Unexpected}, Deserialize, }; use std::fmt::{self, Display}; +use std::fs::{self, File}; +use std::io::{self, Write}; use std::path::PathBuf; +use std::process::exit; + +/// WebP image quality +const IMAGE_QUALITY: f32 = 50.0; + +/// Target height of the thumbnails, depending on wether the image is vertical +/// or horizontal +const HORIZONTAL_THUMB_HEIGHT: u32 = 300; +const VERTICAL_THUMB_HEIGHT: u32 = 800; #[derive(Debug, Clone, PartialEq, Eq)] pub struct PictureInfo { @@ -14,6 +27,72 @@ pub struct PictureInfo { pub struct Escaped<'a>(pub &'a str); +impl PictureInfo { + pub fn render_thumbnail(&self, target_dir: &PathBuf) -> io::Result<()> { + let thumb_path = target_dir.join(self.file_name.clone() + ".webp"); + + // Only try to render thumbnail in case the thumbnail file in the machine + // is older than the source file + if let (Ok(thumb_meta), Ok(img_meta)) = (fs::metadata(&thumb_path), fs::metadata(&self.path)) { + if thumb_meta.modified()? > img_meta.modified()? { + // TODO: Report a warning to the user + return Ok(()); + } + } + + let mut thumb_file = match File::create(&thumb_path) { + Ok(f) => f, + Err(err) => { + eprintln!("ERROR: Couldn't open WebP thumbnail file {thumb_path:?}: {err}"); + exit(1); + } + }; + + let img_reader = match ImageReader::open(&self.path) { + Ok(r) => r, + Err(err) => { + eprintln!( + "ERROR: Couldn't open file {path:?} to render WebP thumbnail: {err}", + path = self.file_name + ); + exit(1); + } + }; + + let img = match img_reader.decode() { + Ok(img) => img, + Err(err) => { + eprintln!( + "ERROR: Failed to decode image file {name:?}: {err}", + name = self.file_name + ); + exit(1); + } + }; + + let h = if img.width() > img.height() { + HORIZONTAL_THUMB_HEIGHT + } else { + VERTICAL_THUMB_HEIGHT + }; + let w = (h * img.width()) / img.height(); + + // We should make sure that the image is in the RGBA8 format so that + // the webp crate can encode it + let img = DynamicImage::from(img.thumbnail(w, h).into_rgba8()); + let mem = webp::Encoder::from_image(&img) + .expect("image should be in the RGBA8 format") + .encode(IMAGE_QUALITY); + + if let Err(err) = thumb_file.write_all(&mem) { + eprintln!("ERROR: Couldn't write WebP thumnail to file {thumb_path:?}: {err}"); + exit(1); + } + + Ok(()) + } +} + impl<'de> Deserialize<'de> for PictureInfo { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where