Compare commits
No commits in common. "77d69221d148c2f55b2f68724bc35ba6ad7deefc" and "b552b922fa4a81d36455cc33260ed2c77b9ea365" have entirely different histories.
77d69221d1
...
b552b922fa
@ -21,7 +21,7 @@ structopt = "0.3.9"
|
|||||||
yup-oauth2 = "^3.1"
|
yup-oauth2 = "^3.1"
|
||||||
warp = "0.1"
|
warp = "0.1"
|
||||||
serde = { version = "1.0.104", features = ["derive"] }
|
serde = { version = "1.0.104", features = ["derive"] }
|
||||||
image = { version = "0.23.0" } #, default-features = false, features = ["jpeg"] }
|
image = "0.23.0"
|
||||||
rust-embed = "5.2.0"
|
rust-embed = "5.2.0"
|
||||||
mime_guess = "2.0.1"
|
mime_guess = "2.0.1"
|
||||||
rocksdb = "0.13.0"
|
rocksdb = "0.13.0"
|
||||||
@ -34,6 +34,6 @@ version = "0.7.0"
|
|||||||
tempdir = "0.3.7"
|
tempdir = "0.3.7"
|
||||||
criterion = "0.3"
|
criterion = "0.3"
|
||||||
|
|
||||||
[[bench]]
|
#[[bench]]
|
||||||
name = "image"
|
#name = "image"
|
||||||
harness = false
|
#harness = false
|
||||||
|
|||||||
@ -1,93 +0,0 @@
|
|||||||
use criterion::BenchmarkId;
|
|
||||||
use criterion::Throughput;
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
|
||||||
|
|
||||||
use image::imageops::FilterType;
|
|
||||||
use image::GenericImageView;
|
|
||||||
|
|
||||||
use photosync::library::load_image;
|
|
||||||
use photosync::library::resize;
|
|
||||||
use photosync::library::save_to_jpeg_bytes;
|
|
||||||
|
|
||||||
pub fn criterion_benchmark(c: &mut Criterion) {
|
|
||||||
const TEST_IMAGE_PATH: &'static str = "testdata/image.jpg";
|
|
||||||
let img = load_image(TEST_IMAGE_PATH).expect("failed to load test image");
|
|
||||||
c.bench_function("Load image", |b| {
|
|
||||||
b.iter(|| black_box(load_image(TEST_IMAGE_PATH)))
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut group = c.benchmark_group("Resizing");
|
|
||||||
for size in [
|
|
||||||
(None, None),
|
|
||||||
(Some(256), Some(256)),
|
|
||||||
(Some(512), Some(512)),
|
|
||||||
(Some(1024), Some(1024)),
|
|
||||||
(Some(2048), Some(2048)),
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
{
|
|
||||||
let (w, h) = size;
|
|
||||||
for filter in [
|
|
||||||
FilterType::Nearest,
|
|
||||||
FilterType::CatmullRom,
|
|
||||||
FilterType::Lanczos3,
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
{
|
|
||||||
let (img_w, img_h) = img.dimensions();
|
|
||||||
let pixels = (img_w * img_h) as u64;
|
|
||||||
group.throughput(Throughput::Elements(pixels));
|
|
||||||
group.bench_with_input(
|
|
||||||
BenchmarkId::new(
|
|
||||||
format!("{:?}", filter),
|
|
||||||
format!(
|
|
||||||
"{}x{}",
|
|
||||||
w.map(|i| i.to_string()).unwrap_or("FULL".to_string()),
|
|
||||||
h.map(|i| i.to_string()).unwrap_or("FULL".to_string())
|
|
||||||
),
|
|
||||||
),
|
|
||||||
&(size, filter),
|
|
||||||
|b, (size, &filter)| b.iter(|| black_box(resize(&img, **size, filter))),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
group.bench_with_input(
|
|
||||||
BenchmarkId::new(
|
|
||||||
"Save to bytes",
|
|
||||||
format!(
|
|
||||||
"{}x{}",
|
|
||||||
w.map(|i| i.to_string()).unwrap_or("FULL".to_string()),
|
|
||||||
h.map(|i| i.to_string()).unwrap_or("FULL".to_string())
|
|
||||||
),
|
|
||||||
),
|
|
||||||
size,
|
|
||||||
|b, size| {
|
|
||||||
let small_img = resize(&img, *size, FilterType::Lanczos3);
|
|
||||||
b.iter(|| black_box(save_to_jpeg_bytes(&small_img)))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
group.bench_with_input(
|
|
||||||
BenchmarkId::new(
|
|
||||||
"Full pipeline Lanczos3",
|
|
||||||
format!(
|
|
||||||
"{}x{}",
|
|
||||||
w.map(|i| i.to_string()).unwrap_or("FULL".to_string()),
|
|
||||||
h.map(|i| i.to_string()).unwrap_or("FULL".to_string())
|
|
||||||
),
|
|
||||||
),
|
|
||||||
size,
|
|
||||||
|b, size| {
|
|
||||||
b.iter(|| {
|
|
||||||
let img = load_image(TEST_IMAGE_PATH).expect("failed to load test image");
|
|
||||||
let small_img = resize(&img, *size, FilterType::Lanczos3);
|
|
||||||
black_box(save_to_jpeg_bytes(&small_img))
|
|
||||||
})
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
group.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
criterion_group!(benches, criterion_benchmark);
|
|
||||||
criterion_main!(benches);
|
|
||||||
@ -7,10 +7,8 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use google_photoslibrary1 as photos;
|
use google_photoslibrary1 as photos;
|
||||||
use image::imageops::FilterType;
|
use image::imageops::FilterType;
|
||||||
use image::DynamicImage;
|
|
||||||
use image::GenericImageView;
|
use image::GenericImageView;
|
||||||
use image::ImageFormat;
|
use image::ImageFormat;
|
||||||
use image::ImageResult;
|
|
||||||
use log::error;
|
use log::error;
|
||||||
use log::info;
|
use log::info;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
@ -30,37 +28,6 @@ pub struct Library {
|
|||||||
cache_db: Arc<DB>,
|
cache_db: Arc<DB>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_image<P>(path: P) -> ImageResult<DynamicImage>
|
|
||||||
where
|
|
||||||
P: AsRef<Path>,
|
|
||||||
{
|
|
||||||
image::io::Reader::open(&path)?
|
|
||||||
.with_guessed_format()?
|
|
||||||
.decode()
|
|
||||||
}
|
|
||||||
|
|
||||||
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),
|
|
||||||
};
|
|
||||||
img.resize_to_fill(w, h, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn save_to_jpeg_bytes(img: &DynamicImage) -> ImageResult<Vec<u8>> {
|
|
||||||
let mut buf = Vec::new();
|
|
||||||
img.write_to(&mut buf, ImageFormat::Jpeg)?;
|
|
||||||
Ok(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Library {
|
impl Library {
|
||||||
pub fn new(root: PathBuf) -> Result<Library, Box<dyn std::error::Error>> {
|
pub fn new(root: PathBuf) -> Result<Library, Box<dyn std::error::Error>> {
|
||||||
let db = DB::open_default(root.join("cache"))?;
|
let db = DB::open_default(root.join("cache"))?;
|
||||||
@ -188,7 +155,7 @@ impl Library {
|
|||||||
pub fn generate_thumbnail(
|
pub fn generate_thumbnail(
|
||||||
&self,
|
&self,
|
||||||
media_items_id: &str,
|
media_items_id: &str,
|
||||||
dimensions: (Option<u32>, Option<u32>),
|
(w, h): (Option<u32>, Option<u32>),
|
||||||
filter: FilterType,
|
filter: FilterType,
|
||||||
) -> Result<Vec<u8>, io::Error> {
|
) -> Result<Vec<u8>, io::Error> {
|
||||||
match self.original(&media_items_id) {
|
match self.original(&media_items_id) {
|
||||||
@ -200,10 +167,20 @@ impl Library {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
Some(path) => {
|
Some(path) => {
|
||||||
let orig_img =
|
let orig_img = image::io::Reader::open(&path)?
|
||||||
load_image(&path).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
.with_guessed_format()?
|
||||||
let img = resize(&orig_img, dimensions, filter);
|
.decode()
|
||||||
let buf = save_to_jpeg_bytes(&img)
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
|
let (orig_w, orig_h) = orig_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),
|
||||||
|
};
|
||||||
|
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))?;
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
testdata/image.jpg
vendored
BIN
testdata/image.jpg
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 MiB |
Loading…
x
Reference in New Issue
Block a user