2016-01-31 16:34:48 +03:00
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use std::fs;
|
|
|
|
use std::io;
|
2015-12-26 22:18:44 +03:00
|
|
|
use image::open as image_open;
|
2016-05-11 19:15:00 +03:00
|
|
|
use image::{FilterType, GenericImage, ImageError, ImageFormat};
|
2016-01-31 16:34:48 +03:00
|
|
|
use rexif::{self, ExifData};
|
2016-08-28 23:07:42 +03:00
|
|
|
use std::ffi::OsStr;
|
2015-12-26 22:18:44 +03:00
|
|
|
|
2016-05-29 22:51:08 +03:00
|
|
|
use rphotos::models::Photo;
|
2015-12-26 22:18:44 +03:00
|
|
|
|
|
|
|
pub struct PhotosDir {
|
2016-05-04 14:16:20 +03:00
|
|
|
basedir: PathBuf,
|
2015-12-26 22:18:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PhotosDir {
|
2016-05-04 14:16:20 +03:00
|
|
|
pub fn new(basedir: PathBuf) -> Self {
|
|
|
|
PhotosDir { basedir: basedir }
|
2015-12-26 22:18:44 +03:00
|
|
|
}
|
|
|
|
|
2016-05-03 08:26:55 +03:00
|
|
|
#[allow(dead_code)]
|
2016-05-04 14:16:20 +03:00
|
|
|
pub fn get_scaled_image(&self,
|
|
|
|
photo: Photo,
|
|
|
|
width: u32,
|
|
|
|
height: u32)
|
|
|
|
-> Result<Vec<u8>, ImageError> {
|
2015-12-26 22:18:44 +03:00
|
|
|
let path = self.basedir.join(photo.path);
|
|
|
|
info!("Should open {:?}", path);
|
2016-05-03 19:37:35 +03:00
|
|
|
let img = try!(image_open(path));
|
2016-05-04 14:16:20 +03:00
|
|
|
let img = if width < img.width() || height < img.height() {
|
|
|
|
img.resize(width, height, FilterType::CatmullRom)
|
|
|
|
} else {
|
|
|
|
img
|
|
|
|
};
|
2015-12-26 22:18:44 +03:00
|
|
|
let img = match photo.rotation {
|
|
|
|
_x @ 0...44 => img,
|
|
|
|
_x @ 45...134 => img.rotate90(),
|
|
|
|
_x @ 135...224 => img.rotate180(),
|
|
|
|
_x @ 225...314 => img.rotate270(),
|
|
|
|
_x @ 315...360 => img,
|
|
|
|
x => {
|
|
|
|
warn!("Should rotate photo {} deg, which is unsupported", x);
|
|
|
|
img
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// TODO Put the icon in some kind of cache!
|
2016-05-04 14:16:20 +03:00
|
|
|
let mut buf = Vec::new();
|
2016-05-03 19:37:35 +03:00
|
|
|
try!(img.save(&mut buf, ImageFormat::JPEG));
|
|
|
|
Ok(buf)
|
2015-12-26 22:18:44 +03:00
|
|
|
}
|
2016-01-31 16:34:48 +03:00
|
|
|
|
2016-04-23 17:43:43 +03:00
|
|
|
#[allow(dead_code)]
|
2016-08-28 23:07:42 +03:00
|
|
|
pub fn has_file<S: AsRef<OsStr> + ?Sized>(&self, path: &S) -> bool {
|
|
|
|
self.basedir.join(Path::new(path)).is_file()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
2016-05-04 14:16:20 +03:00
|
|
|
pub fn find_files(&self,
|
|
|
|
dir: &Path,
|
|
|
|
cb: &Fn(&str, &ExifData))
|
|
|
|
-> io::Result<()> {
|
2016-01-31 16:34:48 +03:00
|
|
|
let absdir = self.basedir.join(dir);
|
|
|
|
if try!(fs::metadata(&absdir)).is_dir() {
|
|
|
|
let bl = self.basedir.to_str().unwrap().len() + 1;
|
|
|
|
debug!("Should look in {:?}", absdir);
|
|
|
|
for entry in try!(fs::read_dir(absdir)) {
|
|
|
|
let entry = try!(entry);
|
|
|
|
if try!(fs::metadata(entry.path())).is_dir() {
|
|
|
|
try!(self.find_files(&entry.path(), cb));
|
|
|
|
} else {
|
|
|
|
let p1 = entry.path();
|
|
|
|
if let Ok(exif) = rexif::parse_file(&p1.to_str().unwrap()) {
|
|
|
|
let path = p1.to_str().unwrap();
|
|
|
|
cb(&path[bl..], &exif);
|
2016-07-24 23:37:09 +03:00
|
|
|
} else {
|
|
|
|
debug!("'{:?}' has no exif data.", p1);
|
2016-01-31 16:34:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
2015-12-26 22:18:44 +03:00
|
|
|
}
|