From 3034dffb0f910ebee25f492d30281a4bd26541fa Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 5 May 2023 10:22:20 +1200 Subject: [PATCH] Move sanity checks to separate file --- src/lib.rs | 58 ++++---------------------------------------- src/sanity_checks.rs | 47 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 53 deletions(-) create mode 100644 src/sanity_checks.rs diff --git a/src/lib.rs b/src/lib.rs index 813433d1..45cfe430 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,6 +60,8 @@ mod headers; mod interlace; mod png; mod reduction; +#[cfg(feature = "sanity-checks")] +mod sanity_checks; /// Private to oxipng; don't use outside tests and benches #[doc(hidden)] @@ -70,6 +72,8 @@ pub mod internal_tests { pub use crate::headers::*; pub use crate::png::*; pub use crate::reduction::*; + #[cfg(feature = "sanity-checks")] + pub use crate::sanity_checks::*; } #[derive(Clone, Debug)] @@ -597,7 +601,7 @@ fn optimize_png( } #[cfg(feature = "sanity-checks")] - debug_assert!(sanity_checks::validate_output(&output, original_data)); + assert!(sanity_checks::validate_output(&output, original_data)); Ok(output) } @@ -1070,55 +1074,3 @@ fn copy_times(input_path_meta: &Metadata, out_path: &Path) -> PngResult<()> { )) }) } - -#[cfg(feature = "sanity-checks")] -mod sanity_checks { - use super::*; - use image::{DynamicImage, GenericImageView, ImageFormat, Pixel}; - use log::error; - use std::io::Cursor; - - /// Validate that the output png data still matches the original image - pub(super) fn validate_output(output: &[u8], original_data: &[u8]) -> bool { - let (old_png, new_png) = rayon::join( - || load_png_image_from_memory(original_data), - || load_png_image_from_memory(output), - ); - - match (new_png, old_png) { - (Err(new_err), _) => { - error!("Failed to read output image for validation: {}", new_err); - false - } - (_, Err(old_err)) => { - // The original image might be invalid if, for example, there is a CRC error, - // and we set fix_errors to true. In that case, all we can do is check that the - // new image is decodable. - warn!("Failed to read input image for validation: {}", old_err); - true - } - (Ok(new_png), Ok(old_png)) => images_equal(&old_png, &new_png), - } - } - - /// Loads a PNG image from memory to a [DynamicImage] - fn load_png_image_from_memory(png_data: &[u8]) -> Result { - let mut reader = image::io::Reader::new(Cursor::new(png_data)); - reader.set_format(ImageFormat::Png); - reader.no_limits(); - reader.decode() - } - - /// Compares images pixel by pixel for equivalent content - fn images_equal(old_png: &DynamicImage, new_png: &DynamicImage) -> bool { - let a = old_png.pixels().filter(|x| { - let p = x.2.channels(); - !(p.len() == 4 && p[3] == 0) - }); - let b = new_png.pixels().filter(|x| { - let p = x.2.channels(); - !(p.len() == 4 && p[3] == 0) - }); - a.eq(b) - } -} diff --git a/src/sanity_checks.rs b/src/sanity_checks.rs new file mode 100644 index 00000000..496b5dfd --- /dev/null +++ b/src/sanity_checks.rs @@ -0,0 +1,47 @@ +use image::{DynamicImage, GenericImageView, ImageFormat, Pixel}; +use log::{error, warn}; +use std::io::Cursor; + +/// Validate that the output png data still matches the original image +pub fn validate_output(output: &[u8], original_data: &[u8]) -> bool { + let (old_png, new_png) = rayon::join( + || load_png_image_from_memory(original_data), + || load_png_image_from_memory(output), + ); + + match (new_png, old_png) { + (Err(new_err), _) => { + error!("Failed to read output image for validation: {}", new_err); + false + } + (_, Err(old_err)) => { + // The original image might be invalid if, for example, there is a CRC error, + // and we set fix_errors to true. In that case, all we can do is check that the + // new image is decodable. + warn!("Failed to read input image for validation: {}", old_err); + true + } + (Ok(new_png), Ok(old_png)) => images_equal(&old_png, &new_png), + } +} + +/// Loads a PNG image from memory to a [DynamicImage] +fn load_png_image_from_memory(png_data: &[u8]) -> Result { + let mut reader = image::io::Reader::new(Cursor::new(png_data)); + reader.set_format(ImageFormat::Png); + reader.no_limits(); + reader.decode() +} + +/// Compares images pixel by pixel for equivalent content +fn images_equal(old_png: &DynamicImage, new_png: &DynamicImage) -> bool { + let a = old_png.pixels().filter(|x| { + let p = x.2.channels(); + !(p.len() == 4 && p[3] == 0) + }); + let b = new_png.pixels().filter(|x| { + let p = x.2.channels(); + !(p.len() == 4 && p[3] == 0) + }); + a.eq(b) +}