diff --git a/Cargo.toml b/Cargo.toml index 68b093c..4a89f8e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,7 @@ authors = ["Thomas Forgione "] [dependencies] image = "*" + +[[bin]] +name = "psnr" +path = "src/main.rs" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..43919b6 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,41 @@ +extern crate image; + +use image::{Pixel, GenericImage, ImageResult, ImageError}; + +pub fn psnr, T: GenericImage>(img1: &T, img2: &T) -> ImageResult { + + let twenty_log10_max: f64 = 20.0 * (std::u32::MAX as f64).log10(); + + if img1.dimensions() != img2.dimensions() { + return Err(ImageError::DimensionError); + } + + let mut mse = 0.0; + + for x in 0 .. img1.dimensions().0 { + for y in 0 .. img1.dimensions().1 { + + let p1 = img1.get_pixel(x, y).to_rgba(); + let p2 = img2.get_pixel(x, y).to_rgba(); + + let dx = p1.data[0] as f64 - p2.data[0] as f64; + let dy = p1.data[1] as f64 - p2.data[1] as f64; + let dz = p1.data[2] as f64 - p2.data[2] as f64; + + let dx = dx * dx; + let dy = dy * dy; + let dz = dz * dz; + + mse += dx + dy + dz; + } + } + + mse /= (img1.dimensions().0 * img1.dimensions().1 * 3) as f64; + Ok(twenty_log10_max - 10.0 * mse.log10()) +} + +pub fn psnr_files(path1: &str, path2: &str) -> ImageResult { + let img1 = image::open(path1)?; + let img2 = image::open(path2)?; + psnr(&img1, &img2) +} diff --git a/src/main.rs b/src/main.rs index ca40023..c9234cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,50 +1,13 @@ extern crate image; +extern crate psnr; use std::env::args; use std::fs; -use image::{ImageResult, ImageError}; +use image::ImageResult; +use psnr::psnr_files; -const MAX: u32 = 255; - -fn mse_files(path1: &str, path2: &str) -> ImageResult { - - let twenty_log10_max: f64 = 20.0 * (MAX as f64).log10(); - - let img1 = image::open(path1)?; - let img2 = image::open(path2)?; - - use image::GenericImage; - - if img1.dimensions() != img2.dimensions() { - return Err(ImageError::DimensionError); - } - - let mut mse = 0.0; - - for x in 0 .. img1.dimensions().0 { - for y in 0 .. img1.dimensions().1 { - let p1 = img1.get_pixel(x, y); - let p2 = img2.get_pixel(x, y); - - let dx = p1[0] as f64 - p2[0] as f64; - let dy = p1[1] as f64 - p2[1] as f64; - let dz = p1[2] as f64 - p2[2] as f64; - - let dx = dx * dx; - let dy = dy * dy; - let dz = dz * dz; - - mse += dx + dy + dz; - } - } - - mse /= (img1.dimensions().0 * img1.dimensions().1 * 3) as f64; - - Ok(twenty_log10_max - 10.0 * mse.log10()) -} - -fn mse_dir(path1: &str, path2: &str) -> Vec<(String, ImageResult)> { +fn psnr_dir(path1: &str, path2: &str) -> Vec<(String, ImageResult)> { let mut dirs1: Vec<_> = fs::read_dir(path1).unwrap() .map(|x|x.unwrap()) .filter(|x| x.file_name().into_string().unwrap().ends_with(".png")) @@ -63,9 +26,9 @@ fn mse_dir(path1: &str, path2: &str) -> Vec<(String, ImageResult)> { for file in dirs1 { let p1 = path1.to_owned() + &file.file_name().to_owned().into_string().unwrap(); let p2 = path2.to_owned() + &file.file_name().to_owned().into_string().unwrap(); - let mse = mse_files(&p1, &p2); + let psnr = psnr_files(&p1, &p2); - let elt = (file.file_name().to_owned().into_string().unwrap(), mse.unwrap()); + let elt = (file.file_name().to_owned().into_string().unwrap(), psnr.unwrap()); println!("{} {}", elt.0, elt.1); res.push((elt.0, Ok(elt.1))); } @@ -77,5 +40,5 @@ fn main() { let path1 = args().nth(1).unwrap(); let path2 = args().nth(2).unwrap(); - let _ = mse_dir(&path1, &path2); + let _ = psnr_dir(&path1, &path2); }