1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use super::config::ProcessorConfig;
use super::processor::{ExifProcessor, ImageProcessor, Processor};
use crate::core::LennaImage;
use exif::{Field, In, Tag, Value};
use image::DynamicImage;
use serde::{Deserialize, Serialize};
use std::include_bytes;
#[repr(C)]
#[derive(Default, Clone)]
pub struct Resize {
config: Config,
}
#[derive(Clone, Serialize, Deserialize)]
struct Config {
width: u32,
height: u32,
}
impl Default for Config {
fn default() -> Self {
Config {
width: 400,
height: 400,
}
}
}
impl ImageProcessor for Resize {
fn process_image(
&self,
image: &mut Box<DynamicImage>,
) -> Result<(), Box<dyn std::error::Error>> {
let resized = image.thumbnail(self.config.width, self.config.height);
*image = Box::new(resized);
Ok(())
}
}
impl ExifProcessor for Resize {
fn process_exif(&self, exif: &mut Box<Vec<Field>>) -> Result<(), Box<dyn std::error::Error>> {
let width = Field {
tag: Tag::PixelXDimension,
ifd_num: In::PRIMARY,
value: Value::Short(vec![self.config.width as u16]),
};
exif.push(width);
let height = Field {
tag: Tag::PixelYDimension,
ifd_num: In::PRIMARY,
value: Value::Short(vec![self.config.height as u16]),
};
exif.push(height);
Ok(())
}
}
impl Processor for Resize {
fn name(&self) -> String {
"resize".into()
}
fn title(&self) -> String {
"Resize".into()
}
fn author(&self) -> String {
"chriamue".into()
}
fn description(&self) -> String {
"Plugin to resize image size.".into()
}
fn process(
&mut self,
config: ProcessorConfig,
image: &mut Box<LennaImage>,
) -> Result<(), Box<dyn std::error::Error>> {
let config: Config = serde_json::from_value(config.config).unwrap();
self.config = config;
self.process_exif(&mut image.exif).unwrap();
self.process_image(&mut image.image).unwrap();
Ok(())
}
fn default_config(&self) -> serde_json::Value {
serde_json::to_value(Config::default()).unwrap()
}
fn config_ui(&self) -> Option<String> {
Some(include_str!("resize.vue").to_string())
}
fn icon(&self) -> Option<Vec<u8>> {
let data: Vec<u8> = include_bytes!("../assets/resize.png").to_vec();
Some(data)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default() {
let resize = Resize::default();
assert_eq!(resize.name(), "resize");
assert_eq!(resize.default_config()["width"], 400);
assert_eq!(resize.default_config()["height"], 400);
let ui = resize.config_ui().unwrap();
assert_eq!(ui.starts_with("<template>"), true);
}
#[test]
fn icon() {
let resize = Resize::default();
let icon = resize.icon();
assert!(icon.is_some());
assert_eq!(icon.unwrap().len(), 36408);
}
}