From 3e8fcc13359b7a2b887721f6c8a8bc417ab9a811 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sat, 22 Oct 2022 22:56:58 +1300 Subject: [PATCH] Switch main compressor to libdeflate --- src/lib.rs | 52 +++++++++++++++++++--------------------- src/main.rs | 64 ++++++++++++++++---------------------------------- tests/flags.rs | 24 ++----------------- 3 files changed, 46 insertions(+), 94 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a6249756..4057398d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -190,7 +190,7 @@ pub struct Options { pub strip: Headers, /// Which DEFLATE algorithm to use /// - /// Default: `Zlib` + /// Default: `Libdeflater` pub deflate: Deflaters, /// Whether to use heuristics to pick the best filter and compression /// @@ -212,10 +212,7 @@ impl Options { 1 => opts.apply_preset_1(), 2 => opts.apply_preset_2(), 3 => opts.apply_preset_3(), - 4 => { - warn!("Level 4 is deprecated and is identical to level 3"); - opts.apply_preset_4() - } + 4 => opts.apply_preset_4(), 5 => opts.apply_preset_5(), 6 => opts.apply_preset_6(), _ => { @@ -233,17 +230,20 @@ impl Options { // on an `Options` struct generated by the `default` method. fn apply_preset_0(mut self) -> Self { self.idat_recoding = false; - if let Deflaters::Zlib { compression, .. } = &mut self.deflate { + self.filter.clear(); + if let Deflaters::Libdeflater { compression } = &mut self.deflate { compression.clear(); - compression.insert(3); + compression.insert(5); } - self.apply_preset_1() + self.use_heuristics = true; + self } fn apply_preset_1(mut self) -> Self { self.filter.clear(); - if let Deflaters::Zlib { strategies, .. } = &mut self.deflate { - strategies.clear(); + if let Deflaters::Libdeflater { compression } = &mut self.deflate { + compression.clear(); + compression.insert(10); } self.use_heuristics = true; self @@ -254,34 +254,38 @@ impl Options { } fn apply_preset_3(mut self) -> Self { - for i in 1..5 { + for i in 1..=4 { self.filter.insert(i); } self } - fn apply_preset_4(self) -> Self { + fn apply_preset_4(mut self) -> Self { + if let Deflaters::Libdeflater { compression } = &mut self.deflate { + compression.clear(); + compression.insert(12); + } self.apply_preset_3() } fn apply_preset_5(mut self) -> Self { - if let Deflaters::Zlib { compression, .. } = &mut self.deflate { + if let Deflaters::Libdeflater { compression } = &mut self.deflate { compression.clear(); - for i in 3..10 { + for i in 9..=12 { compression.insert(i); } } - self.apply_preset_4() + self.apply_preset_3() } fn apply_preset_6(mut self) -> Self { - if let Deflaters::Zlib { compression, .. } = &mut self.deflate { + if let Deflaters::Libdeflater { compression } = &mut self.deflate { compression.clear(); - for i in 1..10 { + for i in 1..=12 { compression.insert(i); } } - self.apply_preset_4() + self.apply_preset_3() } } @@ -292,11 +296,7 @@ impl Default for Options { filter.insert(0); filter.insert(5); let mut compression = IndexSet::new(); - compression.insert(9); - let mut strategies = IndexSet::new(); - for i in 0..4 { - strategies.insert(i); - } + compression.insert(11); // We always need NoOp to be present let mut alphas = IndexSet::new(); alphas.insert(AlphaOptim::NoOp); @@ -317,11 +317,7 @@ impl Default for Options { grayscale_reduction: true, idat_recoding: true, strip: Headers::None, - deflate: Deflaters::Zlib { - compression, - strategies, - window: 15, - }, + deflate: Deflaters::Libdeflater { compression }, use_heuristics: false, timeout: None, } diff --git a/src/main.rs b/src/main.rs index d503b585..b2637b07 100644 --- a/src/main.rs +++ b/src/main.rs @@ -143,7 +143,7 @@ fn main() { } })) .arg(Arg::new("compression") - .help("compression levels (zlib: 1-9, libdeflater: 1-12) - Default: 9 or 12") + .help("zlib compression levels (1-12) - Default: 12") .long("zc") .takes_value(true) .value_name("levels") @@ -153,7 +153,7 @@ fn main() { Err(_) => Err("Invalid option for compression".to_owned()), } }) - .conflicts_with("zopfli")) + .conflicts_with_all(&["zopfli", "libdeflater"])) .arg(Arg::new("strategies") .help("zlib compression strategies (0-3) - Default: 0-3") .long("zs") @@ -164,6 +164,7 @@ fn main() { Err(_) => Err("Invalid option for strategies".to_owned()), } }) + .hide(true) .conflicts_with_all(&["zopfli", "libdeflater"])) .arg(Arg::new("window") .help("zlib window size - Default: 32k") @@ -178,6 +179,7 @@ fn main() { .possible_value("8k") .possible_value("16k") .possible_value("32k") + .hide(true) .conflicts_with_all(&["zopfli", "libdeflater"])) .arg(Arg::new("no-bit-reduction") .help("No bit depth reduction") @@ -204,7 +206,7 @@ fn main() { .help("Write the output even if it is larger than the input") .long("force")) .arg(Arg::new("zopfli") - .help("Use the slower but better compressing Zopfli algorithm, overrides zlib-specific options") + .help("Use the slower but better compressing Zopfli algorithm") .short('Z') .long("zopfli") .conflicts_with("libdeflater")) @@ -212,6 +214,7 @@ fn main() { .help("Use an alternative Libdeflater algorithm, overrides zlib-specific options") .short('D') .long("libdeflater") + .hide(true) .conflicts_with("zopfli")) .arg(Arg::new("timeout") .help("Maximum amount of time, in seconds, to spend on optimizations") @@ -237,16 +240,16 @@ fn main() { } })) .after_help("Optimization levels: - -o 0 => --zc 3 --nz (0 or 1 trials) - -o 1 => --zc 9 (1 trial, determined heuristically) - -o 2 => --zc 9 --zs 0-3 -f 0,5 (8 trials with zlib or 2 trials with other compressors) - -o 3 => --zc 9 --zs 0-3 -f 0-5 (24 trials with zlib or 6 trials with other compressors) - -o 4 => (deprecated; same as `-o 3`) - -o 5 => --zc 3-9 --zs 0-3 -f 0-5 (168 trials with zlib; same as `-o 3` for other compressors) - -o 6 => --zc 1-9 --zs 0-3 -f 0-5 (216 trials with zlib; same as `-o 3` for other compressors) - -o max => (stable alias for the max compression) + -o 0 => --zc 6 --nz (0 or 1 trials) + -o 1 => --zc 10 (1 trial, determined heuristically) + -o 2 => --zc 11 -f 0,5 (2 trials) + -o 3 => --zc 11 -f 0-5 (6 trials) + -o 4 => --zc 12 -f 0-5 (6 trials; same as `-o 3` for zopfli) + -o 5 => --zc 9-12 -f 0-5 (24 trials; same as `-o 3` for zopfli) + -o 6 => --zc 1-12 -f 0-5 (72 trials; same as `-o 3` for zopfli) + -o max => (stable alias for the max compression) - Manually specifying a compression option (zc, zs, etc.) will override the optimization preset, + Manually specifying a compression option (zc, f, etc.) will override the optimization preset, regardless of the order you write the arguments.") .get_matches_from(wild::args()); @@ -501,46 +504,19 @@ fn parse_opts_into_struct( }; } else if matches.is_present("libdeflater") { opts.deflate = Deflaters::Libdeflater { - compression: match matches.value_of("compression") { - Some(x) => parse_numeric_range_opts(x, 1, 12).unwrap(), - _ => indexset! { 12 }, - }, + compression: indexset! { 12 }, }; - } else if let Deflaters::Zlib { - compression, - strategies, - window, - } = &mut opts.deflate - { + } else if let Deflaters::Libdeflater { compression } = &mut opts.deflate { if let Some(x) = matches.value_of("compression") { - *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") { - *strategies = parse_numeric_range_opts(x, 0, 3).unwrap(); - } - - match matches.value_of("window") { - Some("256") => *window = 8, - Some("512") => *window = 9, - Some("1k") => *window = 10, - Some("2k") => *window = 11, - Some("4k") => *window = 12, - Some("8k") => *window = 13, - Some("16k") => *window = 14, - // 32k is default - _ => (), + *compression = parse_numeric_range_opts(x, 1, 12).unwrap(); } } if explicit_level > Some(3) { match opts.deflate { - Deflaters::Zlib { .. } => {} + Deflaters::Libdeflater { .. } => {} _ => { - warn!( - "Level 4 and above are equivalent to level 3 for compressors other than zlib" - ); + warn!("Level 4 and above are equivalent to level 3 for zopfli"); } } } diff --git a/tests/flags.rs b/tests/flags.rs index 11f117f1..c66e6161 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -170,10 +170,10 @@ fn verbose_mode() { }); let mut logs: Vec<_> = receiver.into_iter().collect(); - assert_eq!(logs.len(), 4); + assert_eq!(logs.len(), 1); logs.sort(); for (i, log) in logs.into_iter().enumerate() { - let expected_prefix = format!(" zc = 9 zs = {} f = 0 ", i); + let expected_prefix = format!(" zc = 11 zs = 0 f = 0 "); assert!( log.starts_with(&expected_prefix), "logs[{}] = {:?} doesn't start with {:?}", @@ -597,23 +597,3 @@ fn zopfli_mode() { BitDepth::Eight, ); } - -#[test] -#[cfg(feature = "libdeflater")] -fn libdeflater_mode() { - let input = PathBuf::from("tests/files/zopfli_mode.png"); - let (output, mut opts) = get_opts(&input); - let mut compression = IndexSet::new(); - compression.insert(0); - opts.deflate = Deflaters::Libdeflater { compression }; - - test_it_converts( - input, - &output, - &opts, - ColorType::RGB, - BitDepth::Eight, - ColorType::RGB, - BitDepth::Eight, - ); -}