Use heuristics for filter selection
This commit is contained in:
parent
9408a50b1b
commit
69182bb0ff
1 changed files with 53 additions and 9 deletions
62
src/lib.rs
62
src/lib.rs
|
|
@ -238,7 +238,8 @@ impl Options {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_preset_2(self) -> Self {
|
fn apply_preset_2(mut self) -> Self {
|
||||||
|
self.use_heuristics = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -532,6 +533,57 @@ fn optimize_png(
|
||||||
};
|
};
|
||||||
|
|
||||||
if opts.idat_recoding || reduction_occurred {
|
if opts.idat_recoding || reduction_occurred {
|
||||||
|
let filter_iter = filter.par_iter().with_max_len(1);
|
||||||
|
let mut filters: HashMap<u8, Vec<u8>> = filter_iter
|
||||||
|
.map(|f| {
|
||||||
|
let png = png.clone();
|
||||||
|
(*f, png.raw.filter_image(*f))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
if opts.use_heuristics && filter.len() > 1 {
|
||||||
|
let best_size_heuristics = AtomicMin::new(None);
|
||||||
|
let mut heuristic_results: Vec<TrialOptions> = Vec::with_capacity(filter.len());
|
||||||
|
for f in &filter {
|
||||||
|
heuristic_results.push(TrialOptions {
|
||||||
|
filter: *f,
|
||||||
|
compression: 1,
|
||||||
|
strategy: if *f == 0 {0} else {1},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let filter_heuristics_iter = heuristic_results.into_par_iter().with_max_len(1);
|
||||||
|
let best_filter = filter_heuristics_iter.filter_map(|trial| {
|
||||||
|
if deadline.passed() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let filtered = &filters[&trial.filter];
|
||||||
|
let new_idat = deflate::deflate(
|
||||||
|
filtered,
|
||||||
|
trial.compression,
|
||||||
|
trial.strategy,
|
||||||
|
opts.window,
|
||||||
|
&best_size_heuristics,
|
||||||
|
&deadline,
|
||||||
|
);
|
||||||
|
|
||||||
|
let new_size = match new_idat {
|
||||||
|
Ok(n) => n.len(),
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// update best size across all threads
|
||||||
|
best_size_heuristics.set_min(new_size);
|
||||||
|
|
||||||
|
Some((trial.filter, new_size))
|
||||||
|
});
|
||||||
|
let best_filter = best_filter.reduce_with(|i, j| if i.1 <= j.1 {i} else {j});
|
||||||
|
|
||||||
|
if let Some(result) = best_filter {
|
||||||
|
filter.clear();
|
||||||
|
filter.push(result.0);
|
||||||
|
filters.retain(|&f, _| f == result.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Go through selected permutations and determine the best
|
// Go through selected permutations and determine the best
|
||||||
let combinations = if opts.deflate == Deflaters::Zlib && !deadline.passed() {
|
let combinations = if opts.deflate == Deflaters::Zlib && !deadline.passed() {
|
||||||
filter.len() * compression.len() * strategies.len()
|
filter.len() * compression.len() * strategies.len()
|
||||||
|
|
@ -572,14 +624,6 @@ fn optimize_png(
|
||||||
eprintln!("Trying: {} combinations", results.len());
|
eprintln!("Trying: {} combinations", results.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
let filter_iter = filter.par_iter().with_max_len(1);
|
|
||||||
let filters: HashMap<u8, Vec<u8>> = filter_iter
|
|
||||||
.map(|f| {
|
|
||||||
let png = png.clone();
|
|
||||||
(*f, png.raw.filter_image(*f))
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let original_len = original_png.idat_data.len();
|
let original_len = original_png.idat_data.len();
|
||||||
let added_interlacing = opts.interlace == Some(1) && original_png.raw.ihdr.interlaced == 0;
|
let added_interlacing = opts.interlace == Some(1) && original_png.raw.ihdr.interlaced == 0;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue