1use image::open;
2use image::DynamicImage;
3use image::GenericImageView;
4use image::ImageBuffer;
5use image::Rgba;
6use thiserror::Error;
7
8pub mod options;
9
10#[derive(Error, Debug)]
11pub enum Error {
12 #[error(transparent)]
13 ImageError(#[from] image::ImageError),
14}
15
16const EQUAL_COLOR: Rgba<u8> = Rgba([255, 255, 255, 255]);
17const CHANGED_COLOR: Rgba<u8> = Rgba([255, 0, 0, 255]);
18
19pub fn compare_images(original: &DynamicImage, compared: &DynamicImage) -> DynamicImage {
20 let (width, height) = original.dimensions();
21
22 DynamicImage::ImageRgba8(ImageBuffer::from_fn(width, height, |x, y| {
23 let original_pixel = original.get_pixel(x, y);
24 let compared_pixel = compared.get_pixel(x, y);
25 if original_pixel == compared_pixel {
26 EQUAL_COLOR
27 } else {
28 CHANGED_COLOR
29 }
30 }))
31}
32
33pub fn compare_images_color_difference(
34 original: &DynamicImage,
35 compared: &DynamicImage,
36) -> DynamicImage {
37 let (width, height) = original.dimensions();
38
39 DynamicImage::ImageRgba8(ImageBuffer::from_fn(width, height, |x, y| {
40 let original_pixel = original.get_pixel(x, y);
41 let compared_pixel = compared.get_pixel(x, y);
42 Rgba([
43 rgb_channel_difference(original_pixel[0], compared_pixel[0]),
44 rgb_channel_difference(original_pixel[1], compared_pixel[1]),
45 rgb_channel_difference(original_pixel[2], compared_pixel[2]),
46 255,
47 ])
48 }))
49}
50
51fn rgb_channel_difference(original: u8, compared: u8) -> u8 {
52 255 - ((original as i16 - compared as i16).abs() as u8)
53}
54
55pub fn compare_images_from_path(original: &str, compared: &str) -> Result<DynamicImage, Error> {
56 let original_img = open(original)?;
57 let compared_img = open(compared)?;
58 Ok(compare_images(&original_img, &compared_img))
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn basic_test() {
67 assert_eq!(1, 1);
68 }
69}