diff --git a/Cargo.toml b/Cargo.toml index 702a089..a673481 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,3 +40,7 @@ load_image = "2.12.0" [[bench]] name = "image" harness = false + +# Build dependencies with release optimizations even in dev mode. +[profile.dev.package."*"] +opt-level = 3 diff --git a/src/library.rs b/src/library.rs index 4a9a806..f531d0b 100644 --- a/src/library.rs +++ b/src/library.rs @@ -25,7 +25,7 @@ use rocksdb::IteratorMode; use rocksdb::DB; // Used to ensure DB is invalidated after schema changes. -const LIBRARY_GENERATION: &'static str = "13"; +const LIBRARY_GENERATION: &'static str = "14"; #[derive(Clone)] pub struct Library { @@ -116,6 +116,25 @@ pub fn resize( img: &DynamicImage, dimensions: (Option, Option), filter: FilterType, +) -> DynamicImage { + let (w, h) = dimensions; + let (orig_w, orig_h) = img.dimensions(); + let (w, h) = match (w, h) { + (Some(w), Some(h)) => (w, h), + (Some(w), None) => (w, orig_h * w / orig_w), + (None, Some(h)) => (orig_w * h / orig_h, h), + (None, None) => (orig_w, orig_h), + }; + match filter { + FilterType::Builtin(filter) => img.resize(w, h, filter), + FilterType::Nearest => unimplemented!(), //resize_to_fill_nearest(w, h, img), + } +} + +pub fn resize_to_fill( + img: &DynamicImage, + dimensions: (Option, Option), + filter: FilterType, ) -> DynamicImage { let (w, h) = dimensions; let (orig_w, orig_h) = img.dimensions(); @@ -261,11 +280,13 @@ impl Library { fn generational_key(generation: &str, key: &str) -> String { format!("{}/{}", generation, key) } + pub fn generate_thumbnail( &self, media_items_id: &str, dimensions: (Option, Option), filter: FilterType, + fill: bool, ) -> Result, Box> { match self.original(&media_items_id) { None => { @@ -275,7 +296,11 @@ impl Library { Some(path) => { let orig_img = load_image(&path, dimensions.0, dimensions.1)?; //.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - let img = resize(&orig_img, dimensions, filter); + let img = if fill { + resize_to_fill(&orig_img, dimensions, filter) + } else { + resize(&orig_img, dimensions, filter) + }; let buf = save_to_jpeg_bytes(&img) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; Ok(buf) @@ -286,6 +311,7 @@ impl Library { &self, media_items_id: &str, dimensions: (Option, Option), + fill: bool, ) -> Option> { fn cache_key(media_items_id: &str, dimensions: (Option, Option)) -> String { let dim = match dimensions { @@ -308,6 +334,7 @@ impl Library { media_items_id, dimensions, FilterType::Builtin(imageops::FilterType::Lanczos3), + fill, ) { Ok(bytes) => bytes, Err(e) => { diff --git a/src/web.rs b/src/web.rs index d5b1302..ffb600e 100644 --- a/src/web.rs +++ b/src/web.rs @@ -73,6 +73,7 @@ fn album(lib: Library, id: String) -> Result struct ImageParams { w: Option, h: Option, + fill: Option, } fn image( @@ -81,7 +82,11 @@ fn image( params: ImageParams, ) -> Result { // TODO(wathiede): add caching headers. - match lib.thumbnail(&media_items_id, (params.w, params.h)) { + match lib.thumbnail( + &media_items_id, + (params.w, params.h), + params.fill.unwrap_or(false), + ) { None => { warn!("Couldn't find original {}", &media_items_id); Err(warp::reject::not_found())