deflate() error handling
This commit is contained in:
parent
84d3ba417b
commit
9a98a31a46
3 changed files with 28 additions and 18 deletions
|
|
@ -13,7 +13,7 @@ pub fn inflate(data: &[u8]) -> Result<Vec<u8>, PngError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compress a data stream using the DEFLATE algorithm
|
/// Compress a data stream using the DEFLATE algorithm
|
||||||
pub fn deflate(data: &[u8], zc: u8, zs: u8, zw: u8) -> Vec<u8> {
|
pub fn deflate(data: &[u8], zc: u8, zs: u8, zw: u8) -> Result<Vec<u8>, PngError> {
|
||||||
#[cfg(feature = "cfzlib")]
|
#[cfg(feature = "cfzlib")]
|
||||||
{
|
{
|
||||||
if is_cfzlib_supported() {
|
if is_cfzlib_supported() {
|
||||||
|
|
@ -21,7 +21,7 @@ pub fn deflate(data: &[u8], zc: u8, zs: u8, zw: u8) -> Vec<u8> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
miniz_stream::compress_to_vec_oxipng(data, zc, zw.into(), zs.into())
|
Ok(miniz_stream::compress_to_vec_oxipng(data, zc, zw.into(), zs.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cfzlib")]
|
#[cfg(feature = "cfzlib")]
|
||||||
|
|
@ -40,20 +40,22 @@ fn is_cfzlib_supported() -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cfzlib")]
|
#[cfg(feature = "cfzlib")]
|
||||||
pub fn cfzlib_deflate(data: &[u8], level: u8, strategy: u8, window_bits: u8) -> Vec<u8> {
|
pub fn cfzlib_deflate(data: &[u8], level: u8, strategy: u8, window_bits: u8) -> Result<Vec<u8>, PngError> {
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use cloudflare_zlib_sys::*;
|
use cloudflare_zlib_sys::*;
|
||||||
|
|
||||||
assert!(data.len() < u32::max_value() as usize);
|
assert!(data.len() < u32::max_value() as usize);
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut stream = mem::zeroed();
|
let mut stream = mem::zeroed();
|
||||||
assert_eq!(Z_OK, deflateInit2(
|
if Z_OK != deflateInit2(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
level.into(),
|
level.into(),
|
||||||
Z_DEFLATED,
|
Z_DEFLATED,
|
||||||
window_bits.into(),
|
window_bits.into(),
|
||||||
MAX_MEM_LEVEL,
|
MAX_MEM_LEVEL,
|
||||||
strategy.into()));
|
strategy.into()) {
|
||||||
|
return Err(PngError::new("deflateInit2"));
|
||||||
|
}
|
||||||
|
|
||||||
let max_size = deflateBound(&mut stream, data.len() as uLong) as usize;
|
let max_size = deflateBound(&mut stream, data.len() as uLong) as usize;
|
||||||
// it's important to have the capacity pre-allocated,
|
// it's important to have the capacity pre-allocated,
|
||||||
|
|
@ -65,11 +67,15 @@ pub fn cfzlib_deflate(data: &[u8], level: u8, strategy: u8, window_bits: u8) ->
|
||||||
stream.avail_in = data.len() as uInt;
|
stream.avail_in = data.len() as uInt;
|
||||||
stream.next_out = out.as_mut_ptr();
|
stream.next_out = out.as_mut_ptr();
|
||||||
stream.avail_out = out.capacity() as uInt;
|
stream.avail_out = out.capacity() as uInt;
|
||||||
assert_eq!(Z_STREAM_END, deflate(&mut stream, Z_FINISH));
|
if Z_STREAM_END != deflate(&mut stream, Z_FINISH) {
|
||||||
assert_eq!(Z_OK, deflateEnd(&mut stream));
|
return Err(PngError::new("deflate"));
|
||||||
|
}
|
||||||
|
if Z_OK != deflateEnd(&mut stream) {
|
||||||
|
return Err(PngError::new("deflateEnd"));
|
||||||
|
}
|
||||||
debug_assert!(stream.total_out as usize <= out.capacity());
|
debug_assert!(stream.total_out as usize <= out.capacity());
|
||||||
out.set_len(stream.total_out as usize);
|
out.set_len(stream.total_out as usize);
|
||||||
return out;
|
return Ok(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -501,7 +501,10 @@ fn optimize_png(
|
||||||
let new_idat = if opts.deflate == Deflaters::Zlib {
|
let new_idat = if opts.deflate == Deflaters::Zlib {
|
||||||
deflate::deflate(filtered, trial.compression, trial.strategy, opts.window)
|
deflate::deflate(filtered, trial.compression, trial.strategy, opts.window)
|
||||||
} else {
|
} else {
|
||||||
deflate::zopfli_deflate(filtered).unwrap()
|
deflate::zopfli_deflate(filtered)
|
||||||
|
};
|
||||||
|
let new_idat = if let Ok(n) = new_idat {n} else {
|
||||||
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
if opts.verbosity == Some(1) {
|
if opts.verbosity == Some(1) {
|
||||||
|
|
|
||||||
|
|
@ -603,28 +603,29 @@ impl PngData {
|
||||||
assert!(!alphas.is_empty());
|
assert!(!alphas.is_empty());
|
||||||
let best = alphas
|
let best = alphas
|
||||||
.iter()
|
.iter()
|
||||||
.map(|alpha| {
|
.filter_map(|alpha| {
|
||||||
let mut image = self.clone();
|
let mut image = self.clone();
|
||||||
image.reduce_alpha_channel(*alpha);
|
image.reduce_alpha_channel(*alpha);
|
||||||
let size = STD_FILTERS
|
STD_FILTERS
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| {
|
.filter_map(|f| {
|
||||||
deflate::deflate(
|
deflate::deflate(
|
||||||
&image.filter_image(*f),
|
&image.filter_image(*f),
|
||||||
STD_COMPRESSION,
|
STD_COMPRESSION,
|
||||||
STD_STRATEGY,
|
STD_STRATEGY,
|
||||||
STD_WINDOW,
|
STD_WINDOW,
|
||||||
).len()
|
).ok()
|
||||||
|
.as_ref().map(|l| l.len())
|
||||||
})
|
})
|
||||||
.min()
|
.min()
|
||||||
.unwrap();
|
.map(|size| (size, image))
|
||||||
(size, image)
|
|
||||||
})
|
})
|
||||||
.min_by_key(|&(size, _)| size)
|
.min_by_key(|&(size, _)| size);
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
|
if let Some(best) = best {
|
||||||
self.raw_data = best.1.raw_data;
|
self.raw_data = best.1.raw_data;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reduce_alpha_channel(&mut self, optim: AlphaOptim) -> bool {
|
pub fn reduce_alpha_channel(&mut self, optim: AlphaOptim) -> bool {
|
||||||
let (bpc, bpp) = match self.ihdr_data.color_type {
|
let (bpc, bpp) = match self.ihdr_data.color_type {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue