diff --git a/benches/filters.rs b/benches/filters.rs index 6cf1e4cb..861aaee4 100644 --- a/benches/filters.rs +++ b/benches/filters.rs @@ -13,7 +13,10 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::None, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::None), false) + }); } #[bench] @@ -21,7 +24,10 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::None, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::None), false) + }); } #[bench] @@ -31,7 +37,10 @@ fn filters_4_bits_filter_0(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::None, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::None), false) + }); } #[bench] @@ -41,7 +50,10 @@ fn filters_2_bits_filter_0(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::None, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::None), false) + }); } #[bench] @@ -51,7 +63,10 @@ fn filters_1_bits_filter_0(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::None, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::None), false) + }); } #[bench] @@ -59,7 +74,10 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Sub, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Sub), false) + }); } #[bench] @@ -67,7 +85,10 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Sub, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Sub), false) + }); } #[bench] @@ -77,7 +98,10 @@ fn filters_4_bits_filter_1(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Sub, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Sub), false) + }); } #[bench] @@ -87,7 +111,10 @@ fn filters_2_bits_filter_1(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Sub, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Sub), false) + }); } #[bench] @@ -97,7 +124,10 @@ fn filters_1_bits_filter_1(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Sub, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Sub), false) + }); } #[bench] @@ -105,7 +135,10 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Up, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Up), false) + }); } #[bench] @@ -113,7 +146,10 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Up, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Up), false) + }); } #[bench] @@ -123,7 +159,10 @@ fn filters_4_bits_filter_2(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Up, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Up), false) + }); } #[bench] @@ -133,7 +172,10 @@ fn filters_2_bits_filter_2(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Up, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Up), false) + }); } #[bench] @@ -143,7 +185,10 @@ fn filters_1_bits_filter_2(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Up, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Up), false) + }); } #[bench] @@ -151,7 +196,10 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Average, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Average), false) + }); } #[bench] @@ -159,7 +207,10 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Average, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Average), false) + }); } #[bench] @@ -169,7 +220,10 @@ fn filters_4_bits_filter_3(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Average, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Average), false) + }); } #[bench] @@ -179,7 +233,10 @@ fn filters_2_bits_filter_3(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Average, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Average), false) + }); } #[bench] @@ -189,7 +246,10 @@ fn filters_1_bits_filter_3(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Average, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Average), false) + }); } #[bench] @@ -197,7 +257,10 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Paeth, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Paeth), false) + }); } #[bench] @@ -205,7 +268,10 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Paeth, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Paeth), false) + }); } #[bench] @@ -215,7 +281,10 @@ fn filters_4_bits_filter_4(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Paeth, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Paeth), false) + }); } #[bench] @@ -225,7 +294,10 @@ fn filters_2_bits_filter_4(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Paeth, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Paeth), false) + }); } #[bench] @@ -235,7 +307,10 @@ fn filters_1_bits_filter_4(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Paeth, false)); + b.iter(|| { + png.raw + .filter_image(FilterStrategy::Basic(RowFilter::Paeth), false) + }); } #[bench] @@ -243,7 +318,7 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::MinSum, false)); + b.iter(|| png.raw.filter_image(FilterStrategy::MinSum, false)); } #[bench] @@ -251,7 +326,7 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::MinSum, false)); + b.iter(|| png.raw.filter_image(FilterStrategy::MinSum, false)); } #[bench] @@ -261,7 +336,7 @@ fn filters_4_bits_filter_5(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::MinSum, false)); + b.iter(|| png.raw.filter_image(FilterStrategy::MinSum, false)); } #[bench] @@ -271,7 +346,7 @@ fn filters_2_bits_filter_5(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::MinSum, false)); + b.iter(|| png.raw.filter_image(FilterStrategy::MinSum, false)); } #[bench] @@ -281,5 +356,5 @@ fn filters_1_bits_filter_5(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::MinSum, false)); + b.iter(|| png.raw.filter_image(FilterStrategy::MinSum, false)); } diff --git a/benches/strategies.rs b/benches/strategies.rs index 15f546f1..72d19e90 100644 --- a/benches/strategies.rs +++ b/benches/strategies.rs @@ -13,7 +13,7 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::MinSum, false)); + b.iter(|| png.raw.filter_image(FilterStrategy::MinSum, false)); } #[bench] @@ -21,7 +21,7 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Entropy, false)); + b.iter(|| png.raw.filter_image(FilterStrategy::Entropy, false)); } #[bench] @@ -29,7 +29,7 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Bigrams, false)); + b.iter(|| png.raw.filter_image(FilterStrategy::Bigrams, false)); } #[bench] @@ -37,7 +37,7 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::BigEnt, false)); + b.iter(|| png.raw.filter_image(FilterStrategy::BigEnt, false)); } #[bench] @@ -45,5 +45,5 @@ 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, &Options::default()).unwrap(); - b.iter(|| png.raw.filter_image(RowFilter::Brute, false)); + b.iter(|| png.raw.filter_image(FilterStrategy::Brute, false)); } diff --git a/src/evaluate.rs b/src/evaluate.rs index af6c4070..69c36544 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -17,14 +17,16 @@ use rayon::prelude::*; #[cfg(not(feature = "parallel"))] use crate::rayon; -use crate::{Deadline, PngError, atomicmin::AtomicMin, deflate, filters::RowFilter, png::PngImage}; +use crate::{ + Deadline, PngError, atomicmin::AtomicMin, deflate, filters::FilterStrategy, png::PngImage, +}; pub(crate) struct Candidate { pub image: Arc, pub data: Vec, pub data_is_compressed: bool, pub estimated_output_size: usize, - pub filter: RowFilter, + pub filter: FilterStrategy, // For determining tie-breaker nth: usize, } @@ -44,7 +46,7 @@ impl Candidate { /// Collect image versions and pick one that compresses best pub(crate) struct Evaluator { deadline: Arc, - filters: IndexSet, + filters: IndexSet, deflater: Deflaters, optimize_alpha: bool, final_round: bool, @@ -62,7 +64,7 @@ pub(crate) struct Evaluator { impl Evaluator { pub fn new( deadline: Arc, - filters: IndexSet, + filters: IndexSet, deflater: Deflaters, optimize_alpha: bool, final_round: bool, diff --git a/src/filters.rs b/src/filters.rs index d0b03b1d..42575b47 100644 --- a/src/filters.rs +++ b/src/filters.rs @@ -1,30 +1,67 @@ use std::{fmt, fmt::Display, mem::transmute}; -use crate::error::PngError; - /// Filtering strategy for use in [`Options`][crate::Options] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub enum FilterStrategy { + /// Same filter for all rows + Basic(RowFilter), + /// Minimum sum of absolute differences + MinSum, + /// Shannon entropy + Entropy, + /// Count of distinct bigrams + Bigrams, + /// Shannon entropy of bigrams + BigEnt, + /// Deflate compression + Brute, +} + +impl Display for FilterStrategy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Basic(filter) => filter.fmt(f), + Self::MinSum => "MinSum".fmt(f), + Self::Entropy => "Entropy".fmt(f), + Self::Bigrams => "Bigrams".fmt(f), + Self::BigEnt => "BigEnt".fmt(f), + Self::Brute => "Brute".fmt(f), + } + } +} + +impl TryFrom for FilterStrategy { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + 0..=4 => Ok(Self::Basic(value.try_into()?)), + 5 => Ok(Self::MinSum), + 6 => Ok(Self::Entropy), + 7 => Ok(Self::Bigrams), + 8 => Ok(Self::BigEnt), + 9 => Ok(Self::Brute), + _ => Err(()), + } + } +} + +/// PNG delta filters #[repr(u8)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] pub enum RowFilter { - // Standard filter types None, Sub, Up, Average, Paeth, - // Heuristic strategies - MinSum, - Entropy, - Bigrams, - BigEnt, - Brute, } impl TryFrom for RowFilter { type Error = (); fn try_from(value: u8) -> Result { - if value > Self::LAST { + if value > 4 { return Err(()); } unsafe { transmute(value as i8) } @@ -40,11 +77,6 @@ impl Display for RowFilter { Self::Up => "Up", Self::Average => "Average", Self::Paeth => "Paeth", - Self::MinSum => "MinSum", - Self::Entropy => "Entropy", - Self::Bigrams => "Bigrams", - Self::BigEnt => "BigEnt", - Self::Brute => "Brute", }, f, ) @@ -52,9 +84,7 @@ impl Display for RowFilter { } impl RowFilter { - pub const LAST: u8 = Self::Brute as u8; - pub(crate) const STANDARD: [Self; 5] = - [Self::None, Self::Sub, Self::Up, Self::Average, Self::Paeth]; + pub(crate) const ALL: [Self; 5] = [Self::None, Self::Sub, Self::Up, Self::Average, Self::Paeth]; pub(crate) const SINGLE_LINE: [Self; 2] = [Self::None, Self::Sub]; pub(crate) fn filter_line( @@ -115,7 +145,6 @@ impl RowFilter { }); } } - _ => unreachable!(), } } @@ -140,6 +169,7 @@ impl RowFilter { _ => i - 1, }; match self { + Self::None => unreachable!(), Self::Sub => { for j in 0..color_bytes { pixels[i][j] = pixels[prev][j]; @@ -171,7 +201,6 @@ impl RowFilter { }; } } - _ => unreachable!(), } } } @@ -183,7 +212,7 @@ impl RowFilter { data: &[u8], prev_line: &[u8], buf: &mut Vec, - ) -> Result<(), PngError> { + ) { buf.clear(); buf.reserve(data.len()); assert!(data.len() >= bpp); @@ -232,9 +261,7 @@ impl RowFilter { ); } } - _ => return Err(PngError::InvalidData), } - Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 1af2e8e3..fd9c30a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,7 @@ pub use crate::{ colors::{BitDepth, ColorType}, deflate::Deflaters, error::PngError, - filters::RowFilter, + filters::{FilterStrategy, RowFilter}, headers::StripChunks, interlace::Interlacing, options::{InFile, Options, OutFile}, @@ -432,7 +432,7 @@ fn optimize_raw( opts.filter.clone() } else { // None and Bigrams work well together, especially for alpha reductions - indexset! {RowFilter::None, RowFilter::Bigrams} + indexset! {FilterStrategy::Basic(RowFilter::None), FilterStrategy::Bigrams} }; // This will collect all versions of images and pick one that compresses best let eval = Evaluator::new( @@ -489,7 +489,7 @@ fn perform_trials( deadline: Arc, max_size: Option, mut eval_result: Option, - eval_filters: IndexSet, + eval_filters: IndexSet, eval_deflater: Deflaters, ) -> Option { let mut filters = opts.filter.clone(); @@ -548,10 +548,10 @@ fn perform_trials( // Pick a filter automatically if image.ihdr.bit_depth as u8 >= 8 { // Bigrams is the best all-rounder when there's at least one byte per pixel - filters.insert(RowFilter::Bigrams); + filters.insert(FilterStrategy::Bigrams); } else { // Otherwise delta filters generally don't work well, so just stick with None - filters.insert(RowFilter::None); + filters.insert(FilterStrategy::Basic(RowFilter::None)); } } @@ -627,7 +627,7 @@ fn recompress_frames( png: &mut PngData, opts: &Options, deadline: Arc, - filter: RowFilter, + filter: FilterStrategy, ) -> PngResult<()> { if !opts.idat_recoding || png.frames.is_empty() { return Ok(()); diff --git a/src/main.rs b/src/main.rs index 12794f44..c8732914 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,7 @@ use clap::ArgMatches; mod cli; use indexmap::IndexSet; use log::{Level, LevelFilter, error, warn}; -use oxipng::{Deflaters, InFile, Options, OutFile, PngError, RowFilter, StripChunks}; +use oxipng::{Deflaters, InFile, Options, OutFile, PngError, StripChunks}; use rayon::prelude::*; use crate::cli::DISPLAY_CHUNKS; @@ -36,8 +36,7 @@ fn main() -> ExitCode { // Set the value parser for filters which isn't appropriate to do in the build_command function .mut_arg("filters", |arg| { arg.value_parser(|x: &str| { - parse_numeric_range_opts(x, 0, RowFilter::LAST) - .map_err(|_| "Invalid option for filters") + parse_numeric_range_opts(x, 0, 9).map_err(|_| "Invalid option for filters") }) }) .after_help("Run `oxipng --help` to see full details of all options") diff --git a/src/options.rs b/src/options.rs index 60353f82..8a297a01 100644 --- a/src/options.rs +++ b/src/options.rs @@ -7,7 +7,12 @@ use std::{ use indexmap::{IndexSet, indexset}; use log::warn; -use crate::{deflate::Deflaters, filters::RowFilter, headers::StripChunks, interlace::Interlacing}; +use crate::{ + deflate::Deflaters, + filters::{FilterStrategy, RowFilter}, + headers::StripChunks, + interlace::Interlacing, +}; /// Write destination for [`optimize`][crate::optimize]. /// You can use [`optimize_from_memory`](crate::optimize_from_memory) to avoid external I/O. @@ -94,10 +99,10 @@ pub struct Options { /// /// Default: `false` pub force: bool, - /// Which `RowFilters` to try on the file + /// Which `FilterStrategy` to try on the file /// /// Default: `None,Sub,Entropy,Bigrams` - pub filter: IndexSet, + pub filter: IndexSet, /// Whether to change the interlacing type of the file. /// /// These are the interlacing types avaliable: @@ -207,10 +212,10 @@ impl Options { fn apply_preset_3(mut self) -> Self { self.fast_evaluation = false; self.filter = indexset! { - RowFilter::None, - RowFilter::Bigrams, - RowFilter::BigEnt, - RowFilter::Brute + FilterStrategy::Basic(RowFilter::None), + FilterStrategy::Bigrams, + FilterStrategy::BigEnt, + FilterStrategy::Brute }; self } @@ -224,10 +229,10 @@ impl Options { fn apply_preset_5(mut self) -> Self { self.fast_evaluation = false; - self.filter.insert(RowFilter::Up); - self.filter.insert(RowFilter::MinSum); - self.filter.insert(RowFilter::BigEnt); - self.filter.insert(RowFilter::Brute); + self.filter.insert(FilterStrategy::Basic(RowFilter::Up)); + self.filter.insert(FilterStrategy::MinSum); + self.filter.insert(FilterStrategy::BigEnt); + self.filter.insert(FilterStrategy::Brute); if let Deflaters::Libdeflater { compression } = &mut self.deflate { *compression = 12; } @@ -235,8 +240,9 @@ impl Options { } fn apply_preset_6(mut self) -> Self { - self.filter.insert(RowFilter::Average); - self.filter.insert(RowFilter::Paeth); + self.filter + .insert(FilterStrategy::Basic(RowFilter::Average)); + self.filter.insert(FilterStrategy::Basic(RowFilter::Paeth)); self.apply_preset_5() } } @@ -247,7 +253,12 @@ impl Default for Options { Self { fix_errors: false, force: false, - filter: indexset! {RowFilter::None, RowFilter::Sub, RowFilter::Entropy, RowFilter::Bigrams}, + filter: indexset! { + FilterStrategy::Basic(RowFilter::None), + FilterStrategy::Basic(RowFilter::Sub), + FilterStrategy::Entropy, + FilterStrategy::Bigrams + }, interlace: Some(Interlacing::None), optimize_alpha: false, bit_depth_reduction: true, diff --git a/src/png/mod.rs b/src/png/mod.rs index 66ba002d..8a86f31d 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -376,7 +376,7 @@ impl PngImage { } last_line.resize(line.data.len(), 0); let filter = RowFilter::try_from(line.filter).map_err(|_| PngError::InvalidData)?; - filter.unfilter_line(bpp, line.data, &last_line, &mut unfiltered_buf)?; + filter.unfilter_line(bpp, line.data, &last_line, &mut unfiltered_buf); unfiltered.extend_from_slice(&unfiltered_buf); std::mem::swap(&mut last_line, &mut unfiltered_buf); unfiltered_buf.clear(); @@ -386,7 +386,7 @@ impl PngImage { /// Apply the specified filter type to all rows in the image #[must_use] - pub fn filter_image(&self, filter: RowFilter, optimize_alpha: bool) -> Vec { + pub fn filter_image(&self, strategy: FilterStrategy, optimize_alpha: bool) -> Vec { let mut filtered = Vec::with_capacity(self.data.len()); let bpp = self.bytes_per_channel() * self.channels_per_pixel(); // If alpha optimization is enabled, determine how many bytes of alpha there are per pixel @@ -406,7 +406,7 @@ impl PngImage { // Alpha optimisation may alter the line data, so we need a mutable copy of it let mut line_data = line.data.to_vec(); - if filter <= RowFilter::Paeth { + if let FilterStrategy::Basic(filter) = strategy { // Standard filters let filter = if prev_pass == line.pass || filter <= RowFilter::Sub { filter @@ -431,12 +431,12 @@ impl PngImage { let mut best_line_raw = Vec::new(); // Avoid vertical filtering on first line of each interlacing pass let try_filters = if prev_pass == line.pass { - RowFilter::STANDARD.iter() + RowFilter::ALL.iter() } else { RowFilter::SINGLE_LINE.iter() }; - match filter { - RowFilter::MinSum => { + match strategy { + FilterStrategy::MinSum => { // MSAD algorithm mentioned in libpng reference docs // http://www.libpng.org/pub/png/book/chapter09.html let mut best_size = usize::MAX; @@ -453,7 +453,7 @@ impl PngImage { } } } - RowFilter::Entropy => { + FilterStrategy::Entropy => { // Shannon entropy algorithm, from LodePNG // https://github.com/lvandeve/lodepng let mut best_size = i32::MIN; @@ -476,7 +476,7 @@ impl PngImage { } } } - RowFilter::Bigrams => { + FilterStrategy::Bigrams => { // Count distinct bigrams, from pngwolf // https://bjoern.hoehrmann.de/pngwolf/ let mut best_size = usize::MAX; @@ -495,7 +495,7 @@ impl PngImage { } } } - RowFilter::BigEnt => { + FilterStrategy::BigEnt => { // Bigram entropy, combined from Entropy and Bigrams filters let mut best_size = i32::MIN; // FxHasher is the fastest rust hasher currently available for this purpose @@ -515,7 +515,7 @@ impl PngImage { } } } - RowFilter::Brute => { + FilterStrategy::Brute => { // Brute force by compressing each filter attempt // Similar to that of LodePNG but includes some previous lines for context let mut best_size = usize::MAX; diff --git a/tests/filters.rs b/tests/filters.rs index 99984fda..88d0ffe8 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -12,20 +12,17 @@ const GRAYSCALE_ALPHA: u8 = 4; const RGBA: u8 = 6; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options { + let options = oxipng::Options { force: true, + filter: indexset! {FilterStrategy::Basic(RowFilter::None)}, ..Default::default() }; - let mut filter = IndexSet::new(); - filter.insert(RowFilter::None); - options.filter = filter; - (OutFile::from_path(input.with_extension("out.png")), options) } fn test_it_converts( input: &str, - filter: RowFilter, + filter: FilterStrategy, color_type_in: u8, bit_depth_in: BitDepth, color_type_out: u8, @@ -68,7 +65,7 @@ fn test_it_converts( fn filter_0_for_rgba_16() { test_it_converts( "tests/files/filter_0_for_rgba_16.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), RGBA, BitDepth::Sixteen, RGBA, @@ -80,7 +77,7 @@ fn filter_0_for_rgba_16() { fn filter_1_for_rgba_16() { test_it_converts( "tests/files/filter_1_for_rgba_16.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), RGBA, BitDepth::Sixteen, RGBA, @@ -92,7 +89,7 @@ fn filter_1_for_rgba_16() { fn filter_2_for_rgba_16() { test_it_converts( "tests/files/filter_2_for_rgba_16.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), RGBA, BitDepth::Sixteen, RGBA, @@ -104,7 +101,7 @@ fn filter_2_for_rgba_16() { fn filter_3_for_rgba_16() { test_it_converts( "tests/files/filter_3_for_rgba_16.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), RGBA, BitDepth::Sixteen, RGBA, @@ -116,7 +113,7 @@ fn filter_3_for_rgba_16() { fn filter_4_for_rgba_16() { test_it_converts( "tests/files/filter_4_for_rgba_16.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), RGBA, BitDepth::Sixteen, RGBA, @@ -128,7 +125,7 @@ fn filter_4_for_rgba_16() { fn filter_5_for_rgba_16() { test_it_converts( "tests/files/filter_5_for_rgba_16.png", - RowFilter::MinSum, + FilterStrategy::MinSum, RGBA, BitDepth::Sixteen, RGBA, @@ -140,7 +137,7 @@ fn filter_5_for_rgba_16() { fn filter_0_for_rgba_8() { test_it_converts( "tests/files/filter_0_for_rgba_8.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), RGBA, BitDepth::Eight, RGBA, @@ -152,7 +149,7 @@ fn filter_0_for_rgba_8() { fn filter_1_for_rgba_8() { test_it_converts( "tests/files/filter_1_for_rgba_8.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), RGBA, BitDepth::Eight, RGBA, @@ -164,7 +161,7 @@ fn filter_1_for_rgba_8() { fn filter_2_for_rgba_8() { test_it_converts( "tests/files/filter_2_for_rgba_8.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), RGBA, BitDepth::Eight, RGBA, @@ -176,7 +173,7 @@ fn filter_2_for_rgba_8() { fn filter_3_for_rgba_8() { test_it_converts( "tests/files/filter_3_for_rgba_8.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), RGBA, BitDepth::Eight, RGBA, @@ -188,7 +185,7 @@ fn filter_3_for_rgba_8() { fn filter_4_for_rgba_8() { test_it_converts( "tests/files/filter_4_for_rgba_8.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), RGBA, BitDepth::Eight, RGBA, @@ -200,7 +197,7 @@ fn filter_4_for_rgba_8() { fn filter_5_for_rgba_8() { test_it_converts( "tests/files/filter_5_for_rgba_8.png", - RowFilter::MinSum, + FilterStrategy::MinSum, RGBA, BitDepth::Eight, RGBA, @@ -212,7 +209,7 @@ fn filter_5_for_rgba_8() { fn filter_0_for_rgb_16() { test_it_converts( "tests/files/filter_0_for_rgb_16.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), RGB, BitDepth::Sixteen, RGB, @@ -224,7 +221,7 @@ fn filter_0_for_rgb_16() { fn filter_1_for_rgb_16() { test_it_converts( "tests/files/filter_1_for_rgb_16.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), RGB, BitDepth::Sixteen, RGB, @@ -236,7 +233,7 @@ fn filter_1_for_rgb_16() { fn filter_2_for_rgb_16() { test_it_converts( "tests/files/filter_2_for_rgb_16.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), RGB, BitDepth::Sixteen, RGB, @@ -248,7 +245,7 @@ fn filter_2_for_rgb_16() { fn filter_3_for_rgb_16() { test_it_converts( "tests/files/filter_3_for_rgb_16.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), RGB, BitDepth::Sixteen, RGB, @@ -260,7 +257,7 @@ fn filter_3_for_rgb_16() { fn filter_4_for_rgb_16() { test_it_converts( "tests/files/filter_4_for_rgb_16.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), RGB, BitDepth::Sixteen, RGB, @@ -272,7 +269,7 @@ fn filter_4_for_rgb_16() { fn filter_5_for_rgb_16() { test_it_converts( "tests/files/filter_5_for_rgb_16.png", - RowFilter::MinSum, + FilterStrategy::MinSum, RGB, BitDepth::Sixteen, RGB, @@ -284,7 +281,7 @@ fn filter_5_for_rgb_16() { fn filter_0_for_rgb_8() { test_it_converts( "tests/files/filter_0_for_rgb_8.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), RGB, BitDepth::Eight, RGB, @@ -296,7 +293,7 @@ fn filter_0_for_rgb_8() { fn filter_1_for_rgb_8() { test_it_converts( "tests/files/filter_1_for_rgb_8.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), RGB, BitDepth::Eight, RGB, @@ -308,7 +305,7 @@ fn filter_1_for_rgb_8() { fn filter_2_for_rgb_8() { test_it_converts( "tests/files/filter_2_for_rgb_8.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), RGB, BitDepth::Eight, RGB, @@ -320,7 +317,7 @@ fn filter_2_for_rgb_8() { fn filter_3_for_rgb_8() { test_it_converts( "tests/files/filter_3_for_rgb_8.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), RGB, BitDepth::Eight, RGB, @@ -332,7 +329,7 @@ fn filter_3_for_rgb_8() { fn filter_4_for_rgb_8() { test_it_converts( "tests/files/filter_4_for_rgb_8.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), RGB, BitDepth::Eight, RGB, @@ -344,7 +341,7 @@ fn filter_4_for_rgb_8() { fn filter_5_for_rgb_8() { test_it_converts( "tests/files/filter_5_for_rgb_8.png", - RowFilter::MinSum, + FilterStrategy::MinSum, RGB, BitDepth::Eight, RGB, @@ -356,7 +353,7 @@ fn filter_5_for_rgb_8() { fn filter_0_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_0_for_grayscale_alpha_16.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), GRAYSCALE_ALPHA, BitDepth::Sixteen, GRAYSCALE_ALPHA, @@ -368,7 +365,7 @@ fn filter_0_for_grayscale_alpha_16() { fn filter_1_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_1_for_grayscale_alpha_16.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), GRAYSCALE_ALPHA, BitDepth::Sixteen, GRAYSCALE_ALPHA, @@ -380,7 +377,7 @@ fn filter_1_for_grayscale_alpha_16() { fn filter_2_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_2_for_grayscale_alpha_16.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), GRAYSCALE_ALPHA, BitDepth::Sixteen, GRAYSCALE_ALPHA, @@ -392,7 +389,7 @@ fn filter_2_for_grayscale_alpha_16() { fn filter_3_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_3_for_grayscale_alpha_16.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), GRAYSCALE_ALPHA, BitDepth::Sixteen, GRAYSCALE_ALPHA, @@ -404,7 +401,7 @@ fn filter_3_for_grayscale_alpha_16() { fn filter_4_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_4_for_grayscale_alpha_16.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), GRAYSCALE_ALPHA, BitDepth::Sixteen, GRAYSCALE_ALPHA, @@ -416,7 +413,7 @@ fn filter_4_for_grayscale_alpha_16() { fn filter_5_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_5_for_grayscale_alpha_16.png", - RowFilter::MinSum, + FilterStrategy::MinSum, GRAYSCALE_ALPHA, BitDepth::Sixteen, GRAYSCALE_ALPHA, @@ -428,7 +425,7 @@ fn filter_5_for_grayscale_alpha_16() { fn filter_0_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_0_for_grayscale_alpha_8.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), GRAYSCALE_ALPHA, BitDepth::Eight, GRAYSCALE_ALPHA, @@ -440,7 +437,7 @@ fn filter_0_for_grayscale_alpha_8() { fn filter_1_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_1_for_grayscale_alpha_8.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), GRAYSCALE_ALPHA, BitDepth::Eight, GRAYSCALE_ALPHA, @@ -452,7 +449,7 @@ fn filter_1_for_grayscale_alpha_8() { fn filter_2_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_2_for_grayscale_alpha_8.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), GRAYSCALE_ALPHA, BitDepth::Eight, GRAYSCALE_ALPHA, @@ -464,7 +461,7 @@ fn filter_2_for_grayscale_alpha_8() { fn filter_3_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_3_for_grayscale_alpha_8.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), GRAYSCALE_ALPHA, BitDepth::Eight, GRAYSCALE_ALPHA, @@ -476,7 +473,7 @@ fn filter_3_for_grayscale_alpha_8() { fn filter_4_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_4_for_grayscale_alpha_8.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), GRAYSCALE_ALPHA, BitDepth::Eight, GRAYSCALE_ALPHA, @@ -488,7 +485,7 @@ fn filter_4_for_grayscale_alpha_8() { fn filter_5_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_5_for_grayscale_alpha_8.png", - RowFilter::MinSum, + FilterStrategy::MinSum, GRAYSCALE_ALPHA, BitDepth::Eight, GRAYSCALE_ALPHA, @@ -500,7 +497,7 @@ fn filter_5_for_grayscale_alpha_8() { fn filter_0_for_grayscale_16() { test_it_converts( "tests/files/filter_0_for_grayscale_16.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), GRAYSCALE, BitDepth::Sixteen, GRAYSCALE, @@ -512,7 +509,7 @@ fn filter_0_for_grayscale_16() { fn filter_1_for_grayscale_16() { test_it_converts( "tests/files/filter_1_for_grayscale_16.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), GRAYSCALE, BitDepth::Sixteen, GRAYSCALE, @@ -524,7 +521,7 @@ fn filter_1_for_grayscale_16() { fn filter_2_for_grayscale_16() { test_it_converts( "tests/files/filter_2_for_grayscale_16.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), GRAYSCALE, BitDepth::Sixteen, GRAYSCALE, @@ -536,7 +533,7 @@ fn filter_2_for_grayscale_16() { fn filter_3_for_grayscale_16() { test_it_converts( "tests/files/filter_3_for_grayscale_16.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), GRAYSCALE, BitDepth::Sixteen, GRAYSCALE, @@ -548,7 +545,7 @@ fn filter_3_for_grayscale_16() { fn filter_4_for_grayscale_16() { test_it_converts( "tests/files/filter_4_for_grayscale_16.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), GRAYSCALE, BitDepth::Sixteen, GRAYSCALE, @@ -560,7 +557,7 @@ fn filter_4_for_grayscale_16() { fn filter_5_for_grayscale_16() { test_it_converts( "tests/files/filter_5_for_grayscale_16.png", - RowFilter::MinSum, + FilterStrategy::MinSum, GRAYSCALE, BitDepth::Sixteen, GRAYSCALE, @@ -572,7 +569,7 @@ fn filter_5_for_grayscale_16() { fn filter_0_for_grayscale_8() { test_it_converts( "tests/files/filter_0_for_grayscale_8.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), GRAYSCALE, BitDepth::Eight, GRAYSCALE, @@ -584,7 +581,7 @@ fn filter_0_for_grayscale_8() { fn filter_1_for_grayscale_8() { test_it_converts( "tests/files/filter_1_for_grayscale_8.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), GRAYSCALE, BitDepth::Eight, GRAYSCALE, @@ -596,7 +593,7 @@ fn filter_1_for_grayscale_8() { fn filter_2_for_grayscale_8() { test_it_converts( "tests/files/filter_2_for_grayscale_8.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), GRAYSCALE, BitDepth::Eight, GRAYSCALE, @@ -608,7 +605,7 @@ fn filter_2_for_grayscale_8() { fn filter_3_for_grayscale_8() { test_it_converts( "tests/files/filter_3_for_grayscale_8.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), GRAYSCALE, BitDepth::Eight, GRAYSCALE, @@ -620,7 +617,7 @@ fn filter_3_for_grayscale_8() { fn filter_4_for_grayscale_8() { test_it_converts( "tests/files/filter_4_for_grayscale_8.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), GRAYSCALE, BitDepth::Eight, GRAYSCALE, @@ -632,7 +629,7 @@ fn filter_4_for_grayscale_8() { fn filter_5_for_grayscale_8() { test_it_converts( "tests/files/filter_5_for_grayscale_8.png", - RowFilter::MinSum, + FilterStrategy::MinSum, GRAYSCALE, BitDepth::Eight, GRAYSCALE, @@ -644,7 +641,7 @@ fn filter_5_for_grayscale_8() { fn filter_0_for_palette_4() { test_it_converts( "tests/files/filter_0_for_palette_4.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), INDEXED, BitDepth::Four, INDEXED, @@ -656,7 +653,7 @@ fn filter_0_for_palette_4() { fn filter_1_for_palette_4() { test_it_converts( "tests/files/filter_1_for_palette_4.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), INDEXED, BitDepth::Four, INDEXED, @@ -668,7 +665,7 @@ fn filter_1_for_palette_4() { fn filter_2_for_palette_4() { test_it_converts( "tests/files/filter_2_for_palette_4.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), INDEXED, BitDepth::Four, INDEXED, @@ -680,7 +677,7 @@ fn filter_2_for_palette_4() { fn filter_3_for_palette_4() { test_it_converts( "tests/files/filter_3_for_palette_4.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), INDEXED, BitDepth::Four, INDEXED, @@ -692,7 +689,7 @@ fn filter_3_for_palette_4() { fn filter_4_for_palette_4() { test_it_converts( "tests/files/filter_4_for_palette_4.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), INDEXED, BitDepth::Four, INDEXED, @@ -704,7 +701,7 @@ fn filter_4_for_palette_4() { fn filter_5_for_palette_4() { test_it_converts( "tests/files/filter_5_for_palette_4.png", - RowFilter::MinSum, + FilterStrategy::MinSum, INDEXED, BitDepth::Four, INDEXED, @@ -716,7 +713,7 @@ fn filter_5_for_palette_4() { fn filter_0_for_palette_2() { test_it_converts( "tests/files/filter_0_for_palette_2.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), INDEXED, BitDepth::Two, INDEXED, @@ -728,7 +725,7 @@ fn filter_0_for_palette_2() { fn filter_1_for_palette_2() { test_it_converts( "tests/files/filter_1_for_palette_2.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), INDEXED, BitDepth::Two, INDEXED, @@ -740,7 +737,7 @@ fn filter_1_for_palette_2() { fn filter_2_for_palette_2() { test_it_converts( "tests/files/filter_2_for_palette_2.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), INDEXED, BitDepth::Two, INDEXED, @@ -752,7 +749,7 @@ fn filter_2_for_palette_2() { fn filter_3_for_palette_2() { test_it_converts( "tests/files/filter_3_for_palette_2.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), INDEXED, BitDepth::Two, INDEXED, @@ -764,7 +761,7 @@ fn filter_3_for_palette_2() { fn filter_4_for_palette_2() { test_it_converts( "tests/files/filter_4_for_palette_2.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), INDEXED, BitDepth::Two, INDEXED, @@ -776,7 +773,7 @@ fn filter_4_for_palette_2() { fn filter_5_for_palette_2() { test_it_converts( "tests/files/filter_5_for_palette_2.png", - RowFilter::MinSum, + FilterStrategy::MinSum, INDEXED, BitDepth::Two, INDEXED, @@ -788,7 +785,7 @@ fn filter_5_for_palette_2() { fn filter_0_for_palette_1() { test_it_converts( "tests/files/filter_0_for_palette_1.png", - RowFilter::None, + FilterStrategy::Basic(RowFilter::None), INDEXED, BitDepth::One, INDEXED, @@ -800,7 +797,7 @@ fn filter_0_for_palette_1() { fn filter_1_for_palette_1() { test_it_converts( "tests/files/filter_1_for_palette_1.png", - RowFilter::Sub, + FilterStrategy::Basic(RowFilter::Sub), INDEXED, BitDepth::One, INDEXED, @@ -812,7 +809,7 @@ fn filter_1_for_palette_1() { fn filter_2_for_palette_1() { test_it_converts( "tests/files/filter_2_for_palette_1.png", - RowFilter::Up, + FilterStrategy::Basic(RowFilter::Up), INDEXED, BitDepth::One, INDEXED, @@ -824,7 +821,7 @@ fn filter_2_for_palette_1() { fn filter_3_for_palette_1() { test_it_converts( "tests/files/filter_3_for_palette_1.png", - RowFilter::Average, + FilterStrategy::Basic(RowFilter::Average), INDEXED, BitDepth::One, INDEXED, @@ -836,7 +833,7 @@ fn filter_3_for_palette_1() { fn filter_4_for_palette_1() { test_it_converts( "tests/files/filter_4_for_palette_1.png", - RowFilter::Paeth, + FilterStrategy::Basic(RowFilter::Paeth), INDEXED, BitDepth::One, INDEXED, @@ -848,7 +845,7 @@ fn filter_4_for_palette_1() { fn filter_5_for_palette_1() { test_it_converts( "tests/files/filter_5_for_palette_1.png", - RowFilter::MinSum, + FilterStrategy::MinSum, INDEXED, BitDepth::One, INDEXED, diff --git a/tests/flags.rs b/tests/flags.rs index 1ecffe63..e06d0e23 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -16,7 +16,7 @@ fn get_opts(input: &Path) -> (OutFile, Options) { let options = Options { force: true, fast_evaluation: false, - filter: indexset! {RowFilter::None}, + filter: indexset! {FilterStrategy::Basic(RowFilter::None)}, ..Default::default() }; (OutFile::from_path(input.with_extension("out.png")), options) @@ -409,7 +409,7 @@ fn interlaced_0_to_1_other_filter_mode() { let input = PathBuf::from("tests/files/interlaced_0_to_1_other_filter_mode.png"); let (output, mut opts) = get_opts(&input); opts.interlace = Some(Interlacing::Adam7); - opts.filter = indexset! {RowFilter::Paeth}; + opts.filter = indexset! {FilterStrategy::Basic(RowFilter::Paeth)}; test_it_converts_callbacks( input, diff --git a/tests/interlaced.rs b/tests/interlaced.rs index a8931419..5707d2b1 100644 --- a/tests/interlaced.rs +++ b/tests/interlaced.rs @@ -12,16 +12,13 @@ const GRAYSCALE_ALPHA: u8 = 4; const RGBA: u8 = 6; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options { + let options = oxipng::Options { force: true, fast_evaluation: false, + filter: indexset! {FilterStrategy::Basic(RowFilter::None)}, interlace: None, ..Default::default() }; - let mut filter = IndexSet::new(); - filter.insert(RowFilter::None); - options.filter = filter; - (OutFile::from_path(input.with_extension("out.png")), options) } diff --git a/tests/interlacing.rs b/tests/interlacing.rs index fd72df08..7e24b1b1 100644 --- a/tests/interlacing.rs +++ b/tests/interlacing.rs @@ -9,14 +9,11 @@ const RGB: u8 = 2; const INDEXED: u8 = 3; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options { + let options = oxipng::Options { force: true, + filter: indexset! {FilterStrategy::Basic(RowFilter::None)}, ..Default::default() }; - let mut filter = IndexSet::new(); - filter.insert(RowFilter::None); - options.filter = filter; - (OutFile::from_path(input.with_extension("out.png")), options) } diff --git a/tests/raw.rs b/tests/raw.rs index 3bf49591..59694529 100644 --- a/tests/raw.rs +++ b/tests/raw.rs @@ -5,7 +5,7 @@ use oxipng::{internal_tests::*, *}; fn get_opts() -> Options { Options { force: true, - filter: indexset! { RowFilter::None }, + filter: indexset! {FilterStrategy::Basic(RowFilter::None)}, ..Default::default() } } diff --git a/tests/reduction.rs b/tests/reduction.rs index 4e33f7e2..d81dae36 100644 --- a/tests/reduction.rs +++ b/tests/reduction.rs @@ -12,15 +12,12 @@ const GRAYSCALE_ALPHA: u8 = 4; const RGBA: u8 = 6; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options { + let options = oxipng::Options { force: true, fast_evaluation: false, + filter: indexset! {FilterStrategy::Basic(RowFilter::None)}, ..Default::default() }; - let mut filter = IndexSet::new(); - filter.insert(RowFilter::None); - options.filter = filter; - (OutFile::from_path(input.with_extension("out.png")), options) } diff --git a/tests/regression.rs b/tests/regression.rs index 765a04f5..6caba8c9 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -12,14 +12,11 @@ const GRAYSCALE_ALPHA: u8 = 4; const RGBA: u8 = 6; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options { + let options = oxipng::Options { force: true, + filter: indexset! {FilterStrategy::Basic(RowFilter::None)}, ..Default::default() }; - let mut filter = IndexSet::new(); - filter.insert(RowFilter::None); - options.filter = filter; - (OutFile::from_path(input.with_extension("out.png")), options) } diff --git a/tests/strategies.rs b/tests/strategies.rs index 7f8e0bcc..264e6983 100644 --- a/tests/strategies.rs +++ b/tests/strategies.rs @@ -11,20 +11,16 @@ const INDEXED: u8 = 3; const RGBA: u8 = 6; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options { + let options = oxipng::Options { force: true, ..Default::default() }; - let mut filter = IndexSet::new(); - filter.insert(RowFilter::None); - options.filter = filter; - (OutFile::from_path(input.with_extension("out.png")), options) } fn test_it_converts( input: &str, - filter: RowFilter, + filter: FilterStrategy, color_type_in: u8, bit_depth_in: BitDepth, color_type_out: u8, @@ -34,8 +30,7 @@ fn test_it_converts( let (output, mut opts) = get_opts(&input); let png = PngData::new(&input, &opts).unwrap(); - opts.filter = IndexSet::new(); - opts.filter.insert(filter); + opts.filter = indexset! {filter}; assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); @@ -67,7 +62,7 @@ fn test_it_converts( fn filter_minsum() { test_it_converts( "tests/files/rgb_16_should_be_rgb_16.png", - RowFilter::MinSum, + FilterStrategy::MinSum, RGB, BitDepth::Sixteen, RGB, @@ -79,7 +74,7 @@ fn filter_minsum() { fn filter_entropy() { test_it_converts( "tests/files/rgb_8_should_be_rgb_8.png", - RowFilter::Entropy, + FilterStrategy::Entropy, RGB, BitDepth::Eight, RGB, @@ -91,7 +86,7 @@ fn filter_entropy() { fn filter_bigrams() { test_it_converts( "tests/files/rgba_8_should_be_rgba_8.png", - RowFilter::Bigrams, + FilterStrategy::Bigrams, RGBA, BitDepth::Eight, RGBA, @@ -103,7 +98,7 @@ fn filter_bigrams() { fn filter_bigent() { test_it_converts( "tests/files/grayscale_8_should_be_grayscale_8.png", - RowFilter::BigEnt, + FilterStrategy::BigEnt, GRAYSCALE, BitDepth::Eight, GRAYSCALE, @@ -115,7 +110,7 @@ fn filter_bigent() { fn filter_brute() { test_it_converts( "tests/files/palette_8_should_be_palette_8.png", - RowFilter::Brute, + FilterStrategy::Brute, INDEXED, BitDepth::Eight, INDEXED,