diff --git a/src/evaluate.rs b/src/evaluate.rs index 15222f7a..13cc0473 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -122,15 +122,15 @@ impl Evaluator { if deadline.passed() { return; } - if let Ok(idat_data) = deflate::deflate( - &image.filter_image(filter), - compression, - &best_candidate_size, - ) { + let filtered = image.filter_image(filter); + if let Ok(idat_data) = + deflate::deflate(&filtered, compression, &best_candidate_size) + { best_candidate_size.set_min(idat_data.len()); let new = Candidate { image: PngData { idat_data, + filtered, raw: Arc::clone(&image), }, filter, diff --git a/src/lib.rs b/src/lib.rs index 2912e769..9728245e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -548,7 +548,7 @@ fn optimize_png( info!("Trying: {}", trial.filter); let original_len = idat_original_size; let best_size = AtomicMin::new(if opts.force { None } else { Some(original_len) }); - perform_trial(&png.raw, opts, trial, &best_size) + perform_trial(&png.filtered, opts, trial, &best_size) } } else { // Perform full compression trials of selected filters and determine the best @@ -585,7 +585,8 @@ fn optimize_png( if deadline.passed() { return None; } - perform_trial(&png.raw, opts, trial, &best_size) + let filtered = &png.raw.filter_image(trial.filter); + perform_trial(filtered, opts, trial, &best_size) }); best.reduce_with(|i, j| { if i.1.len() < j.1.len() || (i.1.len() == j.1.len() && i.0 < j.0) { @@ -749,12 +750,11 @@ fn perform_reductions( /// Execute a compression trial fn perform_trial( - png: &PngImage, + filtered: &[u8], opts: &Options, trial: TrialOptions, best_size: &AtomicMin, ) -> Option { - let filtered = &png.filter_image(trial.filter); let new_idat = match opts.deflate { Deflaters::Libdeflater { .. } => deflate::deflate(filtered, trial.compression, best_size), #[cfg(feature = "zopfli")] diff --git a/src/png/mod.rs b/src/png/mod.rs index 58039083..3ef33846 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -47,6 +47,8 @@ pub struct PngData { pub raw: Arc, /// The filtered and compressed data of the IDAT chunk pub idat_data: Vec, + /// The filtered, uncompressed data of the IDAT chunk + pub filtered: Vec, } type PaletteWithTrns = (Option>, Option>); @@ -135,10 +137,11 @@ impl PngData { transparency_pixel, aux_headers, }; - raw.data = raw.unfilter_image()?; + let unfiltered = raw.unfilter_image()?; // Return the PngData Ok(Self { idat_data: idat_headers, + filtered: std::mem::replace(&mut raw.data, unfiltered), raw: Arc::new(raw), }) }