1use anyhow::Error;
2use image::{DynamicImage, GenericImage, GenericImageView, Rgba};
3use std::cmp::max;
4
5pub type Result<T> = std::result::Result<T, Error>;
6
7pub fn diff(before: &DynamicImage, after: &DynamicImage) -> Result<DynamicImage> {
8 let (after_width, after_height) = after.dimensions();
9 let (before_width, before_height) = before.dimensions();
10 let width = max(after_width, before_width);
11 let height = max(after_height, before_height);
12 let mut result = DynamicImage::new_rgba8(width, height);
13
14 for y in 0..height {
15 for x in 0..width {
16 let new_color: [u8; 4];
17 let pixel: Rgba<u8>;
18 if x >= before_width
19 || y >= before_height
20 || x >= after_width
21 || y >= after_height
22 {
23 new_color = [255, 0, 0, 255];
24 pixel = Rgba(new_color);
25 } else {
26 let before_pixel: Rgba<u8> = before.get_pixel(x, y);
27 let after_pixel: Rgba<u8> = after.get_pixel(x, y);
28 let alpha = before_pixel[3];
29
30 let is_diff = before_pixel[0] != after_pixel[0]
31 || before_pixel[1] != after_pixel[1]
32 || before_pixel[2] != after_pixel[2];
33
34 let mut new_red = after_pixel[0];
35 let mut new_green = after_pixel[1];
36 let mut new_blue = after_pixel[2];
37 if is_diff {
38 new_red = 255;
39 new_green = 0;
40 new_blue = 0;
41 }
42
43 new_color = [new_red, new_green, new_blue, alpha];
44 pixel = Rgba(new_color);
45
46 }
47 result.put_pixel(x, y, pixel);
48 }
49 }
50 Ok(result)
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn test_diff() {
59 let before = image::open("test/before.png");
60 let after = image::open("test/after.png").unwrap();
61 let dif = diff(&before.unwrap(), &after);
62 assert_eq!(true, dif.is_ok());
63 }
64}