Implement api to request thumbnails of specific sizes

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 3 years ago
parent ce2533292d
commit 04271b6df0

@ -1526,9 +1526,9 @@ dependencies = [
[[package]] [[package]]
name = "rmp-ipc" name = "rmp-ipc"
version = "0.9.1" version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b0a3f127316ca5ca832cb7e9e616641ffbab659c2cb2ab7210d60e7441f70f" checksum = "87d2b669d0332e1478b88fdecf4c03cc0c8ce1d977a79eba848f4532213567e6"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"byteorder", "byteorder",

@ -1061,9 +1061,9 @@ dependencies = [
[[package]] [[package]]
name = "rmp-ipc" name = "rmp-ipc"
version = "0.9.1" version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b0a3f127316ca5ca832cb7e9e616641ffbab659c2cb2ab7210d60e7441f70f" checksum = "87d2b669d0332e1478b88fdecf4c03cc0c8ce1d977a79eba848f4532213567e6"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"byteorder", "byteorder",

@ -12,7 +12,7 @@ multibase = "0.9.1"
base64 = "0.13.0" base64 = "0.13.0"
toml = "0.5.8" toml = "0.5.8"
serde = "1.0.130" serde = "1.0.130"
rmp-ipc = "0.9.1" rmp-ipc = "0.9.2"
typemap_rev = "0.1.5" typemap_rev = "0.1.5"
futures = "0.3.17" futures = "0.3.17"
thumbnailer = "0.1.0" thumbnailer = "0.1.0"

@ -1295,9 +1295,9 @@ dependencies = [
[[package]] [[package]]
name = "rmp-ipc" name = "rmp-ipc"
version = "0.9.1" version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b0a3f127316ca5ca832cb7e9e616641ffbab659c2cb2ab7210d60e7441f70f" checksum = "87d2b669d0332e1478b88fdecf4c03cc0c8ce1d977a79eba848f4532213567e6"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"byteorder", "byteorder",

@ -1321,9 +1321,9 @@ dependencies = [
[[package]] [[package]]
name = "rmp-ipc" name = "rmp-ipc"
version = "0.9.1" version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b0a3f127316ca5ca832cb7e9e616641ffbab659c2cb2ab7210d60e7441f70f" checksum = "87d2b669d0332e1478b88fdecf4c03cc0c8ce1d977a79eba848f4532213567e6"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"byteorder", "byteorder",

@ -165,18 +165,53 @@ impl Repo {
/// Creates thumbnails of all sizes for a file /// Creates thumbnails of all sizes for a file
#[tracing::instrument(level = "debug", skip(self, file))] #[tracing::instrument(level = "debug", skip(self, file))]
pub async fn create_thumbnails_for_file(&self, file: File) -> RepoResult<()> { pub async fn create_thumbnails_for_file(&self, file: &File) -> RepoResult<()> {
let thumb_storage = self.get_thumbnail_storage()?; let thumb_storage = self.get_thumbnail_storage()?;
let size = ThumbnailSize::Medium; let size = ThumbnailSize::Medium;
let (height, width) = size.dimensions(); let (height, width) = size.dimensions();
let thumbs = file.create_thumbnail([size]).await?; let thumbs = file.create_thumbnail([size]).await?;
for thumb in thumbs { for thumb in thumbs {
self.store_single_thumbnail(file, thumb_storage, height, width, thumb)
.await?;
}
Ok(())
}
#[tracing::instrument(level = "debug", skip(self, file))]
pub async fn create_file_thumbnail(
&self,
file: &File,
size: ThumbnailSize,
) -> RepoResult<Thumbnail> {
let thumb_storage = self.get_thumbnail_storage()?;
let (height, width) = size.dimensions();
let thumb = file
.create_thumbnail([size])
.await?
.pop()
.ok_or_else(|| RepoError::from("Failed to create thumbnail"))?;
let thumbnail = self
.store_single_thumbnail(file, thumb_storage, height, width, thumb)
.await?;
Ok(thumbnail)
}
async fn store_single_thumbnail(
&self,
file: &File,
thumb_storage: &Storage,
height: u32,
width: u32,
thumb: mediarepo_core::thumbnailer::Thumbnail,
) -> RepoResult<Thumbnail> {
let mut buf = Vec::new(); let mut buf = Vec::new();
thumb.write_png(&mut buf)?; thumb.write_png(&mut buf)?;
let hash = thumb_storage.store_entry(Cursor::new(buf)).await?; let hash = thumb_storage.store_entry(Cursor::new(buf)).await?;
Thumbnail::add( let thumbnail = Thumbnail::add(
self.db.clone(), self.db.clone(),
hash.id(), hash.id(),
file.id(), file.id(),
@ -186,9 +221,8 @@ impl Repo {
Some(mime::IMAGE_PNG.to_string()), Some(mime::IMAGE_PNG.to_string()),
) )
.await?; .await?;
}
Ok(()) Ok(thumbnail)
} }
/// Returns all tags stored in the database /// Returns all tags stored in the database

@ -1424,9 +1424,9 @@ dependencies = [
[[package]] [[package]]
name = "rmp-ipc" name = "rmp-ipc"
version = "0.9.1" version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b0a3f127316ca5ca832cb7e9e616641ffbab659c2cb2ab7210d60e7441f70f" checksum = "87d2b669d0332e1478b88fdecf4c03cc0c8ce1d977a79eba848f4532213567e6"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"byteorder", "byteorder",

@ -2,11 +2,13 @@ use crate::from_model::FromModel;
use crate::utils::{file_by_identifier, get_repo_from_context}; use crate::utils::{file_by_identifier, get_repo_from_context};
use compare::Compare; use compare::Compare;
use mediarepo_api::types::files::{ use mediarepo_api::types::files::{
AddFileRequest, FileMetadataResponse, FindFilesByTagsRequest, GetFileThumbnailsRequest, AddFileRequest, FileMetadataResponse, FindFilesByTagsRequest, GetFileThumbnailOfSizeRequest,
ReadFileRequest, SortDirection, SortKey, ThumbnailMetadataResponse, UpdateFileNameRequest, GetFileThumbnailsRequest, ReadFileRequest, SortDirection, SortKey, ThumbnailMetadataResponse,
UpdateFileNameRequest,
}; };
use mediarepo_core::error::RepoError; use mediarepo_core::error::RepoError;
use mediarepo_core::rmp_ipc::prelude::*; use mediarepo_core::rmp_ipc::prelude::*;
use mediarepo_core::thumbnailer::ThumbnailSize;
use mediarepo_database::queries::tags::get_hashes_with_namespaced_tags; use mediarepo_database::queries::tags::get_hashes_with_namespaced_tags;
use mediarepo_model::file::File; use mediarepo_model::file::File;
use std::cmp::Ordering; use std::cmp::Ordering;
@ -29,6 +31,7 @@ impl NamespaceProvider for FilesNamespace {
"read_file" => Self::read_file, "read_file" => Self::read_file,
"get_thumbnails" => Self::thumbnails, "get_thumbnails" => Self::thumbnails,
"read_thumbnail" => Self::read_thumbnail, "read_thumbnail" => Self::read_thumbnail,
"get_thumbnail_of_size" => Self::get_thumbnail_of_size,
"update_file_name" => Self::update_file_name "update_file_name" => Self::update_file_name
); );
} }
@ -137,7 +140,7 @@ impl FilesNamespace {
if thumbnails.len() == 0 { if thumbnails.len() == 0 {
tracing::debug!("No thumbnails for file found. Creating thumbnails..."); tracing::debug!("No thumbnails for file found. Creating thumbnails...");
repo.create_thumbnails_for_file(file.clone()).await?; repo.create_thumbnails_for_file(&file).await?;
tracing::debug!("Thumbnails for file created."); tracing::debug!("Thumbnails for file created.");
} }
thumbnails = file.thumbnails().await?; thumbnails = file.thumbnails().await?;
@ -180,6 +183,54 @@ impl FilesNamespace {
Ok(()) Ok(())
} }
/// Returns a thumbnail that is within the range of the requested sizes
#[tracing::instrument(skip_all)]
async fn get_thumbnail_of_size<S: AsyncProtocolStream>(
ctx: &Context<S>,
event: Event,
) -> IPCResult<()> {
let request = event.data::<GetFileThumbnailOfSizeRequest>()?;
let repo = get_repo_from_context(ctx).await;
let file = file_by_identifier(request.id, &repo).await?;
let thumbnails = file.thumbnails().await?;
let min_size = request.min_size;
let max_size = request.max_size;
let found_thumbnail = thumbnails.into_iter().find(|thumb| {
let height = thumb.height() as u32;
let width = thumb.width() as u32;
height >= min_size.0
&& height <= max_size.0
&& width >= min_size.1
&& width <= max_size.1
});
let thumbnail = if let Some(thumbnail) = found_thumbnail {
thumbnail
} else {
let middle_size = ((max_size.0 + min_size.0) / 2, (max_size.1 + min_size.1) / 2);
let thumbnail = repo
.create_file_thumbnail(&file, ThumbnailSize::Custom(middle_size))
.await?;
thumbnail
};
let mut buf = Vec::new();
thumbnail.get_reader().await?.read_to_end(&mut buf).await?;
let byte_payload = BytePayload::new(buf);
let thumb_payload = ThumbnailMetadataResponse::from_model(thumbnail);
ctx.emitter
.emit_response_to(
event.id(),
Self::name(),
"get_thumbnail_of_size",
TandemPayload::new(thumb_payload, byte_payload),
)
.await?;
Ok(())
}
/// Updates the name of a file /// Updates the name of a file
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
async fn update_file_name<S: AsyncProtocolStream>( async fn update_file_name<S: AsyncProtocolStream>(

@ -286,7 +286,7 @@ async fn add_tags_from_tags_file(
#[tracing::instrument(skip(repo, file))] #[tracing::instrument(skip(repo, file))]
async fn create_file_thumbnails(repo: &Repo, file: File) -> RepoResult<()> { async fn create_file_thumbnails(repo: &Repo, file: File) -> RepoResult<()> {
if file.thumbnails().await?.len() == 0 { if file.thumbnails().await?.len() == 0 {
repo.create_thumbnails_for_file(file).await?; repo.create_thumbnails_for_file(&file).await?;
} }
Ok(()) Ok(())
} }

Loading…
Cancel
Save