use std::error::Error; use std::fs; use std::fmt; extern crate image; extern crate ureq; extern crate md5; #[macro_use] extern crate serde_derive; extern crate serde; extern crate serde_xml_rs; #[macro_use] extern crate lazy_static; pub mod browser; pub mod url_utils; pub mod config; // TODO: Better error for diffs #[derive(Debug)] struct DiffError { pct_diff: f64 } impl DiffError { fn new(pct_diff: f64) -> DiffError { DiffError{pct_diff: pct_diff} } } impl fmt::Display for DiffError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f,"diff showed a {}%", self.pct_diff) } } impl Error for DiffError { fn description(&self) -> &str { "still no num in this str" // format!("{}", %self.pct_diff) // String::from(self.pct_diff.to_string().clone()) } } // TODO: Better error for diffs #[derive(Debug)] pub struct SkipError { } impl SkipError { pub fn new() -> SkipError { SkipError{} } } impl fmt::Display for SkipError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f,"skip") } } impl Error for SkipError { fn description(&self) -> &str { "what goes here?" // format!("{}", %self.pct_diff) // String::from(self.pct_diff.to_string().clone()) } } use image::{ GenericImageView, Rgba, RgbaImage, DynamicImage, ImageBuffer, Pixel, }; fn diff_rgba3(rgba1 : Rgba<u8>, rgba2 : Rgba<u8>) -> i32 { (rgba1[0] as i32 - rgba2[0] as i32).abs() + (rgba1[1] as i32 - rgba2[1] as i32).abs() + (rgba1[2] as i32 - rgba2[2] as i32).abs() } fn get_pct_diff(img_trusted: &DynamicImage, img_testing: &DynamicImage) -> (f64, RgbaImage) { let highlight_rgba = Rgba([255,165,0,188]); let mut accum = 0; let zipper = img_trusted.pixels().zip(img_testing.pixels()); let (width, height) = img_trusted.dimensions(); let mut diff_img: RgbaImage = ImageBuffer::new(width, height); for (px_trusted, px_testing) in zipper { let amount_different = diff_rgba3(px_trusted.2, px_testing.2); let diffed_px = if amount_different > 0 { let mut px_to_mark = px_testing.2.clone(); px_to_mark.blend(&highlight_rgba); px_to_mark } else { px_trusted.2 }; diff_img.put_pixel(px_trusted.0, px_trusted.1, diffed_px); accum += amount_different; } let pct_diff = accum as f64 * 100.0/ (255.0 * 3.0 * (width * height) as f64); println!("Percent difference {}", pct_diff); (pct_diff, diff_img) } pub fn compare( trusted_path: String, testing_path: String, diff_path: String, images_identical: bool, ) -> Result<(), Box<dyn Error>> { if images_identical { fs::copy(&trusted_path, &diff_path)?; Ok(()) } else { let before = image::open(trusted_path)?; let after = image::open(testing_path)?; let (pct_diff, diff_img) = get_pct_diff(&before, &after); diff_img.save(&diff_path)?; // TODO: Shouldn't ever be negative, work through why that happens. if pct_diff > 0.00000000000001 || pct_diff < -0.00000000000001 { Err(Box::new(DiffError::new(pct_diff))) } else { Ok(()) } } }