quad-image 0.1.1

An image host
use std::fs;
use std::io::Read;
use std::path::Path;

use failure::format_err;
use failure::Error;
use failure::ResultExt;
use image;
use rayon::prelude::*;

fn thumb_name(image_id: &str) -> String {
    format!("{}.thumb.jpg", image_id)
}

pub fn generate_all_thumbs() -> Result<(), Error> {
    let mut needed = Vec::with_capacity(100);

    for path in Path::new("e").read_dir()? {
        let path = path?;

        if let Some(s) = path.path().to_str() {
            if !crate::IMAGE_ID.is_match(s) {
                continue;
            }

            if Path::new(&thumb_name(s)).is_file() {
                continue;
            }

            needed.push(s.to_string());
        }
    }

    println!("thumbnailing {} image(s)", needed.len());

    needed
        .par_iter()
        .map(|path| thumbnail(path).with_context(|_| format_err!("thumbnailing {:?}", path)))
        .collect::<Result<Vec<_>, _>>()?;

    println!("thumbnailing complete");

    Ok(())
}

pub fn thumbnail(image_id: &str) -> Result<String, Error> {
    let thumb_name = thumb_name(image_id);

    let mut bytes = Vec::with_capacity(1_000_000);
    fs::File::open(image_id)?.read_to_end(&mut bytes)?;

    let image = image::load_from_memory(&bytes)?;
    let shrunk = image.thumbnail(320, 160);

    let mut temp = tempfile_fast::PersistableTempFile::new_in("e")?;

    shrunk.write_to(&mut temp, image::ImageOutputFormat::JPEG(40))?;

    temp.persist_noclobber(&thumb_name).map_err(|e| e.error)?;
    crate::ingest::make_readable(&thumb_name)?;

    Ok(thumb_name)
}