Use deflater on iCCP chunk as well

This commit is contained in:
Chris Hennick 2023-06-21 09:20:00 -07:00
parent d1a78f97bf
commit a330187a51
No known key found for this signature in database
GPG key ID: 25653935CC8B6C74
3 changed files with 22 additions and 24 deletions

View file

@ -107,23 +107,26 @@ impl Deflater for BufferedZopfliDeflater {
maximum_block_splits: self.max_block_splits,
..Default::default() // for forward compatibility
};
let mut out = Vec::with_capacity(self.output_buffer_size);
let mut buffer = BufWriter::with_capacity(
self.input_buffer_size,
DeflateEncoder::new(
options,
Default::default(),
Cursor::new(Vec::with_capacity(self.output_buffer_size)),
&mut out,
),
);
let result = (|| -> io::Result<Vec<u8>> {
let result = (|| -> io::Result<()> {
buffer.write_all(data)?;
Ok(buffer.into_inner()?.finish()?.into_inner())
buffer.into_inner()?.finish()?;
Ok(())
})();
let result = result.map_err(|e| PngError::new(&e.to_string()))?;
if max_size.get().is_some_and(|max| max < result.len()) {
Err(PngError::DeflatedDataTooLong(result.len()))
result.map_err(|e| PngError::new(&e.to_string()))?;
println!("Compressed {} -> {} bytes", data.len(), out.len());
if max_size.get().is_some_and(|max| max < out.len()) {
Err(PngError::DeflatedDataTooLong(out.len()))
} else {
Ok(result)
Ok(out)
}
}
}

View file

@ -403,7 +403,7 @@ impl RawImage {
.filter(|c| opts.strip.keep(&c.name))
.cloned()
.collect();
postprocess_chunks(&mut png, opts, &self.png.ihdr);
postprocess_chunks(&mut png, opts, &self.png.ihdr, deflater);
Ok(png.output())
}
@ -579,7 +579,7 @@ fn optimize_png(
png.idat_data = new_png.idat_data;
}
postprocess_chunks(png, opts, &raw.ihdr);
postprocess_chunks(png, opts, &raw.ihdr, &opts.deflate);
let output = png.output();
@ -675,17 +675,9 @@ fn optimize_raw<T: Deflater>(
// We should have a result here - fail if not (e.g. deadline passed)
let result = eval_result?;
match opts.deflate {
Deflaters::Libdeflater { compression } if compression <= eval_compression => {
// No further compression required
Some((result.filter, result.idat_data))
}
_ => {
debug!("Trying: {}", result.filter);
let best_size = AtomicMin::new(max_size);
perform_trial(&result.filtered, opts, result.filter, &best_size, deflater)
}
}
debug!("Trying: {}", result.filter);
let best_size = AtomicMin::new(max_size);
perform_trial(&result.filtered, opts, result.filter, &best_size, deflater)
} else {
// Perform full compression trials of selected filters and determine the best
@ -855,7 +847,8 @@ fn report_format(prefix: &str, png: &PngImage) {
}
/// 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<T>(png: &mut PngData, opts: &Options, orig_ihdr: &IhdrData, deflater: &T)
where T: Deflater {
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
let may_replace_iccp = opts.strip != StripChunks::None && opts.strip.keep(b"sRGB");
@ -877,7 +870,7 @@ fn postprocess_chunks(png: &mut PngData, opts: &Options, orig_ihdr: &IhdrData) {
name: *b"sRGB",
data: vec![intent],
};
} else if let Ok(iccp) = construct_iccp(&icc, &opts.deflate) {
} else if let Ok(iccp) = construct_iccp(&icc, deflater) {
let cur_len = png.aux_chunks[iccp_idx].data.len();
let new_len = iccp.data.len();
if new_len < cur_len {

View file

@ -14,6 +14,7 @@ fn get_opts() -> Options {
fn test_it_converts(input: &str) {
let input = PathBuf::from(input);
let opts = get_opts();
let deflater = BufferedZopfliDeflater::default();
let original_data = PngData::read_file(&PathBuf::from(input)).unwrap();
let image = PngData::from_slice(&original_data, &opts).unwrap();
@ -35,7 +36,7 @@ fn test_it_converts(input: &str) {
raw.add_png_chunk(chunk.name, chunk.data);
}
let output = raw.create_optimized_png(&opts).unwrap();
let output = raw.create_optimized_png(&opts, &deflater).unwrap();
let new = PngData::from_slice(&output, &opts).unwrap();
assert!(new.aux_chunks.len() == num_chunks);
@ -52,6 +53,7 @@ fn from_file() {
#[test]
fn custom_indexed() {
let opts = get_opts();
let deflater = BufferedZopfliDeflater::default();
let raw = RawImage::new(
4,
@ -69,7 +71,7 @@ fn custom_indexed() {
)
.unwrap();
raw.create_optimized_png(&opts).unwrap();
raw.create_optimized_png(&opts, &deflater).unwrap();
}
#[test]