Recompress fdATs
This commit is contained in:
parent
f436ef62a3
commit
16ca58b175
1 changed files with 42 additions and 5 deletions
47
src/lib.rs
47
src/lib.rs
|
|
@ -389,7 +389,7 @@ 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, None)
|
let mut png = optimize_raw(self.png.clone(), opts, deadline.clone(), None)
|
||||||
.ok_or_else(|| PngError::new("Failed to optimize input data"))?;
|
.ok_or_else(|| PngError::new("Failed to optimize input data"))?;
|
||||||
|
|
||||||
// Process aux chunks
|
// Process aux chunks
|
||||||
|
|
@ -399,7 +399,7 @@ impl RawImage {
|
||||||
.filter(|c| opts.strip.keep(&c.name))
|
.filter(|c| opts.strip.keep(&c.name))
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
postprocess_chunks(&mut png, opts, &self.png.ihdr);
|
postprocess_chunks(&mut png, opts, deadline, &self.png.ihdr);
|
||||||
|
|
||||||
Ok(png.output())
|
Ok(png.output())
|
||||||
}
|
}
|
||||||
|
|
@ -583,12 +583,12 @@ 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, max_size) {
|
if let Some(new_png) = optimize_raw(raw.clone(), &opts, deadline.clone(), max_size) {
|
||||||
png.raw = new_png.raw;
|
png.raw = new_png.raw;
|
||||||
png.idat_data = new_png.idat_data;
|
png.idat_data = new_png.idat_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
postprocess_chunks(png, &opts, &raw.ihdr);
|
postprocess_chunks(png, &opts, deadline, &raw.ihdr);
|
||||||
|
|
||||||
let output = png.output();
|
let output = png.output();
|
||||||
|
|
||||||
|
|
@ -858,7 +858,12 @@ fn report_format(prefix: &str, png: &PngImage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform cleanup of certain chunks from the `PngData` object, after optimization has been completed
|
/// Perform cleanup of certain chunks from the `PngData` object, after optimization has been completed
|
||||||
fn postprocess_chunks(png: &mut PngData, opts: &Options, orig_ihdr: &IhdrData) {
|
fn postprocess_chunks(
|
||||||
|
png: &mut PngData,
|
||||||
|
opts: &Options,
|
||||||
|
deadline: Arc<Deadline>,
|
||||||
|
orig_ihdr: &IhdrData,
|
||||||
|
) {
|
||||||
if let Some(iccp_idx) = png.aux_chunks.iter().position(|c| &c.name == b"iCCP") {
|
if let Some(iccp_idx) = png.aux_chunks.iter().position(|c| &c.name == b"iCCP") {
|
||||||
// See if we can replace an iCCP chunk with an sRGB chunk
|
// See if we can replace an iCCP chunk with an sRGB chunk
|
||||||
let may_replace_iccp = opts.strip != StripChunks::None && opts.strip.keep(b"sRGB");
|
let may_replace_iccp = opts.strip != StripChunks::None && opts.strip.keep(b"sRGB");
|
||||||
|
|
@ -911,6 +916,38 @@ fn postprocess_chunks(png: &mut PngData, opts: &Options, orig_ihdr: &IhdrData) {
|
||||||
!invalid
|
!invalid
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find fdAT chunks and attempt to recompress them
|
||||||
|
// Note if there are multiple fdATs per frame then decompression will fail and nothing will change
|
||||||
|
let mut fdat: Vec<_> = png
|
||||||
|
.aux_chunks
|
||||||
|
.iter_mut()
|
||||||
|
.filter(|c| &c.name == b"fdAT")
|
||||||
|
.collect();
|
||||||
|
if !fdat.is_empty() {
|
||||||
|
let buffer_size = orig_ihdr.raw_data_size();
|
||||||
|
fdat.par_iter_mut()
|
||||||
|
.with_max_len(1)
|
||||||
|
.enumerate()
|
||||||
|
.for_each(|(i, c)| {
|
||||||
|
if deadline.passed() || c.data.len() <= 4 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Ok(mut data) = deflate::inflate(&c.data[4..], buffer_size).and_then(|data| {
|
||||||
|
let max_size = AtomicMin::new(Some(c.data.len() - 5));
|
||||||
|
opts.deflate.deflate(&data, &max_size)
|
||||||
|
}) {
|
||||||
|
debug!(
|
||||||
|
"Recompressed fdAT #{:<2}: {} ({} bytes decrease)",
|
||||||
|
i,
|
||||||
|
c.data.len(),
|
||||||
|
c.data.len() - 4 - data.len()
|
||||||
|
);
|
||||||
|
c.data.truncate(4);
|
||||||
|
c.data.append(&mut data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if an image was already optimized prior to oxipng's operations
|
/// Check if an image was already optimized prior to oxipng's operations
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue