@@ -3,6 +3,7 @@ extern crate lazy_static;
3
3
extern crate opencv;
4
4
extern crate iron;
5
5
extern crate regex;
6
+ extern crate rexiv2;
6
7
7
8
use opencv:: core as cv;
8
9
use opencv:: types:: { VectorOfint , VectorOfuchar } ;
@@ -29,12 +30,14 @@ fn main() {
29
30
match regex. captures ( & req. url . path . join ( "/" ) ) {
30
31
Some ( cap) => {
31
32
let ext = cap. at ( 3 ) . unwrap ( ) ;
32
- let path = format ! ( "{}{}.{}" , MEDIA_DIRECTORY . to_string( ) , cap. at( 2 ) . unwrap( ) , ext) ;
33
- if !Path :: new ( & path) . exists ( ) {
33
+ let path_regular = format ! ( "{}regular/{}.{}" , MEDIA_DIRECTORY . to_string( ) , cap. at( 2 ) . unwrap( ) , ext) ;
34
+ let path_original = format ! ( "{}original/{}.{}" , MEDIA_DIRECTORY . to_string( ) , cap. at( 2 ) . unwrap( ) , ext) ;
35
+
36
+ if !Path :: new ( & path_original) . exists ( ) {
34
37
return Ok ( Response :: with ( ( iron:: status:: NotFound , "Image not found" ) ) ) ;
35
38
}
36
39
37
- return handle_image ( cap. at ( 1 ) . unwrap ( ) , & path , ext) ;
40
+ return handle_image ( cap. at ( 1 ) . unwrap ( ) , & path_original , & path_regular , ext) ;
38
41
} ,
39
42
None => Ok ( Response :: with ( ( iron:: status:: NotFound , "Invalid url" ) ) ) ,
40
43
}
@@ -43,7 +46,7 @@ fn main() {
43
46
Iron :: new ( handler) . http ( "0.0.0.0:3000" ) . unwrap ( ) ;
44
47
}
45
48
46
- fn handle_image ( filters : & str , path : & str , ext : & str ) -> IronResult < Response > {
49
+ fn handle_image ( filters : & str , path_original : & str , path_regular : & str , ext : & str ) -> IronResult < Response > {
47
50
let splitted: Vec < & str > = filters. split ( "+" ) . collect ( ) ;
48
51
let mut operations: Vec < Transformation > = Vec :: new ( ) ;
49
52
for entry in & splitted {
@@ -57,6 +60,13 @@ fn handle_image(filters: &str, path: &str, ext: &str) -> IronResult<Response> {
57
60
}
58
61
}
59
62
63
+ let path: & str ;
64
+ if is_regular_can_be_used ( & operations, path_regular) {
65
+ path = path_regular;
66
+ } else {
67
+ path = path_original;
68
+ }
69
+
60
70
let mut buffer = VectorOfuchar :: new ( ) ;
61
71
let mut mat = highgui:: imread ( path, highgui:: IMREAD_UNCHANGED ) . unwrap ( ) ;
62
72
@@ -76,6 +86,39 @@ fn handle_image(filters: &str, path: &str, ext: &str) -> IronResult<Response> {
76
86
Ok ( Response :: with ( ( content_type, status:: Ok , buffer. to_vec ( ) ) ) )
77
87
}
78
88
89
+ fn is_regular_can_be_used ( operations : & Vec < Transformation > , path_regular : & str ) -> bool {
90
+ if Path :: new ( & path_regular) . exists ( ) {
91
+ return match rexiv2:: Metadata :: new_from_path ( path_regular) {
92
+ Ok ( meta) => {
93
+ let width = meta. get_pixel_width ( ) ;
94
+ let height = meta. get_pixel_height ( ) ;
95
+ let mut result = false ;
96
+
97
+ for operation in operations {
98
+ match operation. is_regular_can_be_used ( width, height) {
99
+ Cache :: NOT_AFFECT => {
100
+ continue ;
101
+ } ,
102
+ Cache :: NOT_APPLIED => {
103
+ result = false ;
104
+ break ;
105
+ } ,
106
+ Cache :: APPLIED => {
107
+ result = true ;
108
+ break ;
109
+ }
110
+ }
111
+ }
112
+
113
+ result
114
+ } ,
115
+ Err ( err) => false
116
+ }
117
+ }
118
+
119
+ return false ;
120
+ }
121
+
79
122
#[ derive( Debug ) ]
80
123
enum Transformation {
81
124
Resize {
@@ -97,8 +140,17 @@ enum Transformation {
97
140
}
98
141
}
99
142
143
+ enum Cache {
144
+ APPLIED , // return if image can be based on regular
145
+ NOT_APPLIED , // cannot be based on regular
146
+ NOT_AFFECT // has no affect for image size
147
+ }
148
+
100
149
trait TransformationTrait {
101
150
fn apply ( & self , mat : & cv:: Mat ) -> cv:: Mat ;
151
+
152
+ // Return true if regular image can be read for this transformation
153
+ fn is_regular_can_be_used ( & self , width : i32 , height : i32 ) -> Cache ;
102
154
}
103
155
104
156
impl TransformationTrait for Transformation {
@@ -161,7 +213,7 @@ impl TransformationTrait for Transformation {
161
213
} ;
162
214
}
163
215
return cv:: Mat :: rect ( & resized, rect) . unwrap ( ) ;
164
- }
216
+ } ,
165
217
Transformation :: CropCoordinates { x1, y1, x2, y2 } => {
166
218
let rect = cv:: Rect {
167
219
x : x1,
@@ -173,6 +225,35 @@ impl TransformationTrait for Transformation {
173
225
}
174
226
}
175
227
}
228
+ fn is_regular_can_be_used ( & self , regular_width : i32 , regular_height : i32 ) -> Cache {
229
+ match * self {
230
+ Transformation :: Resize { height, width } => {
231
+ let condition: bool ;
232
+ if height. is_some ( ) && width. is_some ( ) {
233
+ condition = regular_width >= width. unwrap ( ) && regular_height >= height. unwrap ( ) ;
234
+ } else if height. is_some ( ) {
235
+ condition = regular_height >= height. unwrap ( ) ;
236
+ } else {
237
+ condition = regular_width >= width. unwrap ( ) ;
238
+ }
239
+
240
+ if condition {
241
+ return Cache :: APPLIED ;
242
+ } else {
243
+ return Cache :: NOT_APPLIED ;
244
+ }
245
+ } ,
246
+ Transformation :: CropCoordinates { x1, y1, x2, y2 } => Cache :: NOT_APPLIED ,
247
+ Transformation :: Crop { height, width } => {
248
+ if regular_width >= width && regular_height >= height {
249
+ return Cache :: APPLIED ;
250
+ } else {
251
+ return Cache :: NOT_APPLIED ;
252
+ }
253
+ } ,
254
+ Transformation :: Rotate { degrees } => Cache :: NOT_AFFECT
255
+ }
256
+ }
176
257
}
177
258
178
259
fn create_operation ( entry : & str ) -> Option < Transformation > {
0 commit comments