Allow baseline to pass through evaluator

This commit is contained in:
Andrew 2022-11-16 18:10:19 +13:00 committed by Josh Holmer
parent 9b5353f0c6
commit affd86a2e5
2 changed files with 13 additions and 18 deletions

View file

@ -22,9 +22,10 @@ use std::sync::Arc;
const STD_COMPRESSION: u8 = 5; const STD_COMPRESSION: u8 = 5;
const STD_FILTERS: [RowFilter; 2] = [RowFilter::None, RowFilter::MinSum]; const STD_FILTERS: [RowFilter; 2] = [RowFilter::None, RowFilter::MinSum];
struct Candidate { pub struct Candidate {
image: PngData, pub image: PngData,
filter: RowFilter, pub filter: RowFilter,
pub is_reduction: bool,
// first wins tie-breaker // first wins tie-breaker
nth: usize, nth: usize,
} }
@ -72,21 +73,17 @@ impl Evaluator {
/// Wait for all evaluations to finish and return smallest reduction /// Wait for all evaluations to finish and return smallest reduction
/// Or `None` if all reductions were worse than baseline. /// Or `None` if all reductions were worse than baseline.
#[cfg(feature = "parallel")] #[cfg(feature = "parallel")]
fn get_best_candidate(self) -> Option<Candidate> { pub fn get_best_candidate(self) -> Option<Candidate> {
let (eval_send, eval_recv) = self.eval_channel; let (eval_send, eval_recv) = self.eval_channel;
drop(eval_send); // disconnect the sender, breaking the loop in the thread drop(eval_send); // disconnect the sender, breaking the loop in the thread
eval_recv.into_iter().min_by_key(Candidate::cmp_key) eval_recv.into_iter().min_by_key(Candidate::cmp_key)
} }
#[cfg(not(feature = "parallel"))] #[cfg(not(feature = "parallel"))]
fn get_best_candidate(self) -> Option<Candidate> { pub fn get_best_candidate(self) -> Option<Candidate> {
self.eval_best_candidate.into_inner() self.eval_best_candidate.into_inner()
} }
pub fn get_result(self) -> Option<PngData> {
self.get_best_candidate().map(|candidate| candidate.image)
}
/// Set baseline image. It will be used only to measure minimum compression level required /// Set baseline image. It will be used only to measure minimum compression level required
pub fn set_baseline(&self, image: Arc<PngImage>) { pub fn set_baseline(&self, image: Arc<PngImage>) {
self.try_image_inner(image, false) self.try_image_inner(image, false)
@ -123,17 +120,13 @@ impl Evaluator {
&best_candidate_size, &best_candidate_size,
) { ) {
best_candidate_size.set_min(idat_data.len()); best_candidate_size.set_min(idat_data.len());
// ignore baseline images after this point
if !is_reduction {
return;
}
// the rest is shipped to the evavluation/collection thread
let new = Candidate { let new = Candidate {
image: PngData { image: PngData {
idat_data, idat_data,
raw: Arc::clone(&image), raw: Arc::clone(&image),
}, },
filter, filter,
is_reduction,
nth, nth,
}; };

View file

@ -506,9 +506,9 @@ fn optimize_png(
eval.set_baseline(png.raw.clone()); eval.set_baseline(png.raw.clone());
} }
perform_reductions(png.raw.clone(), opts, &deadline, &eval); perform_reductions(png.raw.clone(), opts, &deadline, &eval);
let reduction_occurred = if let Some(result) = eval.get_result() { let reduction_occurred = if let Some(result) = eval.get_best_candidate() {
*png = result; *png = result.image;
true result.is_reduction
} else { } else {
false false
}; };
@ -593,9 +593,11 @@ fn optimize_png(
opts.filter, opts.filter,
png.idat_data.len() png.idat_data.len()
); );
} else if reduction_occurred { } else {
*png = original_png; *png = original_png;
} }
} else if png.idat_data.len() > idat_original_size {
*png = original_png;
} }
perform_strip(png, opts); perform_strip(png, opts);