Convert results to return a PngError

Closes #44
This commit is contained in:
Josh Holmer 2016-08-15 22:22:36 -04:00
parent 723c0c29fb
commit d99db3ad23
13 changed files with 129 additions and 96 deletions

View file

@ -11,7 +11,7 @@ matrix:
env: TARGET=x86_64-apple-darwin
cache: cargo
- os: linux
rust: 1.8.0
rust: 1.9.0
env: TARGET=x86_64-unknown-linux-gnu
cache: cargo
- os: linux

View file

@ -1,6 +1,7 @@
**Version 0.11.0 (unreleased)**
- [SEMVER_MAJOR] Bump minimum rustc version to 1.8.0, required by dependencies
- [SEMVER_MAJOR] Bump minimum rustc version to 1.9.0, required by dependencies
- [SEMVER_MINOR] Allow calling optimization presets via crate using `Options::from_preset`
- [SEMVER_MAJOR] Return proper `PngError` type which implements `std::error::Error` from `Result`s
**Version 0.10.0**
- [SEMVER_MINOR] Make clap and regex dependencies optional

48
Cargo.lock generated
View file

@ -7,9 +7,9 @@ dependencies = [
"clap 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
"crc 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -52,7 +52,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"term_size 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -73,7 +73,7 @@ version = "0.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quine-mc_cluskey 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -91,7 +91,7 @@ dependencies = [
[[package]]
name = "crossbeam"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -107,7 +107,7 @@ name = "flate2"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -123,7 +123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "image"
version = "0.10.1"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -142,7 +142,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itertools"
version = "0.4.17"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -161,7 +161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.14"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -170,7 +170,7 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -184,7 +184,7 @@ name = "memchr"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -193,7 +193,7 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -260,7 +260,7 @@ name = "num_cpus"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -281,7 +281,7 @@ dependencies = [
[[package]]
name = "quine-mc_cluskey"
version = "0.2.3"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -289,7 +289,7 @@ name = "rand"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -320,7 +320,7 @@ name = "scoped-pool"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"variance 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -353,7 +353,7 @@ name = "term_size"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -362,7 +362,7 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -426,17 +426,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum clippy 0.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "4eb4e734b771514b74b44e0d04e176e572d6e0637e32fe112331a0063a22ef39"
"checksum clippy_lints 0.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "cd863204278a2011c4bf82417e7e8b869afd949410ce8d0dab14da2c79b96af9"
"checksum crc 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a3f9159e74024e2cdb6f574e9117cdc2e91523a890930a022823d17abedc90a"
"checksum crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fb974f835e90390c5f9dfac00f05b06dc117299f5ea4e85fbc7bb443af4911cc"
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
"checksum enum_primitive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f79eff5be92a4d7d5bddf7daa7d650717ea71628634efe6ca7bcda85b2183c23"
"checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb"
"checksum gcc 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "dcb000abd6df9df4c637f75190297ebe56c1d7e66b56bbf3b4aa7aece15f61a2"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum image 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7cd7efa3558b1acd537f2a6f9bcf15c4ae4842da38d2e2ea7c9ad023f36239b"
"checksum image 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "559d5ebbe9ec73111799e49c07717944b244f8accf5de33a8a8128bc3ecd2e00"
"checksum inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7e0062d2dc2f17d2f13750d95316ae8a2ff909af0fda957084f5defd87c43bb"
"checksum itertools 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7ddb83e0e9730d830afba4e6839077948b4efa22075f7cd80a3867ec286c610f"
"checksum itertools 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6f15d694e7f7d46ef7a6951db981b33f132472f91d11b5a0f44d3980b87ccbc3"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
"checksum libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "39dfaaa0f4da0f1a06876c5d94329d739ad0150868069cc235f1ddf80a0480e7"
"checksum libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "23e3757828fa702a20072c37ff47938e9dd331b92fac6e223d26d4b7a55f7ee2"
"checksum libz-sys 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ab80d82d16acfbf5c0e731297db302378896c0cffbc428dddc61d995a82e15cf"
"checksum matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "15305656809ce5a4805b1ff2946892810992197ce1270ff79baded852187942e"
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
@ -451,7 +451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum num_cpus 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a859041cbf7a70ea1ece4b87d1a2c6ef364dcb68749c88db1f97304b9ec09d5f"
"checksum pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8cee804ecc7eaf201a4a207241472cc870e825206f6c031e3ee2a72fa425f2fa"
"checksum png 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "06208e2ee243e3118a55dda9318f821f206d8563fb8d4df258767f8e62bb0997"
"checksum quine-mc_cluskey 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f9a75e9319beed349f32bb252bcd7cafe4cce6c57a9ddcc9a8ffd3c49c3659"
"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
"checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2"
"checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199"

View file

@ -27,7 +27,7 @@ cp target/release/oxipng /usr/local/bin
Please note that zlib is a required build dependency. Oxipng should work with any 1.x version of zlib,
but you are advised to use the latest version (currently 1.2.8) for security and bug fixes.
The current minimum supported Rust version is **1.8.0**. Oxipng may compile on earlier versions of Rust,
The current minimum supported Rust version is **1.9.0**. Oxipng may compile on earlier versions of Rust,
but there is no guarantee.
Oxipng follows Semantic Versioning.

View file

@ -1,10 +1,11 @@
use error::PngError;
use libz_sys;
use miniz_sys;
use libc::c_int;
use std::cmp::max;
/// Decompress a data stream using the DEFLATE algorithm
pub fn inflate(data: &[u8]) -> Result<Vec<u8>, String> {
pub fn inflate(data: &[u8]) -> Result<Vec<u8>, PngError> {
let mut input = data.to_owned();
let mut stream = super::libz_stream::Stream::new_decompress();
let mut output = Vec::with_capacity(data.len());
@ -12,7 +13,7 @@ pub fn inflate(data: &[u8]) -> Result<Vec<u8>, String> {
match stream.decompress_vec(input.as_mut(), output.as_mut()) {
libz_sys::Z_OK => output.reserve(data.len()),
libz_sys::Z_STREAM_END => break,
c => return Err(format!("Error code on decompress: {}", c)),
c => return Err(PngError::new(&format!("Error code on decompress: {}", c))),
}
}
output.shrink_to_fit();
@ -21,7 +22,7 @@ pub fn inflate(data: &[u8]) -> Result<Vec<u8>, String> {
}
/// Compress a data stream using the zlib implementation of the DEFLATE algorithm
pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result<Vec<u8>, String> {
pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result<Vec<u8>, PngError> {
let mut input = data.to_owned();
// Compressed input should be smaller than decompressed, so allocate less than data.len()
// However, it needs a minimum capacity in order to handle very small images
@ -36,7 +37,7 @@ pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result<Vec<u8>, S
match stream.compress_vec(input.as_mut(), output.as_mut()) {
miniz_sys::MZ_OK => output.reserve(max(1024, data.len() / 20)),
miniz_sys::MZ_STREAM_END => break,
c => return Err(format!("Error code on compress: {}", c)),
c => return Err(PngError::new(&format!("Error code on compress: {}", c))),
}
}
} else {
@ -49,7 +50,7 @@ pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result<Vec<u8>, S
match stream.compress_vec(input.as_mut(), output.as_mut()) {
libz_sys::Z_OK => output.reserve(max(1024, data.len() / 20)),
libz_sys::Z_STREAM_END => break,
c => return Err(format!("Error code on compress: {}", c)),
c => return Err(PngError::new(&format!("Error code on compress: {}", c))),
}
}
}

25
src/error.rs Normal file
View file

@ -0,0 +1,25 @@
use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub struct PngError {
description: String,
}
impl Error for PngError {
fn description(&self) -> &str {
&self.description
}
}
impl fmt::Display for PngError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.description)
}
}
impl PngError {
pub fn new(description: &str) -> PngError {
PngError { description: description.to_owned() }
}
}

View file

@ -1,6 +1,7 @@
use byteorder::{BigEndian, ReadBytesExt};
use colors::{BitDepth, ColorType};
use crc::crc32;
use error::PngError;
use std::io::Cursor;
#[derive(Debug, Clone, Copy)]
@ -45,7 +46,7 @@ pub fn file_header_is_valid(bytes: &[u8]) -> bool {
pub fn parse_next_header(byte_data: &[u8],
byte_offset: &mut usize,
fix_errors: bool)
-> Result<Option<(String, Vec<u8>)>, String> {
-> Result<Option<(String, Vec<u8>)>, PngError> {
let mut rdr = Cursor::new(byte_data.iter()
.skip(*byte_offset)
.take(4)
@ -53,14 +54,14 @@ pub fn parse_next_header(byte_data: &[u8],
.collect::<Vec<u8>>());
let length: u32 = match rdr.read_u32::<BigEndian>() {
Ok(x) => x,
Err(_) => return Err("Invalid data found--unable to read PNG file".to_owned()),
Err(_) => return Err(PngError::new("Invalid data found; unable to read PNG file")),
};
*byte_offset += 4;
let mut header_bytes: Vec<u8> = byte_data.iter().skip(*byte_offset).take(4).cloned().collect();
let header = match String::from_utf8(header_bytes.clone()) {
Ok(x) => x,
Err(_) => return Err("Invalid data found--unable to read PNG file".to_owned()),
Err(_) => return Err(PngError::new("Invalid data found; unable to read PNG file")),
};
if header == "IEND" {
// End of data
@ -81,19 +82,19 @@ pub fn parse_next_header(byte_data: &[u8],
.collect::<Vec<u8>>());
let crc: u32 = match rdr.read_u32::<BigEndian>() {
Ok(x) => x,
Err(_) => return Err("Invalid data found--unable to read PNG file".to_owned()),
Err(_) => return Err(PngError::new("Invalid data found; unable to read PNG file")),
};
*byte_offset += 4;
header_bytes.extend(data.clone());
if !fix_errors && crc32::checksum_ieee(header_bytes.as_ref()) != crc {
return Err(format!("Corrupt data chunk found--CRC Mismatch in {}\nThis may be recoverable by using --fix",
header));
return Err(PngError::new(&format!("CRC Mismatch in {} header; May be recoverable by using --fix",
header)));
}
Ok(Some((header, data)))
}
pub fn parse_ihdr_header(byte_data: &[u8]) -> Result<IhdrData, String> {
pub fn parse_ihdr_header(byte_data: &[u8]) -> Result<IhdrData, PngError> {
let mut rdr = Cursor::new(&byte_data[0..8]);
Ok(IhdrData {
color_type: match byte_data[9] {
@ -102,7 +103,7 @@ pub fn parse_ihdr_header(byte_data: &[u8]) -> Result<IhdrData, String> {
3 => ColorType::Indexed,
4 => ColorType::GrayscaleAlpha,
6 => ColorType::RGBA,
_ => return Err("Unexpected color type in header".to_owned()),
_ => return Err(PngError::new("Unexpected color type in header")),
},
bit_depth: match byte_data[8] {
1 => BitDepth::One,
@ -110,7 +111,7 @@ pub fn parse_ihdr_header(byte_data: &[u8]) -> Result<IhdrData, String> {
4 => BitDepth::Four,
8 => BitDepth::Eight,
16 => BitDepth::Sixteen,
_ => return Err("Unexpected bit depth in header".to_owned()),
_ => return Err(PngError::new("Unexpected bit depth in header")),
},
width: rdr.read_u32::<BigEndian>().unwrap(),
height: rdr.read_u32::<BigEndian>().unwrap(),

View file

@ -8,6 +8,7 @@ extern crate miniz_sys;
extern crate num_cpus;
extern crate scoped_pool;
use error::PngError;
use headers::Headers;
use scoped_pool::Pool;
use std::collections::{HashMap, HashSet};
@ -22,6 +23,7 @@ pub mod deflate {
pub mod libz_stream;
pub mod miniz_stream;
}
mod error;
mod filters;
pub mod headers;
mod interlace;
@ -270,7 +272,7 @@ impl Default for Options {
}
/// Perform optimization on the input file using the options provided
pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> {
pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
// Read in the file and try to decode as PNG.
if opts.verbosity.is_some() {
writeln!(&mut stderr(), "Processing: {}", filepath.to_str().unwrap()).ok();
@ -305,8 +307,8 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> {
.unwrap()))) {
Ok(x) => x,
Err(_) => {
return Err(format!("Unable to write to backup file at {}",
opts.out_file.display()))
return Err(PngError::new(&format!("Unable to write to backup file at {}",
opts.out_file.display())))
}
};
}
@ -315,13 +317,14 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> {
let mut buffer = BufWriter::new(stdout());
match buffer.write_all(&optimized_output) {
Ok(_) => (),
Err(_) => return Err("Unable to write to stdout".to_owned()),
Err(_) => return Err(PngError::new("Unable to write to stdout")),
}
} else {
let out_file = match File::create(&opts.out_file) {
Ok(x) => x,
Err(_) => {
return Err(format!("Unable to write to file {}", opts.out_file.display()))
return Err(PngError::new(&format!("Unable to write to file {}",
opts.out_file.display())))
}
};
@ -377,7 +380,8 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> {
}
}
Err(_) => {
return Err(format!("Unable to write to file {}", opts.out_file.display()))
return Err(PngError::new(&format!("Unable to write to file {}",
opts.out_file.display())))
}
}
}
@ -387,7 +391,7 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> {
/// Perform optimization on the input file using the options provided, where the file is already
/// loaded in-memory
pub fn optimize_from_memory(data: &[u8], opts: &Options) -> Result<Vec<u8>, String> {
pub fn optimize_from_memory(data: &[u8], opts: &Options) -> Result<Vec<u8>, PngError> {
// Read in the file and try to decode as PNG.
if opts.verbosity.is_some() {
writeln!(&mut stderr(), "Processing from memory").ok();

View file

@ -2,6 +2,7 @@ use bit_vec::BitVec;
use byteorder::{BigEndian, WriteBytesExt};
use colors::{BitDepth, ColorType};
use crc::crc32;
use error::PngError;
use filters::*;
use headers::*;
use interlace::{interlace_image, deinterlace_image};
@ -181,28 +182,28 @@ pub struct PngData {
impl PngData {
/// Create a new `PngData` struct by opening a file
pub fn new(filepath: &Path, fix_errors: bool) -> Result<PngData, String> {
pub fn new(filepath: &Path, fix_errors: bool) -> Result<PngData, PngError> {
let mut file = match File::open(filepath) {
Ok(f) => f,
Err(_) => return Err("Failed to open file for reading".to_owned()),
Err(_) => return Err(PngError::new("Failed to open file for reading")),
};
let mut byte_data: Vec<u8> = Vec::new();
// Read raw png data into memory
match file.read_to_end(&mut byte_data) {
Ok(_) => (),
Err(_) => return Err("Failed to read from file".to_owned()),
Err(_) => return Err(PngError::new("Failed to read from file")),
}
PngData::from_slice(&byte_data, fix_errors)
}
/// Create a new `PngData` struct by reading a slice
pub fn from_slice(byte_data: &[u8], fix_errors: bool) -> Result<PngData, String> {
pub fn from_slice(byte_data: &[u8], fix_errors: bool) -> Result<PngData, PngError> {
let mut byte_offset: usize = 0;
// Test that png header is valid
let header: Vec<u8> = byte_data.iter().take(8).cloned().collect();
if !file_header_is_valid(header.as_ref()) {
return Err("Invalid PNG header detected".to_owned());
return Err(PngError::new("Invalid PNG header detected"));
}
byte_offset += 8;
// Read the data headers
@ -226,10 +227,10 @@ impl PngData {
}
// Parse the headers into our PngData
if idat_headers.is_empty() {
return Err("Image data was empty, skipping".to_owned());
return Err(PngError::new("Image data was empty, skipping"));
}
if aux_headers.get("IHDR").is_none() {
return Err("Image header data was missing, skipping".to_owned());
return Err(PngError::new("Image header data was missing, skipping"));
}
let ihdr_header = match parse_ihdr_header(aux_headers.remove("IHDR").unwrap().as_ref()) {
Ok(x) => x,
@ -388,11 +389,7 @@ impl PngData {
// http://www.libpng.org/pub/png/book/chapter09.html
let mut trials: HashMap<u8, Vec<u8>> = HashMap::with_capacity(5);
// Avoid vertical filtering on first line of each interlacing pass
for filter in if last_pass == line.pass {
0..5
} else {
0..2
} {
for filter in if last_pass == line.pass { 0..5 } else { 0..2 } {
trials.insert(filter, filter_line(filter, bpp, &line.data, &last_line));
}
let (best_filter, best_line) = trials.iter()

View file

@ -6,6 +6,7 @@ use image::Pixel;
use oxipng::colors::{BitDepth, ColorType};
use oxipng::png;
use std::collections::HashSet;
use std::error::Error;
use std::fs::remove_file;
use std::path::Path;
use std::path::PathBuf;
@ -36,7 +37,7 @@ fn test_it_converts(input: &Path,
match oxipng::optimize(input, opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -44,7 +45,7 @@ fn test_it_converts(input: &Path,
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};

View file

@ -7,6 +7,7 @@ use oxipng::colors::{BitDepth, ColorType};
use oxipng::headers::Headers;
use oxipng::png;
use std::collections::HashSet;
use std::error::Error;
use std::fs::remove_file;
use std::path::Path;
use std::path::PathBuf;
@ -37,7 +38,7 @@ fn test_it_converts(input: &Path,
match oxipng::optimize(input, opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -45,7 +46,7 @@ fn test_it_converts(input: &Path,
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -93,7 +94,7 @@ fn strip_headers_list() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -101,7 +102,7 @@ fn strip_headers_list() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -134,7 +135,7 @@ fn strip_headers_safe() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -142,7 +143,7 @@ fn strip_headers_safe() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -175,7 +176,7 @@ fn strip_headers_all() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -183,7 +184,7 @@ fn strip_headers_all() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -216,7 +217,7 @@ fn strip_headers_none() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -224,7 +225,7 @@ fn strip_headers_none() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -255,7 +256,7 @@ fn interlacing_0_to_1() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -263,7 +264,7 @@ fn interlacing_0_to_1() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -292,7 +293,7 @@ fn interlacing_1_to_0() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -300,7 +301,7 @@ fn interlacing_1_to_0() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -331,7 +332,7 @@ fn interlacing_0_to_1_small_files() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -339,7 +340,7 @@ fn interlacing_0_to_1_small_files() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -372,7 +373,7 @@ fn interlacing_1_to_0_small_files() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -380,7 +381,7 @@ fn interlacing_1_to_0_small_files() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -414,7 +415,7 @@ fn interlaced_0_to_1_other_filter_mode() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -422,7 +423,7 @@ fn interlaced_0_to_1_other_filter_mode() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -470,7 +471,7 @@ fn fix_errors() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -478,7 +479,7 @@ fn fix_errors() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -504,7 +505,7 @@ fn issue_42() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -512,7 +513,7 @@ fn issue_42() {
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};

View file

@ -6,6 +6,7 @@ use image::Pixel;
use oxipng::colors::{BitDepth, ColorType};
use oxipng::png;
use std::collections::HashSet;
use std::error::Error;
use std::fs::remove_file;
use std::path::Path;
use std::path::PathBuf;
@ -37,7 +38,7 @@ fn test_it_converts(input: &Path,
match oxipng::optimize(input, opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -45,7 +46,7 @@ fn test_it_converts(input: &Path,
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};

View file

@ -6,6 +6,7 @@ use image::Pixel;
use oxipng::colors::{BitDepth, ColorType};
use oxipng::png;
use std::collections::HashSet;
use std::error::Error;
use std::fs::remove_file;
use std::path::Path;
use std::path::PathBuf;
@ -37,7 +38,7 @@ fn test_it_converts(input: &Path,
match oxipng::optimize(input, opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -45,7 +46,7 @@ fn test_it_converts(input: &Path,
Ok(x) => x,
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -1247,7 +1248,7 @@ fn palette_should_be_reduced_with_dupes() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -1255,7 +1256,7 @@ fn palette_should_be_reduced_with_dupes() {
Ok(x) => x,
Err(x) => {
remove_file(&output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -1287,7 +1288,7 @@ fn palette_should_be_reduced_with_unused() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -1295,7 +1296,7 @@ fn palette_should_be_reduced_with_unused() {
Ok(x) => x,
Err(x) => {
remove_file(&output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};
@ -1327,7 +1328,7 @@ fn palette_should_be_reduced_with_both() {
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned()),
Err(x) => panic!(x.description().to_owned()),
};
assert!(output.exists());
@ -1335,7 +1336,7 @@ fn palette_should_be_reduced_with_both() {
Ok(x) => x,
Err(x) => {
remove_file(&output).ok();
panic!(x.to_owned())
panic!(x.description().to_owned())
}
};