Skip to main content

create_thumbnail: rearrange the tests; unexport a couple of functions

ID
f89b9c8
date
2026-09-24 05:10:13+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
35224b6
message
create_thumbnail: rearrange the tests; unexport a couple of functions
changed files
1 file, 100 additions, 100 deletions

Changed files

src/create_thumbnail.rs (8803 → 8795)

diff --git a/src/create_thumbnail.rs b/src/create_thumbnail.rs
index eb0d5c8..04fe0c3 100644
--- a/src/create_thumbnail.rs
+++ b/src/create_thumbnail.rs
@@ -35,6 +35,106 @@ pub fn create_thumbnail(
     }
 }
 
+/// Create a thumbnail for an animated GIF.
+///
+/// This will use `ffmpeg` to create an MP4 file of the desired dimensions
+/// which plays the GIF on a loop.  This is typically much smaller and more
+/// space-efficient than creating a resized GIF.
+///
+/// This function assumes that the original GIF file definitely exists.
+///
+/// TODO: It would be nice to have a test for the case where `ffmpeg` isn't
+/// installed, but I'm not sure how to simulate that.
+///
+fn create_animated_gif_thumbnail(
+    gif_path: &PathBuf,
+    out_dir: &PathBuf,
+    width: u32,
+    height: u32,
+) -> Result<PathBuf, ThumbnailError> {
+    let file_name = gif_path
+        .file_name()
+        .ok_or(ThumbnailError::MissingFileName)?;
+
+    let thumbnail_path = out_dir.join(file_name).with_extension("mp4");
+
+    let gif_path_str = gif_path
+        .to_str()
+        .ok_or(ThumbnailError::PathConversionError)?;
+    let thumbnail_path_str = thumbnail_path
+        .to_str()
+        .ok_or(ThumbnailError::PathConversionError)?;
+
+    // There's a subtlety here with ffmpeg I don't understand fully -- if
+    // the width/height aren't even, it doesn't create the MP4, instead
+    // failing with the error:
+    //
+    //     width not divisible by 2
+    //
+    // I don't usually need these files to be pixel-perfect width, so
+    // fudging by a single pixel or two is fine.
+    let dimension_str = format!("scale={}:{}", ensure_even(width), ensure_even(height));
+
+    let output = Command::new("ffmpeg")
+        .args([
+            "-i",
+            gif_path_str,
+            "-movflags",
+            "faststart",
+            "-pix_fmt",
+            "yuv420p",
+            "-vf",
+            &dimension_str,
+            thumbnail_path_str,
+        ])
+        .output()
+        .map_err(|e| ThumbnailError::CommandFailed(format!("Failed to run ffmpeg: {}", e)))?;
+
+    if output.status.success() {
+        Ok(thumbnail_path)
+    } else {
+        let stderr = str::from_utf8(&output.stderr)?;
+        Err(ThumbnailError::CommandFailed(stderr.to_string()))
+    }
+}
+
+/// Return this value if it's even, or the closest value which is even.
+fn ensure_even(x: u32) -> u32 {
+    if x % 2 == 0 {
+        x
+    } else {
+        x + 1
+    }
+}
+
+/// Create a thumbnail for a static (non-animated) image.
+///
+/// This function assumes that the original image file definitely exists.
+///
+fn create_static_thumbnail(
+    image_path: &PathBuf,
+    out_dir: &PathBuf,
+    width: u32,
+    height: u32,
+) -> Result<PathBuf, ThumbnailError> {
+    let file_name = image_path
+        .file_name()
+        .ok_or(ThumbnailError::MissingFileName)?;
+
+    let thumbnail_path = out_dir.join(file_name);
+
+    let mut decoder = ImageReader::open(image_path)?.into_decoder()?;
+    let orientation = decoder.orientation()?;
+    let mut img = DynamicImage::from_decoder(decoder)?;
+    img.apply_orientation(orientation);
+
+    img.resize(width, height, FilterType::Lanczos3)
+        .save(&thumbnail_path)
+        .map_err(ThumbnailError::ImageSaveError)?;
+
+    Ok(thumbnail_path)
+}
+
 #[cfg(test)]
 mod test_create_thumbnail {
     use std::path::PathBuf;
@@ -161,103 +261,3 @@ mod test_create_thumbnail {
         assert_eq!(get_dimensions(&thumbnail_path), (180, 120));
     }
 }
-
-/// Return this value if it's even, or the closest value which is even.
-fn ensure_even(x: u32) -> u32 {
-    if x % 2 == 0 {
-        x
-    } else {
-        x + 1
-    }
-}
-
-/// Create a thumbnail for an animated GIF.
-///
-/// This will use `ffmpeg` to create an MP4 file of the desired dimensions
-/// which plays the GIF on a loop.  This is typically much smaller and more
-/// space-efficient than creating a resized GIF.
-///
-/// This function assumes that the original GIF file definitely exists.
-///
-/// TODO: It would be nice to have a test for the case where `ffmpeg` isn't
-/// installed, but I'm not sure how to simulate that.
-///
-pub fn create_animated_gif_thumbnail(
-    gif_path: &PathBuf,
-    out_dir: &PathBuf,
-    width: u32,
-    height: u32,
-) -> Result<PathBuf, ThumbnailError> {
-    let file_name = gif_path
-        .file_name()
-        .ok_or(ThumbnailError::MissingFileName)?;
-
-    let thumbnail_path = out_dir.join(file_name).with_extension("mp4");
-
-    let gif_path_str = gif_path
-        .to_str()
-        .ok_or(ThumbnailError::PathConversionError)?;
-    let thumbnail_path_str = thumbnail_path
-        .to_str()
-        .ok_or(ThumbnailError::PathConversionError)?;
-
-    // There's a subtlety here with ffmpeg I don't understand fully -- if
-    // the width/height aren't even, it doesn't create the MP4, instead
-    // failing with the error:
-    //
-    //     width not divisible by 2
-    //
-    // I don't usually need these files to be pixel-perfect width, so
-    // fudging by a single pixel or two is fine.
-    let dimension_str = format!("scale={}:{}", ensure_even(width), ensure_even(height));
-
-    let output = Command::new("ffmpeg")
-        .args([
-            "-i",
-            gif_path_str,
-            "-movflags",
-            "faststart",
-            "-pix_fmt",
-            "yuv420p",
-            "-vf",
-            &dimension_str,
-            thumbnail_path_str,
-        ])
-        .output()
-        .map_err(|e| ThumbnailError::CommandFailed(format!("Failed to run ffmpeg: {}", e)))?;
-
-    if output.status.success() {
-        Ok(thumbnail_path)
-    } else {
-        let stderr = str::from_utf8(&output.stderr)?;
-        Err(ThumbnailError::CommandFailed(stderr.to_string()))
-    }
-}
-
-/// Create a thumbnail for a static (non-animated) image.
-///
-/// This function assumes that the original image file definitely exists.
-///
-pub fn create_static_thumbnail(
-    image_path: &PathBuf,
-    out_dir: &PathBuf,
-    width: u32,
-    height: u32,
-) -> Result<PathBuf, ThumbnailError> {
-    let file_name = image_path
-        .file_name()
-        .ok_or(ThumbnailError::MissingFileName)?;
-
-    let thumbnail_path = out_dir.join(file_name);
-
-    let mut decoder = ImageReader::open(image_path)?.into_decoder()?;
-    let orientation = decoder.orientation()?;
-    let mut img = DynamicImage::from_decoder(decoder)?;
-    img.apply_orientation(orientation);
-
-    img.resize(width, height, FilterType::Lanczos3)
-        .save(&thumbnail_path)
-        .map_err(ThumbnailError::ImageSaveError)?;
-
-    Ok(thumbnail_path)
-}