From 6c1d071f702e4debf7757338ebbac2215547de51 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 21 Oct 2022 13:38:19 +1300 Subject: [PATCH] Allow --zc with libdeflater --- benches/libdeflater.rs | 10 ++++----- src/deflate/deflater.rs | 4 ++-- src/deflate/mod.rs | 5 ++++- src/lib.rs | 49 ++++++++++++++++++++++++++++------------- src/main.rs | 18 ++++++++++----- tests/flags.rs | 4 +++- 6 files changed, 60 insertions(+), 30 deletions(-) diff --git a/benches/libdeflater.rs b/benches/libdeflater.rs index cac7a723..d7917a0c 100644 --- a/benches/libdeflater.rs +++ b/benches/libdeflater.rs @@ -13,7 +13,7 @@ fn libdeflater_16_bits_strategy_0(b: &mut Bencher) { let png = PngData::new(&input, false).unwrap(); b.iter(|| { - libdeflater_deflate(png.raw.data.as_ref(), &AtomicMin::new(None)).ok(); + libdeflater_deflate(png.raw.data.as_ref(), 12, &AtomicMin::new(None)).ok(); }); } @@ -23,7 +23,7 @@ fn libdeflater_8_bits_strategy_0(b: &mut Bencher) { let png = PngData::new(&input, false).unwrap(); b.iter(|| { - libdeflater_deflate(png.raw.data.as_ref(), &AtomicMin::new(None)).ok(); + libdeflater_deflate(png.raw.data.as_ref(), 12, &AtomicMin::new(None)).ok(); }); } @@ -35,7 +35,7 @@ fn libdeflater_4_bits_strategy_0(b: &mut Bencher) { let png = PngData::new(&input, false).unwrap(); b.iter(|| { - libdeflater_deflate(png.raw.data.as_ref(), &AtomicMin::new(None)).ok(); + libdeflater_deflate(png.raw.data.as_ref(), 12, &AtomicMin::new(None)).ok(); }); } @@ -47,7 +47,7 @@ fn libdeflater_2_bits_strategy_0(b: &mut Bencher) { let png = PngData::new(&input, false).unwrap(); b.iter(|| { - libdeflater_deflate(png.raw.data.as_ref(), &AtomicMin::new(None)).ok(); + libdeflater_deflate(png.raw.data.as_ref(), 12, &AtomicMin::new(None)).ok(); }); } @@ -59,6 +59,6 @@ fn libdeflater_1_bits_strategy_0(b: &mut Bencher) { let png = PngData::new(&input, false).unwrap(); b.iter(|| { - libdeflater_deflate(png.raw.data.as_ref(), &AtomicMin::new(None)).ok(); + libdeflater_deflate(png.raw.data.as_ref(), 12, &AtomicMin::new(None)).ok(); }); } diff --git a/src/deflate/deflater.rs b/src/deflate/deflater.rs index 45db30f5..67e9ba10 100644 --- a/src/deflate/deflater.rs +++ b/src/deflate/deflater.rs @@ -2,8 +2,8 @@ use crate::atomicmin::AtomicMin; use crate::{PngError, PngResult}; use libdeflater::{CompressionError, CompressionLvl, Compressor}; -pub fn deflate(data: &[u8], max_size: &AtomicMin) -> PngResult> { - let mut compressor = Compressor::new(CompressionLvl::best()); +pub fn deflate(data: &[u8], level: u8, max_size: &AtomicMin) -> PngResult> { + let mut compressor = Compressor::new(CompressionLvl::new(level.into()).unwrap()); let capacity = max_size.get().unwrap_or(data.len() / 2); let mut dest = vec![0; capacity]; let len = compressor diff --git a/src/deflate/mod.rs b/src/deflate/mod.rs index e1b4fdf9..0c109f96 100644 --- a/src/deflate/mod.rs +++ b/src/deflate/mod.rs @@ -104,5 +104,8 @@ pub enum Deflaters { }, #[cfg(feature = "libdeflater")] /// Use libdeflater. - Libdeflater, + Libdeflater { + /// Which compression levels to try on the file (1-12) + compression: IndexSet, + }, } diff --git a/src/lib.rs b/src/lib.rs index 5aeef68c..a6249756 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -560,26 +560,43 @@ fn optimize_png( let mut results: Vec = Vec::with_capacity(combinations); for f in &filter { - if let Deflaters::Zlib { compression, .. } = &opts.deflate { - for zc in compression { - for zs in strategies.as_ref().unwrap() { + match &opts.deflate { + Deflaters::Zlib { compression, .. } => { + for zc in compression { + for zs in strategies.as_ref().unwrap() { + results.push(TrialOptions { + filter: *f, + compression: *zc, + strategy: *zs, + }); + } + if deadline.passed() { + break; + } + } + } + #[cfg(feature = "zopfli")] + Deflaters::Zopfli { .. } => { + // Zopfli has no additional options. + results.push(TrialOptions { + filter: *f, + compression: 0, + strategy: 0, + }); + } + #[cfg(feature = "libdeflater")] + Deflaters::Libdeflater { compression } => { + for zc in compression { results.push(TrialOptions { filter: *f, compression: *zc, - strategy: *zs, + strategy: 0, }); - } - if deadline.passed() { - break; + if deadline.passed() { + break; + } } } - } else { - // Zopfli and Libdeflater compression have no additional options. - results.push(TrialOptions { - filter: *f, - compression: 0, - strategy: 0, - }); } if deadline.passed() { @@ -620,7 +637,9 @@ fn optimize_png( #[cfg(feature = "zopfli")] Deflaters::Zopfli { iterations } => deflate::zopfli_deflate(filtered, iterations), #[cfg(feature = "libdeflater")] - Deflaters::Libdeflater => deflate::libdeflater_deflate(filtered, &best_size), + Deflaters::Libdeflater { .. } => { + deflate::libdeflater_deflate(filtered, trial.compression, &best_size) + } }; let new_idat = match new_idat { diff --git a/src/main.rs b/src/main.rs index adf51a4a..d503b585 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,7 @@ #![allow(clippy::cognitive_complexity)] use clap::{AppSettings, Arg, ArgMatches, Command}; -use indexmap::IndexSet; +use indexmap::{indexset, IndexSet}; use log::{error, warn}; use oxipng::AlphaOptim; use oxipng::Deflaters; @@ -143,17 +143,17 @@ fn main() { } })) .arg(Arg::new("compression") - .help("zlib compression levels (1-9) - Default: 9") + .help("compression levels (zlib: 1-9, libdeflater: 1-12) - Default: 9 or 12") .long("zc") .takes_value(true) .value_name("levels") .validator(|x| { - match parse_numeric_range_opts(x, 1, 9) { + match parse_numeric_range_opts(x, 1, 12) { Ok(_) => Ok(()), Err(_) => Err("Invalid option for compression".to_owned()), } }) - .conflicts_with_all(&["zopfli", "libdeflater"])) + .conflicts_with("zopfli")) .arg(Arg::new("strategies") .help("zlib compression strategies (0-3) - Default: 0-3") .long("zs") @@ -500,7 +500,12 @@ fn parse_opts_into_struct( iterations: NonZeroU8::new(15).unwrap(), }; } else if matches.is_present("libdeflater") { - opts.deflate = Deflaters::Libdeflater; + opts.deflate = Deflaters::Libdeflater { + compression: match matches.value_of("compression") { + Some(x) => parse_numeric_range_opts(x, 1, 12).unwrap(), + _ => indexset! { 12 }, + }, + }; } else if let Deflaters::Zlib { compression, strategies, @@ -508,7 +513,8 @@ fn parse_opts_into_struct( } = &mut opts.deflate { if let Some(x) = matches.value_of("compression") { - *compression = parse_numeric_range_opts(x, 1, 9).unwrap(); + *compression = parse_numeric_range_opts(x, 1, 9) + .map_err(|_| "Compression levels 10-12 are only valid for libdeflater".to_owned())? } if let Some(x) = matches.value_of("strategies") { diff --git a/tests/flags.rs b/tests/flags.rs index f99324bd..11f117f1 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -603,7 +603,9 @@ fn zopfli_mode() { fn libdeflater_mode() { let input = PathBuf::from("tests/files/zopfli_mode.png"); let (output, mut opts) = get_opts(&input); - opts.deflate = Deflaters::Libdeflater; + let mut compression = IndexSet::new(); + compression.insert(0); + opts.deflate = Deflaters::Libdeflater { compression }; test_it_converts( input,