Switch main compressor to libdeflate
This commit is contained in:
parent
f688d20fe6
commit
3e8fcc1335
3 changed files with 46 additions and 94 deletions
52
src/lib.rs
52
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,
|
||||
}
|
||||
|
|
|
|||
64
src/main.rs
64
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue