extern crate image;
use image::RgbImage;
pub(crate) type MetricFn = fn(&RgbImage, &RgbImage) -> i64;
pub fn norm_l1(img1: &RgbImage, img2: &RgbImage) -> i64 {
img1.pixels().zip(img2.pixels()).fold(0, |sum, (p1, p2)| {
sum + (p1[0].abs_diff(p2[0]) as i64)
+ (p1[1].abs_diff(p2[1]) as i64)
+ (p1[2].abs_diff(p2[2]) as i64)
})
}
pub fn norm_l2(img1: &RgbImage, img2: &RgbImage) -> i64 {
img1.pixels()
.zip(img2.pixels())
.fold(0, |sum, (p1, p2)| {
sum + (p1[0].abs_diff(p2[0]) as i64).pow(2)
+ (p1[1].abs_diff(p2[1]) as i64).pow(2)
+ (p1[2].abs_diff(p2[2]) as i64).pow(2)
})
.isqrt()
}
#[inline]
fn luminance(pixel: &[u8; 3]) -> i64 {
(0.299 * pixel[0] as f64 + 0.587 * pixel[1] as f64 + 0.114 * pixel[2] as f64) as i64
}
pub fn luminance_l1(img1: &RgbImage, img2: &RgbImage) -> i64 {
img1.pixels().zip(img2.pixels()).fold(0, |sum, (p1, p2)| {
let lum1 = luminance(&p1.0);
let lum2 = luminance(&p2.0);
sum + (lum1 - lum2).abs()
})
}
pub fn luminance_l2(img1: &RgbImage, img2: &RgbImage) -> i64 {
img1.pixels()
.zip(img2.pixels())
.fold(0, |sum, (p1, p2)| {
let lum1 = luminance(&p1.0);
let lum2 = luminance(&p2.0);
sum + (lum1 - lum2).abs().pow(2)
})
.isqrt()
}
pub fn avg_color(img1: &RgbImage, img2: &RgbImage) -> i64 {
let avg1 = img1.pixels().fold((0, 0, 0), |(r1, g1, b1), p1| {
(r1 + p1[0] as i64, g1 + p1[1] as i64, b1 + p1[2] as i64)
});
let avg2 = img2.pixels().fold((0, 0, 0), |(r2, g2, b2), p2| {
(r2 + p2[0] as i64, g2 + p2[1] as i64, b2 + p2[2] as i64)
});
(avg1.0.abs_diff(avg2.0) + avg1.1.abs_diff(avg2.1) + avg1.2.abs_diff(avg2.2)) as i64
/ (3 * img1.width() as i64 * img1.height() as i64)
}