Use deflater on iCCP chunk as well
This commit is contained in:
parent
d1a78f97bf
commit
a330187a51
3 changed files with 22 additions and 24 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
23
src/lib.rs
23
src/lib.rs
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
Loading…
Reference in a new issue