Ensure evaluator returns no result when all candidates are too large (#754)
There was a small crack in the fast evaluation logic where a phase 2 candidate's IDAT could be compressed below the best size from phase 1, but the estimated output size (which includes chunks like PLTE) was above. This candidate could end up getting returned from the evaluator if no other filter actually did compress better, and would then be used for the final compression even though the phase 1 candidate was actually better. The issue could potentially affect small, indexed images in `--fast` mode (o2 and below). Fixes #753.
This commit is contained in:
parent
f99ce277da
commit
fa2c69071c
1 changed files with 13 additions and 4 deletions
|
|
@ -154,6 +154,19 @@ impl Evaluator {
|
|||
let idat_data = deflater.deflate(&filtered, best_candidate_size.get());
|
||||
if let Ok(idat_data) = idat_data {
|
||||
let estimated_output_size = image.estimated_output_size(&idat_data);
|
||||
trace!(
|
||||
"Eval: {}-bit {:23} {:8} {} bytes",
|
||||
image.ihdr.bit_depth, description, filter, estimated_output_size
|
||||
);
|
||||
|
||||
// Skip if it exceeds best known size. (This is important to ensure
|
||||
// the evaluator returns no result when all candidates are too large.)
|
||||
if let Some(max) = best_candidate_size.get() {
|
||||
if estimated_output_size > max {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We only need to retain the IDAT data in the final round
|
||||
let new = Candidate {
|
||||
image: image.clone(),
|
||||
|
|
@ -164,10 +177,6 @@ impl Evaluator {
|
|||
nth,
|
||||
};
|
||||
best_candidate_size.set_min(estimated_output_size);
|
||||
trace!(
|
||||
"Eval: {}-bit {:23} {:8} {} bytes",
|
||||
image.ihdr.bit_depth, description, filter, estimated_output_size
|
||||
);
|
||||
|
||||
#[cfg(feature = "parallel")]
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue