stapix

Yet another static page generator for photo galleries

Commit
497770438ca689ac5654f3f2e07b7d4eeed4b31b
Parent
791bf7edf2bb285bc126af9baa3bfdde1a147479
Author
Pablo <pablo-escobar@riseup.net>
Date

Moved the rendering code back to the main file

Diffstat

2 files changed, 87 insertions, 93 deletions

Status File Name N° Changes Insertions Deletions
Modified src/main.rs 91 86 5
Modified src/picture.rs 89 1 88
diff --git a/src/main.rs b/src/main.rs
@@ -1,3 +1,5 @@
+use image::io::Reader as ImageReader;
+use image::DynamicImage;
 use std::env;
 use std::fmt::{self, Display};
 use std::fs::{self, File};
@@ -25,6 +27,14 @@ const PAGE_TITLE: &str = "Pablo&apos;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();
 
@@ -89,9 +99,6 @@ fn render_gallery(pics: Vec<Picture>) -> io::Result<()> {
     }
 
     // ========================================================================
-    let mut thumb_path = PathBuf::from(TARGET_PATH);
-    thumb_path.push(THUMBS_PATH);
-
     let rendering_pool = ThreadPool::with_name(
         String::from("thumbnails renderer"),
         num_cpus::get() + 1
@@ -101,9 +108,8 @@ fn render_gallery(pics: Vec<Picture>) -> io::Result<()> {
     for pic in &pics {
         let sender = sender.clone();
         let pic = pic.clone();
-        let thumb_path = thumb_path.clone();
         rendering_pool.execute(move || {
-            sender.send(pic.render_thumbnail(&thumb_path))
+            sender.send(render_thumbnail(pic))
                 .expect("channel should still be alive awaiting for the completion of this task");
         });
     }
@@ -314,6 +320,81 @@ fn usage_config() {
     eprintln!("   ...");
 }
 
+/// Returns `true` if rendering succeded (or was skipped) and `false`
+/// otherwise. All warinings and error messages should be logged in here.
+// TODO: Render GIF files as mp4 instead
+fn render_thumbnail(pic: Picture) -> bool {
+    let mut thumb_path = PathBuf::from(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)) {
+        let thumb_mod_date = thumb_meta.modified()
+            .expect("os should support file modification date");
+        let img_mod_date = img_meta.modified()
+            .expect("os should support file modification date");
+
+        if thumb_mod_date > img_mod_date {
+            println!("WARNING: Skipped rendering the WebP thumbnail for {name:?}.\nUpdate {path:?} to overwrite this behaviour",
+                     name = pic.file_name, path = pic.path);
+            return true;
+        }
+    }
+
+    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}");
+            return false;
+        }
+    };
+
+    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
+            );
+            return false;
+        }
+    };
+
+    let img = match img_reader.decode() {
+        Ok(img)  => img,
+        Err(err) => {
+            eprintln!(
+                "ERROR: Faileded to decode image file {name:?}: {err}",
+                name = pic.file_name
+            );
+            return false;
+        }
+    };
+
+    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}");
+        return false;
+    }
+
+    true
+}
+
 impl<'a> Display for Escaped<'a> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         for c in self.0.chars() {
diff --git a/src/picture.rs b/src/picture.rs
@@ -1,20 +1,8 @@
-use image::io::Reader as ImageReader;
-use image::DynamicImage;
 use serde::{
     de::{Deserializer, Error, Unexpected},
     Deserialize,
 };
-use std::fs::{self, File};
-use std::io::Write;
-use std::path::{PathBuf, Path};
-
-/// 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;
+use std::path::PathBuf;
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct Picture {
@@ -23,81 +11,6 @@ pub struct Picture {
     pub alt: String,
 }
 
-impl Picture {
-    // TODO: Render GIF files as mp4 instead
-    /// Returns `true` if rendering succeded (or was skipped) and `false`
-    /// otherwise. All warinings and error messages should be logged in here.
-    pub fn render_thumbnail(&self, target_dir: &Path) -> bool {
-        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)) {
-            let thumb_mod_date = thumb_meta.modified()
-                .expect("os should support file modification date");
-            let img_mod_date = img_meta.modified()
-                .expect("os should support file modification date");
-
-            if thumb_mod_date > img_mod_date {
-                println!("WARNING: Skipped rendering the WebP thumbnail for {name:?}.\nUpdate {path:?} to overwrite this behaviour",
-                         name = self.file_name, path = self.path);
-                return true;
-            }
-        }
-
-        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}");
-                return false;
-            }
-        };
-
-        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
-                );
-                return false;
-            }
-        };
-
-        let img = match img_reader.decode() {
-            Ok(img)  => img,
-            Err(err) => {
-                eprintln!(
-                    "ERROR: Faileded to decode image file {name:?}: {err}",
-                    name = self.file_name
-                );
-                return false;
-            }
-        };
-
-        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}");
-            return false;
-        }
-
-        true
-    }
-}
-
 impl<'de> Deserialize<'de> for Picture {
     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     where