Move thumbnail generation to thumbnailer crate

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 3 years ago
parent 31d8c7d6fd
commit 2735033859

@ -230,6 +230,9 @@ name = "cc"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
@ -746,6 +749,15 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "jobserver"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
version = "0.1.22"
@ -793,6 +805,15 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "libwebp-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e70c064738b35a28fd6f991d27c0d9680353641d167ae3702a8228dd8272ef6"
dependencies = [
"cc",
]
[[package]]
name = "lock_api"
version = "0.4.5"
@ -828,8 +849,8 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "mediarepo-api"
version = "0.4.1"
source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=b123e69d92dfd384d37b9005c8e261c69fddfcc5#b123e69d92dfd384d37b9005c8e261c69fddfcc5"
version = "0.4.2"
source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=28b25e94eb2cdb8cec86e3e452081a649b8cd64e#28b25e94eb2cdb8cec86e3e452081a649b8cd64e"
dependencies = [
"chrono",
"serde",
@ -844,7 +865,6 @@ version = "0.1.0"
dependencies = [
"base64",
"futures 0.3.17",
"image",
"multibase",
"multihash",
"rmp-ipc",
@ -852,6 +872,7 @@ dependencies = [
"serde",
"sqlx",
"thiserror",
"thumbnailer",
"tokio",
"toml",
"typemap_rev",
@ -2004,6 +2025,19 @@ dependencies = [
"once_cell",
]
[[package]]
name = "thumbnailer"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10341d6f800bc62e7b6cf98b78851385db843bdae629bc4353d30c2fde0ed011"
dependencies = [
"image",
"mime",
"rayon",
"thiserror",
"webp",
]
[[package]]
name = "tiff"
version = "0.6.1"
@ -2420,6 +2454,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webp"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0041a9fcbdbf6402c3cb0ec7c2c1a1c240efd523519a0763ae07753bc95f7713"
dependencies = [
"image",
"libwebp-sys",
]
[[package]]
name = "weezl"
version = "0.1.5"

@ -188,6 +188,9 @@ name = "cc"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
@ -603,6 +606,15 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "jobserver"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
version = "0.1.22"
@ -639,6 +651,15 @@ version = "0.2.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
[[package]]
name = "libwebp-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e70c064738b35a28fd6f991d27c0d9680353641d167ae3702a8228dd8272ef6"
dependencies = [
"cc",
]
[[package]]
name = "lock_api"
version = "0.4.5"
@ -669,7 +690,6 @@ version = "0.1.0"
dependencies = [
"base64",
"futures",
"image",
"multibase",
"multihash",
"rmp-ipc",
@ -677,6 +697,7 @@ dependencies = [
"serde",
"sqlx",
"thiserror",
"thumbnailer",
"tokio",
"toml",
"typemap_rev",
@ -697,6 +718,12 @@ dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "minimal-lexical"
version = "0.1.3"
@ -1324,6 +1351,19 @@ dependencies = [
"syn",
]
[[package]]
name = "thumbnailer"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10341d6f800bc62e7b6cf98b78851385db843bdae629bc4353d30c2fde0ed011"
dependencies = [
"image",
"mime",
"rayon",
"thiserror",
"webp",
]
[[package]]
name = "tiff"
version = "0.6.1"
@ -1545,6 +1585,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webp"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0041a9fcbdbf6402c3cb0ec7c2c1a1c240efd523519a0763ae07753bc95f7713"
dependencies = [
"image",
"libwebp-sys",
]
[[package]]
name = "weezl"
version = "0.1.5"

@ -14,8 +14,8 @@ toml = "0.5.8"
serde = "1.0.130"
rmp-ipc = "0.7.2"
typemap_rev = "0.1.5"
image = "0.23.14"
futures = "0.3.17"
thumbnailer = "0.1.0"
[dependencies.sea-orm]
version = "0.2.4"

@ -30,7 +30,7 @@ pub enum RepoError {
Raw(StringError),
#[error(transparent)]
Image(#[from] image::error::ImageError),
Thumbnailer(#[from] thumbnailer::error::ThumbError),
}
#[derive(Error, Debug)]

@ -1,58 +0,0 @@
use crate::error::RepoResult;
use image::imageops::FilterType;
use image::io::Reader as ImageReader;
use image::{DynamicImage, ImageOutputFormat};
use std::io::Cursor;
use std::path::PathBuf;
use tokio::fs::OpenOptions;
use tokio::io::{AsyncRead, AsyncReadExt, BufReader};
/// Represents the different sizes of a thumbnail
#[derive(Clone, Copy, Debug)]
pub enum ThumbnailSize {
Small,
Medium,
Large,
}
impl ThumbnailSize {
pub fn dimensions(&self) -> (u32, u32) {
match self {
ThumbnailSize::Small => (128, 128),
ThumbnailSize::Medium => (256, 256),
ThumbnailSize::Large => (512, 512),
}
}
}
/// Reads an image from a path
pub async fn read_image_from_path(path: &PathBuf) -> RepoResult<DynamicImage> {
let file = OpenOptions::new().read(true).open(path).await?;
let mut reader = BufReader::new(file);
read_image(&mut reader).await
}
/// Reads an image from a reader
pub async fn read_image<R: AsyncRead + Unpin>(reader: &mut R) -> RepoResult<DynamicImage> {
let mut buf = Vec::new();
reader.read_to_end(&mut buf).await?;
let image = ImageReader::new(Cursor::new(buf))
.with_guessed_format()?
.decode()?;
Ok(image)
}
/// Returns the bytes of an image in the png format
pub fn get_image_bytes_png(image: DynamicImage) -> RepoResult<Vec<u8>> {
let mut buf = Vec::new();
image.write_to(&mut buf, ImageOutputFormat::Png)?;
Ok(buf)
}
/// Creates a thumbnail with the defined thumbnail size
pub fn create_thumbnail(image: DynamicImage, size: ThumbnailSize) -> DynamicImage {
let (height, width) = size.dimensions();
image.resize(height, width, FilterType::Nearest)
}

@ -1,11 +1,10 @@
pub mod context;
pub mod error;
pub mod file_hash_store;
pub mod image_processing;
pub mod settings;
pub mod type_keys;
pub mod utils;
pub use futures;
pub use image;
pub use rmp_ipc;
pub use thumbnailer;

@ -201,6 +201,9 @@ name = "cc"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
@ -666,6 +669,15 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "jobserver"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
version = "0.1.22"
@ -713,6 +725,15 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "libwebp-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e70c064738b35a28fd6f991d27c0d9680353641d167ae3702a8228dd8272ef6"
dependencies = [
"cc",
]
[[package]]
name = "lock_api"
version = "0.4.5"
@ -743,7 +764,6 @@ version = "0.1.0"
dependencies = [
"base64",
"futures",
"image",
"multibase",
"multihash",
"rmp-ipc",
@ -751,6 +771,7 @@ dependencies = [
"serde",
"sqlx",
"thiserror",
"thumbnailer",
"tokio",
"toml",
"typemap_rev",
@ -782,6 +803,12 @@ dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "minimal-lexical"
version = "0.1.3"
@ -1684,6 +1711,19 @@ dependencies = [
"syn",
]
[[package]]
name = "thumbnailer"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10341d6f800bc62e7b6cf98b78851385db843bdae629bc4353d30c2fde0ed011"
dependencies = [
"image",
"mime",
"rayon",
"thiserror",
"webp",
]
[[package]]
name = "tiff"
version = "0.6.1"
@ -1953,6 +1993,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webp"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0041a9fcbdbf6402c3cb0ec7c2c1a1c240efd523519a0763ae07753bc95f7713"
dependencies = [
"image",
"libwebp-sys",
]
[[package]]
name = "weezl"
version = "0.1.5"

@ -201,6 +201,9 @@ name = "cc"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
@ -666,6 +669,15 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "jobserver"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
version = "0.1.22"
@ -713,6 +725,15 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "libwebp-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e70c064738b35a28fd6f991d27c0d9680353641d167ae3702a8228dd8272ef6"
dependencies = [
"cc",
]
[[package]]
name = "lock_api"
version = "0.4.5"
@ -743,7 +764,6 @@ version = "0.1.0"
dependencies = [
"base64",
"futures",
"image",
"multibase",
"multihash",
"rmp-ipc",
@ -751,6 +771,7 @@ dependencies = [
"serde",
"sqlx",
"thiserror",
"thumbnailer",
"tokio",
"toml",
"typemap_rev",
@ -1716,6 +1737,19 @@ dependencies = [
"syn",
]
[[package]]
name = "thumbnailer"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10341d6f800bc62e7b6cf98b78851385db843bdae629bc4353d30c2fde0ed011"
dependencies = [
"image",
"mime",
"rayon",
"thiserror",
"webp",
]
[[package]]
name = "tiff"
version = "0.6.1"
@ -1995,6 +2029,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webp"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0041a9fcbdbf6402c3cb0ec7c2c1a1c240efd523519a0763ae07753bc95f7713"
dependencies = [
"image",
"libwebp-sys",
]
[[package]]
name = "weezl"
version = "0.1.5"

@ -1,25 +1,26 @@
use crate::file_type::FileType;
use crate::storage::Storage;
use crate::tag::Tag;
use crate::thumbnail::Thumbnail;
use std::fmt::Debug;
use std::io::Cursor;
use std::str::FromStr;
use chrono::{Local, NaiveDateTime};
use mediarepo_core::error::{RepoError, RepoResult};
use mediarepo_core::image::GenericImageView;
use mediarepo_core::image_processing::{
create_thumbnail, get_image_bytes_png, read_image, ThumbnailSize,
};
use sea_orm::prelude::*;
use sea_orm::sea_query::{Expr, Query};
use sea_orm::{Condition, DatabaseConnection, Set};
use sea_orm::{JoinType, QuerySelect};
use tokio::io::{AsyncReadExt, BufReader};
use mediarepo_core::error::RepoResult;
use mediarepo_core::thumbnailer::{self, Thumbnail as ThumbnailerThumb, ThumbnailSize};
use mediarepo_database::entities::file;
use mediarepo_database::entities::hash;
use mediarepo_database::entities::hash_tag;
use mediarepo_database::entities::namespace;
use mediarepo_database::entities::tag;
use mime::Mime;
use sea_orm::prelude::*;
use sea_orm::sea_query::{Expr, Query};
use sea_orm::{Condition, DatabaseConnection, Set};
use sea_orm::{JoinType, QuerySelect};
use std::fmt::Debug;
use tokio::io::BufReader;
use crate::file_type::FileType;
use crate::storage::Storage;
use crate::tag::Tag;
use crate::thumbnail::Thumbnail;
#[derive(Clone)]
pub struct File {
@ -331,31 +332,21 @@ impl File {
/// Creates a thumbnail for the file
#[tracing::instrument(level = "debug", skip(self))]
pub async fn create_thumbnail(
&self,
size: ThumbnailSize,
) -> RepoResult<(Vec<u8>, Mime, (u32, u32))> {
match self.file_type() {
FileType::Image => self.create_image_thumbnail(size).await,
_ => Err(RepoError::from(
"Unsupported file type for thumbnail generation",
)),
}
}
/// Creates a thumbnail for an image
#[tracing::instrument(level = "debug", skip(self))]
async fn create_image_thumbnail(
pub async fn create_thumbnail<I: IntoIterator<Item = ThumbnailSize> + Debug>(
&self,
size: ThumbnailSize,
) -> RepoResult<(Vec<u8>, Mime, (u32, u32))> {
let mut reader = self.get_reader().await?;
let image = read_image(&mut reader).await?;
let thumb_image = create_thumbnail(image, size);
let actual_size = (thumb_image.height(), thumb_image.width());
let bytes = get_image_bytes_png(thumb_image)?;
Ok((bytes, mime::IMAGE_PNG, actual_size))
sizes: I,
) -> RepoResult<Vec<ThumbnailerThumb>> {
let mut buf = Vec::new();
self.get_reader().await?.read_to_end(&mut buf).await?;
let mime_type = self
.model
.mime_type
.clone()
.map(|mime_type| mime::Mime::from_str(&mime_type).unwrap())
.unwrap_or(mime::IMAGE_STAR);
let thumbs = thumbnailer::create_thumbnails(Cursor::new(buf), mime_type, sizes)?;
Ok(thumbs)
}
/// Returns the active model of the file with only the id set

@ -5,7 +5,7 @@ use crate::storage::Storage;
use crate::tag::Tag;
use crate::thumbnail::Thumbnail;
use mediarepo_core::error::{RepoError, RepoResult};
use mediarepo_core::image_processing::ThumbnailSize;
use mediarepo_core::thumbnailer::ThumbnailSize;
use mediarepo_core::utils::parse_namespace_and_tag;
use mediarepo_database::get_database;
use sea_orm::DatabaseConnection;
@ -167,13 +167,15 @@ impl Repo {
#[tracing::instrument(level = "debug", skip(self, file))]
pub async fn create_thumbnails_for_file(&self, file: File) -> RepoResult<()> {
let thumb_storage = self.get_thumbnail_storage()?;
for size in [
ThumbnailSize::Small,
ThumbnailSize::Medium,
ThumbnailSize::Large,
] {
let (bytes, mime, (height, width)) = file.create_thumbnail(size).await?;
let hash = thumb_storage.store_entry(Cursor::new(bytes)).await?;
let size = ThumbnailSize::Medium;
let (height, width) = size.dimensions();
let thumbs = file.create_thumbnail([size]).await?;
for thumb in thumbs {
let mut buf = Vec::new();
thumb.write_png(&mut buf)?;
let hash = thumb_storage.store_entry(Cursor::new(buf)).await?;
Thumbnail::add(
self.db.clone(),
hash.id(),
@ -181,7 +183,7 @@ impl Repo {
thumb_storage.id(),
height as i32,
width as i32,
Some(mime.to_string()),
Some(mime::IMAGE_PNG.to_string()),
)
.await?;
}

@ -201,6 +201,9 @@ name = "cc"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
@ -696,6 +699,15 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "jobserver"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
version = "0.1.22"
@ -743,6 +755,15 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "libwebp-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e70c064738b35a28fd6f991d27c0d9680353641d167ae3702a8228dd8272ef6"
dependencies = [
"cc",
]
[[package]]
name = "lock_api"
version = "0.4.5"
@ -769,8 +790,8 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "mediarepo-api"
version = "0.4.1"
source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=b123e69d92dfd384d37b9005c8e261c69fddfcc5#b123e69d92dfd384d37b9005c8e261c69fddfcc5"
version = "0.4.2"
source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=28b25e94eb2cdb8cec86e3e452081a649b8cd64e#28b25e94eb2cdb8cec86e3e452081a649b8cd64e"
dependencies = [
"chrono",
"serde",
@ -785,7 +806,6 @@ version = "0.1.0"
dependencies = [
"base64",
"futures 0.3.17",
"image",
"multibase",
"multihash",
"rmp-ipc",
@ -793,6 +813,7 @@ dependencies = [
"serde",
"sqlx",
"thiserror",
"thumbnailer",
"tokio",
"toml",
"typemap_rev",
@ -1845,6 +1866,19 @@ dependencies = [
"syn 1.0.80",
]
[[package]]
name = "thumbnailer"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10341d6f800bc62e7b6cf98b78851385db843bdae629bc4353d30c2fde0ed011"
dependencies = [
"image",
"mime",
"rayon",
"thiserror",
"webp",
]
[[package]]
name = "tiff"
version = "0.6.1"
@ -2151,6 +2185,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webp"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0041a9fcbdbf6402c3cb0ec7c2c1a1c240efd523519a0763ae07753bc95f7713"
dependencies = [
"image",
"libwebp-sys",
]
[[package]]
name = "weezl"
version = "0.1.5"

@ -33,4 +33,4 @@ features = ["tokio-executor"]
[dependencies.mediarepo-api]
git = "https://github.com/Trivernis/mediarepo-api.git"
rev = "b123e69d92dfd384d37b9005c8e261c69fddfcc5"
rev = "28b25e94eb2cdb8cec86e3e452081a649b8cd64e"
Loading…
Cancel
Save