From d74a8117d758aa66664f514710f49f1de65ba719 Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Mon, 17 Feb 2020 17:50:43 -0800 Subject: [PATCH] Refactor thumbnail generation. --- src/library.rs | 75 ++++++++++++++++++++++++++------------------------ src/web.rs | 1 + 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/library.rs b/src/library.rs index 40c52d8..afefd54 100644 --- a/src/library.rs +++ b/src/library.rs @@ -6,6 +6,8 @@ use std::path::PathBuf; use std::sync::Arc; use google_photoslibrary1 as photos; +use image::imageops::FilterType; +use image::ImageFormat; use log::error; use log::info; use log::warn; @@ -16,7 +18,7 @@ use rocksdb::IteratorMode; use rocksdb::DB; // Used to ensure DB is invalidated after schema changes. -const LIBRARY_GENERATION: &'static str = "2"; +const LIBRARY_GENERATION: &'static str = "5"; #[derive(Clone)] pub struct Library { @@ -143,36 +145,35 @@ impl Library { fn generational_key(generation: &str, key: &str) -> String { format!("{}/{}", generation, key) } - pub fn thumbnail(&self, media_items_id: &str, dimensions: (u32, u32)) -> Option> { - fn generate_thumbnail( - lib: &Library, - media_items_id: &str, - dimensions: (u32, u32), - ) -> Result, io::Error> { - let (w, h) = dimensions; - match lib.original(&media_items_id) { - None => { - warn!("Couldn't find original {}", &media_items_id); - Err(io::Error::new( - io::ErrorKind::NotFound, - format!("{}", media_items_id), - )) - } - Some(path) => { - let orig_img = image::io::Reader::open(&path)? - .with_guessed_format()? - .decode() - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - // TODO (wathiede) resize..fill - let img = - orig_img.resize_to_fill(w, h, image::imageops::FilterType::CatmullRom); - let mut buf = Vec::new(); - img.write_to(&mut buf, image::ImageFormat::Jpeg) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - Ok(buf) - } + pub fn generate_thumbnail( + &self, + media_items_id: &str, + dimensions: (u32, u32), + filter: FilterType, + ) -> Result, io::Error> { + let (w, h) = dimensions; + match self.original(&media_items_id) { + None => { + warn!("Couldn't find original {}", &media_items_id); + Err(io::Error::new( + io::ErrorKind::NotFound, + format!("{}", media_items_id), + )) + } + Some(path) => { + let orig_img = image::io::Reader::open(&path)? + .with_guessed_format()? + .decode() + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + let img = orig_img.resize_to_fill(w, h, filter); + let mut buf = Vec::new(); + img.write_to(&mut buf, ImageFormat::Jpeg) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + Ok(buf) } } + } + pub fn thumbnail(&self, media_items_id: &str, dimensions: (u32, u32)) -> Option> { fn cache_key(media_items_id: &str, dimensions: (u32, u32)) -> String { let (w, h) = dimensions; Library::generational_key( @@ -191,13 +192,15 @@ impl Library { // Cache miss, fill cache and return. Ok(None) => { info!("cache MISS {}", key); - let bytes = match generate_thumbnail(self, media_items_id, dimensions) { - Ok(bytes) => bytes, - Err(e) => { - error!("Failed to generate thumbnail for {}: {}", media_items_id, e); - return None; - } - }; + let bytes = + match self.generate_thumbnail(media_items_id, dimensions, FilterType::Lanczos3) + { + Ok(bytes) => bytes, + Err(e) => { + error!("Failed to generate thumbnail for {}: {}", media_items_id, e); + return None; + } + }; match db.put(key.as_bytes(), &bytes) { Ok(_) => Some(bytes), Err(e) => { diff --git a/src/web.rs b/src/web.rs index d1a93f8..fed5daf 100644 --- a/src/web.rs +++ b/src/web.rs @@ -80,6 +80,7 @@ fn image( media_items_id: String, params: ImageParams, ) -> Result { + // TODO(wathiede): add caching headers. match lib.thumbnail( &media_items_id, (params.w.unwrap_or(0), params.h.unwrap_or(0)),