Add data_is_compressed property

This commit is contained in:
Andrew 2025-03-08 14:29:38 +13:00
parent dd023f740b
commit 5a2e4387ce
2 changed files with 24 additions and 26 deletions

View file

@ -21,9 +21,9 @@ use crate::{atomicmin::AtomicMin, deflate, filters::RowFilter, png::PngImage, De
pub(crate) struct Candidate { pub(crate) struct Candidate {
pub image: Arc<PngImage>, pub image: Arc<PngImage>,
pub idat_data: Vec<u8>, pub data: Vec<u8>,
pub data_is_compressed: bool,
pub estimated_output_size: usize, pub estimated_output_size: usize,
pub filtered: Vec<u8>,
pub filter: RowFilter, pub filter: RowFilter,
// For determining tie-breaker // For determining tie-breaker
nth: usize, nth: usize,
@ -149,13 +149,12 @@ impl Evaluator {
let idat_data = deflater.deflate(&filtered, best_candidate_size.get()); let idat_data = deflater.deflate(&filtered, best_candidate_size.get());
if let Ok(idat_data) = idat_data { if let Ok(idat_data) = idat_data {
let estimated_output_size = image.estimated_output_size(&idat_data); let estimated_output_size = image.estimated_output_size(&idat_data);
// In the final round, we need the IDAT data but not the filtered data // For the final round we need the IDAT data, otherwise the filtered data
// Otherwise, we want to keep the filtered data for the next round
let new = Candidate { let new = Candidate {
image: image.clone(), image: image.clone(),
idat_data: if final_round { idat_data } else { vec![] }, data: if final_round { idat_data } else { filtered },
data_is_compressed: final_round,
estimated_output_size, estimated_output_size,
filtered: if final_round { vec![] } else { filtered },
filter, filter,
nth, nth,
}; };

View file

@ -170,7 +170,7 @@ impl RawImage {
let mut png = PngData { let mut png = PngData {
raw: result.image, raw: result.image,
idat_data: result.idat_data, idat_data: result.data,
aux_chunks, aux_chunks,
frames: Vec::new(), frames: Vec::new(),
}; };
@ -359,7 +359,7 @@ fn optimize_png(
}; };
if let Some(result) = optimize_raw(raw.clone(), &opts, deadline.clone(), max_size) { if let Some(result) = optimize_raw(raw.clone(), &opts, deadline.clone(), max_size) {
png.raw = result.image; png.raw = result.image;
png.idat_data = result.idat_data; png.idat_data = result.data;
recompress_frames(png, &opts, deadline, result.filter)?; recompress_frames(png, &opts, deadline, result.filter)?;
postprocess_chunks(&mut png.aux_chunks, &png.raw.ihdr, &raw.ihdr); postprocess_chunks(&mut png.aux_chunks, &png.raw.ihdr, &raw.ihdr);
} }
@ -470,7 +470,7 @@ fn optimize_raw(
(eval_result?, eval_deflater) (eval_result?, eval_deflater)
}; };
if !result.idat_data.is_empty() if result.data_is_compressed
&& max_size.map_or(true, |max_size| result.estimated_output_size < max_size) && max_size.map_or(true, |max_size| result.estimated_output_size < max_size)
{ {
debug!("Found better result:"); debug!("Found better result:");
@ -517,27 +517,26 @@ fn perform_trials(
eval_result = Some(result); eval_result = Some(result);
} }
} }
if opts.deflate == eval_deflater {
// No further compression required
return eval_result;
}
// We should have a result here - fail if not (e.g. deadline passed) // We should have a result here - fail if not (e.g. deadline passed)
let mut result = eval_result?; let mut result = eval_result?;
// Recompress with the main deflater if !result.data_is_compressed {
debug!("Trying filter {} with {}", result.filter, opts.deflate); // Compress with the main deflater
match opts.deflate.deflate(&result.filtered, max_size) { debug!("Trying filter {} with {}", result.filter, opts.deflate);
Ok(idat_data) => { match opts.deflate.deflate(&result.data, max_size) {
result.estimated_output_size = result.image.estimated_output_size(&idat_data); Ok(idat_data) => {
result.idat_data = idat_data; result.estimated_output_size = result.image.estimated_output_size(&idat_data);
trace!("{} bytes", result.estimated_output_size); result.data = idat_data;
} result.data_is_compressed = true;
Err(PngError::DeflatedDataTooLong(bytes)) => { trace!("{} bytes", result.estimated_output_size);
trace!(">{bytes} bytes"); }
} Err(PngError::DeflatedDataTooLong(bytes)) => {
Err(_) => (), trace!(">{bytes} bytes");
}; }
Err(_) => (),
};
}
return Some(result); return Some(result);
} }