Benchmark more jpeg decoders. Do downsizing decode with jpeg_decoder.

This commit is contained in:
2020-02-22 17:19:57 -08:00
parent 7f64a4d2f6
commit 1c82313c98
4 changed files with 225 additions and 19 deletions

View File

@@ -1,6 +1,7 @@
use std::fs;
use std::fs::File;
use std::io;
use std::io::BufReader;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
@@ -10,8 +11,10 @@ use image::imageops;
use image::DynamicImage;
use image::GenericImage;
use image::GenericImageView;
use image::ImageBuffer;
use image::ImageFormat;
use image::ImageResult;
use jpeg_decoder::Decoder;
use log::error;
use log::info;
use log::warn;
@@ -22,7 +25,7 @@ use rocksdb::IteratorMode;
use rocksdb::DB;
// Used to ensure DB is invalidated after schema changes.
const LIBRARY_GENERATION: &'static str = "12";
const LIBRARY_GENERATION: &'static str = "13";
#[derive(Clone)]
pub struct Library {
@@ -31,13 +34,35 @@ pub struct Library {
cache_db: Arc<DB>,
}
pub fn load_image<P>(path: P) -> ImageResult<DynamicImage>
pub fn load_image<P>(
path: P,
width_hint: Option<u32>,
height_hint: Option<u32>,
) -> Result<DynamicImage, Box<dyn std::error::Error>>
where
P: AsRef<Path>,
{
image::io::Reader::open(&path)?
.with_guessed_format()?
.decode()
// TODO(wathiede): fall back to image::load_image when jpeg decoding fails.
let file = File::open(path).expect("failed to open file");
let mut decoder = Decoder::new(BufReader::new(file));
let (w, h) = match (width_hint, height_hint) {
(Some(w), Some(h)) => {
let got = decoder.scale(w as u16, h as u16)?;
info!("Hinted at {}x{}, got {}x{}", w, h, got.0, got.1);
(got.0 as u32, got.1 as u32)
}
// TODO(wathiede): handle partial hints by grabbing info and then computing the absent
// dimenison.
_ => {
decoder.read_info()?;
let info = decoder.info().unwrap();
(info.width as u32, info.height as u32)
}
};
let pixels = decoder.decode().expect("failed to decode image");
Ok(DynamicImage::ImageRgb8(
ImageBuffer::from_raw(w, h, pixels).expect("pixels to small for given dimensions"),
))
}
#[derive(Clone, Copy, Debug)]
@@ -241,18 +266,15 @@ impl Library {
media_items_id: &str,
dimensions: (Option<u32>, Option<u32>),
filter: FilterType,
) -> Result<Vec<u8>, io::Error> {
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
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),
))
Err(io::Error::new(io::ErrorKind::NotFound, format!("{}", media_items_id)).into())
}
Some(path) => {
let orig_img =
load_image(&path).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
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 buf = save_to_jpeg_bytes(&img)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
@@ -288,7 +310,8 @@ impl Library {
let bytes = match self.generate_thumbnail(
media_items_id,
dimensions,
FilterType::Builtin(imageops::FilterType::Lanczos3),
FilterType::Nearest,
//FilterType::Builtin(imageops::FilterType::Lanczos3),
) {
Ok(bytes) => bytes,
Err(e) => {