From 2f78a9ef05c45a686b0572927f8019328225c17d Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Sun, 9 Jul 2023 13:32:32 -0400 Subject: [PATCH] Revert "Provide BufferedZopfliDeflater and allow user to pass in a custom Deflater (#530)" This reverts commit 2a59419bdfe0d8d5be3f9bbd316f82bb33492675. --- .whitesource | 14 ------ Cargo.lock | 1 - Cargo.toml | 2 - benches/zopfli.rs | 29 ++++------- src/atomicmin.rs | 2 +- src/colors.rs | 12 ++--- src/deflate/mod.rs | 94 ++++-------------------------------- src/deflate/zopfli_oxipng.rs | 60 +++-------------------- src/headers.rs | 9 ++-- src/lib.rs | 70 +++++++++++---------------- src/main.rs | 9 ++-- src/png/mod.rs | 6 +-- tests/flags.rs | 5 +- tests/raw.rs | 6 +-- 14 files changed, 77 insertions(+), 242 deletions(-) delete mode 100644 .whitesource diff --git a/.whitesource b/.whitesource deleted file mode 100644 index 9c7ae90b4..000000000 --- a/.whitesource +++ /dev/null @@ -1,14 +0,0 @@ -{ - "scanSettings": { - "baseBranches": [] - }, - "checkRunSettings": { - "vulnerableCheckRunConclusionLevel": "failure", - "displayMode": "diff", - "useMendCheckNames": true - }, - "issueSettings": { - "minSeverityLevel": "LOW", - "issueType": "DEPENDENCY" - } -} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 02c89caa4..aa4dc97c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -479,7 +479,6 @@ dependencies = [ "rgb", "rustc-hash", "rustc_version", - "simd-adler32", "stderrlog", "wild", "zopfli", diff --git a/Cargo.toml b/Cargo.toml index 8898674a3..20f25ffc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,6 @@ required-features = ["zopfli"] [dependencies] zopfli = { version = "0.7.4", optional = true, default-features = false, features = ["std", "zlib"] } -simd-adler32 = { version = "0.3.5", optional = true, default-features = false } rgb = "0.8.36" indexmap = "2.0.0" libdeflater = "0.14.0" @@ -67,7 +66,6 @@ version = "0.24.6" rustc_version = "0.4.0" [features] -zopfli = ["zopfli/std", "zopfli/zlib", "simd-adler32"] binary = ["clap", "wild", "stderrlog"] default = ["binary", "filetime", "parallel", "zopfli"] parallel = ["rayon", "indexmap/rayon", "crossbeam-channel"] diff --git a/benches/zopfli.rs b/benches/zopfli.rs index acef19513..03f83f651 100644 --- a/benches/zopfli.rs +++ b/benches/zopfli.rs @@ -5,19 +5,20 @@ extern crate test; use oxipng::internal_tests::*; use oxipng::*; +use std::num::NonZeroU8; use std::path::PathBuf; use test::Bencher; +// SAFETY: trivially safe. Stopgap solution until const unwrap is stabilized. +const DEFAULT_ZOPFLI_ITERATIONS: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(15) }; + #[bench] fn zopfli_16_bits_strategy_0(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(); - let max_size = AtomicMin::new(Some(png.idat_data.len())); b.iter(|| { - BufferedZopfliDeflater::default() - .deflate(png.raw.data.as_ref(), &max_size) - .ok(); + zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok(); }); } @@ -25,12 +26,9 @@ fn zopfli_16_bits_strategy_0(b: &mut Bencher) { fn zopfli_8_bits_strategy_0(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(); - let max_size = AtomicMin::new(Some(png.idat_data.len())); b.iter(|| { - BufferedZopfliDeflater::default() - .deflate(png.raw.data.as_ref(), &max_size) - .ok(); + zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok(); }); } @@ -40,12 +38,9 @@ fn zopfli_4_bits_strategy_0(b: &mut Bencher) { "tests/files/palette_4_should_be_palette_4.png", )); let png = PngData::new(&input, &Options::default()).unwrap(); - let max_size = AtomicMin::new(Some(png.idat_data.len())); b.iter(|| { - BufferedZopfliDeflater::default() - .deflate(png.raw.data.as_ref(), &max_size) - .ok(); + zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok(); }); } @@ -55,12 +50,9 @@ fn zopfli_2_bits_strategy_0(b: &mut Bencher) { "tests/files/palette_2_should_be_palette_2.png", )); let png = PngData::new(&input, &Options::default()).unwrap(); - let max_size = AtomicMin::new(Some(png.idat_data.len())); b.iter(|| { - BufferedZopfliDeflater::default() - .deflate(png.raw.data.as_ref(), &max_size) - .ok(); + zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok(); }); } @@ -70,11 +62,8 @@ fn zopfli_1_bits_strategy_0(b: &mut Bencher) { "tests/files/palette_1_should_be_palette_1.png", )); let png = PngData::new(&input, &Options::default()).unwrap(); - let max_size = AtomicMin::new(Some(png.idat_data.len())); b.iter(|| { - BufferedZopfliDeflater::default() - .deflate(png.raw.data.as_ref(), &max_size) - .ok(); + zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok(); }); } diff --git a/src/atomicmin.rs b/src/atomicmin.rs index 2df7028cb..69a379f27 100644 --- a/src/atomicmin.rs +++ b/src/atomicmin.rs @@ -23,7 +23,7 @@ impl AtomicMin { } /// Unset value is usize_max - pub const fn as_atomic_usize(&self) -> &AtomicUsize { + pub fn as_atomic_usize(&self) -> &AtomicUsize { &self.val } diff --git a/src/colors.rs b/src/colors.rs index 238bf2626..d81b13467 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -45,7 +45,7 @@ impl Display for ColorType { impl ColorType { /// Get the code used by the PNG specification to denote this color type #[inline] - pub const fn png_header_code(&self) -> u8 { + pub fn png_header_code(&self) -> u8 { match self { ColorType::Grayscale { .. } => 0, ColorType::RGB { .. } => 2, @@ -56,7 +56,7 @@ impl ColorType { } #[inline] - pub(crate) const fn channels_per_pixel(&self) -> u8 { + pub(crate) fn channels_per_pixel(&self) -> u8 { match self { ColorType::Grayscale { .. } | ColorType::Indexed { .. } => 1, ColorType::GrayscaleAlpha => 2, @@ -66,12 +66,12 @@ impl ColorType { } #[inline] - pub(crate) const fn is_rgb(&self) -> bool { + pub(crate) fn is_rgb(&self) -> bool { matches!(self, ColorType::RGB { .. } | ColorType::RGBA) } #[inline] - pub(crate) const fn is_gray(&self) -> bool { + pub(crate) fn is_gray(&self) -> bool { matches!( self, ColorType::Grayscale { .. } | ColorType::GrayscaleAlpha @@ -79,12 +79,12 @@ impl ColorType { } #[inline] - pub(crate) const fn has_alpha(&self) -> bool { + pub(crate) fn has_alpha(&self) -> bool { matches!(self, ColorType::GrayscaleAlpha | ColorType::RGBA) } #[inline] - pub(crate) const fn has_trns(&self) -> bool { + pub(crate) fn has_trns(&self) -> bool { match self { ColorType::Grayscale { transparent_shade } => transparent_shade.is_some(), ColorType::RGB { transparent_color } => transparent_color.is_some(), diff --git a/src/deflate/mod.rs b/src/deflate/mod.rs index d7d4f9629..0e8a65f32 100644 --- a/src/deflate/mod.rs +++ b/src/deflate/mod.rs @@ -7,15 +7,10 @@ pub use deflater::inflate; use std::{fmt, fmt::Display}; #[cfg(feature = "zopfli")] -use std::io::{self, copy, BufWriter, Cursor, Write}; - -#[cfg(feature = "zopfli")] -use zopfli::{DeflateEncoder, Options}; +use std::num::NonZeroU8; #[cfg(feature = "zopfli")] mod zopfli_oxipng; #[cfg(feature = "zopfli")] -use simd_adler32::Adler32; -#[cfg(feature = "zopfli")] pub use zopfli_oxipng::deflate as zopfli_deflate; #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -29,21 +24,19 @@ pub enum Deflaters { #[cfg(feature = "zopfli")] /// Use the better but slower Zopfli implementation Zopfli { - /// Zopfli compression options - options: Options, + /// The number of compression iterations to do. 15 iterations are fine + /// for small files, but bigger files will need to be compressed with + /// less iterations, or else they will be too slow. + iterations: NonZeroU8, }, } -pub trait Deflater: Sync + Send { - fn deflate(&self, data: &[u8], max_size: &AtomicMin) -> PngResult>; -} - -impl Deflater for Deflaters { - fn deflate(&self, data: &[u8], max_size: &AtomicMin) -> PngResult> { +impl Deflaters { + pub(crate) fn deflate(self, data: &[u8], max_size: &AtomicMin) -> PngResult> { let compressed = match self { - Self::Libdeflater { compression } => deflate(data, *compression, max_size)?, + Self::Libdeflater { compression } => deflate(data, compression, max_size)?, #[cfg(feature = "zopfli")] - Self::Zopfli { options } => zopfli_deflate(data, options)?, + Self::Zopfli { iterations } => zopfli_deflate(data, iterations)?, }; if let Some(max) = max_size.get() { if compressed.len() > max { @@ -54,75 +47,6 @@ impl Deflater for Deflaters { } } -#[cfg(feature = "zopfli")] -#[derive(Copy, Clone, Debug)] -pub struct BufferedZopfliDeflater { - input_buffer_size: usize, - output_buffer_size: usize, - options: Options, -} - -#[cfg(feature = "zopfli")] -impl BufferedZopfliDeflater { - pub const fn new( - input_buffer_size: usize, - output_buffer_size: usize, - options: Options, - ) -> Self { - BufferedZopfliDeflater { - input_buffer_size, - output_buffer_size, - options, - } - } -} - -#[cfg(feature = "zopfli")] -impl Default for BufferedZopfliDeflater { - fn default() -> Self { - BufferedZopfliDeflater { - input_buffer_size: 1024 * 1024, - output_buffer_size: 64 * 1024, - options: Options::default(), - } - } -} - -#[cfg(feature = "zopfli")] -impl Deflater for BufferedZopfliDeflater { - /// Fork of the zlib_compress function in Zopfli. - fn deflate(&self, data: &[u8], max_size: &AtomicMin) -> PngResult> { - let mut out = Cursor::new(Vec::with_capacity(self.output_buffer_size)); - let cmf = 120; /* CM 8, CINFO 7. See zlib spec.*/ - let flevel = 3; - let fdict = 0; - let mut cmfflg: u16 = 256 * cmf + fdict * 32 + flevel * 64; - let fcheck = 31 - cmfflg % 31; - cmfflg += fcheck; - - let out = (|| -> io::Result> { - let mut rolling_adler = Adler32::new(); - let mut in_data = - zopfli_oxipng::HashingAndCountingRead::new(data, &mut rolling_adler, None); - out.write_all(&cmfflg.to_be_bytes())?; - let mut buffer = BufWriter::with_capacity( - self.input_buffer_size, - DeflateEncoder::new(self.options, Default::default(), &mut out), - ); - copy(&mut in_data, &mut buffer)?; - buffer.into_inner()?.finish()?; - out.write_all(&rolling_adler.finish().to_be_bytes())?; - Ok(out.into_inner()) - })(); - let out = out.map_err(|e| PngError::new(&e.to_string()))?; - if max_size.get().map(|max| max < out.len()).unwrap_or(false) { - Err(PngError::DeflatedDataTooLong(out.len())) - } else { - Ok(out) - } - } -} - impl Display for Deflaters { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/deflate/zopfli_oxipng.rs b/src/deflate/zopfli_oxipng.rs index 3c6c8d4f5..b59b93df6 100644 --- a/src/deflate/zopfli_oxipng.rs +++ b/src/deflate/zopfli_oxipng.rs @@ -1,64 +1,18 @@ use crate::{PngError, PngResult}; -use simd_adler32::Adler32; -use std::io::{Error, ErrorKind, Read}; +use std::num::NonZeroU8; -pub fn deflate(data: &[u8], options: &zopfli::Options) -> PngResult> { +pub fn deflate(data: &[u8], iterations: NonZeroU8) -> PngResult> { use std::cmp::max; let mut output = Vec::with_capacity(max(1024, data.len() / 20)); - match zopfli::compress(options, &zopfli::Format::Zlib, data, &mut output) { + let options = zopfli::Options { + iteration_count: iterations, + ..Default::default() + }; + match zopfli::compress(&options, &zopfli::Format::Zlib, data, &mut output) { Ok(_) => (), Err(_) => return Err(PngError::new("Failed to compress in zopfli")), }; output.shrink_to_fit(); Ok(output) } - -/// Forked from zopfli crate -pub trait Hasher { - fn update(&mut self, data: &[u8]); -} - -impl Hasher for &mut Adler32 { - fn update(&mut self, data: &[u8]) { - Adler32::write(self, data) - } -} - -/// A reader that wraps another reader, a hasher and an optional counter, -/// updating the hasher state and incrementing a counter of bytes read so -/// far for each block of data read. -pub struct HashingAndCountingRead<'counter, R: Read, H: Hasher> { - inner: R, - hasher: H, - bytes_read: Option<&'counter mut u32>, -} - -impl<'counter, R: Read, H: Hasher> HashingAndCountingRead<'counter, R, H> { - pub fn new(inner: R, hasher: H, bytes_read: Option<&'counter mut u32>) -> Self { - Self { - inner, - hasher, - bytes_read, - } - } -} - -impl Read for HashingAndCountingRead<'_, R, H> { - fn read(&mut self, buf: &mut [u8]) -> Result { - match self.inner.read(buf) { - Ok(bytes_read) => { - self.hasher.update(&buf[..bytes_read]); - - if let Some(total_bytes_read) = &mut self.bytes_read { - **total_bytes_read = total_bytes_read - .checked_add(bytes_read.try_into().map_err(|_| ErrorKind::Other)?) - .ok_or(ErrorKind::Other)?; - } - - Ok(bytes_read) - } - Err(err) => Err(err), - } - } -} diff --git a/src/headers.rs b/src/headers.rs index 3a973c597..8a70a85ee 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -1,8 +1,9 @@ use crate::colors::{BitDepth, ColorType}; -use crate::deflate::{crc32, inflate, Deflater}; +use crate::deflate::{crc32, inflate}; use crate::error::PngError; use crate::interlace::Interlacing; use crate::AtomicMin; +use crate::Deflaters; use crate::PngResult; use indexmap::IndexSet; use log::warn; @@ -27,7 +28,7 @@ impl IhdrData { /// Bits per pixel #[must_use] #[inline] - pub const fn bpp(&self) -> usize { + pub fn bpp(&self) -> usize { self.bit_depth as usize * self.color_type.channels_per_pixel() as usize } @@ -38,7 +39,7 @@ impl IhdrData { let h = self.height as usize; let bpp = self.bpp(); - const fn bitmap_size(bpp: usize, w: usize, h: usize) -> usize { + fn bitmap_size(bpp: usize, w: usize, h: usize) -> usize { ((w * bpp + 7) / 8) * h } @@ -248,7 +249,7 @@ pub fn extract_icc(iccp: &Chunk) -> Option> { } /// Construct an iCCP chunk by compressing the ICC profile -pub fn construct_iccp(icc: &[u8], deflater: &T) -> PngResult { +pub fn construct_iccp(icc: &[u8], deflater: Deflaters) -> PngResult { let mut compressed = deflater.deflate(icc, &AtomicMin::new(None))?; let mut data = Vec::with_capacity(compressed.len() + 5); data.extend(b"icc"); // Profile name - generally unused, can be anything diff --git a/src/lib.rs b/src/lib.rs index 9c26a40c9..23cc7a93d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ use crate::headers::*; use crate::png::PngData; use crate::png::PngImage; use crate::reduction::*; -use log::{debug, error, info, trace, warn}; +use log::{debug, info, trace, warn}; use rayon::prelude::*; use std::borrow::Cow; use std::fmt; @@ -42,7 +42,6 @@ use std::sync::Arc; use std::time::{Duration, Instant}; pub use crate::colors::{BitDepth, ColorType}; -use crate::deflate::Deflater; pub use crate::deflate::Deflaters; pub use crate::error::PngError; pub use crate::filters::RowFilter; @@ -250,7 +249,7 @@ impl Options { self } - const fn apply_preset_2(self) -> Self { + fn apply_preset_2(self) -> Self { self } @@ -382,19 +381,15 @@ 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) = construct_iccp(data, deflater) { self.aux_chunks.push(iccp); } } /// Create an optimized png from the raw image data using the options provided - pub fn create_optimized_png( - &self, - opts: &Options, - deflater: &T, - ) -> PngResult> { + pub fn create_optimized_png(&self, opts: &Options) -> PngResult> { let deadline = Arc::new(Deadline::new(opts.timeout)); - let mut png = optimize_raw(self.png.clone(), opts, deadline.clone(), None, deflater) + let mut png = optimize_raw(self.png.clone(), opts, deadline.clone(), None) .ok_or_else(|| PngError::new("Failed to optimize input data"))?; // Process aux chunks @@ -404,7 +399,7 @@ impl RawImage { .filter(|c| opts.strip.keep(&c.name)) .cloned() .collect(); - postprocess_chunks(&mut png, opts, deadline, &self.png.ihdr, deflater); + postprocess_chunks(&mut png, opts, deadline, &self.png.ihdr); Ok(png.output()) } @@ -517,7 +512,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<( )) })?; // force drop and thereby closing of file handle before modifying any timestamp - drop(buffer); + std::mem::drop(buffer); if let Some(metadata_input) = &opt_metadata_preserved { copy_times(metadata_input, output_path)?; } @@ -588,18 +583,12 @@ fn optimize_png( } else { Some(png.estimated_output_size()) }; - if let Some(new_png) = optimize_raw( - raw.clone(), - &opts, - deadline.clone(), - max_size, - &opts.deflate, - ) { + 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; } - postprocess_chunks(png, &opts, deadline, &raw.ihdr, &opts.deflate); + postprocess_chunks(png, &opts, deadline, &raw.ihdr); let output = png.output(); @@ -639,12 +628,11 @@ fn optimize_png( } /// Perform optimization on the input image data using the options provided -fn optimize_raw( +fn optimize_raw( image: Arc, opts: &Options, deadline: Arc, max_size: Option, - deflater: &T, ) -> Option { // Libdeflate has four algorithms: 1-4 = 'greedy', 5-7 = 'lazy', 8-9 = 'lazy2', 10-12 = 'near-optimal' // 5 is the minimumm required for a decent evaluation result @@ -705,9 +693,17 @@ fn optimize_raw( // We should have a result here - fail if not (e.g. deadline passed) let result = eval_result?; - debug!("Trying: {}", result.filter); - let best_size = AtomicMin::new(max_size); - perform_trial(&result.filtered, opts, result.filter, &best_size, deflater) + 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) + } + } } else { // Perform full compression trials of selected filters and determine the best @@ -731,7 +727,7 @@ fn optimize_raw( return None; } let filtered = &png.filter_image(filter, opts.optimize_alpha); - perform_trial(filtered, opts, filter, &best_size, deflater) + perform_trial(filtered, opts, filter, &best_size) }); best.reduce_with(|i, j| { if i.1.len() < j.1.len() || (i.1.len() == j.1.len() && i.0 < j.0) { @@ -783,15 +779,13 @@ fn optimize_raw( } /// Execute a compression trial -fn perform_trial( +fn perform_trial( filtered: &[u8], opts: &Options, filter: RowFilter, best_size: &AtomicMin, - deflater: &T, ) -> Option { - let result = deflater.deflate(filtered, best_size); - match result { + match opts.deflate.deflate(filtered, best_size) { Ok(new_idat) => { let bytes = new_idat.len(); best_size.set_min(bytes); @@ -812,10 +806,7 @@ fn perform_trial( ); None } - Err(e) => { - error!("I/O error: {}", e); - None - } + Err(_) => None, } } @@ -877,15 +868,12 @@ fn report_format(prefix: &str, png: &PngImage) { } /// Perform cleanup of certain chunks from the `PngData` object, after optimization has been completed -fn postprocess_chunks( +fn postprocess_chunks( png: &mut PngData, opts: &Options, deadline: Arc, 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"); @@ -907,7 +895,7 @@ fn postprocess_chunks( name: *b"sRGB", data: vec![intent], }; - } else if let Ok(iccp) = construct_iccp(&icc, deflater) { + } else 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 { @@ -973,7 +961,7 @@ fn postprocess_chunks( } /// Check if an image was already optimized prior to oxipng's operations -const fn is_fully_optimized(original_size: usize, optimized_size: usize, opts: &Options) -> bool { +fn is_fully_optimized(original_size: usize, optimized_size: usize, opts: &Options) -> bool { original_size <= optimized_size && !opts.force } diff --git a/src/main.rs b/src/main.rs index 9afc43fa6..19768cbd8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,8 @@ use oxipng::RowFilter; use oxipng::StripChunks; use oxipng::{InFile, OutFile}; use std::fs::DirBuilder; +#[cfg(feature = "zopfli")] +use std::num::NonZeroU8; use std::path::PathBuf; use std::process::exit; use std::time::Duration; @@ -515,10 +517,9 @@ fn parse_opts_into_struct( if matches.get_flag("zopfli") { #[cfg(feature = "zopfli")] - let zopfli_opts = zopfli::Options::default(); - opts.deflate = Deflaters::Zopfli { - options: zopfli_opts, - }; + if let Some(iterations) = NonZeroU8::new(15) { + opts.deflate = Deflaters::Zopfli { iterations }; + } } else if let Deflaters::Libdeflater { compression } = &mut opts.deflate { if let Some(x) = matches.get_one::("compression") { *compression = *x as u8; diff --git a/src/png/mod.rs b/src/png/mod.rs index d6bdc8618..46ccc04a0 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -260,13 +260,13 @@ impl PngImage { /// Return the number of channels in the image, based on color type #[inline] - pub const fn channels_per_pixel(&self) -> usize { + pub fn channels_per_pixel(&self) -> usize { self.ihdr.color_type.channels_per_pixel() as usize } /// Return the number of bytes per channel in the image #[inline] - pub const fn bytes_per_channel(&self) -> usize { + pub fn bytes_per_channel(&self) -> usize { match self.ihdr.bit_depth { BitDepth::Sixteen => 2, // Depths lower than 8 will round up to 1 byte @@ -491,7 +491,7 @@ fn write_png_block(key: &[u8], chunk: &[u8], output: &mut Vec) { } // Integer approximation for i * log2(i) - much faster than float calculations -const fn ilog2i(i: u32) -> u32 { +fn ilog2i(i: u32) -> u32 { let log = 32 - i.leading_zeros() - 1; i * log + ((i - (1 << log)) << 1) } diff --git a/tests/flags.rs b/tests/flags.rs index 1384a97fd..5d3bdc2f1 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -677,10 +677,7 @@ fn zopfli_mode() { let input = PathBuf::from("tests/files/zopfli_mode.png"); let (output, mut opts) = get_opts(&input); opts.deflate = Deflaters::Zopfli { - options: zopfli::Options { - iteration_count: NonZeroU8::new(15).unwrap(), - maximum_block_splits: 15, - }, + iterations: NonZeroU8::new(15).unwrap(), }; test_it_converts( diff --git a/tests/raw.rs b/tests/raw.rs index 8aebc1f83..c3e16fb2f 100644 --- a/tests/raw.rs +++ b/tests/raw.rs @@ -14,7 +14,6 @@ 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(); @@ -36,7 +35,7 @@ fn test_it_converts(input: &str) { raw.add_png_chunk(chunk.name, chunk.data); } - let output = raw.create_optimized_png(&opts, &deflater).unwrap(); + let output = raw.create_optimized_png(&opts).unwrap(); let new = PngData::from_slice(&output, &opts).unwrap(); assert!(new.aux_chunks.len() == num_chunks); @@ -53,7 +52,6 @@ fn from_file() { #[test] fn custom_indexed() { let opts = get_opts(); - let deflater = BufferedZopfliDeflater::default(); let raw = RawImage::new( 4, @@ -71,7 +69,7 @@ fn custom_indexed() { ) .unwrap(); - raw.create_optimized_png(&opts, &deflater).unwrap(); + raw.create_optimized_png(&opts).unwrap(); } #[test]