Return candidate from optimize_raw
This commit is contained in:
parent
78b9bd47d0
commit
d8da0b2423
2 changed files with 26 additions and 31 deletions
54
src/lib.rs
54
src/lib.rs
|
|
@ -156,16 +156,21 @@ impl RawImage {
|
||||||
/// Create an optimized png from the raw image data using the options provided
|
/// Create an optimized png from the raw image data using the options provided
|
||||||
pub fn create_optimized_png(&self, opts: &Options) -> PngResult<Vec<u8>> {
|
pub fn create_optimized_png(&self, opts: &Options) -> PngResult<Vec<u8>> {
|
||||||
let deadline = Arc::new(Deadline::new(opts.timeout));
|
let deadline = Arc::new(Deadline::new(opts.timeout));
|
||||||
let mut png = optimize_raw(self.png.clone(), opts, deadline.clone(), None)
|
let Some(result) = optimize_raw(self.png.clone(), opts, deadline, None) else {
|
||||||
.ok_or_else(|| PngError::new("Failed to optimize input data"))?;
|
return Err(PngError::new("Failed to optimize input data"));
|
||||||
|
};
|
||||||
|
|
||||||
// Process aux chunks
|
let mut png = PngData {
|
||||||
png.aux_chunks = self
|
raw: result.image,
|
||||||
.aux_chunks
|
idat_data: result.idat_data,
|
||||||
.iter()
|
aux_chunks: self
|
||||||
.filter(|c| opts.strip.keep(&c.name))
|
.aux_chunks
|
||||||
.cloned()
|
.iter()
|
||||||
.collect();
|
.filter(|c| opts.strip.keep(&c.name))
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
frames: Vec::new(),
|
||||||
|
};
|
||||||
postprocess_chunks(&mut png, opts, &self.png.ihdr);
|
postprocess_chunks(&mut png, opts, &self.png.ihdr);
|
||||||
|
|
||||||
Ok(png.output())
|
Ok(png.output())
|
||||||
|
|
@ -359,14 +364,13 @@ fn optimize_png(
|
||||||
} else {
|
} else {
|
||||||
Some(png.estimated_output_size())
|
Some(png.estimated_output_size())
|
||||||
};
|
};
|
||||||
if let Some(new_png) = optimize_raw(raw.clone(), &opts, deadline.clone(), max_size) {
|
if let Some(result) = optimize_raw(raw.clone(), &opts, deadline.clone(), max_size) {
|
||||||
png.raw = new_png.raw;
|
png.raw = result.image;
|
||||||
png.idat_data = new_png.idat_data;
|
png.idat_data = result.idat_data;
|
||||||
png.filter = new_png.filter;
|
recompress_frames(png, &opts, deadline, result.filter)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
postprocess_chunks(png, &opts, &raw.ihdr);
|
postprocess_chunks(png, &opts, &raw.ihdr);
|
||||||
recompress_frames(png, &opts, deadline)?;
|
|
||||||
|
|
||||||
let output = png.output();
|
let output = png.output();
|
||||||
|
|
||||||
|
|
@ -415,7 +419,7 @@ fn optimize_raw(
|
||||||
opts: &Options,
|
opts: &Options,
|
||||||
deadline: Arc<Deadline>,
|
deadline: Arc<Deadline>,
|
||||||
max_size: Option<usize>,
|
max_size: Option<usize>,
|
||||||
) -> Option<PngData> {
|
) -> Option<Candidate> {
|
||||||
// Libdeflate has four algorithms: 0 = 'uncompressed', 1-4 = 'greedy', 5-7 = 'lazy', 8-9 = 'lazy2', 10-12 = 'near-optimal'
|
// Libdeflate has four algorithms: 0 = 'uncompressed', 1-4 = 'greedy', 5-7 = 'lazy', 8-9 = 'lazy2', 10-12 = 'near-optimal'
|
||||||
// 5 is the minimumm required for a decent evaluation result
|
// 5 is the minimumm required for a decent evaluation result
|
||||||
// 7 is not noticeably slower than 5 and improves evaluation of filters in 'fast' mode (o2 and lower)
|
// 7 is not noticeably slower than 5 and improves evaluation of filters in 'fast' mode (o2 and lower)
|
||||||
|
|
@ -471,13 +475,7 @@ fn optimize_raw(
|
||||||
if max_size.map_or(true, |max_size| result.estimated_output_size() < max_size) {
|
if max_size.map_or(true, |max_size| result.estimated_output_size() < max_size) {
|
||||||
debug!("Found better result:");
|
debug!("Found better result:");
|
||||||
debug!(" zc = {} f = {}", deflater, result.filter);
|
debug!(" zc = {} f = {}", deflater, result.filter);
|
||||||
return Some(PngData {
|
return Some(result);
|
||||||
raw: result.image,
|
|
||||||
idat_data: result.idat_data,
|
|
||||||
aux_chunks: Vec::new(),
|
|
||||||
frames: Vec::new(),
|
|
||||||
filter: Some(result.filter),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -677,15 +675,15 @@ fn postprocess_chunks(png: &mut PngData, opts: &Options, orig_ihdr: &IhdrData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recompress the additional frames of an APNG
|
/// Recompress the additional frames of an APNG
|
||||||
fn recompress_frames(png: &mut PngData, opts: &Options, deadline: Arc<Deadline>) -> PngResult<()> {
|
fn recompress_frames(
|
||||||
|
png: &mut PngData,
|
||||||
|
opts: &Options,
|
||||||
|
deadline: Arc<Deadline>,
|
||||||
|
filter: RowFilter,
|
||||||
|
) -> PngResult<()> {
|
||||||
if !opts.idat_recoding || png.frames.is_empty() {
|
if !opts.idat_recoding || png.frames.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
// Use the same filter chosen for the main image
|
|
||||||
// No filter means we failed to optimise the main image and we shouldn't bother trying here
|
|
||||||
let Some(filter) = png.filter else {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
png.frames
|
png.frames
|
||||||
.par_iter_mut()
|
.par_iter_mut()
|
||||||
.with_max_len(1)
|
.with_max_len(1)
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,6 @@ pub struct PngData {
|
||||||
pub aux_chunks: Vec<Chunk>,
|
pub aux_chunks: Vec<Chunk>,
|
||||||
/// APNG frames
|
/// APNG frames
|
||||||
pub frames: Vec<Frame>,
|
pub frames: Vec<Frame>,
|
||||||
/// The filter strategy applied to the idat_data (initially unknown)
|
|
||||||
pub filter: Option<RowFilter>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PngData {
|
impl PngData {
|
||||||
|
|
@ -184,7 +182,6 @@ impl PngData {
|
||||||
raw: Arc::new(raw),
|
raw: Arc::new(raw),
|
||||||
aux_chunks,
|
aux_chunks,
|
||||||
frames,
|
frames,
|
||||||
filter: None,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue