From 4894c4a072e9d40538a6d3fb2057571dacadf6c1 Mon Sep 17 00:00:00 2001 From: Joshua Holmer Date: Mon, 18 Jan 2016 20:03:39 -0500 Subject: [PATCH] Make our tests fail again Although now they test that the conversion was lossless, which is extremely important for this program to be useful --- Cargo.toml | 3 + src/png.rs | 4 +- ...ette.png => palette_should_be_palette.png} | Bin ...test_rgb.png => rgb_should_be_palette.png} | Bin ...st_rgba.png => rgba_should_be_palette.png} | Bin tests/oxipng.rs | 326 ++++++++++++++++-- 6 files changed, 310 insertions(+), 23 deletions(-) rename tests/files/{test_palette.png => palette_should_be_palette.png} (100%) rename tests/files/{test_rgb.png => rgb_should_be_palette.png} (100%) rename tests/files/{test_rgba.png => rgba_should_be_palette.png} (100%) diff --git a/Cargo.toml b/Cargo.toml index 4e4d7b5f..c51b0a70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,6 @@ crc = "^1.0.0" libc = "^0.2.4" libz-sys = "^1.0.0" regex = "^0.1.8" + +[dev-dependencies] +image = "^0.6.1" diff --git a/src/png.rs b/src/png.rs index 2a99f6fe..f319c501 100644 --- a/src/png.rs +++ b/src/png.rs @@ -574,10 +574,10 @@ impl PngData { pub fn reduce_bit_depth(&mut self) -> bool { if self.ihdr_data.bit_depth != BitDepth::Sixteen { if self.ihdr_data.color_type == ColorType::Indexed || - self.ihdr_data.color_type == ColorType::Grayscale { + self.ihdr_data.color_type == ColorType::Grayscale { return match reduce_bit_depth_8_or_less(self) { Some(_) => true, - None => false + None => false, }; } return false; diff --git a/tests/files/test_palette.png b/tests/files/palette_should_be_palette.png similarity index 100% rename from tests/files/test_palette.png rename to tests/files/palette_should_be_palette.png diff --git a/tests/files/test_rgb.png b/tests/files/rgb_should_be_palette.png similarity index 100% rename from tests/files/test_rgb.png rename to tests/files/rgb_should_be_palette.png diff --git a/tests/files/test_rgba.png b/tests/files/rgba_should_be_palette.png similarity index 100% rename from tests/files/test_rgba.png rename to tests/files/rgba_should_be_palette.png diff --git a/tests/oxipng.rs b/tests/oxipng.rs index c85e69b2..005f78ff 100644 --- a/tests/oxipng.rs +++ b/tests/oxipng.rs @@ -1,5 +1,8 @@ +extern crate image; extern crate oxipng; +use image::GenericImage; +use image::Pixel; use oxipng::png; use std::collections::HashSet; use std::fs::remove_file; @@ -47,8 +50,8 @@ fn get_opts(input: &Path) -> oxipng::Options { } #[test] -fn reduce_rgba_png() { - let input = PathBuf::from("tests/files/test_rgba.png"); +fn rgba_should_be_rgba() { + let input = PathBuf::from("tests/files/rgba_should_be_rgba.png"); let opts = get_opts(&input); let output = opts.out_file.clone(); @@ -59,23 +62,28 @@ fn reduce_rgba_png() { assert!(output.exists()); let png = match png::PngData::new(&output) { - Ok(x) => { - remove_file(output).ok(); - x - }, + Ok(x) => x, Err(x) => { remove_file(output).ok(); panic!(x.to_owned()) }, }; - assert!(png.ihdr_data.color_type == png::ColorType::Indexed); + assert!(png.ihdr_data.color_type == png::ColorType::RGBA); assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight); + + let old_png = image::open(&input).unwrap(); + let new_png = image::open(&output).unwrap(); + + remove_file(output).ok(); + + // Conversion should be lossless + assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>()); } #[test] -fn reduce_rgb_png() { - let input = PathBuf::from("tests/files/test_rgb.png"); +fn rgba_should_be_rgb() { + let input = PathBuf::from("tests/files/rgba_should_be_rgb.png"); let opts = get_opts(&input); let output = opts.out_file.clone(); @@ -86,23 +94,28 @@ fn reduce_rgb_png() { assert!(output.exists()); let png = match png::PngData::new(&output) { - Ok(x) => { - remove_file(output).ok(); - x - }, + Ok(x) => x, Err(x) => { remove_file(output).ok(); panic!(x.to_owned()) }, }; - assert!(png.ihdr_data.color_type == png::ColorType::Indexed); + assert!(png.ihdr_data.color_type == png::ColorType::RGB); assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight); + + let old_png = image::open(&input).unwrap(); + let new_png = image::open(&output).unwrap(); + + remove_file(output).ok(); + + // Conversion should be lossless + assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>()); } #[test] -fn reduce_palette_png() { - let input = PathBuf::from("tests/files/test_palette.png"); +fn rgba_should_be_palette() { + let input = PathBuf::from("tests/files/rgba_should_be_palette.png"); let opts = get_opts(&input); let output = opts.out_file.clone(); @@ -113,10 +126,7 @@ fn reduce_palette_png() { assert!(output.exists()); let png = match png::PngData::new(&output) { - Ok(x) => { - remove_file(output).ok(); - x - }, + Ok(x) => x, Err(x) => { remove_file(output).ok(); panic!(x.to_owned()) @@ -125,11 +135,243 @@ fn reduce_palette_png() { assert!(png.ihdr_data.color_type == png::ColorType::Indexed); assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight); + + let old_png = image::open(&input).unwrap(); + let new_png = image::open(&output).unwrap(); + + remove_file(output).ok(); + + // Conversion should be lossless + assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>()); +} + +#[test] +fn rgba_should_be_grayscale_alpha() { + let input = PathBuf::from("tests/files/rgba_should_be_grayscale_alpha.png"); + let opts = get_opts(&input); + let output = opts.out_file.clone(); + + match oxipng::optimize(&input, &opts) { + Ok(_) => (), + Err(x) => panic!(x.to_owned()) + }; + assert!(output.exists()); + + let png = match png::PngData::new(&output) { + Ok(x) => x, + Err(x) => { + remove_file(output).ok(); + panic!(x.to_owned()) + }, + }; + + assert!(png.ihdr_data.color_type == png::ColorType::GrayscaleAlpha); + assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight); + + let old_png = image::open(&input).unwrap(); + let new_png = image::open(&output).unwrap(); + + remove_file(output).ok(); + + // Conversion should be lossless + assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>()); +} + +#[test] +fn rgba_should_be_grayscale() { + let input = PathBuf::from("tests/files/rgba_should_be_grayscale.png"); + let opts = get_opts(&input); + let output = opts.out_file.clone(); + + match oxipng::optimize(&input, &opts) { + Ok(_) => (), + Err(x) => panic!(x.to_owned()) + }; + assert!(output.exists()); + + let png = match png::PngData::new(&output) { + Ok(x) => x, + Err(x) => { + remove_file(output).ok(); + panic!(x.to_owned()) + }, + }; + + assert!(png.ihdr_data.color_type == png::ColorType::Grayscale); + assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight); + + let old_png = image::open(&input).unwrap(); + let new_png = image::open(&output).unwrap(); + + remove_file(output).ok(); + + // Conversion should be lossless + assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>()); +} + +#[test] +fn rgb_should_be_rgb() { + let input = PathBuf::from("tests/files/rgb_should_be_rgb.png"); + let opts = get_opts(&input); + let output = opts.out_file.clone(); + + match oxipng::optimize(&input, &opts) { + Ok(_) => (), + Err(x) => panic!(x.to_owned()) + }; + assert!(output.exists()); + + let png = match png::PngData::new(&output) { + Ok(x) => x, + Err(x) => { + remove_file(output).ok(); + panic!(x.to_owned()) + }, + }; + + assert!(png.ihdr_data.color_type == png::ColorType::RGB); + assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight); + + let old_png = image::open(&input).unwrap(); + let new_png = image::open(&output).unwrap(); + + remove_file(output).ok(); + + // Conversion should be lossless + assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>()); +} + +#[test] +fn rgb_should_be_palette() { + let input = PathBuf::from("tests/files/rgb_should_be_palette.png"); + let opts = get_opts(&input); + let output = opts.out_file.clone(); + + match oxipng::optimize(&input, &opts) { + Ok(_) => (), + Err(x) => panic!(x.to_owned()) + }; + assert!(output.exists()); + + let png = match png::PngData::new(&output) { + Ok(x) => x, + Err(x) => { + remove_file(output).ok(); + panic!(x.to_owned()) + }, + }; + + assert!(png.ihdr_data.color_type == png::ColorType::Indexed); + assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight); + + let old_png = image::open(&input).unwrap(); + let new_png = image::open(&output).unwrap(); + + remove_file(output).ok(); + + // Conversion should be lossless + assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>()); +} + +#[test] +fn rgb_should_be_grayscale() { + let input = PathBuf::from("tests/files/rgb_should_be_grayscale.png"); + let opts = get_opts(&input); + let output = opts.out_file.clone(); + + match oxipng::optimize(&input, &opts) { + Ok(_) => (), + Err(x) => panic!(x.to_owned()) + }; + assert!(output.exists()); + + let png = match png::PngData::new(&output) { + Ok(x) => x, + Err(x) => { + remove_file(output).ok(); + panic!(x.to_owned()) + }, + }; + + assert!(png.ihdr_data.color_type == png::ColorType::Grayscale); + assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight); + + let old_png = image::open(&input).unwrap(); + let new_png = image::open(&output).unwrap(); + + remove_file(output).ok(); + + // Conversion should be lossless + assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>()); +} + +#[test] +fn palette_should_be_palette() { + let input = PathBuf::from("tests/files/palette_should_be_palette.png"); + let opts = get_opts(&input); + let output = opts.out_file.clone(); + + match oxipng::optimize(&input, &opts) { + Ok(_) => (), + Err(x) => panic!(x.to_owned()) + }; + assert!(output.exists()); + + let png = match png::PngData::new(&output) { + Ok(x) => x, + Err(x) => { + remove_file(output).ok(); + panic!(x.to_owned()) + }, + }; + + assert!(png.ihdr_data.color_type == png::ColorType::Indexed); + assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight); + + let old_png = image::open(&input).unwrap(); + let new_png = image::open(&output).unwrap(); + + remove_file(output).ok(); + + // Conversion should be lossless + assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>()); +} + +#[test] +fn palette_should_be_grayscale() { + let input = PathBuf::from("tests/files/palette_should_be_grayscale.png"); + let opts = get_opts(&input); + let output = opts.out_file.clone(); + + match oxipng::optimize(&input, &opts) { + Ok(_) => (), + Err(x) => panic!(x.to_owned()) + }; + assert!(output.exists()); + + let png = match png::PngData::new(&output) { + Ok(x) => x, + Err(x) => { + remove_file(output).ok(); + panic!(x.to_owned()) + }, + }; + + assert!(png.ihdr_data.color_type == png::ColorType::Grayscale); + assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight); + + let old_png = image::open(&input).unwrap(); + let new_png = image::open(&output).unwrap(); + + remove_file(output).ok(); + + // Conversion should be lossless + assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::>>()); } #[test] fn strip_headers() { - let input = PathBuf::from("tests/files/test_rgb.png"); + let input = PathBuf::from("tests/files/rgb_should_be_palette.png"); let mut opts = get_opts(&input); opts.strip = true; let output = opts.out_file.clone(); @@ -153,3 +395,45 @@ fn strip_headers() { assert!(!png.aux_headers.contains_key("tEXt")); } + +#[test] +#[ignore] +fn downgrade_16_to_8() { + unimplemented!(); +} + +#[test] +#[ignore] +fn downgrade_8_to_4() { + unimplemented!(); +} + +#[test] +#[ignore] +fn downgrade_8_to_2() { + unimplemented!(); +} + +#[test] +#[ignore] +fn downgrade_8_to_1() { + unimplemented!(); +} + +#[test] +#[ignore] +fn downgrade_4_to_2() { + unimplemented!(); +} + +#[test] +#[ignore] +fn downgrade_4_to_1() { + unimplemented!(); +} + +#[test] +#[ignore] +fn downgrade_2_to_1() { + unimplemented!(); +}