From b9cf095cfa3a69e915d782fb287f4f794af84685 Mon Sep 17 00:00:00 2001 From: trivernis Date: Wed, 16 Dec 2020 17:32:30 +0100 Subject: [PATCH] Add image filters Signed-off-by: trivernis --- README.md | 2 +- src/elements/mod.rs | 20 ++++++++++++++++++ src/parser/inline.rs | 26 +++++++++++++---------- src/utils/image_converting.rs | 39 ++++++++++++++++++++++++++++++++++- 4 files changed, 74 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index b8b8004..181b9a9 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,7 @@ Hide a section (including subsections) in the TOC #[toc-hidden] Section Set the size of an image -!(url)[width = 42% height=auto] +!(url)[width = 42%, height=auto, grayscale, brightness=10, contrast=1.2] Set the source of a quote [author=Me date=[[date]] display="{{author}} - {{date}}"]> It's me diff --git a/src/elements/mod.rs b/src/elements/mod.rs index 12d4d8c..da3363a 100644 --- a/src/elements/mod.rs +++ b/src/elements/mod.rs @@ -710,6 +710,8 @@ impl Placeholder { pub trait Metadata { fn get_bool(&self, key: &str) -> bool; fn get_string(&self, key: &str) -> Option; + fn get_float(&self, key: &str) -> Option; + fn get_integer(&self, key: &str) -> Option; fn get_string_map(&self) -> HashMap; } @@ -730,6 +732,24 @@ impl Metadata for InlineMetadata { } } + fn get_float(&self, key: &str) -> Option { + if let Some(MetadataValue::Float(f)) = self.data.get(key) { + Some(*f) + } else if let Some(MetadataValue::Integer(i)) = self.data.get(key) { + Some(*i as f64) + } else { + None + } + } + + fn get_integer(&self, key: &str) -> Option { + if let Some(MetadataValue::Integer(i)) = self.data.get(key) { + Some(*i) + } else { + None + } + } + fn get_string_map(&self) -> HashMap { let mut string_map = HashMap::new(); for (k, v) in &self.data { diff --git a/src/parser/inline.rs b/src/parser/inline.rs index 9895c06..39bd2d6 100644 --- a/src/parser/inline.rs +++ b/src/parser/inline.rs @@ -140,21 +140,24 @@ impl ParseInline for Parser { self.ctm.seek_one()?; if let Ok(url) = self.parse_url(true) { - let metadata = if let Ok(meta) = self.parse_inline_metadata() { - Some(meta) - } else { - None - }; + let metadata = self.parse_inline_metadata().ok(); + let path = url.url.clone(); + let pending_image = self + .options + .document + .images + .lock() + .add_image(PathBuf::from(path)); + + if let Some(meta) = &metadata { + pending_image.lock().assign_from_meta(meta) + } + Ok(Image { url, metadata, - image_data: self - .options - .document - .images - .lock() - .add_image(PathBuf::from(path)), + image_data: pending_image, }) } else { Err(self.ctm.rewind_with_error(start_index)) @@ -502,6 +505,7 @@ impl ParseInline for Parser { self.ctm.seek_any(&INLINE_WHITESPACE)?; let mut value = MetadataValue::Bool(true); + if self.ctm.check_char(&EQ) { self.ctm.seek_one()?; self.ctm.seek_any(&INLINE_WHITESPACE)?; diff --git a/src/utils/image_converting.rs b/src/utils/image_converting.rs index d0d5aab..84e7cbf 100644 --- a/src/utils/image_converting.rs +++ b/src/utils/image_converting.rs @@ -1,3 +1,4 @@ +use crate::elements::Metadata; use crate::utils::caching::CacheStorage; use crate::utils::downloads::download_path; use image::imageops::FilterType; @@ -60,6 +61,9 @@ pub struct PendingImage { pub data: Option>, cache: CacheStorage, pub mime: Mime, + brightness: Option, + contrast: Option, + grayscale: bool, } impl PendingImage { @@ -71,9 +75,22 @@ impl PendingImage { data: None, cache: CacheStorage::new(), mime, + brightness: None, + contrast: None, + grayscale: false, } } + pub fn assign_from_meta(&mut self, meta: &M) { + if let Some(brightness) = meta.get_integer("brightness") { + self.brightness = Some(brightness as i32); + } + if let Some(contrast) = meta.get_float("contrast") { + self.contrast = Some(contrast as f32); + } + self.grayscale = meta.get_bool("grayscale"); + } + /// Converts the image to the specified target format (specified by target_extension) pub fn convert( &mut self, @@ -87,6 +104,7 @@ impl PendingImage { .and_then(|extension| ImageFormat::from_extension(extension)) }) .unwrap_or(ImageFormat::Png); + let output_path = self.get_output_path(format, target_size); self.mime = get_mime(&output_path); @@ -118,6 +136,18 @@ impl PendingImage { image = image.resize(width, height, FilterType::Lanczos3); } } + + if let Some(brightness) = self.brightness { + image = image.brighten(brightness); + } + + if let Some(contrast) = self.contrast { + image = image.adjust_contrast(contrast); + } + if self.grayscale { + image = image.grayscale(); + } + let data = Vec::new(); let mut writer = Cursor::new(data); @@ -155,7 +185,14 @@ impl PendingImage { if let Some(target_size) = target_size { file_name += &*format!("-{}-{}", target_size.0, target_size.1); } - file_name += format!("-{}-converted", type_name).as_str(); + if let Some(b) = self.brightness { + file_name += &*format!("-{}", b); + } + if let Some(c) = self.contrast { + file_name += &*format!("-{}", c); + } + + file_name += format!("-{}", type_name).as_str(); path.set_file_name(file_name); path.set_extension(extension);