Skip to content

Commit 31e796c

Browse files
committed
Revert "Provide BufferedZopfliDeflater and allow user to pass in a custom Deflater (oxipng#530)"
This reverts commit 2a59419.
1 parent 775e718 commit 31e796c

File tree

14 files changed

+77
-242
lines changed

14 files changed

+77
-242
lines changed

.whitesource

Lines changed: 0 additions & 14 deletions
This file was deleted.

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ required-features = ["zopfli"]
2828

2929
[dependencies]
3030
zopfli = { version = "0.7.4", optional = true, default-features = false, features = ["std", "zlib"] }
31-
simd-adler32 = { version = "0.3.5", optional = true, default-features = false }
3231
rgb = "0.8.36"
3332
indexmap = "2.0.0"
3433
libdeflater = "0.14.0"
@@ -67,7 +66,6 @@ version = "0.24.6"
6766
rustc_version = "0.4.0"
6867

6968
[features]
70-
zopfli = ["zopfli/std", "zopfli/zlib", "simd-adler32"]
7169
binary = ["clap", "wild", "stderrlog"]
7270
default = ["binary", "filetime", "parallel", "zopfli"]
7371
parallel = ["rayon", "indexmap/rayon", "crossbeam-channel"]

benches/zopfli.rs

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,30 @@ extern crate test;
55

66
use oxipng::internal_tests::*;
77
use oxipng::*;
8+
use std::num::NonZeroU8;
89
use std::path::PathBuf;
910
use test::Bencher;
1011

12+
// SAFETY: trivially safe. Stopgap solution until const unwrap is stabilized.
13+
const DEFAULT_ZOPFLI_ITERATIONS: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(15) };
14+
1115
#[bench]
1216
fn zopfli_16_bits_strategy_0(b: &mut Bencher) {
1317
let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png"));
1418
let png = PngData::new(&input, &Options::default()).unwrap();
15-
let max_size = AtomicMin::new(Some(png.idat_data.len()));
1619

1720
b.iter(|| {
18-
BufferedZopfliDeflater::default()
19-
.deflate(png.raw.data.as_ref(), &max_size)
20-
.ok();
21+
zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok();
2122
});
2223
}
2324

2425
#[bench]
2526
fn zopfli_8_bits_strategy_0(b: &mut Bencher) {
2627
let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png"));
2728
let png = PngData::new(&input, &Options::default()).unwrap();
28-
let max_size = AtomicMin::new(Some(png.idat_data.len()));
2929

3030
b.iter(|| {
31-
BufferedZopfliDeflater::default()
32-
.deflate(png.raw.data.as_ref(), &max_size)
33-
.ok();
31+
zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok();
3432
});
3533
}
3634

@@ -40,12 +38,9 @@ fn zopfli_4_bits_strategy_0(b: &mut Bencher) {
4038
"tests/files/palette_4_should_be_palette_4.png",
4139
));
4240
let png = PngData::new(&input, &Options::default()).unwrap();
43-
let max_size = AtomicMin::new(Some(png.idat_data.len()));
4441

4542
b.iter(|| {
46-
BufferedZopfliDeflater::default()
47-
.deflate(png.raw.data.as_ref(), &max_size)
48-
.ok();
43+
zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok();
4944
});
5045
}
5146

@@ -55,12 +50,9 @@ fn zopfli_2_bits_strategy_0(b: &mut Bencher) {
5550
"tests/files/palette_2_should_be_palette_2.png",
5651
));
5752
let png = PngData::new(&input, &Options::default()).unwrap();
58-
let max_size = AtomicMin::new(Some(png.idat_data.len()));
5953

6054
b.iter(|| {
61-
BufferedZopfliDeflater::default()
62-
.deflate(png.raw.data.as_ref(), &max_size)
63-
.ok();
55+
zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok();
6456
});
6557
}
6658

@@ -70,11 +62,8 @@ fn zopfli_1_bits_strategy_0(b: &mut Bencher) {
7062
"tests/files/palette_1_should_be_palette_1.png",
7163
));
7264
let png = PngData::new(&input, &Options::default()).unwrap();
73-
let max_size = AtomicMin::new(Some(png.idat_data.len()));
7465

7566
b.iter(|| {
76-
BufferedZopfliDeflater::default()
77-
.deflate(png.raw.data.as_ref(), &max_size)
78-
.ok();
67+
zopfli_deflate(png.raw.data.as_ref(), DEFAULT_ZOPFLI_ITERATIONS).ok();
7968
});
8069
}

src/atomicmin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl AtomicMin {
2323
}
2424

2525
/// Unset value is usize_max
26-
pub const fn as_atomic_usize(&self) -> &AtomicUsize {
26+
pub fn as_atomic_usize(&self) -> &AtomicUsize {
2727
&self.val
2828
}
2929

src/colors.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl Display for ColorType {
4545
impl ColorType {
4646
/// Get the code used by the PNG specification to denote this color type
4747
#[inline]
48-
pub const fn png_header_code(&self) -> u8 {
48+
pub fn png_header_code(&self) -> u8 {
4949
match self {
5050
ColorType::Grayscale { .. } => 0,
5151
ColorType::RGB { .. } => 2,
@@ -56,7 +56,7 @@ impl ColorType {
5656
}
5757

5858
#[inline]
59-
pub(crate) const fn channels_per_pixel(&self) -> u8 {
59+
pub(crate) fn channels_per_pixel(&self) -> u8 {
6060
match self {
6161
ColorType::Grayscale { .. } | ColorType::Indexed { .. } => 1,
6262
ColorType::GrayscaleAlpha => 2,
@@ -66,25 +66,25 @@ impl ColorType {
6666
}
6767

6868
#[inline]
69-
pub(crate) const fn is_rgb(&self) -> bool {
69+
pub(crate) fn is_rgb(&self) -> bool {
7070
matches!(self, ColorType::RGB { .. } | ColorType::RGBA)
7171
}
7272

7373
#[inline]
74-
pub(crate) const fn is_gray(&self) -> bool {
74+
pub(crate) fn is_gray(&self) -> bool {
7575
matches!(
7676
self,
7777
ColorType::Grayscale { .. } | ColorType::GrayscaleAlpha
7878
)
7979
}
8080

8181
#[inline]
82-
pub(crate) const fn has_alpha(&self) -> bool {
82+
pub(crate) fn has_alpha(&self) -> bool {
8383
matches!(self, ColorType::GrayscaleAlpha | ColorType::RGBA)
8484
}
8585

8686
#[inline]
87-
pub(crate) const fn has_trns(&self) -> bool {
87+
pub(crate) fn has_trns(&self) -> bool {
8888
match self {
8989
ColorType::Grayscale { transparent_shade } => transparent_shade.is_some(),
9090
ColorType::RGB { transparent_color } => transparent_color.is_some(),

src/deflate/mod.rs

Lines changed: 9 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,10 @@ pub use deflater::inflate;
77
use std::{fmt, fmt::Display};
88

99
#[cfg(feature = "zopfli")]
10-
use std::io::{self, copy, BufWriter, Cursor, Write};
11-
12-
#[cfg(feature = "zopfli")]
13-
use zopfli::{DeflateEncoder, Options};
10+
use std::num::NonZeroU8;
1411
#[cfg(feature = "zopfli")]
1512
mod zopfli_oxipng;
1613
#[cfg(feature = "zopfli")]
17-
use simd_adler32::Adler32;
18-
#[cfg(feature = "zopfli")]
1914
pub use zopfli_oxipng::deflate as zopfli_deflate;
2015

2116
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -29,21 +24,19 @@ pub enum Deflaters {
2924
#[cfg(feature = "zopfli")]
3025
/// Use the better but slower Zopfli implementation
3126
Zopfli {
32-
/// Zopfli compression options
33-
options: Options,
27+
/// The number of compression iterations to do. 15 iterations are fine
28+
/// for small files, but bigger files will need to be compressed with
29+
/// less iterations, or else they will be too slow.
30+
iterations: NonZeroU8,
3431
},
3532
}
3633

37-
pub trait Deflater: Sync + Send {
38-
fn deflate(&self, data: &[u8], max_size: &AtomicMin) -> PngResult<Vec<u8>>;
39-
}
40-
41-
impl Deflater for Deflaters {
42-
fn deflate(&self, data: &[u8], max_size: &AtomicMin) -> PngResult<Vec<u8>> {
34+
impl Deflaters {
35+
pub(crate) fn deflate(self, data: &[u8], max_size: &AtomicMin) -> PngResult<Vec<u8>> {
4336
let compressed = match self {
44-
Self::Libdeflater { compression } => deflate(data, *compression, max_size)?,
37+
Self::Libdeflater { compression } => deflate(data, compression, max_size)?,
4538
#[cfg(feature = "zopfli")]
46-
Self::Zopfli { options } => zopfli_deflate(data, options)?,
39+
Self::Zopfli { iterations } => zopfli_deflate(data, iterations)?,
4740
};
4841
if let Some(max) = max_size.get() {
4942
if compressed.len() > max {
@@ -54,75 +47,6 @@ impl Deflater for Deflaters {
5447
}
5548
}
5649

57-
#[cfg(feature = "zopfli")]
58-
#[derive(Copy, Clone, Debug)]
59-
pub struct BufferedZopfliDeflater {
60-
input_buffer_size: usize,
61-
output_buffer_size: usize,
62-
options: Options,
63-
}
64-
65-
#[cfg(feature = "zopfli")]
66-
impl BufferedZopfliDeflater {
67-
pub const fn new(
68-
input_buffer_size: usize,
69-
output_buffer_size: usize,
70-
options: Options,
71-
) -> Self {
72-
BufferedZopfliDeflater {
73-
input_buffer_size,
74-
output_buffer_size,
75-
options,
76-
}
77-
}
78-
}
79-
80-
#[cfg(feature = "zopfli")]
81-
impl Default for BufferedZopfliDeflater {
82-
fn default() -> Self {
83-
BufferedZopfliDeflater {
84-
input_buffer_size: 1024 * 1024,
85-
output_buffer_size: 64 * 1024,
86-
options: Options::default(),
87-
}
88-
}
89-
}
90-
91-
#[cfg(feature = "zopfli")]
92-
impl Deflater for BufferedZopfliDeflater {
93-
/// Fork of the zlib_compress function in Zopfli.
94-
fn deflate(&self, data: &[u8], max_size: &AtomicMin) -> PngResult<Vec<u8>> {
95-
let mut out = Cursor::new(Vec::with_capacity(self.output_buffer_size));
96-
let cmf = 120; /* CM 8, CINFO 7. See zlib spec.*/
97-
let flevel = 3;
98-
let fdict = 0;
99-
let mut cmfflg: u16 = 256 * cmf + fdict * 32 + flevel * 64;
100-
let fcheck = 31 - cmfflg % 31;
101-
cmfflg += fcheck;
102-
103-
let out = (|| -> io::Result<Vec<u8>> {
104-
let mut rolling_adler = Adler32::new();
105-
let mut in_data =
106-
zopfli_oxipng::HashingAndCountingRead::new(data, &mut rolling_adler, None);
107-
out.write_all(&cmfflg.to_be_bytes())?;
108-
let mut buffer = BufWriter::with_capacity(
109-
self.input_buffer_size,
110-
DeflateEncoder::new(self.options, Default::default(), &mut out),
111-
);
112-
copy(&mut in_data, &mut buffer)?;
113-
buffer.into_inner()?.finish()?;
114-
out.write_all(&rolling_adler.finish().to_be_bytes())?;
115-
Ok(out.into_inner())
116-
})();
117-
let out = out.map_err(|e| PngError::new(&e.to_string()))?;
118-
if max_size.get().map(|max| max < out.len()).unwrap_or(false) {
119-
Err(PngError::DeflatedDataTooLong(out.len()))
120-
} else {
121-
Ok(out)
122-
}
123-
}
124-
}
125-
12650
impl Display for Deflaters {
12751
#[inline]
12852
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

src/deflate/zopfli_oxipng.rs

Lines changed: 7 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,18 @@
11
use crate::{PngError, PngResult};
2-
use simd_adler32::Adler32;
3-
use std::io::{Error, ErrorKind, Read};
2+
use std::num::NonZeroU8;
43

5-
pub fn deflate(data: &[u8], options: &zopfli::Options) -> PngResult<Vec<u8>> {
4+
pub fn deflate(data: &[u8], iterations: NonZeroU8) -> PngResult<Vec<u8>> {
65
use std::cmp::max;
76

87
let mut output = Vec::with_capacity(max(1024, data.len() / 20));
9-
match zopfli::compress(options, &zopfli::Format::Zlib, data, &mut output) {
8+
let options = zopfli::Options {
9+
iteration_count: iterations,
10+
..Default::default()
11+
};
12+
match zopfli::compress(&options, &zopfli::Format::Zlib, data, &mut output) {
1013
Ok(_) => (),
1114
Err(_) => return Err(PngError::new("Failed to compress in zopfli")),
1215
};
1316
output.shrink_to_fit();
1417
Ok(output)
1518
}
16-
17-
/// Forked from zopfli crate
18-
pub trait Hasher {
19-
fn update(&mut self, data: &[u8]);
20-
}
21-
22-
impl Hasher for &mut Adler32 {
23-
fn update(&mut self, data: &[u8]) {
24-
Adler32::write(self, data)
25-
}
26-
}
27-
28-
/// A reader that wraps another reader, a hasher and an optional counter,
29-
/// updating the hasher state and incrementing a counter of bytes read so
30-
/// far for each block of data read.
31-
pub struct HashingAndCountingRead<'counter, R: Read, H: Hasher> {
32-
inner: R,
33-
hasher: H,
34-
bytes_read: Option<&'counter mut u32>,
35-
}
36-
37-
impl<'counter, R: Read, H: Hasher> HashingAndCountingRead<'counter, R, H> {
38-
pub fn new(inner: R, hasher: H, bytes_read: Option<&'counter mut u32>) -> Self {
39-
Self {
40-
inner,
41-
hasher,
42-
bytes_read,
43-
}
44-
}
45-
}
46-
47-
impl<R: Read, H: Hasher> Read for HashingAndCountingRead<'_, R, H> {
48-
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
49-
match self.inner.read(buf) {
50-
Ok(bytes_read) => {
51-
self.hasher.update(&buf[..bytes_read]);
52-
53-
if let Some(total_bytes_read) = &mut self.bytes_read {
54-
**total_bytes_read = total_bytes_read
55-
.checked_add(bytes_read.try_into().map_err(|_| ErrorKind::Other)?)
56-
.ok_or(ErrorKind::Other)?;
57-
}
58-
59-
Ok(bytes_read)
60-
}
61-
Err(err) => Err(err),
62-
}
63-
}
64-
}

0 commit comments

Comments
 (0)