diff --git a/benches/deflate.rs b/benches/deflate.rs index de9e0318..d8cc984b 100644 --- a/benches/deflate.rs +++ b/benches/deflate.rs @@ -3,15 +3,15 @@ extern crate oxipng; extern crate test; +use oxipng::internal_tests::*; +use oxipng::*; use std::path::PathBuf; use test::Bencher; -use oxipng::internal_tests::*; - #[bench] fn deflate_16_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { let min = AtomicMin::new(None); @@ -22,7 +22,7 @@ fn deflate_16_bits(b: &mut Bencher) { #[bench] fn deflate_8_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { let min = AtomicMin::new(None); @@ -35,7 +35,7 @@ fn deflate_4_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { let min = AtomicMin::new(None); @@ -48,7 +48,7 @@ fn deflate_2_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_2_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { let min = AtomicMin::new(None); @@ -61,7 +61,7 @@ fn deflate_1_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_1_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { let min = AtomicMin::new(None); @@ -72,7 +72,7 @@ fn deflate_1_bits(b: &mut Bencher) { #[bench] fn inflate_generic(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| inflate(png.idat_data.as_ref(), png.raw.ihdr.raw_data_size())); } diff --git a/benches/filters.rs b/benches/filters.rs index b1ce453a..67c701a6 100644 --- a/benches/filters.rs +++ b/benches/filters.rs @@ -3,14 +3,15 @@ extern crate oxipng; extern crate test; -use oxipng::{internal_tests::*, RowFilter}; +use oxipng::internal_tests::*; +use oxipng::*; use std::path::PathBuf; use test::Bencher; #[bench] fn filters_16_bits_filter_0(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::None, false); @@ -20,7 +21,7 @@ fn filters_16_bits_filter_0(b: &mut Bencher) { #[bench] fn filters_8_bits_filter_0(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::None, false); @@ -32,7 +33,7 @@ fn filters_4_bits_filter_0(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::None, false); @@ -44,7 +45,7 @@ fn filters_2_bits_filter_0(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_2_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::None, false); @@ -56,7 +57,7 @@ fn filters_1_bits_filter_0(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_1_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::None, false); @@ -66,7 +67,7 @@ fn filters_1_bits_filter_0(b: &mut Bencher) { #[bench] fn filters_16_bits_filter_1(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Sub, false); @@ -76,7 +77,7 @@ fn filters_16_bits_filter_1(b: &mut Bencher) { #[bench] fn filters_8_bits_filter_1(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Sub, false); @@ -88,7 +89,7 @@ fn filters_4_bits_filter_1(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Sub, false); @@ -100,7 +101,7 @@ fn filters_2_bits_filter_1(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_2_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Sub, false); @@ -112,7 +113,7 @@ fn filters_1_bits_filter_1(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_1_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Sub, false); @@ -122,7 +123,7 @@ fn filters_1_bits_filter_1(b: &mut Bencher) { #[bench] fn filters_16_bits_filter_2(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Up, false); @@ -132,7 +133,7 @@ fn filters_16_bits_filter_2(b: &mut Bencher) { #[bench] fn filters_8_bits_filter_2(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Up, false); @@ -144,7 +145,7 @@ fn filters_4_bits_filter_2(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Up, false); @@ -156,7 +157,7 @@ fn filters_2_bits_filter_2(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_2_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Up, false); @@ -168,7 +169,7 @@ fn filters_1_bits_filter_2(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_1_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Up, false); @@ -178,7 +179,7 @@ fn filters_1_bits_filter_2(b: &mut Bencher) { #[bench] fn filters_16_bits_filter_3(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Average, false); @@ -188,7 +189,7 @@ fn filters_16_bits_filter_3(b: &mut Bencher) { #[bench] fn filters_8_bits_filter_3(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Average, false); @@ -200,7 +201,7 @@ fn filters_4_bits_filter_3(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Average, false); @@ -212,7 +213,7 @@ fn filters_2_bits_filter_3(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_2_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Average, false); @@ -224,7 +225,7 @@ fn filters_1_bits_filter_3(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_1_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Average, false); @@ -234,7 +235,7 @@ fn filters_1_bits_filter_3(b: &mut Bencher) { #[bench] fn filters_16_bits_filter_4(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Paeth, false); @@ -244,7 +245,7 @@ fn filters_16_bits_filter_4(b: &mut Bencher) { #[bench] fn filters_8_bits_filter_4(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Paeth, false); @@ -256,7 +257,7 @@ fn filters_4_bits_filter_4(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Paeth, false); @@ -268,7 +269,7 @@ fn filters_2_bits_filter_4(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_2_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Paeth, false); @@ -280,7 +281,7 @@ fn filters_1_bits_filter_4(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_1_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Paeth, false); @@ -290,7 +291,7 @@ fn filters_1_bits_filter_4(b: &mut Bencher) { #[bench] fn filters_16_bits_filter_5(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::MinSum, false); @@ -300,7 +301,7 @@ fn filters_16_bits_filter_5(b: &mut Bencher) { #[bench] fn filters_8_bits_filter_5(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::MinSum, false); @@ -312,7 +313,7 @@ fn filters_4_bits_filter_5(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::MinSum, false); @@ -324,7 +325,7 @@ fn filters_2_bits_filter_5(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_2_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::MinSum, false); @@ -336,7 +337,7 @@ fn filters_1_bits_filter_5(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_1_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::MinSum, false); diff --git a/benches/interlacing.rs b/benches/interlacing.rs index def3d5a4..3c17eadc 100644 --- a/benches/interlacing.rs +++ b/benches/interlacing.rs @@ -3,14 +3,15 @@ extern crate oxipng; extern crate test; -use oxipng::{internal_tests::*, Interlacing}; +use oxipng::internal_tests::*; +use oxipng::*; use std::path::PathBuf; use test::Bencher; #[bench] fn interlacing_16_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| png.raw.change_interlacing(Interlacing::Adam7)); } @@ -18,7 +19,7 @@ fn interlacing_16_bits(b: &mut Bencher) { #[bench] fn interlacing_8_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| png.raw.change_interlacing(Interlacing::Adam7)); } @@ -28,7 +29,7 @@ fn interlacing_4_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| png.raw.change_interlacing(Interlacing::Adam7)); } @@ -38,7 +39,7 @@ fn interlacing_2_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_2_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| png.raw.change_interlacing(Interlacing::Adam7)); } @@ -48,7 +49,7 @@ fn interlacing_1_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_1_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| png.raw.change_interlacing(Interlacing::Adam7)); } @@ -58,7 +59,7 @@ fn deinterlacing_16_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/interlaced_rgb_16_should_be_rgb_16.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| png.raw.change_interlacing(Interlacing::None)); } @@ -68,7 +69,7 @@ fn deinterlacing_8_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/interlaced_rgb_8_should_be_rgb_8.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| png.raw.change_interlacing(Interlacing::None)); } @@ -78,7 +79,7 @@ fn deinterlacing_4_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/interlaced_palette_4_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| png.raw.change_interlacing(Interlacing::None)); } @@ -88,7 +89,7 @@ fn deinterlacing_2_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/interlaced_palette_2_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| png.raw.change_interlacing(Interlacing::None)); } @@ -98,7 +99,7 @@ fn deinterlacing_1_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/interlaced_palette_1_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| png.raw.change_interlacing(Interlacing::None)); } diff --git a/benches/reductions.rs b/benches/reductions.rs index 28803a38..16aae41f 100644 --- a/benches/reductions.rs +++ b/benches/reductions.rs @@ -4,13 +4,14 @@ extern crate oxipng; extern crate test; use oxipng::internal_tests::*; +use oxipng::*; use std::path::PathBuf; use test::Bencher; #[bench] fn reductions_16_to_8_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_16_to_8(&png.raw)); } @@ -20,7 +21,7 @@ fn reductions_8_to_4_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_8_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -30,7 +31,7 @@ fn reductions_8_to_2_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_8_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -40,7 +41,7 @@ fn reductions_8_to_1_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_8_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -50,7 +51,7 @@ fn reductions_4_to_2_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -60,7 +61,7 @@ fn reductions_4_to_1_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -70,7 +71,7 @@ fn reductions_2_to_1_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_2_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -80,7 +81,7 @@ fn reductions_grayscale_8_to_4_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/grayscale_8_should_be_grayscale_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -90,7 +91,7 @@ fn reductions_grayscale_8_to_2_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/grayscale_8_should_be_grayscale_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -100,7 +101,7 @@ fn reductions_grayscale_8_to_1_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/grayscale_8_should_be_grayscale_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -110,7 +111,7 @@ fn reductions_grayscale_4_to_2_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/grayscale_4_should_be_grayscale_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -120,7 +121,7 @@ fn reductions_grayscale_4_to_1_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/grayscale_4_should_be_grayscale_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -130,7 +131,7 @@ fn reductions_grayscale_2_to_1_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/grayscale_2_should_be_grayscale_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw, 1)); } @@ -138,7 +139,7 @@ fn reductions_grayscale_2_to_1_bits(b: &mut Bencher) { #[bench] fn reductions_rgba_to_rgb_16(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| alpha::reduced_alpha_channel(&png.raw, false)); } @@ -146,7 +147,7 @@ fn reductions_rgba_to_rgb_16(b: &mut Bencher) { #[bench] fn reductions_rgba_to_rgb_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| alpha::reduced_alpha_channel(&png.raw, false)); } @@ -156,7 +157,7 @@ fn reductions_rgba_to_grayscale_alpha_16(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/rgba_16_should_be_grayscale_alpha_16.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| color::reduced_rgb_to_grayscale(&png.raw)); } @@ -166,7 +167,7 @@ fn reductions_rgba_to_grayscale_alpha_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/rgba_8_should_be_grayscale_alpha_8.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| color::reduced_rgb_to_grayscale(&png.raw)); } @@ -176,7 +177,7 @@ fn reductions_rgba_to_grayscale_16(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/rgba_16_should_be_grayscale_16.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { color::reduced_rgb_to_grayscale(&png.raw) @@ -189,7 +190,7 @@ fn reductions_rgba_to_grayscale_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/rgba_8_should_be_grayscale_8.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { color::reduced_rgb_to_grayscale(&png.raw) @@ -202,7 +203,7 @@ fn reductions_rgb_to_grayscale_16(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/rgb_16_should_be_grayscale_16.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| color::reduced_rgb_to_grayscale(&png.raw)); } @@ -210,7 +211,7 @@ fn reductions_rgb_to_grayscale_16(b: &mut Bencher) { #[bench] fn reductions_rgb_to_grayscale_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_grayscale_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| color::reduced_rgb_to_grayscale(&png.raw)); } @@ -218,7 +219,7 @@ fn reductions_rgb_to_grayscale_8(b: &mut Bencher) { #[bench] fn reductions_rgba_to_palette_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_should_be_palette_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| color::reduced_to_indexed(&png.raw)); } @@ -226,7 +227,7 @@ fn reductions_rgba_to_palette_8(b: &mut Bencher) { #[bench] fn reductions_rgb_to_palette_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_palette_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| color::reduced_to_indexed(&png.raw)); } @@ -236,7 +237,7 @@ fn reductions_grayscale_8_to_palette_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/grayscale_8_should_be_palette_8.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| color::reduced_to_indexed(&png.raw)); } @@ -246,7 +247,7 @@ fn reductions_palette_8_to_grayscale_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_8_should_be_grayscale_8.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| color::indexed_to_channels(&png.raw)); } @@ -256,7 +257,7 @@ fn reductions_palette_duplicate_reduction(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_should_be_reduced_with_dupes.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| palette::reduced_palette(&png.raw, false)); } @@ -266,7 +267,7 @@ fn reductions_palette_unused_reduction(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_should_be_reduced_with_unused.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| palette::reduced_palette(&png.raw, false)); } @@ -276,7 +277,7 @@ fn reductions_palette_full_reduction(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_should_be_reduced_with_both.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| palette::reduced_palette(&png.raw, false)); } @@ -286,7 +287,7 @@ fn reductions_palette_sort(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_8_should_be_palette_8.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| palette::sorted_palette(&png.raw)); } @@ -294,7 +295,7 @@ fn reductions_palette_sort(b: &mut Bencher) { #[bench] fn reductions_alpha(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| alpha::cleaned_alpha_channel(&png.raw)); } diff --git a/benches/strategies.rs b/benches/strategies.rs index de5a009a..c3aab816 100644 --- a/benches/strategies.rs +++ b/benches/strategies.rs @@ -3,14 +3,15 @@ extern crate oxipng; extern crate test; -use oxipng::{internal_tests::*, RowFilter}; +use oxipng::internal_tests::*; +use oxipng::*; use std::path::PathBuf; use test::Bencher; #[bench] fn filters_minsum(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::MinSum, false); @@ -20,7 +21,7 @@ fn filters_minsum(b: &mut Bencher) { #[bench] fn filters_entropy(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Entropy, false); @@ -30,7 +31,7 @@ fn filters_entropy(b: &mut Bencher) { #[bench] fn filters_bigrams(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Bigrams, false); @@ -40,7 +41,7 @@ fn filters_bigrams(b: &mut Bencher) { #[bench] fn filters_bigent(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::BigEnt, false); @@ -50,7 +51,7 @@ fn filters_bigent(b: &mut Bencher) { #[bench] fn filters_brute(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { png.raw.filter_image(RowFilter::Brute, false); diff --git a/benches/zopfli.rs b/benches/zopfli.rs index a9b91e08..03f83f65 100644 --- a/benches/zopfli.rs +++ b/benches/zopfli.rs @@ -4,6 +4,7 @@ extern crate oxipng; extern crate test; use oxipng::internal_tests::*; +use oxipng::*; use std::num::NonZeroU8; use std::path::PathBuf; use test::Bencher; @@ -14,7 +15,7 @@ const DEFAULT_ZOPFLI_ITERATIONS: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(1 #[bench] fn zopfli_16_bits_strategy_0(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok(); @@ -24,7 +25,7 @@ fn zopfli_16_bits_strategy_0(b: &mut Bencher) { #[bench] fn zopfli_8_bits_strategy_0(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok(); @@ -36,7 +37,7 @@ fn zopfli_4_bits_strategy_0(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_4_should_be_palette_4.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok(); @@ -48,7 +49,7 @@ fn zopfli_2_bits_strategy_0(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_2_should_be_palette_2.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok(); @@ -60,7 +61,7 @@ fn zopfli_1_bits_strategy_0(b: &mut Bencher) { let input = test::black_box(PathBuf::from( "tests/files/palette_1_should_be_palette_1.png", )); - let png = PngData::new(&input, false).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); b.iter(|| { zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok(); diff --git a/src/colors.rs b/src/colors.rs index 59cd589e..744ec720 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -70,14 +70,6 @@ impl ColorType { matches!(self, ColorType::RGB { .. } | ColorType::RGBA) } - #[inline] - pub(crate) fn is_grayscale(&self) -> bool { - matches!( - self, - ColorType::Grayscale { .. } | ColorType::GrayscaleAlpha - ) - } - #[inline] pub(crate) fn has_alpha(&self) -> bool { matches!(self, ColorType::GrayscaleAlpha | ColorType::RGBA) diff --git a/src/evaluate.rs b/src/evaluate.rs index 15763a2c..80f50d16 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -140,6 +140,7 @@ impl Evaluator { idat_data, filtered, raw: Arc::clone(&image), + aux_chunks: Vec::new(), }, filter, is_reduction, diff --git a/src/headers.rs b/src/headers.rs index 33ccaf88..18f84efd 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -5,8 +5,6 @@ use crate::interlace::Interlacing; use crate::PngResult; use indexmap::IndexSet; use rgb::{RGB16, RGBA8}; -use std::io; -use std::io::{Cursor, Read}; #[derive(Debug, Clone)] /// Headers from the IHDR chunk of the image @@ -62,24 +60,40 @@ impl IhdrData { } } +#[derive(Debug, Clone)] +pub struct Chunk { + pub name: [u8; 4], + pub data: Vec, +} + #[derive(Debug, PartialEq, Eq, Clone)] -/// Options to use for performing operations on headers (such as stripping) -pub enum Headers { +/// Options to use when stripping chunks +pub enum StripChunks { /// None None, /// Remove specific chunks - Strip(Vec), + Strip(IndexSet<[u8; 4]>), /// Remove all chunks that won't affect rendering Safe, /// Remove all non-critical chunks except these - Keep(IndexSet), - /// All non-critical headers + Keep(IndexSet<[u8; 4]>), + /// All non-critical chunks All, } -impl Headers { +impl StripChunks { /// List of chunks that will be kept when using the `Safe` option pub const KEEP_SAFE: [[u8; 4]; 4] = [*b"cICP", *b"iCCP", *b"sRGB", *b"pHYs"]; + + pub(crate) fn keep(&self, name: &[u8; 4]) -> bool { + match &self { + StripChunks::None => true, + StripChunks::Keep(names) => names.contains(name), + StripChunks::Strip(names) => !names.contains(name), + StripChunks::Safe => Self::KEEP_SAFE.contains(name), + StripChunks::All => false, + } + } } #[inline] @@ -90,27 +104,26 @@ pub fn file_header_is_valid(bytes: &[u8]) -> bool { } #[derive(Debug, Clone, Copy)] -pub struct RawHeader<'a> { +pub struct RawChunk<'a> { pub name: [u8; 4], pub data: &'a [u8], } -pub fn parse_next_header<'a>( +pub fn parse_next_chunk<'a>( byte_data: &'a [u8], byte_offset: &mut usize, fix_errors: bool, -) -> PngResult>> { - let mut rdr = Cursor::new( +) -> PngResult>> { + let length = read_be_u32( byte_data .get(*byte_offset..*byte_offset + 4) .ok_or(PngError::TruncatedData)?, ); - let length = read_be_u32(&mut rdr).unwrap(); *byte_offset += 4; - let header_start = *byte_offset; + let chunk_start = *byte_offset; let chunk_name = byte_data - .get(header_start..header_start + 4) + .get(chunk_start..chunk_start + 4) .ok_or(PngError::TruncatedData)?; if chunk_name == b"IEND" { // End of data @@ -122,37 +135,34 @@ pub fn parse_next_header<'a>( .get(*byte_offset..*byte_offset + length as usize) .ok_or(PngError::TruncatedData)?; *byte_offset += length as usize; - let mut rdr = Cursor::new( + let crc = read_be_u32( byte_data .get(*byte_offset..*byte_offset + 4) .ok_or(PngError::TruncatedData)?, ); - let crc = read_be_u32(&mut rdr).unwrap(); *byte_offset += 4; - let header_bytes = byte_data - .get(header_start..header_start + 4 + length as usize) + let chunk_bytes = byte_data + .get(chunk_start..chunk_start + 4 + length as usize) .ok_or(PngError::TruncatedData)?; - if !fix_errors && crc32(header_bytes) != crc { + if !fix_errors && crc32(chunk_bytes) != crc { return Err(PngError::new(&format!( - "CRC Mismatch in {} header; May be recoverable by using --fix", + "CRC Mismatch in {} chunk; May be recoverable by using --fix", String::from_utf8_lossy(chunk_name) ))); } - let mut name = [0_u8; 4]; - name.copy_from_slice(chunk_name); - Ok(Some(RawHeader { name, data })) + let name: [u8; 4] = chunk_name.try_into().unwrap(); + Ok(Some(RawChunk { name, data })) } -pub fn parse_ihdr_header( +pub fn parse_ihdr_chunk( byte_data: &[u8], palette_data: Option>, trns_data: Option>, ) -> PngResult { // This eliminates bounds checks for the rest of the function let interlaced = byte_data.get(12).copied().ok_or(PngError::TruncatedData)?; - let mut rdr = Cursor::new(&byte_data[0..8]); Ok(IhdrData { color_type: match byte_data[9] { 0 => ColorType::Grayscale { @@ -175,8 +185,8 @@ pub fn parse_ihdr_header( _ => return Err(PngError::new("Unexpected color type in header")), }, bit_depth: byte_data[8].try_into()?, - width: read_be_u32(&mut rdr).map_err(|_| PngError::TruncatedData)?, - height: read_be_u32(&mut rdr).map_err(|_| PngError::TruncatedData)?, + width: read_be_u32(&byte_data[0..4]), + height: read_be_u32(&byte_data[4..8]), interlaced: interlaced.try_into()?, }) } @@ -201,8 +211,6 @@ fn palette_to_rgba( } #[inline] -fn read_be_u32>(rdr: &mut Cursor) -> Result { - let mut int_buf = [0; 4]; - rdr.read_exact(&mut int_buf)?; - Ok(u32::from_be_bytes(int_buf)) +fn read_be_u32(bytes: &[u8]) -> u32 { + u32::from_be_bytes(bytes.try_into().unwrap()) } diff --git a/src/interlace.rs b/src/interlace.rs index 0fd63f21..0293dce1 100644 --- a/src/interlace.rs +++ b/src/interlace.rs @@ -90,7 +90,6 @@ pub fn interlace_image(png: &PngImage) -> PngImage { interlaced: Interlacing::Adam7, ..png.ihdr }, - aux_headers: png.aux_headers.clone(), } } @@ -105,7 +104,6 @@ pub fn deinterlace_image(png: &PngImage) -> PngImage { interlaced: Interlacing::None, ..png.ihdr }, - aux_headers: png.aux_headers.clone(), } } diff --git a/src/lib.rs b/src/lib.rs index 5e4909c2..cdd0d043 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ mod rayon; use crate::atomicmin::AtomicMin; use crate::deflate::{crc32, inflate}; use crate::evaluate::Evaluator; -use crate::headers::IhdrData; +use crate::headers::{Chunk, IhdrData}; use crate::png::PngData; use crate::png::PngImage; use crate::reduction::*; @@ -45,7 +45,7 @@ pub use crate::colors::{BitDepth, ColorType}; pub use crate::deflate::Deflaters; pub use crate::error::PngError; pub use crate::filters::RowFilter; -pub use crate::headers::Headers; +pub use crate::headers::StripChunks; pub use crate::interlace::Interlacing; pub use indexmap::{indexset, IndexMap, IndexSet}; pub use rgb::{RGB16, RGBA8}; @@ -67,9 +67,7 @@ mod sanity_checks; #[doc(hidden)] pub mod internal_tests { pub use crate::atomicmin::*; - pub use crate::colors::*; pub use crate::deflate::*; - pub use crate::headers::*; pub use crate::png::*; pub use crate::reduction::*; #[cfg(feature = "sanity-checks")] @@ -189,10 +187,10 @@ pub struct Options { /// /// Default: `true` pub idat_recoding: bool, - /// Which headers to strip from the PNG file, if any + /// Which chunks to strip from the PNG file, if any /// /// Default: `None` - pub strip: Headers, + pub strip: StripChunks, /// Which DEFLATE algorithm to use /// /// Default: `Libdeflater` @@ -306,7 +304,7 @@ impl Default for Options { palette_reduction: true, grayscale_reduction: true, idat_recoding: true, - strip: Headers::None, + strip: StripChunks::None, deflate: Deflaters::Libdeflater { compression: 11 }, fast_evaluation: true, timeout: None, @@ -318,6 +316,7 @@ impl Default for Options { /// A raw image definition which can be used to create an optimized png pub struct RawImage { png: Arc, + aux_chunks: Vec, } impl RawImage { @@ -363,16 +362,14 @@ impl RawImage { interlaced: Interlacing::None, }, data, - aux_headers: IndexMap::new(), }), + aux_chunks: Vec::new(), }) } /// Add a png chunk, such as "iTXt", to be included in the output - pub fn add_png_chunk(&mut self, chunk_type: [u8; 4], data: Vec) { - // We can guarantee this will succeed - failure indicates a bug - let png = Arc::get_mut(&mut self.png).unwrap(); - png.aux_headers.insert(chunk_type, data); + pub fn add_png_chunk(&mut self, name: [u8; 4], data: Vec) { + self.aux_chunks.push(Chunk { name, data }); } /// Add an ICC profile for the image @@ -390,8 +387,18 @@ impl RawImage { /// Create an optimized png from the raw image data using the options provided pub fn create_optimized_png(&self, opts: &Options) -> PngResult> { let deadline = Arc::new(Deadline::new(opts.timeout)); - let png = optimize_raw(Arc::clone(&self.png), opts, deadline, None) + let mut png = optimize_raw(self.png.clone(), opts, deadline, None) .ok_or_else(|| PngError::new("Failed to optimize input data"))?; + + // Process aux chunks + png.aux_chunks = self + .aux_chunks + .iter() + .filter(|c| opts.strip.keep(&c.name)) + .cloned() + .collect(); + postprocess_chunks(&mut png, opts, &self.png.ihdr); + Ok(png.output()) } } @@ -434,7 +441,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<( } }; - let mut png = PngData::from_slice(&in_data, opts.fix_errors)?; + let mut png = PngData::from_slice(&in_data, opts)?; if opts.check { info!("Running in check mode, not optimizing"); @@ -522,7 +529,7 @@ pub fn optimize_from_memory(data: &[u8], opts: &Options) -> PngResult> { let deadline = Arc::new(Deadline::new(opts.timeout)); let original_size = data.len(); - let mut png = PngData::from_slice(data, opts.fix_errors)?; + let mut png = PngData::from_slice(data, opts)?; // Run the optimizer on the decoded PNG. let optimized_output = optimize_png(&mut png, data, opts, deadline)?; @@ -553,27 +560,27 @@ fn optimize_png( // Print png info let file_original_size = original_data.len(); let idat_original_size = png.idat_data.len(); + let raw = png.raw.clone(); debug!( " {}x{} pixels, PNG format", - png.raw.ihdr.width, png.raw.ihdr.height + raw.ihdr.width, raw.ihdr.height ); - report_format(" ", &png.raw); + report_format(" ", &raw); debug!(" IDAT size = {} bytes", idat_original_size); debug!(" File size = {} bytes", file_original_size); - // Do this first so that reductions can ignore certain chunks such as bKGD - perform_strip(png, opts); - let max_size = if opts.force { None } else { Some(png.estimated_output_size()) }; - if let Some(new_png) = optimize_raw(png.raw.clone(), opts, deadline, max_size) { + if let Some(new_png) = optimize_raw(raw.clone(), opts, deadline, max_size) { png.raw = new_png.raw; png.idat_data = new_png.idat_data; } + postprocess_chunks(png, opts, &raw.ihdr); + let output = png.output(); if idat_original_size >= png.idat_data.len() { @@ -734,8 +741,9 @@ fn optimize_raw( let image = PngData { raw: png, // The filtered data has not been retained here, but we don't need to return it - filtered: vec![], + filtered: Vec::new(), idat_data, + aux_chunks: Vec::new(), }; if image.estimated_output_size() < max_size.unwrap_or(usize::MAX) { debug!("Found better combination:"); @@ -867,49 +875,41 @@ fn report_format(prefix: &str, png: &PngImage) { ); } -/// Strip headers from the `PngData` object, as requested by the passed `Options` -fn perform_strip(png: &mut PngData, opts: &Options) { - let raw = Arc::make_mut(&mut png.raw); - match opts.strip { - // Strip headers - Headers::None => (), - Headers::Keep(ref hdrs) => raw - .aux_headers - .retain(|hdr, _| std::str::from_utf8(hdr).map_or(false, |name| hdrs.contains(name))), - Headers::Strip(ref hdrs) => { - for hdr in hdrs { - raw.aux_headers.remove(hdr.as_bytes()); +/// Perform cleanup of certain chunks from the `PngData` object, after optimization has been completed +fn postprocess_chunks(png: &mut PngData, opts: &Options, orig_ihdr: &IhdrData) { + // See if we can replace an iCCP chunk with an sRGB chunk + if opts.strip != StripChunks::None && opts.strip.keep(b"sRGB") { + if let Some(iccp_idx) = png.aux_chunks.iter().position(|c| &c.name == b"iCCP") { + if png.aux_chunks.iter().any(|c| &c.name == b"sRGB") { + // Files aren't supposed to have both chunks, so we chose to honor sRGB + trace!("Removing iCCP chunk due to conflict with sRGB chunk"); + png.aux_chunks.remove(iccp_idx); + } else if let Some(intent) = srgb_rendering_intent(&png.aux_chunks[iccp_idx].data) { + // sRGB-like profile can be safely replaced with + // an sRGB chunk with the same rendering intent + trace!("Replacing iCCP chunk with equivalent sRGB chunk"); + png.aux_chunks[iccp_idx] = Chunk { + name: *b"sRGB", + data: vec![intent], + }; } } - Headers::Safe => raw - .aux_headers - .retain(|hdr, _| Headers::KEEP_SAFE.contains(hdr)), - Headers::All => { - raw.aux_headers = IndexMap::new(); - } } - let may_replace_iccp = match opts.strip { - Headers::Keep(ref hdrs) => hdrs.contains("sRGB"), - Headers::Strip(ref hdrs) => !hdrs.iter().any(|v| v == "sRGB"), - Headers::Safe => true, - Headers::None | Headers::All => false, - }; - - if may_replace_iccp { - if raw.aux_headers.get(b"sRGB").is_some() { - // Files aren't supposed to have both chunks, so we chose to honor sRGB - raw.aux_headers.remove(b"iCCP"); - } else if let Some(intent) = raw - .aux_headers - .get(b"iCCP") - .and_then(|iccp| srgb_rendering_intent(iccp)) - { - // sRGB-like profile can be safely replaced with - // an sRGB chunk with the same rendering intent - raw.aux_headers.remove(b"iCCP"); - raw.aux_headers.insert(*b"sRGB", vec![intent]); - } + // If the color type has changed, some chunks may be invalid and should be dropped + // While these could potentially be converted, they have no known use case today and + // are generally more trouble than they're worth + if orig_ihdr.color_type != png.raw.ihdr.color_type { + png.aux_chunks.retain(|c| { + let invalid = &c.name == b"bKGD" || &c.name == b"sBIT" || &c.name == b"hIST"; + if invalid { + warn!( + "Removing {} chunk as it no longer matches the image data", + std::str::from_utf8(&c.name).unwrap() + ); + } + !invalid + }); } } diff --git a/src/main.rs b/src/main.rs index 3676e85e..585f7086 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,9 +17,9 @@ use clap::{AppSettings, Arg, ArgAction, ArgMatches, Command}; use indexmap::IndexSet; use log::{error, warn}; use oxipng::Deflaters; -use oxipng::Headers; use oxipng::Options; use oxipng::RowFilter; +use oxipng::StripChunks; use oxipng::{InFile, OutFile}; use std::fs::DirBuilder; #[cfg(feature = "zopfli")] @@ -496,40 +496,44 @@ fn parse_opts_into_struct( opts.idat_recoding = false; } - if let Some(hdrs) = matches.value_of("keep") { - opts.strip = Headers::Keep(hdrs.split(',').map(|x| x.trim().to_owned()).collect()) + if let Some(keep) = matches.value_of("keep") { + let names = keep + .split(',') + .map(parse_chunk_name) + .collect::>()?; + opts.strip = StripChunks::Keep(names) } - if let Some(hdrs) = matches.value_of("strip") { - let hdrs = hdrs - .split(',') - .map(|x| x.trim().to_owned()) - .collect::>(); - if hdrs.contains(&"safe".to_owned()) || hdrs.contains(&"all".to_owned()) { - if hdrs.len() > 1 { - return Err( - "'safe' or 'all' presets for --strip should be used by themselves".to_owned(), - ); - } - if hdrs[0] == "safe" { - opts.strip = Headers::Safe; - } else { - opts.strip = Headers::All; - } + if let Some(strip) = matches.value_of("strip") { + if strip == "safe" { + opts.strip = StripChunks::Safe; + } else if strip == "all" { + opts.strip = StripChunks::All; } else { const FORBIDDEN_CHUNKS: [[u8; 4]; 5] = [*b"IHDR", *b"IDAT", *b"tRNS", *b"PLTE", *b"IEND"]; - for i in &hdrs { - if FORBIDDEN_CHUNKS.iter().any(|chunk| chunk == i.as_bytes()) { - return Err(format!("{} chunk is not allowed to be stripped", i)); - } - } - opts.strip = Headers::Strip(hdrs); + let names = strip + .split(',') + .map(|x| { + if x == "safe" || x == "all" { + return Err( + "'safe' or 'all' presets for --strip should be used by themselves" + .to_owned(), + ); + } + let name = parse_chunk_name(x)?; + if FORBIDDEN_CHUNKS.contains(&name) { + return Err(format!("{} chunk is not allowed to be stripped", x)); + } + Ok(name) + }) + .collect::>()?; + opts.strip = StripChunks::Strip(names); } } if matches.is_present("strip-safe") { - opts.strip = Headers::Safe; + opts.strip = StripChunks::Safe; } if matches.is_present("zopfli") { @@ -556,6 +560,13 @@ fn parse_opts_into_struct( Ok((out_file, out_dir, opts)) } +fn parse_chunk_name(name: &str) -> Result<[u8; 4], String> { + name.trim() + .as_bytes() + .try_into() + .map_err(|_| format!("Invalid chunk name {}", name)) +} + fn parse_numeric_range_opts( input: &str, min_value: u8, diff --git a/src/png/mod.rs b/src/png/mod.rs index c25c52a9..0a07bf32 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -4,6 +4,7 @@ use crate::error::PngError; use crate::filters::*; use crate::headers::*; use crate::interlace::{deinterlace_image, interlace_image, Interlacing}; +use crate::Options; use bitvec::bitarr; use indexmap::IndexMap; use libdeflater::{CompressionLvl, Compressor}; @@ -30,8 +31,6 @@ pub struct PngImage { pub ihdr: IhdrData, /// The uncompressed, unfiltered data from the IDAT chunk pub data: Vec, - /// All non-critical headers from the PNG are stored here - pub aux_headers: IndexMap<[u8; 4], Vec>, } /// Contains all data relevant to a PNG image @@ -43,15 +42,17 @@ pub struct PngData { pub idat_data: Vec, /// The filtered, uncompressed data of the IDAT chunk pub filtered: Vec, + /// All non-critical chunks from the PNG are stored here + pub aux_chunks: Vec, } impl PngData { /// Create a new `PngData` struct by opening a file #[inline] - pub fn new(filepath: &Path, fix_errors: bool) -> Result { + pub fn new(filepath: &Path, opts: &Options) -> Result { let byte_data = Self::read_file(filepath)?; - Self::from_slice(&byte_data, fix_errors) + Self::from_slice(&byte_data, opts) } pub fn read_file(filepath: &Path) -> Result, PngError> { @@ -80,7 +81,7 @@ impl PngData { } /// Create a new `PngData` struct by reading a slice - pub fn from_slice(byte_data: &[u8], fix_errors: bool) -> Result { + pub fn from_slice(byte_data: &[u8], opts: &Options) -> Result { let mut byte_offset: usize = 0; // Test that png header is valid let header = byte_data.get(0..8).ok_or(PngError::TruncatedData)?; @@ -88,49 +89,60 @@ impl PngData { return Err(PngError::NotPNG); } byte_offset += 8; - // Read the data headers - let mut aux_headers: IndexMap<[u8; 4], Vec> = IndexMap::new(); - let mut idat_headers: Vec = Vec::new(); - while let Some(header) = parse_next_header(byte_data, &mut byte_offset, fix_errors)? { - match &header.name { - b"IDAT" => idat_headers.extend_from_slice(header.data), + + // Read the data chunks + let mut idat_data: Vec = Vec::new(); + let mut key_chunks: IndexMap<[u8; 4], Vec> = IndexMap::new(); + let mut aux_chunks: Vec = Vec::new(); + while let Some(chunk) = parse_next_chunk(byte_data, &mut byte_offset, opts.fix_errors)? { + match &chunk.name { + b"IDAT" => idat_data.extend_from_slice(chunk.data), b"acTL" => return Err(PngError::APNGNotSupported), + b"IHDR" | b"PLTE" | b"tRNS" => { + key_chunks.insert(chunk.name, chunk.data.to_owned()); + } _ => { - aux_headers.insert(header.name, header.data.to_owned()); + if opts.strip.keep(&chunk.name) { + aux_chunks.push(Chunk { + name: chunk.name, + data: chunk.data.to_owned(), + }) + } } } } - // Parse the headers into our PngData - if idat_headers.is_empty() { + + // Parse the chunks into our PngData + if idat_data.is_empty() { return Err(PngError::ChunkMissing("IDAT")); } - let ihdr = match aux_headers.remove(b"IHDR") { + let ihdr_chunk = match key_chunks.remove(b"IHDR") { Some(ihdr) => ihdr, None => return Err(PngError::ChunkMissing("IHDR")), }; - let ihdr_header = parse_ihdr_header( - &ihdr, - aux_headers.remove(b"PLTE"), - aux_headers.remove(b"tRNS"), + let ihdr = parse_ihdr_chunk( + &ihdr_chunk, + key_chunks.remove(b"PLTE"), + key_chunks.remove(b"tRNS"), )?; - let raw_data = deflate::inflate(idat_headers.as_ref(), ihdr_header.raw_data_size())?; + let raw_data = deflate::inflate(idat_data.as_ref(), ihdr.raw_data_size())?; // Reject files with incorrect width/height or truncated data - if raw_data.len() != ihdr_header.raw_data_size() { + if raw_data.len() != ihdr.raw_data_size() { return Err(PngError::TruncatedData); } let mut raw = PngImage { - ihdr: ihdr_header, + ihdr, data: raw_data, - aux_headers, }; let unfiltered = raw.unfilter_image()?; // Return the PngData Ok(Self { - idat_data: idat_headers, + idat_data, filtered: std::mem::replace(&mut raw.data, unfiltered), raw: Arc::new(raw), + aux_chunks, }) } @@ -173,14 +185,13 @@ impl PngData { ihdr_data.write_all(&[0]).ok(); // Filter method -- 5-way adaptive filtering ihdr_data.write_all(&[self.raw.ihdr.interlaced as u8]).ok(); write_png_block(b"IHDR", &ihdr_data, &mut output); - // Ancillary headers - for (key, header) in self - .raw - .aux_headers + // Ancillary chunks + for chunk in self + .aux_chunks .iter() - .filter(|&(key, _)| !(key == b"bKGD" || key == b"hIST" || key == b"tRNS")) + .filter(|c| !(&c.name == b"bKGD" || &c.name == b"hIST" || &c.name == b"tRNS")) { - write_png_block(key, header, &mut output); + write_png_block(&chunk.name, &chunk.data, &mut output); } // Palette and transparency match &self.raw.ihdr.color_type { @@ -210,14 +221,13 @@ impl PngData { } _ => {} } - // Special ancillary headers that need to come after PLTE but before IDAT - for (key, header) in self - .raw - .aux_headers + // Special ancillary chunks that need to come after PLTE but before IDAT + for chunk in self + .aux_chunks .iter() - .filter(|&(key, _)| key == b"bKGD" || key == b"hIST" || key == b"tRNS") + .filter(|c| &c.name == b"bKGD" || &c.name == b"hIST" || &c.name == b"tRNS") { - write_png_block(key, header, &mut output); + write_png_block(&chunk.name, &chunk.data, &mut output); } // IDAT data write_png_block(b"IDAT", &self.idat_data, &mut output); @@ -451,14 +461,15 @@ impl PngImage { filtered } } -fn write_png_block(key: &[u8], header: &[u8], output: &mut Vec) { - let mut header_data = Vec::with_capacity(header.len() + 4); - header_data.extend_from_slice(key); - header_data.extend_from_slice(header); - output.reserve(header_data.len() + 8); - output.extend_from_slice(&(header_data.len() as u32 - 4).to_be_bytes()); - let crc = deflate::crc32(&header_data); - output.append(&mut header_data); + +fn write_png_block(key: &[u8], chunk: &[u8], output: &mut Vec) { + let mut chunk_data = Vec::with_capacity(chunk.len() + 4); + chunk_data.extend_from_slice(key); + chunk_data.extend_from_slice(chunk); + output.reserve(chunk_data.len() + 8); + output.extend_from_slice(&(chunk_data.len() as u32 - 4).to_be_bytes()); + let crc = deflate::crc32(&chunk_data); + output.append(&mut chunk_data); output.extend_from_slice(&crc.to_be_bytes()); } diff --git a/src/reduction/alpha.rs b/src/reduction/alpha.rs index 4b9fd439..3045ddf6 100644 --- a/src/reduction/alpha.rs +++ b/src/reduction/alpha.rs @@ -25,7 +25,6 @@ pub fn cleaned_alpha_channel(png: &PngImage) -> Option { Some(PngImage { data: reduced, ihdr: png.ihdr.clone(), - aux_headers: png.aux_headers.clone(), }) } @@ -88,20 +87,11 @@ pub fn reduced_alpha_channel(png: &PngImage, optimize_alpha: bool) -> Option Option { bit_depth: BitDepth::Eight, ..png.ihdr }, - aux_headers: png.aux_headers.clone(), }) } @@ -155,6 +154,5 @@ pub fn reduced_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> O bit_depth: (minimum_bits as u8).try_into().unwrap(), ..png.ihdr }, - aux_headers: png.aux_headers.clone(), }) } diff --git a/src/reduction/color.rs b/src/reduction/color.rs index 177ae1d6..630619d2 100644 --- a/src/reduction/color.rs +++ b/src/reduction/color.rs @@ -3,7 +3,7 @@ use crate::headers::IhdrData; use crate::png::PngImage; use indexmap::IndexSet; use rgb::alt::Gray; -use rgb::{ComponentMap, ComponentSlice, FromSlice, RGB, RGBA, RGBA8}; +use rgb::{ComponentMap, ComponentSlice, FromSlice, RGB, RGBA}; use rustc_hash::FxHasher; use std::hash::{BuildHasherDefault, Hash}; @@ -41,7 +41,7 @@ pub fn reduced_to_indexed(png: &PngImage) -> Option { } let mut raw_data = Vec::with_capacity(png.data.len() / png.channels_per_pixel()); - let mut palette: Vec<_> = match png.ihdr.color_type { + let palette: Vec<_> = match png.ihdr.color_type { ColorType::Grayscale { transparent_shade } => { let pmap = build_palette(png.data.as_gray().iter().cloned(), &mut raw_data)?; // Convert the Gray16 transparency to Gray8 @@ -81,51 +81,12 @@ pub fn reduced_to_indexed(png: &PngImage) -> Option { _ => return None, }; - let mut aux_headers = png.aux_headers.clone(); - if let Some(bkgd_header) = aux_headers.remove(b"bKGD") { - let bg = if png.ihdr.color_type.is_rgb() && bkgd_header.len() == 6 { - // In bKGD 16-bit values are used even for 8-bit images - Some(RGBA8::new( - bkgd_header[1], - bkgd_header[3], - bkgd_header[5], - 255, - )) - } else if png.ihdr.color_type.is_grayscale() && bkgd_header.len() == 2 { - Some(RGBA8::new( - bkgd_header[1], - bkgd_header[1], - bkgd_header[1], - 255, - )) - } else { - None - }; - if let Some(bg) = bg { - let idx = palette.iter().position(|&px| px == bg).or_else(|| { - if palette.len() < 256 { - palette.push(bg); - Some(palette.len() - 1) - } else { - None // No space in palette to store the bg as an index - } - })?; - aux_headers.insert(*b"bKGD", vec![idx as u8]); - } - } - - if let Some(sbit_header) = png.aux_headers.get(b"sBIT") { - // Some programs save the sBIT header as RGB even if the image is RGBA. - aux_headers.insert(*b"sBIT", sbit_header.iter().cloned().take(3).collect()); - } - Some(PngImage { data: raw_data, ihdr: IhdrData { color_type: ColorType::Indexed { palette }, ..png.ihdr }, - aux_headers, }) } @@ -150,18 +111,6 @@ pub fn reduced_rgb_to_grayscale(png: &PngImage) -> Option { reduced.extend_from_slice(&pixel[last_color..]); } - let mut aux_headers = png.aux_headers.clone(); - if let Some(sbit_header) = png.aux_headers.get(b"sBIT") { - if let Some(&byte) = sbit_header.first() { - aux_headers.insert(*b"sBIT", vec![byte]); - } - } - if let Some(bkgd_header) = png.aux_headers.get(b"bKGD") { - if let Some(b) = bkgd_header.get(0..2) { - aux_headers.insert(*b"bKGD", b.to_owned()); - } - } - let color_type = match png.ihdr.color_type { ColorType::RGB { transparent_color } => ColorType::Grayscale { // Copy the transparent component if it is also gray @@ -178,7 +127,6 @@ pub fn reduced_rgb_to_grayscale(png: &PngImage) -> Option { color_type, ..png.ihdr }, - aux_headers, }) } @@ -223,25 +171,11 @@ pub fn indexed_to_channels(png: &PngImage) -> Option { data.extend_from_slice(&color.as_slice()[ch_start..=ch_end]); } - // Update bKGD if it exists - let mut aux_headers = png.aux_headers.clone(); - if let Some(idx) = aux_headers.remove(b"bKGD").and_then(|b| b.first().cloned()) { - if let Some(color) = palette.get(idx as usize) { - let bkgd = if is_gray { - vec![0, color.r] - } else { - vec![0, color.r, 0, color.g, 0, color.b] - }; - aux_headers.insert(*b"bKGD", bkgd); - } - } - Some(PngImage { ihdr: IhdrData { color_type, ..png.ihdr }, data, - aux_headers, }) } diff --git a/src/reduction/palette.rs b/src/reduction/palette.rs index 83c14e24..8c610d03 100644 --- a/src/reduction/palette.rs +++ b/src/reduction/palette.rs @@ -30,15 +30,6 @@ pub fn reduced_palette(png: &PngImage, optimize_alpha: bool) -> Option } } - // Update bKGD if it exists, ensuring it comes last in the palette if otherwise unused - let mut aux_headers = png.aux_headers.clone(); - if let Some(idx) = aux_headers.remove(b"bKGD").and_then(|b| b.first().cloned()) { - if let Some(&color) = palette.get(idx as usize) { - let idx = add_color_to_set(color, &mut condensed, optimize_alpha); - aux_headers.insert(*b"bKGD", vec![idx]); - } - } - let data = if did_change { // Reassign data bytes to new indices let byte_map = palette_map_to_byte_map(png.ihdr.bit_depth, &palette_map); @@ -59,7 +50,6 @@ pub fn reduced_palette(png: &PngImage, optimize_alpha: bool) -> Option ..png.ihdr }, data, - aux_headers, }) } @@ -145,15 +135,6 @@ pub fn sorted_palette(png: &PngImage) -> Option { let mut enumerated: Vec<_> = palette.iter().enumerate().collect(); - // If the background is the last entry in the palette we should make sure it stays last - // Otherwise an entry that's unused by the idat could prevent reduction to a lower depth - let mut aux_headers = png.aux_headers.clone(); - let bkgd_idx = aux_headers.remove(b"bKGD").and_then(|b| b.first().cloned()); - let bkgd_last = match bkgd_idx { - Some(idx) if idx as usize + 1 == palette.len() => enumerated.pop(), - _ => None, - }; - // Sort the palette enumerated.sort_by(|a, b| { // Sort by ascending alpha and descending luma @@ -167,10 +148,6 @@ pub fn sorted_palette(png: &PngImage) -> Option { color_val(a.1).cmp(&color_val(b.1)) }); - if let Some(bkgd) = bkgd_last { - enumerated.push(bkgd); - } - // Extract the new palette and determine if anything changed let (old_map, palette): (Vec<_>, Vec) = enumerated.into_iter().unzip(); if old_map.iter().enumerate().all(|(a, b)| a == *b) { @@ -185,17 +162,11 @@ pub fn sorted_palette(png: &PngImage) -> Option { let byte_map = palette_map_to_byte_map(png.ihdr.bit_depth, &new_map); let data = png.data.iter().map(|&b| byte_map[b as usize]).collect(); - // Update bKGD if it exists - if let Some(idx) = bkgd_idx.map(|idx| new_map[idx as usize]) { - aux_headers.insert(*b"bKGD", vec![idx]); - } - Some(PngImage { ihdr: IhdrData { color_type: ColorType::Indexed { palette }, ..png.ihdr }, data, - aux_headers, }) } diff --git a/tests/filters.rs b/tests/filters.rs index 065c1259..17e79b81 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -1,6 +1,6 @@ use indexmap::IndexSet; -use oxipng::{internal_tests::*, RowFilter}; -use oxipng::{InFile, OutFile}; +use oxipng::internal_tests::*; +use oxipng::*; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -37,7 +37,7 @@ fn test_it_converts( let input = PathBuf::from(input); let (output, mut opts) = get_opts(&input); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); opts.filter = IndexSet::new(); opts.filter.insert(filter); assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); @@ -50,7 +50,7 @@ fn test_it_converts( let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); diff --git a/tests/flags.rs b/tests/flags.rs index ebb2108e..bff73ef9 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -1,6 +1,6 @@ -use indexmap::IndexSet; -use oxipng::{internal_tests::*, Interlacing, RowFilter}; -use oxipng::{InFile, OutFile}; +use indexmap::{indexset, IndexSet}; +use oxipng::internal_tests::*; +use oxipng::*; #[cfg(feature = "filetime")] use std::cell::RefCell; use std::fs::remove_file; @@ -47,7 +47,7 @@ fn test_it_converts_callbacks( CBPOST: FnMut(&Path), CBPRE: FnMut(&Path), { - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); @@ -63,7 +63,7 @@ fn test_it_converts_callbacks( callback_post(output); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -203,17 +203,24 @@ fn verbose_mode() { } } +fn count_chunk(png: &PngData, name: &[u8; 4]) -> usize { + png.aux_chunks + .iter() + .filter(|chunk| &chunk.name == name) + .count() +} + #[test] fn strip_headers_list() { let input = PathBuf::from("tests/files/strip_headers_list.png"); let (output, mut opts) = get_opts(&input); - opts.strip = Headers::Strip(vec!["iCCP".to_owned(), "tEXt".to_owned()]); + opts.strip = StripChunks::Strip(indexset![*b"iCCP", *b"tEXt"]); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); - assert!(png.raw.aux_headers.contains_key(b"tEXt")); - assert!(png.raw.aux_headers.contains_key(b"iTXt")); - assert!(png.raw.aux_headers.contains_key(b"iCCP")); + assert_eq!(count_chunk(&png, b"tEXt"), 1); + assert_eq!(count_chunk(&png, b"iTXt"), 1); + assert_eq!(count_chunk(&png, b"iCCP"), 1); match oxipng::optimize(&InFile::Path(input), &output, &opts) { Ok(_) => (), @@ -222,7 +229,7 @@ fn strip_headers_list() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -230,9 +237,9 @@ fn strip_headers_list() { } }; - assert!(!png.raw.aux_headers.contains_key(b"tEXt")); - assert!(png.raw.aux_headers.contains_key(b"iTXt")); - assert!(!png.raw.aux_headers.contains_key(b"iCCP")); + assert_eq!(count_chunk(&png, b"tEXt"), 0); + assert_eq!(count_chunk(&png, b"iTXt"), 1); + assert_eq!(count_chunk(&png, b"iCCP"), 0); remove_file(output).ok(); } @@ -241,13 +248,13 @@ fn strip_headers_list() { fn strip_headers_safe() { let input = PathBuf::from("tests/files/strip_headers_safe.png"); let (output, mut opts) = get_opts(&input); - opts.strip = Headers::Safe; + opts.strip = StripChunks::Safe; - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); - assert!(png.raw.aux_headers.contains_key(b"tEXt")); - assert!(png.raw.aux_headers.contains_key(b"iTXt")); - assert!(png.raw.aux_headers.contains_key(b"iCCP")); + assert_eq!(count_chunk(&png, b"tEXt"), 1); + assert_eq!(count_chunk(&png, b"iTXt"), 1); + assert_eq!(count_chunk(&png, b"iCCP"), 1); match oxipng::optimize(&InFile::Path(input), &output, &opts) { Ok(_) => (), @@ -256,7 +263,7 @@ fn strip_headers_safe() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -264,9 +271,9 @@ fn strip_headers_safe() { } }; - assert!(!png.raw.aux_headers.contains_key(b"tEXt")); - assert!(!png.raw.aux_headers.contains_key(b"iTXt")); - assert!(png.raw.aux_headers.contains_key(b"sRGB")); + assert_eq!(count_chunk(&png, b"tEXt"), 0); + assert_eq!(count_chunk(&png, b"iTXt"), 0); + assert_eq!(count_chunk(&png, b"sRGB"), 1); remove_file(output).ok(); } @@ -275,13 +282,13 @@ fn strip_headers_safe() { fn strip_headers_all() { let input = PathBuf::from("tests/files/strip_headers_all.png"); let (output, mut opts) = get_opts(&input); - opts.strip = Headers::All; + opts.strip = StripChunks::All; - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); - assert!(png.raw.aux_headers.contains_key(b"tEXt")); - assert!(png.raw.aux_headers.contains_key(b"iTXt")); - assert!(png.raw.aux_headers.contains_key(b"iCCP")); + assert_eq!(count_chunk(&png, b"tEXt"), 1); + assert_eq!(count_chunk(&png, b"iTXt"), 1); + assert_eq!(count_chunk(&png, b"iCCP"), 1); match oxipng::optimize(&InFile::Path(input), &output, &opts) { Ok(_) => (), @@ -290,7 +297,7 @@ fn strip_headers_all() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -298,9 +305,9 @@ fn strip_headers_all() { } }; - assert!(!png.raw.aux_headers.contains_key(b"tEXt")); - assert!(!png.raw.aux_headers.contains_key(b"iTXt")); - assert!(!png.raw.aux_headers.contains_key(b"iCCP")); + assert_eq!(count_chunk(&png, b"tEXt"), 0); + assert_eq!(count_chunk(&png, b"iTXt"), 0); + assert_eq!(count_chunk(&png, b"iCCP"), 0); remove_file(output).ok(); } @@ -309,13 +316,13 @@ fn strip_headers_all() { fn strip_headers_none() { let input = PathBuf::from("tests/files/strip_headers_none.png"); let (output, mut opts) = get_opts(&input); - opts.strip = Headers::None; + opts.strip = StripChunks::None; - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &Options::default()).unwrap(); - assert!(png.raw.aux_headers.contains_key(b"tEXt")); - assert!(png.raw.aux_headers.contains_key(b"iTXt")); - assert!(png.raw.aux_headers.contains_key(b"iCCP")); + assert_eq!(count_chunk(&png, b"tEXt"), 1); + assert_eq!(count_chunk(&png, b"iTXt"), 1); + assert_eq!(count_chunk(&png, b"iCCP"), 1); match oxipng::optimize(&InFile::Path(input), &output, &opts) { Ok(_) => (), @@ -324,7 +331,7 @@ fn strip_headers_none() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -332,9 +339,9 @@ fn strip_headers_none() { } }; - assert!(png.raw.aux_headers.contains_key(b"tEXt")); - assert!(png.raw.aux_headers.contains_key(b"iTXt")); - assert!(png.raw.aux_headers.contains_key(b"iCCP")); + assert_eq!(count_chunk(&png, b"tEXt"), 1); + assert_eq!(count_chunk(&png, b"iTXt"), 1); + assert_eq!(count_chunk(&png, b"iCCP"), 1); remove_file(output).ok(); } @@ -345,7 +352,7 @@ fn interlacing_0_to_1() { let (output, mut opts) = get_opts(&input); opts.interlace = Some(Interlacing::Adam7); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.interlaced, Interlacing::None); @@ -356,7 +363,7 @@ fn interlacing_0_to_1() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -375,7 +382,7 @@ fn interlacing_1_to_0() { let (output, mut opts) = get_opts(&input); opts.interlace = Some(Interlacing::None); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.interlaced, Interlacing::Adam7); @@ -386,7 +393,7 @@ fn interlacing_1_to_0() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -405,7 +412,7 @@ fn interlacing_0_to_1_small_files() { let (output, mut opts) = get_opts(&input); opts.interlace = Some(Interlacing::Adam7); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.interlaced, Interlacing::None); assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); @@ -418,7 +425,7 @@ fn interlacing_0_to_1_small_files() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -439,7 +446,7 @@ fn interlacing_1_to_0_small_files() { let (output, mut opts) = get_opts(&input); opts.interlace = Some(Interlacing::None); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.interlaced, Interlacing::Adam7); assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); @@ -452,7 +459,7 @@ fn interlacing_1_to_0_small_files() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -476,7 +483,7 @@ fn interlaced_0_to_1_other_filter_mode() { filter.insert(RowFilter::Paeth); opts.filter = filter; - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.interlaced, Interlacing::None); @@ -487,7 +494,7 @@ fn interlaced_0_to_1_other_filter_mode() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -570,7 +577,7 @@ fn fix_errors() { let (output, mut opts) = get_opts(&input); opts.fix_errors = true; - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.color_type.png_header_code(), RGBA); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); @@ -582,7 +589,7 @@ fn fix_errors() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, false) { + let png = match PngData::new(output, &Options::default()) { Ok(x) => x, Err(x) => { remove_file(output).ok(); diff --git a/tests/interlaced.rs b/tests/interlaced.rs index 52540a85..573c3182 100644 --- a/tests/interlaced.rs +++ b/tests/interlaced.rs @@ -1,6 +1,6 @@ use indexmap::IndexSet; -use oxipng::{internal_tests::*, Interlacing, RowFilter}; -use oxipng::{InFile, OutFile}; +use oxipng::internal_tests::*; +use oxipng::*; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -35,7 +35,7 @@ fn test_it_converts( ) { let input = PathBuf::from(input); let (output, opts) = get_opts(&input); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); @@ -48,7 +48,7 @@ fn test_it_converts( let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); diff --git a/tests/interlacing.rs b/tests/interlacing.rs index 10f558e6..2e971979 100644 --- a/tests/interlacing.rs +++ b/tests/interlacing.rs @@ -1,6 +1,6 @@ use indexmap::IndexSet; -use oxipng::{internal_tests::*, Interlacing, RowFilter}; -use oxipng::{InFile, OutFile}; +use oxipng::internal_tests::*; +use oxipng::*; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -33,7 +33,7 @@ fn test_it_converts( ) { let input = PathBuf::from(input); let (output, mut opts) = get_opts(&input); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); opts.interlace = Some(interlace); assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); @@ -53,7 +53,7 @@ fn test_it_converts( let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); diff --git a/tests/lib.rs b/tests/lib.rs index 8f5e28d1..a32de8b1 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,6 +1,4 @@ -use oxipng::Headers; -use oxipng::OutFile; -use std::default::Default; +use oxipng::*; use std::fs; use std::fs::File; use std::io::prelude::*; @@ -11,9 +9,7 @@ fn optimize_from_memory() { let mut in_file_buf: Vec = Vec::new(); in_file.read_to_end(&mut in_file_buf).unwrap(); - let opts: oxipng::Options = Default::default(); - - let result = oxipng::optimize_from_memory(&in_file_buf, &opts); + let result = oxipng::optimize_from_memory(&in_file_buf, &Options::default()); assert!(result.is_ok()); } @@ -23,9 +19,7 @@ fn optimize_from_memory_corrupted() { let mut in_file_buf: Vec = Vec::new(); in_file.read_to_end(&mut in_file_buf).unwrap(); - let opts: oxipng::Options = Default::default(); - - let result = oxipng::optimize_from_memory(&in_file_buf, &opts); + let result = oxipng::optimize_from_memory(&in_file_buf, &Options::default()); assert!(result.is_err()); } @@ -35,44 +29,36 @@ fn optimize_from_memory_apng() { let mut in_file_buf: Vec = Vec::new(); in_file.read_to_end(&mut in_file_buf).unwrap(); - let opts: oxipng::Options = Default::default(); - - let result = oxipng::optimize_from_memory(&in_file_buf, &opts); + let result = oxipng::optimize_from_memory(&in_file_buf, &Options::default()); assert!(result.is_err()); } #[test] fn optimize() { - let opts: oxipng::Options = Default::default(); - let result = oxipng::optimize( &"tests/files/fully_optimized.png".into(), &OutFile::Path(None), - &opts, + &Options::default(), ); assert!(result.is_ok()); } #[test] fn optimize_corrupted() { - let opts: oxipng::Options = Default::default(); - let result = oxipng::optimize( &"tests/files/corrupted_header.png".into(), &OutFile::Path(None), - &opts, + &Options::default(), ); assert!(result.is_err()); } #[test] fn optimize_apng() { - let opts: oxipng::Options = Default::default(); - let result = oxipng::optimize( &"tests/files/apng_file.png".into(), &OutFile::Path(None), - &opts, + &Options::default(), ); assert!(result.is_err()); } @@ -80,12 +66,12 @@ fn optimize_apng() { #[test] fn optimize_srgb_icc() { let file = fs::read("tests/files/badsrgb.png").unwrap(); - let mut opts: oxipng::Options = Default::default(); + let mut opts = Options::default(); let result = oxipng::optimize_from_memory(&file, &opts); assert!(result.unwrap().len() > 1000); - opts.strip = Headers::Safe; + opts.strip = StripChunks::Safe; let result = oxipng::optimize_from_memory(&file, &opts); assert!(result.unwrap().len() < 1000); } diff --git a/tests/raw.rs b/tests/raw.rs index 03802444..c3e16fb2 100644 --- a/tests/raw.rs +++ b/tests/raw.rs @@ -16,11 +16,11 @@ fn test_it_converts(input: &str) { let opts = get_opts(); let original_data = PngData::read_file(&PathBuf::from(input)).unwrap(); - let png = PngData::from_slice(&original_data, opts.fix_errors).unwrap(); - let png = Arc::try_unwrap(png.raw).unwrap(); + let image = PngData::from_slice(&original_data, &opts).unwrap(); + let png = Arc::try_unwrap(image.raw).unwrap(); - let num_headers = png.aux_headers.len(); - assert!(num_headers > 0); + let num_chunks = image.aux_chunks.len(); + assert!(num_chunks > 0); let mut raw = RawImage::new( png.ihdr.width, @@ -31,14 +31,14 @@ fn test_it_converts(input: &str) { ) .unwrap(); - for (chunk_type, data) in png.aux_headers { - raw.add_png_chunk(chunk_type, data); + for chunk in image.aux_chunks { + raw.add_png_chunk(chunk.name, chunk.data); } let output = raw.create_optimized_png(&opts).unwrap(); - let new = PngData::from_slice(&output, opts.fix_errors).unwrap(); - assert!(new.raw.aux_headers.len() == num_headers); + let new = PngData::from_slice(&output, &opts).unwrap(); + assert!(new.aux_chunks.len() == num_chunks); #[cfg(feature = "sanity-checks")] assert!(validate_output(&output, &original_data)); diff --git a/tests/reduction.rs b/tests/reduction.rs index 3d6577eb..8a1a1e34 100644 --- a/tests/reduction.rs +++ b/tests/reduction.rs @@ -1,6 +1,6 @@ use indexmap::IndexSet; -use oxipng::{internal_tests::*, Interlacing, RowFilter}; -use oxipng::{InFile, OutFile}; +use oxipng::internal_tests::*; +use oxipng::*; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -37,7 +37,7 @@ fn test_it_converts( let input = PathBuf::from(input); let (output, mut opts) = get_opts(&input); opts.optimize_alpha = optimize_alpha; - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in, "test file is broken"); @@ -50,7 +50,7 @@ fn test_it_converts( let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -933,7 +933,7 @@ fn palette_should_be_reduced_with_dupes() { let input = PathBuf::from("tests/files/palette_should_be_reduced_with_dupes.png"); let (output, opts) = get_opts(&input); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); @@ -948,7 +948,7 @@ fn palette_should_be_reduced_with_dupes() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -970,7 +970,7 @@ fn palette_should_be_reduced_with_unused() { let input = PathBuf::from("tests/files/palette_should_be_reduced_with_unused.png"); let (output, opts) = get_opts(&input); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); @@ -985,7 +985,7 @@ fn palette_should_be_reduced_with_unused() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -1007,7 +1007,7 @@ fn palette_should_be_reduced_with_both() { let input = PathBuf::from("tests/files/palette_should_be_reduced_with_both.png"); let (output, opts) = get_opts(&input); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); @@ -1022,7 +1022,7 @@ fn palette_should_be_reduced_with_both() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); diff --git a/tests/regression.rs b/tests/regression.rs index c24c8373..c84a25dd 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -1,6 +1,6 @@ use indexmap::IndexSet; -use oxipng::{internal_tests::*, Interlacing, RowFilter}; -use oxipng::{InFile, OutFile}; +use oxipng::internal_tests::*; +use oxipng::*; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -36,7 +36,7 @@ fn test_it_converts( ) { let input = PathBuf::from(input); let (output, opts) = custom.unwrap_or_else(|| get_opts(&input)); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!( png.raw.ihdr.color_type.png_header_code(), @@ -52,7 +52,7 @@ fn test_it_converts( let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -70,13 +70,7 @@ fn test_it_converts( "optimized to wrong bit depth" ); if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type { - let mut max_palette_size = 1 << (png.raw.ihdr.bit_depth as u8); - // Ensure bKGD color is valid - if let Some(&idx) = png.raw.aux_headers.get(b"bKGD").and_then(|b| b.first()) { - assert!(palette.len() > idx as usize); - max_palette_size = max_palette_size.max(idx as usize + 1); - } - assert!(palette.len() <= max_palette_size); + assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth as u8)); } remove_file(output).ok(); @@ -100,7 +94,7 @@ fn issue_42() { let (output, mut opts) = get_opts(&input); opts.interlace = Some(Interlacing::Adam7); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); assert_eq!(png.raw.ihdr.interlaced, Interlacing::None); assert_eq!(png.raw.ihdr.color_type, ColorType::GrayscaleAlpha); @@ -113,7 +107,7 @@ fn issue_42() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -231,7 +225,7 @@ fn issue_59() { None, RGBA, BitDepth::Eight, - RGBA, + INDEXED, BitDepth::Eight, ); } diff --git a/tests/strategies.rs b/tests/strategies.rs index 415014fe..8b4b9478 100644 --- a/tests/strategies.rs +++ b/tests/strategies.rs @@ -1,6 +1,6 @@ use indexmap::IndexSet; -use oxipng::{internal_tests::*, RowFilter}; -use oxipng::{InFile, OutFile}; +use oxipng::internal_tests::*; +use oxipng::*; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -36,7 +36,7 @@ fn test_it_converts( let input = PathBuf::from(input); let (output, mut opts) = get_opts(&input); - let png = PngData::new(&input, opts.fix_errors).unwrap(); + let png = PngData::new(&input, &opts).unwrap(); opts.filter = IndexSet::new(); opts.filter.insert(filter); assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); @@ -49,7 +49,7 @@ fn test_it_converts( let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(output, opts.fix_errors) { + let png = match PngData::new(output, &opts) { Ok(x) => x, Err(x) => { remove_file(output).ok();