Use non-filling resize on server side. Client does filling.

This commit is contained in:
Bill Thiede 2020-02-23 08:46:20 -08:00
parent 792471bf00
commit 7ec3a11037
3 changed files with 39 additions and 3 deletions

View File

@ -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

View File

@ -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<u32>, Option<u32>),
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<u32>, Option<u32>),
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<u32>, Option<u32>),
filter: FilterType,
fill: bool,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
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<u32>, Option<u32>),
fill: bool,
) -> Option<Vec<u8>> {
fn cache_key(media_items_id: &str, dimensions: (Option<u32>, Option<u32>)) -> 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) => {

View File

@ -73,6 +73,7 @@ fn album(lib: Library, id: String) -> Result<impl warp::Reply, warp::Rejection>
struct ImageParams {
w: Option<u32>,
h: Option<u32>,
fill: Option<bool>,
}
fn image(
@ -81,7 +82,11 @@ fn image(
params: ImageParams,
) -> Result<impl warp::Reply, warp::Rejection> {
// 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())