use crate::error::ThumbResult;
use image;
use image::imageops::FilterType;
use image::{DynamicImage, GenericImageView, ImageOutputFormat};
use mime::Mime;
use rayon::prelude::*;
use std::io::{BufRead, Seek, Write};
use crate::formats::get_base_image;
pub use size::ThumbnailSize;
pub mod error;
mod formats;
mod size;
pub(crate) mod utils;
#[derive(Clone, Debug)]
pub struct Thumbnail {
inner: DynamicImage,
}
impl Thumbnail {
pub fn write_png<W: Write + Seek>(self, writer: &mut W) -> ThumbResult<()> {
let image = DynamicImage::ImageRgba8(self.inner.into_rgba8());
image.write_to(writer, ImageOutputFormat::Png)?;
Ok(())
}
pub fn write_jpeg<W: Write + Seek>(self, writer: &mut W, quality: u8) -> ThumbResult<()> {
let image = DynamicImage::ImageRgb8(self.inner.into_rgb8());
image.write_to(writer, ImageOutputFormat::Jpeg(quality))?;
Ok(())
}
pub fn size(&self) -> (u32, u32) {
self.inner.dimensions()
}
}
pub fn create_thumbnails<R: BufRead + Seek, I: IntoIterator<Item = ThumbnailSize>>(
reader: R,
mime: Mime,
sizes: I,
) -> ThumbResult<Vec<Thumbnail>> {
let image = get_base_image(reader, mime)?;
let sizes: Vec<ThumbnailSize> = sizes.into_iter().collect();
let thumbnails = resize_images(image, &sizes)
.into_iter()
.map(|image| Thumbnail { inner: image })
.collect();
Ok(thumbnails)
}
fn resize_images(image: DynamicImage, sizes: &[ThumbnailSize]) -> Vec<DynamicImage> {
sizes
.into_par_iter()
.map(|size| {
let (width, height) = size.dimensions();
image.resize(width, height, FilterType::Lanczos3)
})
.collect()
}