diff --git a/src/lib.rs b/src/lib.rs index aa43bf2d..42f8fbd9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -365,6 +365,7 @@ fn optimize_png( if let Some(new_png) = optimize_raw(raw.clone(), &opts, deadline.clone(), max_size) { png.raw = new_png.raw; png.idat_data = new_png.idat_data; + png.filter = new_png.filter; } postprocess_chunks(png, &opts, &raw.ihdr); @@ -533,6 +534,7 @@ fn optimize_raw( idat_data, aux_chunks: Vec::new(), frames: Vec::new(), + filter: Some(filter), }; if image.estimated_output_size() < max_size.unwrap_or(usize::MAX) { debug!("Found better combination:"); @@ -553,6 +555,7 @@ fn optimize_raw( idat_data: result.idat_data, aux_chunks: Vec::new(), frames: Vec::new(), + filter: Some(result.filter), }; if image.estimated_output_size() < max_size.unwrap_or(usize::MAX) { debug!("Found better combination:"); diff --git a/src/png/mod.rs b/src/png/mod.rs index 9f856f94..a67fe1e0 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -50,6 +50,8 @@ pub struct PngData { pub aux_chunks: Vec, /// APNG frames pub frames: Vec, + /// The filter strategy applied to the idat_data (initially unknown) + pub filter: Option, } impl PngData { @@ -173,24 +175,16 @@ impl PngData { key_chunks.remove(b"PLTE"), key_chunks.remove(b"tRNS"), )?; - let raw_data = deflate::inflate(idat_data.as_ref(), ihdr.raw_data_size())?; - // Reject files with incorrect width/height or truncated data - if raw_data.len() != ihdr.raw_data_size() { - return Err(PngError::TruncatedData); - } + let raw = PngImage::new(ihdr, &idat_data)?; - let mut raw = PngImage { - ihdr, - data: raw_data, - }; - raw.data = raw.unfilter_image()?; // Return the PngData Ok(Self { idat_data, raw: Arc::new(raw), aux_chunks, frames, + filter: None, }) } @@ -292,6 +286,22 @@ impl PngData { } impl PngImage { + pub fn new(ihdr: IhdrData, compressed_data: &[u8]) -> Result { + let raw_data = deflate::inflate(compressed_data, ihdr.raw_data_size())?; + + // Reject files with incorrect width/height or truncated data + if raw_data.len() != ihdr.raw_data_size() { + return Err(PngError::TruncatedData); + } + + let mut image = Self { + ihdr, + data: raw_data, + }; + image.data = image.unfilter_image()?; + Ok(image) + } + /// Convert the image to the specified interlacing type /// Returns true if the interlacing was changed, false otherwise /// The `interlace` parameter specifies the *new* interlacing mode