From 89b2b480ced9cd358e102ff4cf8ade2bbee393a9 Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Thu, 9 May 2019 20:13:15 +0200 Subject: [PATCH] implement image preview --- .../src/persistency/image_convert/mod.rs | 34 +++++++++++-------- .../src/persistency/mod.rs | 29 ++++++++++++---- .../texture-sync-server/src/server_state.rs | 13 ++----- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/server/texture-sync-server/src/persistency/image_convert/mod.rs b/server/texture-sync-server/src/persistency/image_convert/mod.rs index 3b7d6be..2c609de 100644 --- a/server/texture-sync-server/src/persistency/image_convert/mod.rs +++ b/server/texture-sync-server/src/persistency/image_convert/mod.rs @@ -1,19 +1,23 @@ -// TODO: remove on implementation -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] - - use crate::model::*; +use ::image::*; -pub struct ConvertConfig { - pub desired_size: (usize, usize), -} +// TODO: Deside on ::image::FilterType; +// TODO: Think about size; Hard Code?? -pub fn generate_preview( - input: &[u8], - format: TextureFormat, - config: &ConvertConfig, -) -> ::image::ImageResult> { - unimplemented!() +const RESIZE: u32 = 256; + +pub fn generate_preview(input: &[u8], format: TextureFormat) -> ImageResult> { + // Yes, this guesses the format :D + // Also the resize function takes a maximum size and preservs the ratio. + let img = + ::image::load_from_memory(input)?.resize(RESIZE, RESIZE, ::image::FilterType::Lanczos3); + + let mut out: Vec = Vec::new(); + + match format { + TextureFormat::JPEG => img.write_to(&mut out, ImageOutputFormat::JPEG(95))?, + TextureFormat::PNG => img.write_to(&mut out, ImageOutputFormat::PNG)?, + } + + Ok(out) } diff --git a/server/texture-sync-server/src/persistency/mod.rs b/server/texture-sync-server/src/persistency/mod.rs index 8339025..33c900b 100644 --- a/server/texture-sync-server/src/persistency/mod.rs +++ b/server/texture-sync-server/src/persistency/mod.rs @@ -7,6 +7,7 @@ use std::path::{Path, PathBuf}; mod image_convert; mod metadata_file; +/* pub type TextureFileResult = Result, TextureFileError>; pub enum TextureFileError { NotFound, @@ -25,6 +26,7 @@ impl From<::image::ImageError> for TextureFileError { TextureFileError::ImageError(err) } } +*/ pub struct DataStore { //data_path: PathBuf, @@ -35,7 +37,7 @@ pub struct DataStore { id_index: HashMap, name_index: HashMap, - _preview_cache: HashMap<(TextureFormat, Sha256), Vec>, + preview_cache: HashMap<(TextureFormat, Sha256), Vec>, } impl DataStore { @@ -65,7 +67,7 @@ impl DataStore { id_index: Default::default(), name_index: Default::default(), - _preview_cache: Default::default(), + preview_cache: Default::default(), }; let metadata_file = metadata_file::MetadataFile::load(&store.index_file_path())?; @@ -172,10 +174,25 @@ impl DataStore { pub fn get_texture_preview( &mut self, - _hash: &Sha256, - _desired_format: TextureFormat, - ) -> TextureFileResult { - unimplemented!(); + hash: &Sha256, + desired_format: TextureFormat, + ) -> io::Result> { + let key = (desired_format.clone(), hash.clone()); + + if let Some(preview) = self.preview_cache.get(&key) { + return Ok(preview.clone()); + } + + let original = self.read_texture_file_by_hash(&hash)?; + + let preview = + image_convert::generate_preview(&original[..], desired_format).map_err(|_e| { + io::Error::new(io::ErrorKind::InvalidData, "Invalid Texture Image on Disk.") + })?; + + self.preview_cache.insert(key, preview.clone()); + + Ok(preview) } pub fn borrow_textures(&self) -> impl Iterator { diff --git a/server/texture-sync-server/src/server_state.rs b/server/texture-sync-server/src/server_state.rs index 0c619e6..09ef116 100644 --- a/server/texture-sync-server/src/server_state.rs +++ b/server/texture-sync-server/src/server_state.rs @@ -56,16 +56,9 @@ impl ProtocolHandler for ServerState { ) -> ProtocolResult> { let mut data_store = self.data_store.write().unwrap(); - match data_store.get_texture_preview(&hash, format) { - Ok(data) => Ok(data), - Err(TextureFileError::NotFound) => Err(ProtocolError::FileNotFound( - "Texture not found!".to_string(), - )), - Err(TextureFileError::ImageError(_)) => Err(ProtocolError::FileNotFound( - "Didn't Find valid Texture File".to_string(), - )), - Err(TextureFileError::IoError(err)) => Err(ProtocolError::InternalServerError(err)), - } + let preview = data_store.get_texture_preview(&hash, format)?; + + Ok(preview) } fn replace_texture(