diff --git a/src/deflate/mod.rs b/src/deflate/mod.rs index b8b4ceab..4de86b7f 100644 --- a/src/deflate/mod.rs +++ b/src/deflate/mod.rs @@ -13,7 +13,7 @@ pub use zopfli_oxipng::deflate as zopfli_deflate; /// DEFLATE algorithms supported by oxipng (for use in [`Options`][crate::Options]) #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum Deflaters { +pub enum Deflater { /// Use libdeflater. Libdeflater { /// Which compression level to use on the file (0-12) @@ -29,7 +29,7 @@ pub enum Deflaters { }, } -impl Deflaters { +impl Deflater { pub(crate) fn deflate(self, data: &[u8], max_size: Option) -> PngResult> { let compressed = match self { Self::Libdeflater { compression } => deflate(data, compression, max_size)?, @@ -45,7 +45,7 @@ impl Deflaters { } } -impl Display for Deflaters { +impl Display for Deflater { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/src/evaluate.rs b/src/evaluate.rs index 9463cf6b..d5c38e85 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -10,7 +10,7 @@ use std::sync::{ #[cfg(feature = "parallel")] use crossbeam_channel::{Receiver, Sender, unbounded}; -use deflate::Deflaters; +use deflate::Deflater; use indexmap::IndexSet; use log::trace; use rayon::prelude::*; @@ -50,7 +50,7 @@ impl Candidate { pub(crate) struct Evaluator { deadline: Arc, filters: IndexSet, - deflater: Deflaters, + deflater: Deflater, optimize_alpha: bool, final_round: bool, nth: AtomicUsize, @@ -68,7 +68,7 @@ impl Evaluator { pub fn new( deadline: Arc, filters: IndexSet, - deflater: Deflaters, + deflater: Deflater, optimize_alpha: bool, final_round: bool, ) -> Self { diff --git a/src/headers.rs b/src/headers.rs index db48f15b..e81a5a99 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -3,7 +3,7 @@ use log::{debug, trace, warn}; use rgb::{RGB16, RGBA8}; use crate::{ - Deflaters, Options, PngResult, + Deflater, Options, PngResult, colors::{BitDepth, ColorType}, deflate::{crc32, inflate}, display_chunks::DISPLAY_CHUNKS, @@ -276,7 +276,7 @@ pub fn extract_icc(iccp: &Chunk) -> Option> { } /// Make an iCCP chunk by compressing the ICC profile -pub fn make_iccp(icc: &[u8], deflater: Deflaters, max_size: Option) -> PngResult { +pub fn make_iccp(icc: &[u8], deflater: Deflater, max_size: Option) -> PngResult { let mut compressed = deflater.deflate(icc, max_size)?; let mut data = Vec::with_capacity(compressed.len() + 5); data.extend(b"icc"); // Profile name - generally unused, can be anything @@ -348,7 +348,7 @@ pub fn preprocess_chunks(aux_chunks: &mut Vec, opts: &mut Options) { } else if opts.idat_recoding { // Try recompressing the profile let cur_len = aux_chunks[iccp_idx].data.len(); - if let Ok(iccp) = make_iccp(&icc, opts.deflate, Some(cur_len - 1)) { + if let Ok(iccp) = make_iccp(&icc, opts.deflater, Some(cur_len - 1)) { debug!( "Recompressed iCCP chunk: {} ({} bytes decrease)", iccp.data.len(), diff --git a/src/lib.rs b/src/lib.rs index 2a000a17..6a449b99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,7 @@ pub use rgb::{RGB16, RGBA8}; pub use crate::{ colors::{BitDepth, ColorType}, - deflate::Deflaters, + deflate::Deflater, error::PngError, filters::{FilterStrategy, RowFilter}, headers::StripChunks, @@ -146,7 +146,7 @@ impl RawImage { /// Add an ICC profile for the image pub fn add_icc_profile(&mut self, data: &[u8]) { // Compress with fastest compression level - will be recompressed during optimization - let deflater = Deflaters::Libdeflater { compression: 1 }; + let deflater = Deflater::Libdeflater { compression: 1 }; if let Ok(iccp) = make_iccp(data, deflater, None) { self.aux_chunks.push(iccp); } @@ -422,16 +422,16 @@ fn optimize_raw( // 8 is a little slower but not noticeably when used only for reductions (o3 and higher) // 9 is not appreciably better than 8 // 10 and higher are quite slow - good for filters but only good for reductions if matching the main zc level - let compression = match opts.deflate { - Deflaters::Libdeflater { compression } => { + let compression = match opts.deflater { + Deflater::Libdeflater { compression } => { if opts.fast_evaluation { 7 } else { 8 }.min(compression) } _ => 8, }; - let eval_deflater = Deflaters::Libdeflater { compression }; + let eval_deflater = Deflater::Libdeflater { compression }; // If only one filter is selected, use this for evaluations - let eval_filters = if opts.filter.len() == 1 { - opts.filter.clone() + let eval_filters = if opts.filters.len() == 1 { + opts.filters.clone() } else { // None and Bigrams work well together, especially for alpha reductions indexset! {FilterStrategy::NONE, FilterStrategy::Bigrams} @@ -442,7 +442,7 @@ fn optimize_raw( eval_filters.clone(), eval_deflater, false, - opts.deflate == eval_deflater, + opts.deflater == eval_deflater, ); let mut new_image = perform_reductions(image.clone(), opts, &deadline, &eval); let eval_result = eval.get_best_candidate(); @@ -467,7 +467,7 @@ fn optimize_raw( eval_filters, eval_deflater, ); - (result?, opts.deflate) + (result?, opts.deflater) } else { // If idat_recoding is off and reductions were attempted but ended up choosing the baseline, // we should still check if the evaluator compressed the baseline smaller than the original. @@ -492,9 +492,9 @@ fn perform_trials( max_size: Option, mut eval_result: Option, eval_filters: IndexSet, - eval_deflater: Deflaters, + eval_deflater: Deflater, ) -> Option { - let mut filters = opts.filter.clone(); + let mut filters = opts.filters.clone(); let fast_eval = opts.fast_evaluation && (filters.len() > 1 || eval_result.is_some()); if fast_eval { // Perform a fast evaluation of selected filters followed by a single main compression trial @@ -511,7 +511,7 @@ fn perform_trials( filters, eval_deflater, opts.optimize_alpha, - opts.deflate == eval_deflater, + opts.deflater == eval_deflater, ); if let Some(result) = &eval_result { eval.set_best_size(result.estimated_output_size); @@ -527,9 +527,9 @@ fn perform_trials( if result.idat_data.is_none() { // Compress with the main deflater - debug!("Trying filter {} with {}", result.filter, opts.deflate); + debug!("Trying filter {} with {}", result.filter, opts.deflater); let (data, _) = image.filter_image(result.filter_used.clone(), opts.optimize_alpha); - match opts.deflate.deflate(&data, max_size) { + match opts.deflater.deflate(&data, max_size) { Ok(idat_data) => { result.estimated_output_size = result.image.estimated_output_size(&idat_data); result.idat_data = Some(idat_data); @@ -557,8 +557,8 @@ fn perform_trials( } } - debug!("Trying {} filters with {}", filters.len(), opts.deflate); - let eval = Evaluator::new(deadline, filters, opts.deflate, opts.optimize_alpha, true); + debug!("Trying {} filters with {}", filters.len(), opts.deflater); + let eval = Evaluator::new(deadline, filters, opts.deflater, opts.optimize_alpha, true); if let Some(max_size) = max_size { eval.set_best_size(max_size); } @@ -650,7 +650,7 @@ fn recompress_frames( let image = PngImage::new(ihdr, &frame.data)?; let (filtered, _) = image.filter_image(filter.clone(), opts.optimize_alpha); let max_size = Some(frame.data.len() - 1); - if let Ok(data) = opts.deflate.deflate(&filtered, max_size) { + if let Ok(data) = opts.deflater.deflate(&filtered, max_size) { debug!( "Recompressed fdAT #{:<2}: {} ({} bytes decrease)", i, diff --git a/src/main.rs b/src/main.rs index 17909628..506cd47a 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, FilterStrategy, InFile, Options, OutFile, PngError, StripChunks}; +use oxipng::{Deflater, FilterStrategy, InFile, Options, OutFile, PngError, StripChunks}; use rayon::prelude::*; use crate::cli::DISPLAY_CHUNKS; @@ -198,7 +198,7 @@ fn parse_opts_into_struct( }; if let Some(x) = matches.get_one::>("filters") { - opts.filter = x + opts.filters = x .iter() .map(|&f| match f { 0..=4 => FilterStrategy::Basic(f.try_into().unwrap()), @@ -336,12 +336,12 @@ fn parse_opts_into_struct( #[cfg(feature = "zopfli")] if matches.get_flag("zopfli") { let iterations = *matches.get_one::("iterations").unwrap(); - opts.deflate = Deflaters::Zopfli { + opts.deflater = Deflater::Zopfli { iterations: NonZeroU8::new(iterations as u8).unwrap(), }; } - if let (Deflaters::Libdeflater { compression }, Some(x)) = - (&mut opts.deflate, matches.get_one::("compression")) + if let (Deflater::Libdeflater { compression }, Some(x)) = + (&mut opts.deflater, matches.get_one::("compression")) { *compression = *x as u8; } diff --git a/src/options.rs b/src/options.rs index 48f30141..bcddf08b 100644 --- a/src/options.rs +++ b/src/options.rs @@ -8,7 +8,7 @@ use indexmap::{IndexSet, indexset}; use log::warn; use crate::{ - deflate::Deflaters, filters::FilterStrategy, headers::StripChunks, interlace::Interlacing, + deflate::Deflater, filters::FilterStrategy, headers::StripChunks, interlace::Interlacing, }; /// Write destination for [`optimize`][crate::optimize]. @@ -99,7 +99,7 @@ pub struct Options { /// Which `FilterStrategy` to try on the file /// /// Default: `None,Sub,Entropy,Bigrams` - pub filter: IndexSet, + pub filters: IndexSet, /// Whether to change the interlacing type of the file. /// /// These are the interlacing types avaliable: @@ -148,7 +148,7 @@ pub struct Options { #[cfg_attr(feature = "zopfli", doc = "(e.g. Zopfli)")] /// /// Default: `Libdeflater` - pub deflate: Deflaters, + pub deflater: Deflater, /// Whether to use fast evaluation to pick the best filter /// /// Default: `true` @@ -187,16 +187,16 @@ impl Options { // The following methods make assumptions that they are operating // on an `Options` struct generated by the `default` method. fn apply_preset_0(mut self) -> Self { - self.filter.clear(); - if let Deflaters::Libdeflater { compression } = &mut self.deflate { + self.filters.clear(); + if let Deflater::Libdeflater { compression } = &mut self.deflater { *compression = 5; } self } fn apply_preset_1(mut self) -> Self { - self.filter.clear(); - if let Deflaters::Libdeflater { compression } = &mut self.deflate { + self.filters.clear(); + if let Deflater::Libdeflater { compression } = &mut self.deflater { *compression = 10; } self @@ -208,7 +208,7 @@ impl Options { fn apply_preset_3(mut self) -> Self { self.fast_evaluation = false; - self.filter = indexset! { + self.filters = indexset! { FilterStrategy::NONE, FilterStrategy::Bigrams, FilterStrategy::BigEnt, @@ -218,7 +218,7 @@ impl Options { } fn apply_preset_4(mut self) -> Self { - if let Deflaters::Libdeflater { compression } = &mut self.deflate { + if let Deflater::Libdeflater { compression } = &mut self.deflater { *compression = 12; } self.apply_preset_3() @@ -226,19 +226,19 @@ impl Options { fn apply_preset_5(mut self) -> Self { self.fast_evaluation = false; - self.filter.insert(FilterStrategy::UP); - self.filter.insert(FilterStrategy::MinSum); - self.filter.insert(FilterStrategy::BigEnt); - self.filter.insert(FilterStrategy::Brute); - if let Deflaters::Libdeflater { compression } = &mut self.deflate { + self.filters.insert(FilterStrategy::UP); + self.filters.insert(FilterStrategy::MinSum); + self.filters.insert(FilterStrategy::BigEnt); + self.filters.insert(FilterStrategy::Brute); + if let Deflater::Libdeflater { compression } = &mut self.deflater { *compression = 12; } self } fn apply_preset_6(mut self) -> Self { - self.filter.insert(FilterStrategy::AVERAGE); - self.filter.insert(FilterStrategy::PAETH); + self.filters.insert(FilterStrategy::AVERAGE); + self.filters.insert(FilterStrategy::PAETH); self.apply_preset_5() } } @@ -249,7 +249,7 @@ impl Default for Options { Self { fix_errors: false, force: false, - filter: indexset! { + filters: indexset! { FilterStrategy::NONE, FilterStrategy::SUB, FilterStrategy::Entropy, @@ -264,7 +264,7 @@ impl Default for Options { idat_recoding: true, scale_16: false, strip: StripChunks::None, - deflate: Deflaters::Libdeflater { compression: 11 }, + deflater: Deflater::Libdeflater { compression: 11 }, fast_evaluation: true, timeout: None, } diff --git a/src/reduction/mod.rs b/src/reduction/mod.rs index 132ae802..c8444fff 100644 --- a/src/reduction/mod.rs +++ b/src/reduction/mod.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::{ColorType, Deadline, Deflaters, Options, evaluate::Evaluator, png::PngImage}; +use crate::{ColorType, Deadline, Deflater, Options, evaluate::Evaluator, png::PngImage}; pub mod alpha; use crate::alpha::*; @@ -21,8 +21,8 @@ pub(crate) fn perform_reductions( // At low compression levels, skip some transformations which are less likely to be effective // This currently affects optimization presets 0-2 - let cheap = match opts.deflate { - Deflaters::Libdeflater { compression } => compression < 12 && opts.fast_evaluation, + let cheap = match opts.deflater { + Deflater::Libdeflater { compression } => compression < 12 && opts.fast_evaluation, _ => false, }; diff --git a/tests/filters.rs b/tests/filters.rs index 3d696360..4f6f0025 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -14,7 +14,6 @@ const RGBA: u8 = 6; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let options = oxipng::Options { force: true, - filter: indexset! {FilterStrategy::NONE}, ..Default::default() }; (OutFile::from_path(input.with_extension("out.png")), options) @@ -32,8 +31,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.filters = 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); diff --git a/tests/flags.rs b/tests/flags.rs index 4baa619b..787df238 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! {FilterStrategy::NONE}, + filters: indexset! {FilterStrategy::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! {FilterStrategy::PAETH}; + opts.filters = indexset! {FilterStrategy::PAETH}; test_it_converts_callbacks( input, @@ -649,7 +649,7 @@ fn scale_16() { fn zopfli_mode() { let input = PathBuf::from("tests/files/zopfli_mode.png"); let (output, mut opts) = get_opts(&input); - opts.deflate = Deflaters::Zopfli { + opts.deflater = Deflater::Zopfli { iterations: NonZeroU8::new(15).unwrap(), }; diff --git a/tests/interlaced.rs b/tests/interlaced.rs index b9007d9b..037ace6c 100644 --- a/tests/interlaced.rs +++ b/tests/interlaced.rs @@ -15,7 +15,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let options = oxipng::Options { force: true, fast_evaluation: false, - filter: indexset! {FilterStrategy::NONE}, + filters: indexset! {FilterStrategy::NONE}, interlace: None, ..Default::default() }; diff --git a/tests/interlacing.rs b/tests/interlacing.rs index ea7fd5a9..95b2c55d 100644 --- a/tests/interlacing.rs +++ b/tests/interlacing.rs @@ -11,7 +11,7 @@ const INDEXED: u8 = 3; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let options = oxipng::Options { force: true, - filter: indexset! {FilterStrategy::NONE}, + filters: indexset! {FilterStrategy::NONE}, ..Default::default() }; (OutFile::from_path(input.with_extension("out.png")), options) diff --git a/tests/raw.rs b/tests/raw.rs index d50a58e1..155f415a 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! {FilterStrategy::NONE}, + filters: indexset! {FilterStrategy::NONE}, ..Default::default() } } diff --git a/tests/reduction.rs b/tests/reduction.rs index 6ba3236d..bfe15160 100644 --- a/tests/reduction.rs +++ b/tests/reduction.rs @@ -15,7 +15,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let options = oxipng::Options { force: true, fast_evaluation: false, - filter: indexset! {FilterStrategy::NONE}, + filters: indexset! {FilterStrategy::NONE}, ..Default::default() }; (OutFile::from_path(input.with_extension("out.png")), options) diff --git a/tests/regression.rs b/tests/regression.rs index 89756c29..716b8905 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -14,7 +14,7 @@ const RGBA: u8 = 6; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let options = oxipng::Options { force: true, - filter: indexset! {FilterStrategy::NONE}, + filters: indexset! {FilterStrategy::NONE}, ..Default::default() }; (OutFile::from_path(input.with_extension("out.png")), options) diff --git a/tests/strategies.rs b/tests/strategies.rs index 264e6983..de4db2c3 100644 --- a/tests/strategies.rs +++ b/tests/strategies.rs @@ -30,7 +30,7 @@ fn test_it_converts( let (output, mut opts) = get_opts(&input); let png = PngData::new(&input, &opts).unwrap(); - opts.filter = indexset! {filter}; + opts.filters = 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);