├── .circleci
└── config.yml
├── .gitignore
├── CHANGELOG.md
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── README.md
├── src
├── diff.rs
├── image_creator.rs
├── lib.rs
├── main.rs
├── mkdir.rs
└── rename.rs
└── test
└── images
├── after.png
├── before.png
├── diff.png
├── marked_after.png
└── marked_before.png
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | defaults: &defaults
2 | working_directory: ~/lcs-image-diff-rs
3 | docker:
4 | - image: rustlang/rust:nightly
5 | environment:
6 | DISPLAY: ":99"
7 |
8 | version: 2
9 | jobs:
10 | build:
11 | <<: *defaults
12 | steps:
13 | - checkout
14 | - run:
15 | name: Test
16 | command: |
17 | rustup run nightly cargo test
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | /target/
3 | **/*.rs.bk
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 |
4 |
5 | ## [0.1.7](https://github.com/bokuweb/lcs-image-diff-rs/compare/0.1.6...0.1.7) (2019-01-06)
6 |
7 | ### Refactor
8 |
9 | Split crate to library and binary #4
10 |
11 |
12 | ## [0.1.6](https://github.com/bokuweb/lcs-image-diff-rs/compare/0.1.5...0.1.6) (2018-03-15)
13 |
14 | ### Bug Fixes
15 |
16 | * Fixed a bug, panic occurred when difference width image input
17 |
18 |
19 | ## [0.1.5](https://github.com/bokuweb/lcs-image-diff-rs/compare/0.1.4...0.1.5) (2018-02-25)
20 |
21 | ### Perf
22 |
23 | * Improve performance
24 |
25 |
26 | ## [0.1.4](https://github.com/bokuweb/lcs-image-diff-rs/compare/0.1.3...0.1.4) (2018-02-23)
27 |
28 | ### Bug Fixes
29 |
30 | * Fix bug, when specify only filename permission required
31 |
32 |
33 |
34 | ## [0.1.3](https://github.com/bokuweb/lcs-image-diff-rs/compare/0.1.2...0.1.3) (2018-02-23)
35 |
36 | ### Bug Fixes
37 |
38 | * Fix bug, panic occurred when dir is already exists
39 |
40 |
41 | ## [0.1.1](https://github.com/bokuweb/lcs-image-diff-rs/compare/0.1.0...0.1.1) (2018-02-23)
42 |
43 | ### Bug Fixes
44 |
45 | * Fix marked range size was wrong.
46 |
47 |
48 | ## [0.1.2](https://github.com/bokuweb/lcs-image-diff-rs/compare/0.1.1...0.1.2) (2018-02-23)
49 |
50 | ### Features
51 |
52 | * Modify default marked color
53 |
54 |
55 | ## [0.1.1](https://github.com/bokuweb/lcs-image-diff-rs/compare/0.1.0...0.1.1) (2018-02-23)
56 |
57 | ### Bug Fixes
58 |
59 | * Fix marked range size was wrong.
60 |
61 | ### Features
62 |
63 | * Modify default marked color
64 |
65 |
66 |
67 | ## 0.1.0 (2018-02-13)
68 |
69 | First release :tada:
70 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | [[package]]
2 | name = "adler32"
3 | version = "1.0.2"
4 | source = "registry+https://github.com/rust-lang/crates.io-index"
5 |
6 | [[package]]
7 | name = "ansi_term"
8 | version = "0.10.2"
9 | source = "registry+https://github.com/rust-lang/crates.io-index"
10 |
11 | [[package]]
12 | name = "arrayvec"
13 | version = "0.4.7"
14 | source = "registry+https://github.com/rust-lang/crates.io-index"
15 | dependencies = [
16 | "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
17 | ]
18 |
19 | [[package]]
20 | name = "atty"
21 | version = "0.2.6"
22 | source = "registry+https://github.com/rust-lang/crates.io-index"
23 | dependencies = [
24 | "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
25 | "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
26 | "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
27 | ]
28 |
29 | [[package]]
30 | name = "base64"
31 | version = "0.9.0"
32 | source = "registry+https://github.com/rust-lang/crates.io-index"
33 | dependencies = [
34 | "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
35 | "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
36 | ]
37 |
38 | [[package]]
39 | name = "bitflags"
40 | version = "1.0.1"
41 | source = "registry+https://github.com/rust-lang/crates.io-index"
42 |
43 | [[package]]
44 | name = "byteorder"
45 | version = "1.2.1"
46 | source = "registry+https://github.com/rust-lang/crates.io-index"
47 |
48 | [[package]]
49 | name = "cfg-if"
50 | version = "0.1.2"
51 | source = "registry+https://github.com/rust-lang/crates.io-index"
52 |
53 | [[package]]
54 | name = "clap"
55 | version = "2.30.0"
56 | source = "registry+https://github.com/rust-lang/crates.io-index"
57 | dependencies = [
58 | "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
59 | "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
60 | "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
61 | "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
62 | "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
63 | "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
64 | "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
65 | ]
66 |
67 | [[package]]
68 | name = "color_quant"
69 | version = "1.0.0"
70 | source = "registry+https://github.com/rust-lang/crates.io-index"
71 |
72 | [[package]]
73 | name = "crossbeam-deque"
74 | version = "0.2.0"
75 | source = "registry+https://github.com/rust-lang/crates.io-index"
76 | dependencies = [
77 | "crossbeam-epoch 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
78 | "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
79 | ]
80 |
81 | [[package]]
82 | name = "crossbeam-epoch"
83 | version = "0.3.0"
84 | source = "registry+https://github.com/rust-lang/crates.io-index"
85 | dependencies = [
86 | "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
87 | "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
88 | "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
89 | "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
90 | "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
91 | "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
92 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
93 | ]
94 |
95 | [[package]]
96 | name = "crossbeam-utils"
97 | version = "0.2.2"
98 | source = "registry+https://github.com/rust-lang/crates.io-index"
99 | dependencies = [
100 | "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
101 | ]
102 |
103 | [[package]]
104 | name = "deflate"
105 | version = "0.7.17"
106 | source = "registry+https://github.com/rust-lang/crates.io-index"
107 | dependencies = [
108 | "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
109 | "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
110 | ]
111 |
112 | [[package]]
113 | name = "either"
114 | version = "1.4.0"
115 | source = "registry+https://github.com/rust-lang/crates.io-index"
116 |
117 | [[package]]
118 | name = "fuchsia-zircon"
119 | version = "0.3.3"
120 | source = "registry+https://github.com/rust-lang/crates.io-index"
121 | dependencies = [
122 | "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
123 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
124 | ]
125 |
126 | [[package]]
127 | name = "fuchsia-zircon-sys"
128 | version = "0.3.3"
129 | source = "registry+https://github.com/rust-lang/crates.io-index"
130 |
131 | [[package]]
132 | name = "futures"
133 | version = "0.1.18"
134 | source = "registry+https://github.com/rust-lang/crates.io-index"
135 |
136 | [[package]]
137 | name = "futures-cpupool"
138 | version = "0.1.8"
139 | source = "registry+https://github.com/rust-lang/crates.io-index"
140 | dependencies = [
141 | "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
142 | "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
143 | ]
144 |
145 | [[package]]
146 | name = "gif"
147 | version = "0.10.1"
148 | source = "registry+https://github.com/rust-lang/crates.io-index"
149 | dependencies = [
150 | "color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
151 | "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
152 | ]
153 |
154 | [[package]]
155 | name = "image"
156 | version = "0.20.1"
157 | source = "registry+https://github.com/rust-lang/crates.io-index"
158 | dependencies = [
159 | "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
160 | "gif 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
161 | "jpeg-decoder 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
162 | "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
163 | "num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
164 | "num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
165 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
166 | "png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
167 | "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
168 | "tiff 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
169 | ]
170 |
171 | [[package]]
172 | name = "inflate"
173 | version = "0.4.4"
174 | source = "registry+https://github.com/rust-lang/crates.io-index"
175 | dependencies = [
176 | "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
177 | ]
178 |
179 | [[package]]
180 | name = "jpeg-decoder"
181 | version = "0.1.14"
182 | source = "registry+https://github.com/rust-lang/crates.io-index"
183 | dependencies = [
184 | "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
185 | "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
186 | ]
187 |
188 | [[package]]
189 | name = "lazy_static"
190 | version = "0.2.11"
191 | source = "registry+https://github.com/rust-lang/crates.io-index"
192 |
193 | [[package]]
194 | name = "lazy_static"
195 | version = "1.0.0"
196 | source = "registry+https://github.com/rust-lang/crates.io-index"
197 |
198 | [[package]]
199 | name = "lcs-diff"
200 | version = "0.1.1"
201 | source = "registry+https://github.com/rust-lang/crates.io-index"
202 |
203 | [[package]]
204 | name = "lcs-image-diff"
205 | version = "0.1.6"
206 | dependencies = [
207 | "base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
208 | "clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
209 | "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
210 | "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
211 | "image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
212 | "lcs-diff 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
213 | ]
214 |
215 | [[package]]
216 | name = "libc"
217 | version = "0.2.36"
218 | source = "registry+https://github.com/rust-lang/crates.io-index"
219 |
220 | [[package]]
221 | name = "lzw"
222 | version = "0.10.0"
223 | source = "registry+https://github.com/rust-lang/crates.io-index"
224 |
225 | [[package]]
226 | name = "memoffset"
227 | version = "0.2.1"
228 | source = "registry+https://github.com/rust-lang/crates.io-index"
229 |
230 | [[package]]
231 | name = "nodrop"
232 | version = "0.1.12"
233 | source = "registry+https://github.com/rust-lang/crates.io-index"
234 |
235 | [[package]]
236 | name = "num-derive"
237 | version = "0.2.3"
238 | source = "registry+https://github.com/rust-lang/crates.io-index"
239 | dependencies = [
240 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
241 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
242 | "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
243 | "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
244 | ]
245 |
246 | [[package]]
247 | name = "num-integer"
248 | version = "0.1.39"
249 | source = "registry+https://github.com/rust-lang/crates.io-index"
250 | dependencies = [
251 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
252 | ]
253 |
254 | [[package]]
255 | name = "num-iter"
256 | version = "0.1.35"
257 | source = "registry+https://github.com/rust-lang/crates.io-index"
258 | dependencies = [
259 | "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
260 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
261 | ]
262 |
263 | [[package]]
264 | name = "num-rational"
265 | version = "0.2.1"
266 | source = "registry+https://github.com/rust-lang/crates.io-index"
267 | dependencies = [
268 | "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
269 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
270 | ]
271 |
272 | [[package]]
273 | name = "num-traits"
274 | version = "0.2.6"
275 | source = "registry+https://github.com/rust-lang/crates.io-index"
276 |
277 | [[package]]
278 | name = "num_cpus"
279 | version = "1.8.0"
280 | source = "registry+https://github.com/rust-lang/crates.io-index"
281 | dependencies = [
282 | "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
283 | ]
284 |
285 | [[package]]
286 | name = "png"
287 | version = "0.12.0"
288 | source = "registry+https://github.com/rust-lang/crates.io-index"
289 | dependencies = [
290 | "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
291 | "deflate 0.7.17 (registry+https://github.com/rust-lang/crates.io-index)",
292 | "inflate 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
293 | "num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
294 | ]
295 |
296 | [[package]]
297 | name = "proc-macro2"
298 | version = "0.4.24"
299 | source = "registry+https://github.com/rust-lang/crates.io-index"
300 | dependencies = [
301 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
302 | ]
303 |
304 | [[package]]
305 | name = "quote"
306 | version = "0.6.10"
307 | source = "registry+https://github.com/rust-lang/crates.io-index"
308 | dependencies = [
309 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
310 | ]
311 |
312 | [[package]]
313 | name = "rand"
314 | version = "0.4.2"
315 | source = "registry+https://github.com/rust-lang/crates.io-index"
316 | dependencies = [
317 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
318 | "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
319 | "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
320 | ]
321 |
322 | [[package]]
323 | name = "rayon"
324 | version = "1.0.0"
325 | source = "registry+https://github.com/rust-lang/crates.io-index"
326 | dependencies = [
327 | "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
328 | "rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
329 | ]
330 |
331 | [[package]]
332 | name = "rayon-core"
333 | version = "1.4.0"
334 | source = "registry+https://github.com/rust-lang/crates.io-index"
335 | dependencies = [
336 | "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
337 | "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
338 | "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
339 | "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
340 | "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
341 | ]
342 |
343 | [[package]]
344 | name = "redox_syscall"
345 | version = "0.1.37"
346 | source = "registry+https://github.com/rust-lang/crates.io-index"
347 |
348 | [[package]]
349 | name = "redox_termios"
350 | version = "0.1.1"
351 | source = "registry+https://github.com/rust-lang/crates.io-index"
352 | dependencies = [
353 | "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
354 | ]
355 |
356 | [[package]]
357 | name = "safemem"
358 | version = "0.2.0"
359 | source = "registry+https://github.com/rust-lang/crates.io-index"
360 |
361 | [[package]]
362 | name = "scoped_threadpool"
363 | version = "0.1.9"
364 | source = "registry+https://github.com/rust-lang/crates.io-index"
365 |
366 | [[package]]
367 | name = "scopeguard"
368 | version = "0.3.3"
369 | source = "registry+https://github.com/rust-lang/crates.io-index"
370 |
371 | [[package]]
372 | name = "strsim"
373 | version = "0.7.0"
374 | source = "registry+https://github.com/rust-lang/crates.io-index"
375 |
376 | [[package]]
377 | name = "syn"
378 | version = "0.15.22"
379 | source = "registry+https://github.com/rust-lang/crates.io-index"
380 | dependencies = [
381 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
382 | "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
383 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
384 | ]
385 |
386 | [[package]]
387 | name = "termion"
388 | version = "1.5.1"
389 | source = "registry+https://github.com/rust-lang/crates.io-index"
390 | dependencies = [
391 | "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
392 | "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
393 | "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
394 | ]
395 |
396 | [[package]]
397 | name = "textwrap"
398 | version = "0.9.0"
399 | source = "registry+https://github.com/rust-lang/crates.io-index"
400 | dependencies = [
401 | "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
402 | ]
403 |
404 | [[package]]
405 | name = "tiff"
406 | version = "0.2.1"
407 | source = "registry+https://github.com/rust-lang/crates.io-index"
408 | dependencies = [
409 | "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
410 | "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
411 | "num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
412 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
413 | ]
414 |
415 | [[package]]
416 | name = "unicode-width"
417 | version = "0.1.4"
418 | source = "registry+https://github.com/rust-lang/crates.io-index"
419 |
420 | [[package]]
421 | name = "unicode-xid"
422 | version = "0.1.0"
423 | source = "registry+https://github.com/rust-lang/crates.io-index"
424 |
425 | [[package]]
426 | name = "vec_map"
427 | version = "0.8.0"
428 | source = "registry+https://github.com/rust-lang/crates.io-index"
429 |
430 | [[package]]
431 | name = "winapi"
432 | version = "0.3.4"
433 | source = "registry+https://github.com/rust-lang/crates.io-index"
434 | dependencies = [
435 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
436 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
437 | ]
438 |
439 | [[package]]
440 | name = "winapi-i686-pc-windows-gnu"
441 | version = "0.4.0"
442 | source = "registry+https://github.com/rust-lang/crates.io-index"
443 |
444 | [[package]]
445 | name = "winapi-x86_64-pc-windows-gnu"
446 | version = "0.4.0"
447 | source = "registry+https://github.com/rust-lang/crates.io-index"
448 |
449 | [metadata]
450 | "checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45"
451 | "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
452 | "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
453 | "checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859"
454 | "checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4"
455 | "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
456 | "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
457 | "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
458 | "checksum clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c07b9257a00f3fc93b7f3c417fc15607ec7a56823bc2c37ec744e266387de5b"
459 | "checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d"
460 | "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
461 | "checksum crossbeam-epoch 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "59796cc6cbbdc6bb319161349db0c3250ec73ec7fcb763a51065ec4e2e158552"
462 | "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
463 | "checksum deflate 0.7.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4dddda59aaab719767ab11d3efd9a714e95b610c4445d4435765021e9d52dfb1"
464 | "checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
465 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
466 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
467 | "checksum futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0bab5b5e94f5c31fc764ba5dd9ad16568aae5d4825538c01d6bca680c9bf94a7"
468 | "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
469 | "checksum gif 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4bca55ac1f213920ce3527ccd62386f1f15fa3f1714aeee1cf93f2c416903f"
470 | "checksum image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44665b4395d1844c96e7dc8ed5754782a1cdfd9ef458a80bbe45702681450504"
471 | "checksum inflate 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "84c683bde2d8413b8f1be3e459c30e4817672b6e7a31d9212b0323154e76eba7"
472 | "checksum jpeg-decoder 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0dfe27a6c0dabd772d0f9b9f8701c4ca12c4d1eebcadf2be1f6f70396f6a1434"
473 | "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
474 | "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
475 | "checksum lcs-diff 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c172ea7099cef89eb5a1a6e1f55d79a753823a0201d362f6ec5508028efcf4ed"
476 | "checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
477 | "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
478 | "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
479 | "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
480 | "checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d"
481 | "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
482 | "checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593"
483 | "checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"
484 | "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
485 | "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
486 | "checksum png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f54b9600d584d3b8a739e1662a595fab051329eff43f20e7d8cc22872962145b"
487 | "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
488 | "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
489 | "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
490 | "checksum rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "485541959c8ecc49865526fe6c4de9653dd6e60d829d6edf0be228167b60372d"
491 | "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
492 | "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
493 | "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
494 | "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
495 | "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
496 | "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
497 | "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
498 | "checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7"
499 | "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
500 | "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
501 | "checksum tiff 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a2cc6c4fd13cb1cfd20abdb196e794ceccb29371855b7e7f575945f920a5b3c2"
502 | "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
503 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
504 | "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
505 | "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
506 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
507 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
508 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "lcs-image-diff"
3 | version = "0.1.6"
4 | repository = "https://github.com/bokuweb/lcs-image-diff-rs"
5 | license = "MIT"
6 | readme = "README.md"
7 | authors = ["bokuweb "]
8 | description = "Image diff tool with LCS algorithm"
9 | keywords = [
10 | "diff",
11 | "image",
12 | "lcs",
13 | ]
14 |
15 | [lib]
16 | name = "lcs_image_diff"
17 | path = "src/lib.rs"
18 |
19 | [[bin]]
20 | name = "lcs-image-diff"
21 | path = "src/main.rs"
22 | required-features = ["binary"]
23 |
24 | [features]
25 | default = ["binary"]
26 | binary = ["futures", "futures-cpupool", "all_image_formats"]
27 | all_image_formats = [
28 | "image/gif_codec",
29 | "image/jpeg",
30 | "image/ico",
31 | "image/png_codec",
32 | "image/pnm",
33 | "image/tga",
34 | "image/tiff",
35 | "image/webp",
36 | "image/bmp",
37 | "image/hdr",
38 | "image/dxt",
39 | "image/jpeg_rayon"
40 | ]
41 |
42 | [dependencies]
43 | base64 = "0.9.0"
44 | clap = "2.30.0"
45 | futures = { version = "0.1.18", optional = true }
46 | futures-cpupool = { version = "0.1.8", optional = true }
47 | image = { version = "0.20", default-features = false }
48 | lcs-diff = "0.1.1"
49 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 @bokuweb
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # lcs-image-diff
2 | Image diff library and tool with LCS algorithm. rust port of [murooka/go-diff-image](https://github.com/murooka/go-diff-image)
3 |
4 | [](https://crates.io/crates/lcs-image-diff)
5 | [](https://circleci.com/gh/bokuweb/lcs-image-diff-rs/tree/master)
6 |
7 | ## Requirements
8 | - latest Rust (recommend [rustup](https://www.rustup.rs/))
9 |
10 | ## Library
11 |
12 | ### Usage
13 |
14 | ```toml
15 | # Cargo.toml
16 | [dependencies]
17 | image = "0.20"
18 | lcs-image-diff = { version = "0.1", default-features = false }
19 | ```
20 |
21 | ```rust
22 | use lcs_image_diff::compare;
23 |
24 | let mut before = image::open("before.png")?;
25 | let mut after = image::open("after.png")?;
26 |
27 | let diff = compare(&mut before, &mut after, 100.0 / 256.0)?;
28 |
29 | before.save("marked_before.png")?;
30 | after.save("marked_after.png")?;
31 | diff.save("diff.png")?;
32 | ```
33 |
34 | ## Binary
35 |
36 | ### Installation
37 |
38 | ``` bash
39 | cargo install lcs-image-diff
40 | ```
41 |
42 | ### Usage
43 |
44 | ```
45 | lcs-image-diff path/to/before.png path/to/after.png path/to/diff.png
46 | ```
47 |
48 | ## Example
49 |
50 | | before.png | after.png | diff.png |
51 | | --------------- |---------------| -------------------- |
52 | |  |  ||
53 |
54 | `lcs-image-diff` outputs marked before and after images too.
55 |
56 | | marked_before.png | marked_after.png |
57 | | --------------- |---------------|
58 | |  |  |
59 |
60 | ## LICENSE
61 |
62 | The MIT License (MIT)
63 |
64 | Copyright (c) 2018 @bokuweb
65 |
66 | Permission is hereby granted, free of charge, to any person obtaining a copy
67 | of this software and associated documentation files (the "Software"), to deal
68 | in the Software without restriction, including without limitation the rights
69 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
70 | copies of the Software, and to permit persons to whom the Software is
71 | furnished to do so, subject to the following conditions:
72 |
73 | The above copyright notice and this permission notice shall be included in all
74 | copies or substantial portions of the Software.
75 |
76 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
77 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
78 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
79 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
80 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
82 | SOFTWARE.
83 |
--------------------------------------------------------------------------------
/src/diff.rs:
--------------------------------------------------------------------------------
1 | use super::base64::encode;
2 | use super::lcs_diff;
3 |
4 | #[derive(Debug)]
5 | pub struct CompareImage {
6 | dimensions: (u32, u32),
7 | pixels: Vec,
8 | }
9 |
10 | impl CompareImage {
11 | pub fn new(dimensions: (u32, u32), pixels: Vec) -> Self {
12 | CompareImage { dimensions, pixels }
13 | }
14 |
15 | pub fn create_encoded_rows(&self) -> Vec {
16 | self.pixels
17 | .chunks(self.dimensions.0 as usize * 4)
18 | .map(|chunk| encode(chunk))
19 | .collect()
20 | }
21 | }
22 |
23 | pub fn diff(imga: CompareImage, imgb: CompareImage) -> Vec> {
24 | let imga = imga.create_encoded_rows();
25 | let imgb = imgb.create_encoded_rows();
26 | lcs_diff::diff(&imga, &imgb)
27 | }
--------------------------------------------------------------------------------
/src/image_creator.rs:
--------------------------------------------------------------------------------
1 | use std::cmp;
2 | use super::image::*;
3 | use super::lcs_diff::*;
4 | use super::base64::decode;
5 |
6 | pub static BLACK: (u8, u8, u8) = (0, 0, 0);
7 | pub static RED: (u8, u8, u8) = (255, 119, 119);
8 | pub static GREEN: (u8, u8, u8) = (99, 195, 99);
9 |
10 | fn compute_range(r: &Vec) -> Vec<(usize, usize)> {
11 | let mut i = 0;
12 | let mut j = 0;
13 | let mut acc: usize;
14 | let mut y1: usize;
15 | let mut ranges: Vec<(usize, usize)> = Vec::new();
16 | while i < r.len() {
17 | y1 = r[i];
18 | acc = y1;
19 | i += 1;
20 | loop {
21 | if i >= r.len() {
22 | break;
23 | }
24 | let index = r[i];
25 | if acc + 1 != index {
26 | break;
27 | }
28 | acc = index;
29 | i += 1;
30 | j += 1;
31 | }
32 | let y2 = y1 + j;
33 | j = 0;
34 | ranges.push((y1, y2));
35 | }
36 | ranges
37 | }
38 |
39 | fn blend_diff_area(img: &mut G, ranges: Vec<(usize, usize)>, rgb: (u8, u8, u8), rate: f32)
40 | where
41 | G: GenericImage>,
42 | {
43 | for (y1, y2) in ranges {
44 | for y in y1..(y2 + 1) {
45 | for x in 0..img.dimensions().0 {
46 | let p = img.get_pixel(x, y as u32);
47 | let blended = blend(p, rgb, rate);
48 | img.put_pixel(x, y as u32, blended);
49 | }
50 | }
51 | }
52 | }
53 |
54 | fn blend(base: Rgba, rgb: (u8, u8, u8), rate: f32) -> Rgba {
55 | return Rgba {
56 | data: [
57 | (base.data[0] as f32 * (1.0 - rate) + rgb.0 as f32 * (rate)) as u8,
58 | (base.data[1] as f32 * (1.0 - rate) + rgb.1 as f32 * (rate)) as u8,
59 | (base.data[2] as f32 * (1.0 - rate) + rgb.2 as f32 * (rate)) as u8,
60 | base.data[3],
61 | ],
62 | };
63 | }
64 |
65 | fn put_diff_pixels(
66 | y: usize,
67 | img: &mut ImageBuffer, Vec>,
68 | row_width: u32,
69 | data: &String,
70 | rgb: (u8, u8, u8),
71 | rate: f32,
72 | ) -> Result<(), base64::DecodeError> {
73 | let row = decode(data)?;
74 | for x in 0..img.dimensions().0 {
75 | let index = x as usize * 4;
76 | let pixel: Rgba = if row_width > x {
77 | Rgba {
78 | data: [row[index], row[index + 1], row[index + 2], row[index + 3]],
79 | }
80 | } else {
81 | Rgba { data: [0, 0, 0, 0] }
82 | };
83 | img.put_pixel(x as u32, y as u32, blend(pixel, rgb, rate));
84 | }
85 | Ok(())
86 | }
87 |
88 | pub fn mark_org_image(
89 | base: &mut DynamicImage,
90 | color: (u8, u8, u8),
91 | rate: f32,
92 | indexes: &Vec,
93 | ) {
94 | let range = compute_range(indexes);
95 | blend_diff_area(base, range, color, rate);
96 | }
97 |
98 | pub fn get_diff_image(
99 | before_width: u32,
100 | after_width: u32,
101 | result: &Vec>,
102 | rate: f32,
103 | ) -> Result {
104 | let height = result.len() as u32;
105 | let width = cmp::max(before_width, after_width);
106 | let mut img: ImageBuffer, Vec> = ImageBuffer::new(width, height);
107 | for (y, d) in result.iter().enumerate() {
108 | match d {
109 | &DiffResult::Added(ref a) => {
110 | put_diff_pixels(y, &mut img, after_width, &a.data, GREEN, rate)?
111 | }
112 | &DiffResult::Removed(ref r) => {
113 | put_diff_pixels(y, &mut img, before_width, &r.data, RED, rate)?
114 | }
115 | &DiffResult::Common(ref c) => {
116 | put_diff_pixels(y, &mut img, width, &c.data, BLACK, 0.0)?
117 | }
118 | }
119 | }
120 | Ok(ImageRgba8(img))
121 | }
122 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | extern crate base64;
2 | extern crate image;
3 | extern crate lcs_diff;
4 |
5 | mod diff;
6 | mod image_creator;
7 |
8 | use diff::*;
9 | use image_creator::*;
10 | use image::*;
11 | pub use base64::DecodeError;
12 |
13 | /// Accepts two mutable references to `image::DynamicImage` and rate.
14 | /// Returns diff `image::DynamicImage` and marks removed and added
15 | /// parts on input images.
16 | ///
17 | /// # Examples
18 | ///
19 | /// ```no_run
20 | /// extern crate image;
21 | /// # use std::error::Error;
22 | /// # fn main() -> Result<(), Box> {
23 | /// use lcs_image_diff::compare;
24 | ///
25 | /// let mut before = image::open("before.png")?;
26 | /// let mut after = image::open("after.png")?;
27 | ///
28 | /// let diff = compare(&mut before, &mut after, 100.0 / 256.0)?;
29 | ///
30 | /// before.save("marked_before.png")?;
31 | /// after.save("marked_after.png")?;
32 | /// diff.save("diff.png")?;
33 | /// # Ok(())
34 | /// # }
35 | /// ```
36 | pub fn compare(
37 | before: &mut DynamicImage,
38 | after: &mut DynamicImage,
39 | rate: f32
40 | ) -> Result {
41 | let compare_before = CompareImage::new(before.dimensions(), before.raw_pixels());
42 | let compare_after = CompareImage::new(after.dimensions(), after.raw_pixels());
43 | let result = diff(compare_before, compare_after);
44 |
45 | let mut added: Vec = Vec::new();
46 | let mut removed: Vec = Vec::new();
47 | for d in result.iter() {
48 | match d {
49 | &lcs_diff::DiffResult::Added(ref a) => added.push(a.new_index.unwrap()),
50 | &lcs_diff::DiffResult::Removed(ref r) => removed.push(r.old_index.unwrap()),
51 | _ => (),
52 | }
53 | }
54 |
55 | mark_org_image(before, RED, rate, &removed);
56 | mark_org_image(after, GREEN, rate, &added);
57 |
58 | get_diff_image(before.dimensions().0, after.dimensions().0, &result, rate)
59 | }
60 |
--------------------------------------------------------------------------------
/src/main.rs:
--------------------------------------------------------------------------------
1 | extern crate futures;
2 | extern crate futures_cpupool;
3 | extern crate image;
4 | extern crate lcs_image_diff;
5 |
6 | #[macro_use]
7 | extern crate clap;
8 |
9 | mod mkdir;
10 | mod rename;
11 |
12 | use std::path::Path;
13 | use image::*;
14 | use rename::*;
15 | use mkdir::*;
16 | use clap::{App, Arg};
17 | use futures_cpupool::CpuPool;
18 | use futures::{future, Future};
19 | use lcs_image_diff::compare;
20 |
21 | static RATE: f32 = 100.0 / 256.0;
22 |
23 | pub fn save_image(image: &DynamicImage, filename: &str) {
24 | let path = Path::new(filename).parent().unwrap();
25 | let _result = mkdirp(path);
26 | image.save(filename).unwrap();
27 | }
28 |
29 | fn main() {
30 | let app = App::new(crate_name!())
31 | .version(crate_version!())
32 | .author(crate_authors!())
33 | .about(crate_description!())
34 | .arg(
35 | Arg::with_name("before_image")
36 | .help("path to before image")
37 | .required(true),
38 | )
39 | .arg(
40 | Arg::with_name("after_image")
41 | .help("path to after image")
42 | .required(true),
43 | )
44 | .arg(
45 | Arg::with_name("diff_image")
46 | .help("path to diff image")
47 | .required(true),
48 | );
49 | let matches = app.get_matches();
50 | let before_image = matches.value_of("before_image").unwrap();
51 | let after_image = matches.value_of("after_image").unwrap();
52 | let diff_image = matches.value_of("diff_image").unwrap().to_owned();
53 | let mut before = image::open(before_image).unwrap();
54 | let mut after = image::open(after_image).unwrap();
55 |
56 | let marked_before = add_prefix_to_file_name(&before_image, &"marked_");
57 | let marked_after = add_prefix_to_file_name(&after_image, &"marked_");
58 |
59 | let result = compare(&mut before, &mut after, RATE).unwrap();
60 |
61 | {
62 | let thread_pool = CpuPool::new_num_cpus();
63 | let before_thread = thread_pool.spawn_fn(move || -> Result<(), ()> {
64 | save_image(&before, &marked_before);
65 | Ok(())
66 | });
67 | let after_thread = thread_pool.spawn_fn(move || -> Result<(), ()> {
68 | save_image(&after, &marked_after);
69 | Ok(())
70 | });
71 | let result_thread = thread_pool.spawn_fn(move || -> Result<(), ()> {
72 | save_image(&result, &diff_image);
73 | Ok(())
74 | });
75 | future::join_all(vec![before_thread, after_thread, result_thread])
76 | .wait()
77 | .unwrap();
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/mkdir.rs:
--------------------------------------------------------------------------------
1 | use std::io;
2 | use std::path::Path;
3 | use std::fs::create_dir_all;
4 |
5 | pub fn mkdirp>(p: P) -> io::Result<()> {
6 | if let Err(e) = create_dir_all(p) {
7 | if e.kind() != io::ErrorKind::AlreadyExists {
8 | return Ok(());
9 | }
10 | return Err(e);
11 | }
12 | Ok(())
13 | }
--------------------------------------------------------------------------------
/src/rename.rs:
--------------------------------------------------------------------------------
1 | use std::path::Path;
2 |
3 | pub fn add_prefix_to_file_name(file_name: &str, prefix: &str) -> String {
4 | let path = Path::new(file_name);
5 | let file_name = path.file_name().unwrap();
6 | let dir = path.parent().unwrap();
7 | if dir.to_str().unwrap() == "" {
8 | return format!("{}{}", prefix, file_name.to_str().unwrap());
9 | }
10 | format!("{}/{}{}",
11 | dir.to_str().unwrap(),
12 | prefix,
13 | file_name.to_str().unwrap())
14 | }
15 |
16 | #[test]
17 | fn shoud_add_prefix_with_dir() {
18 | let filename = add_prefix_to_file_name(&"foo/bar/filename.png", &"sample_");
19 | assert_eq!(filename, "foo/bar/sample_filename.png");
20 | }
21 |
22 | #[test]
23 | fn shoud_add_prefix_without_dir() {
24 | let filename = add_prefix_to_file_name(&"filename.png", &"sample_");
25 | assert_eq!(filename, "sample_filename.png");
26 | }
--------------------------------------------------------------------------------
/test/images/after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bokuweb/lcs-image-diff-rs/d29feda97e6365e4f6d922c2773b3ca2a494b6a0/test/images/after.png
--------------------------------------------------------------------------------
/test/images/before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bokuweb/lcs-image-diff-rs/d29feda97e6365e4f6d922c2773b3ca2a494b6a0/test/images/before.png
--------------------------------------------------------------------------------
/test/images/diff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bokuweb/lcs-image-diff-rs/d29feda97e6365e4f6d922c2773b3ca2a494b6a0/test/images/diff.png
--------------------------------------------------------------------------------
/test/images/marked_after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bokuweb/lcs-image-diff-rs/d29feda97e6365e4f6d922c2773b3ca2a494b6a0/test/images/marked_after.png
--------------------------------------------------------------------------------
/test/images/marked_before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bokuweb/lcs-image-diff-rs/d29feda97e6365e4f6d922c2773b3ca2a494b6a0/test/images/marked_before.png
--------------------------------------------------------------------------------