Don't use atomicmin in deflater
This commit is contained in:
parent
74c5c4173b
commit
78b9bd47d0
7 changed files with 35 additions and 64 deletions
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<Vec<u8>> {
|
||||
pub fn deflate(data: &[u8], level: u8, max_size: Option<usize>) -> PngResult<Vec<u8>> {
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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<Vec<u8>> {
|
||||
pub(crate) fn deflate(self, data: &[u8], max_size: Option<usize>) -> PngResult<Vec<u8>> {
|
||||
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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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<Vec<u8>> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Construct an iCCP chunk by compressing the ICC profile
|
||||
pub fn construct_iccp(icc: &[u8], deflater: Deflaters) -> PngResult<Chunk> {
|
||||
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<usize>) -> PngResult<Chunk> {
|
||||
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
|
||||
|
|
|
|||
45
src/lib.rs
45
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<T> = Result<T, PngError>;
|
||||
|
|
@ -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<Deadline>)
|
|||
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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue