Refactor thumbnail generation.

This commit is contained in:
Bill Thiede 2020-02-17 17:50:43 -08:00
parent 43974b7406
commit d74a8117d7
2 changed files with 40 additions and 36 deletions

View File

@ -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<Vec<u8>> {
fn generate_thumbnail(
lib: &Library,
media_items_id: &str,
dimensions: (u32, u32),
) -> Result<Vec<u8>, 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<Vec<u8>, 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<Vec<u8>> {
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) => {

View File

@ -80,6 +80,7 @@ fn image(
media_items_id: String,
params: ImageParams,
) -> Result<impl warp::Reply, warp::Rejection> {
// TODO(wathiede): add caching headers.
match lib.thumbnail(
&media_items_id,
(params.w.unwrap_or(0), params.h.unwrap_or(0)),