diff --git a/benches/deflate.rs b/benches/deflate.rs index 13373182..bec6965a 100644 --- a/benches/deflate.rs +++ b/benches/deflate.rs @@ -13,10 +13,7 @@ fn deflate_16_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png")); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| { - let min = AtomicMin::new(None); - deflate(png.raw.data.as_ref(), 12, &min) - }); + b.iter(|| deflate(png.raw.data.as_ref(), 12, None)); } #[bench] @@ -24,10 +21,7 @@ fn deflate_8_bits(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png")); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| { - let min = AtomicMin::new(None); - deflate(png.raw.data.as_ref(), 12, &min) - }); + b.iter(|| deflate(png.raw.data.as_ref(), 12, None)); } #[bench] @@ -37,10 +31,7 @@ fn deflate_4_bits(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| { - let min = AtomicMin::new(None); - deflate(png.raw.data.as_ref(), 12, &min) - }); + b.iter(|| deflate(png.raw.data.as_ref(), 12, None)); } #[bench] @@ -50,10 +41,7 @@ fn deflate_2_bits(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| { - let min = AtomicMin::new(None); - deflate(png.raw.data.as_ref(), 12, &min) - }); + b.iter(|| deflate(png.raw.data.as_ref(), 12, None)); } #[bench] @@ -63,10 +51,7 @@ fn deflate_1_bits(b: &mut Bencher) { )); let png = PngData::new(&input, &Options::default()).unwrap(); - b.iter(|| { - let min = AtomicMin::new(None); - deflate(png.raw.data.as_ref(), 12, &min) - }); + b.iter(|| deflate(png.raw.data.as_ref(), 12, None)); } #[bench] diff --git a/src/atomicmin.rs b/src/atomicmin.rs index 8cbe273e..57303e6d 100644 --- a/src/atomicmin.rs +++ b/src/atomicmin.rs @@ -22,11 +22,6 @@ impl AtomicMin { } } - /// Unset value is `usize_max` - pub const fn as_atomic_usize(&self) -> &AtomicUsize { - &self.val - } - /// Try a new value, returning true if it is the new minimum pub fn set_min(&self, new_val: usize) -> bool { new_val < self.val.fetch_min(new_val, SeqCst) diff --git a/src/deflate/deflater.rs b/src/deflate/deflater.rs index a744cdc7..9ba19f59 100644 --- a/src/deflate/deflater.rs +++ b/src/deflate/deflater.rs @@ -1,12 +1,10 @@ use libdeflater::*; -use crate::{atomicmin::AtomicMin, PngError, PngResult}; +use crate::{PngError, PngResult}; -pub fn deflate(data: &[u8], level: u8, max_size: &AtomicMin) -> PngResult> { +pub fn deflate(data: &[u8], level: u8, max_size: Option) -> PngResult> { let mut compressor = Compressor::new(CompressionLvl::new(level.into()).unwrap()); - let capacity = max_size - .get() - .unwrap_or_else(|| compressor.zlib_compress_bound(data.len())); + let capacity = max_size.unwrap_or_else(|| compressor.zlib_compress_bound(data.len())); let mut dest = vec![0; capacity]; let len = compressor .zlib_compress(data, &mut dest) diff --git a/src/deflate/mod.rs b/src/deflate/mod.rs index 4a023975..a9bd4afe 100644 --- a/src/deflate/mod.rs +++ b/src/deflate/mod.rs @@ -5,7 +5,7 @@ use std::{fmt, fmt::Display}; pub use deflater::{crc32, deflate, inflate}; -use crate::{AtomicMin, PngError, PngResult}; +use crate::{PngError, PngResult}; #[cfg(feature = "zopfli")] mod zopfli_oxipng; #[cfg(feature = "zopfli")] @@ -30,13 +30,13 @@ pub enum Deflaters { } impl Deflaters { - pub(crate) fn deflate(self, data: &[u8], max_size: &AtomicMin) -> PngResult> { + pub(crate) fn deflate(self, data: &[u8], max_size: Option) -> PngResult> { let compressed = match self { Self::Libdeflater { compression } => deflate(data, compression, max_size)?, #[cfg(feature = "zopfli")] Self::Zopfli { iterations } => zopfli_deflate(data, iterations)?, }; - if let Some(max) = max_size.get() { + if let Some(max) = max_size { if compressed.len() > max { return Err(PngError::DeflatedDataTooLong(max)); } diff --git a/src/evaluate.rs b/src/evaluate.rs index 5370a4dc..5fe06ea9 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -147,7 +147,7 @@ impl Evaluator { return; } let filtered = image.filter_image(filter, optimize_alpha); - let idat_data = deflater.deflate(&filtered, &best_candidate_size); + let idat_data = deflater.deflate(&filtered, best_candidate_size.get()); if let Ok(idat_data) = idat_data { let new = Candidate { image: image.clone(), diff --git a/src/headers.rs b/src/headers.rs index 3478b1a3..43f0781a 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -8,7 +8,7 @@ use crate::{ display_chunks::DISPLAY_CHUNKS, error::PngError, interlace::Interlacing, - AtomicMin, Deflaters, PngResult, + Deflaters, PngResult, }; #[derive(Debug, Clone)] @@ -275,9 +275,9 @@ pub fn extract_icc(iccp: &Chunk) -> Option> { } } -/// Construct an iCCP chunk by compressing the ICC profile -pub fn construct_iccp(icc: &[u8], deflater: Deflaters) -> PngResult { - let mut compressed = deflater.deflate(icc, &AtomicMin::new(None))?; +/// Make an iCCP chunk by compressing the ICC profile +pub fn make_iccp(icc: &[u8], deflater: Deflaters, max_size: Option) -> PngResult { + let mut compressed = deflater.deflate(icc, max_size)?; let mut data = Vec::with_capacity(compressed.len() + 5); data.extend(b"icc"); // Profile name - generally unused, can be anything data.extend([0, 0]); // Null separator, zlib compression method diff --git a/src/lib.rs b/src/lib.rs index 45823ab2..4f1fea10 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,13 +42,6 @@ use log::{debug, info, trace, warn}; use rayon::prelude::*; pub use rgb::{RGB16, RGBA8}; -use crate::{ - atomicmin::AtomicMin, - evaluate::{Candidate, Evaluator}, - headers::*, - png::{PngData, PngImage}, - reduction::*, -}; pub use crate::{ colors::{BitDepth, ColorType}, deflate::Deflaters, @@ -58,6 +51,12 @@ pub use crate::{ interlace::Interlacing, options::{InFile, Options, OutFile}, }; +use crate::{ + evaluate::{Candidate, Evaluator}, + headers::*, + png::{PngData, PngImage}, + reduction::*, +}; mod apng; mod atomicmin; @@ -80,7 +79,7 @@ mod sanity_checks; pub mod internal_tests { #[cfg(feature = "sanity-checks")] pub use crate::sanity_checks::*; - pub use crate::{atomicmin::*, deflate::*, png::*, reduction::*}; + pub use crate::{deflate::*, png::*, reduction::*}; } pub type PngResult = Result; @@ -149,7 +148,7 @@ impl RawImage { pub fn add_icc_profile(&mut self, data: &[u8]) { // Compress with fastest compression level - will be recompressed during optimization let deflater = Deflaters::Libdeflater { compression: 1 }; - if let Ok(iccp) = construct_iccp(data, deflater) { + if let Ok(iccp) = make_iccp(data, deflater, None) { self.aux_chunks.push(iccp); } } @@ -529,10 +528,7 @@ fn perform_trials( // Recompress with the main deflater debug!("Trying filter {}, zc = {}", result.filter, opts.deflate); - match opts - .deflate - .deflate(&result.filtered, &AtomicMin::new(max_size)) - { + match opts.deflate.deflate(&result.filtered, max_size) { Ok(idat_data) => { result.idat_data = idat_data; trace!("{} bytes", result.estimated_output_size()); @@ -649,17 +645,14 @@ fn postprocess_chunks(png: &mut PngData, opts: &Options, orig_ihdr: &IhdrData) { }; } else if opts.idat_recoding { // Try recompressing the profile - if let Ok(iccp) = construct_iccp(&icc, opts.deflate) { - let cur_len = png.aux_chunks[iccp_idx].data.len(); - let new_len = iccp.data.len(); - if new_len < cur_len { - debug!( - "Recompressed iCCP chunk: {} ({} bytes decrease)", - new_len, - cur_len - new_len - ); - png.aux_chunks[iccp_idx] = iccp; - } + let cur_len = png.aux_chunks[iccp_idx].data.len(); + if let Ok(iccp) = make_iccp(&icc, opts.deflate, Some(cur_len - 1)) { + debug!( + "Recompressed iCCP chunk: {} ({} bytes decrease)", + iccp.data.len(), + cur_len - iccp.data.len() + ); + png.aux_chunks[iccp_idx] = iccp; } } } @@ -706,8 +699,8 @@ fn recompress_frames(png: &mut PngData, opts: &Options, deadline: Arc) ihdr.height = frame.height; let image = PngImage::new(ihdr, &frame.data)?; let filtered = image.filter_image(filter, opts.optimize_alpha); - let max_size = AtomicMin::new(Some(frame.data.len() - 1)); - if let Ok(data) = opts.deflate.deflate(&filtered, &max_size) { + let max_size = Some(frame.data.len() - 1); + if let Ok(data) = opts.deflate.deflate(&filtered, max_size) { debug!( "Recompressed fdAT #{:<2}: {} ({} bytes decrease)", i,