Merge branch 'master' into libdeflate
This commit is contained in:
commit
7c6b6152b5
10 changed files with 91 additions and 117 deletions
96
src/lib.rs
96
src/lib.rs
|
|
@ -34,7 +34,7 @@ use log::{debug, info, trace, warn};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fs::{copy, File, Metadata};
|
use std::fs::{File, Metadata};
|
||||||
use std::io::{stdin, stdout, BufWriter, Read, Write};
|
use std::io::{stdin, stdout, BufWriter, Read, Write};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
@ -76,15 +76,36 @@ pub mod internal_tests {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum OutFile {
|
pub enum OutFile {
|
||||||
/// Path(None) means same as input
|
/// Don't actually write any output, just calculate the best results.
|
||||||
Path(Option<PathBuf>),
|
None,
|
||||||
|
/// Write output to a file.
|
||||||
|
///
|
||||||
|
/// * `path`: Path to write the output file. `None` means same as input.
|
||||||
|
/// * `preserve_attrs`: Ensure the output file has the same permissions & timestamps as the input file.
|
||||||
|
Path {
|
||||||
|
path: Option<PathBuf>,
|
||||||
|
preserve_attrs: bool,
|
||||||
|
},
|
||||||
|
/// Write to standard output.
|
||||||
StdOut,
|
StdOut,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OutFile {
|
impl OutFile {
|
||||||
|
/// Construct a new `OutFile` with the given path.
|
||||||
|
///
|
||||||
|
/// This is a convenience method for `OutFile::Path { path: Some(path), preserve_attrs: false }`.
|
||||||
|
pub fn from_path(path: PathBuf) -> Self {
|
||||||
|
OutFile::Path {
|
||||||
|
path: Some(path),
|
||||||
|
preserve_attrs: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn path(&self) -> Option<&Path> {
|
pub fn path(&self) -> Option<&Path> {
|
||||||
match *self {
|
match *self {
|
||||||
OutFile::Path(Some(ref p)) => Some(p.as_path()),
|
OutFile::Path {
|
||||||
|
path: Some(ref p), ..
|
||||||
|
} => Some(p.as_path()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,30 +147,14 @@ pub type PngResult<T> = Result<T, PngError>;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
/// Options controlling the output of the `optimize` function
|
/// Options controlling the output of the `optimize` function
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
/// Whether the input file should be backed up before writing the output.
|
|
||||||
///
|
|
||||||
/// Default: `false`
|
|
||||||
pub backup: bool,
|
|
||||||
/// Attempt to fix errors when decoding the input file rather than returning an `Err`.
|
/// Attempt to fix errors when decoding the input file rather than returning an `Err`.
|
||||||
///
|
///
|
||||||
/// Default: `false`
|
/// Default: `false`
|
||||||
pub fix_errors: bool,
|
pub fix_errors: bool,
|
||||||
/// Don't actually run any optimizations, just parse the PNG file.
|
|
||||||
///
|
|
||||||
/// Default: `false`
|
|
||||||
pub check: bool,
|
|
||||||
/// Don't actually write any output, just calculate the best results.
|
|
||||||
///
|
|
||||||
/// Default: `false`
|
|
||||||
pub pretend: bool,
|
|
||||||
/// Write to output even if there was no improvement in compression.
|
/// Write to output even if there was no improvement in compression.
|
||||||
///
|
///
|
||||||
/// Default: `false`
|
/// Default: `false`
|
||||||
pub force: bool,
|
pub force: bool,
|
||||||
/// Ensure the output file has the same permissions as the input file.
|
|
||||||
///
|
|
||||||
/// Default: `false`
|
|
||||||
pub preserve_attrs: bool,
|
|
||||||
/// Which RowFilters to try on the file
|
/// Which RowFilters to try on the file
|
||||||
///
|
///
|
||||||
/// Default: `None,Sub,Entropy,Bigrams`
|
/// Default: `None,Sub,Entropy,Bigrams`
|
||||||
|
|
@ -294,12 +299,8 @@ impl Default for Options {
|
||||||
fn default() -> Options {
|
fn default() -> Options {
|
||||||
// Default settings based on -o 2 from the CLI interface
|
// Default settings based on -o 2 from the CLI interface
|
||||||
Options {
|
Options {
|
||||||
backup: false,
|
|
||||||
check: false,
|
|
||||||
pretend: false,
|
|
||||||
fix_errors: false,
|
fix_errors: false,
|
||||||
force: false,
|
force: false,
|
||||||
preserve_attrs: false,
|
|
||||||
filter: indexset! {RowFilter::None, RowFilter::Sub, RowFilter::Entropy, RowFilter::Bigrams},
|
filter: indexset! {RowFilter::None, RowFilter::Sub, RowFilter::Entropy, RowFilter::Bigrams},
|
||||||
interlace: Some(Interlacing::None),
|
interlace: Some(Interlacing::None),
|
||||||
optimize_alpha: false,
|
optimize_alpha: false,
|
||||||
|
|
@ -416,7 +417,13 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
||||||
let opt_metadata_preserved;
|
let opt_metadata_preserved;
|
||||||
let in_data = match *input {
|
let in_data = match *input {
|
||||||
InFile::Path(ref input_path) => {
|
InFile::Path(ref input_path) => {
|
||||||
if opts.preserve_attrs {
|
if matches!(
|
||||||
|
output,
|
||||||
|
OutFile::Path {
|
||||||
|
preserve_attrs: true,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
) {
|
||||||
opt_metadata_preserved = input_path
|
opt_metadata_preserved = input_path
|
||||||
.metadata()
|
.metadata()
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
|
@ -445,11 +452,6 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
||||||
|
|
||||||
let mut png = PngData::from_slice(&in_data, opts)?;
|
let mut png = PngData::from_slice(&in_data, opts)?;
|
||||||
|
|
||||||
if opts.check {
|
|
||||||
info!("Running in check mode, not optimizing");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the optimizer on the decoded PNG.
|
// Run the optimizer on the decoded PNG.
|
||||||
let mut optimized_output = optimize_png(&mut png, &in_data, opts, deadline)?;
|
let mut optimized_output = optimize_png(&mut png, &in_data, opts, deadline)?;
|
||||||
|
|
||||||
|
|
@ -458,8 +460,8 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
||||||
if is_fully_optimized(in_data.len(), optimized_output.len(), opts) {
|
if is_fully_optimized(in_data.len(), optimized_output.len(), opts) {
|
||||||
match (output, input) {
|
match (output, input) {
|
||||||
// if p is None, it also means same as the input path
|
// if p is None, it also means same as the input path
|
||||||
(OutFile::Path(ref p), InFile::Path(ref input_path))
|
(OutFile::Path { path, .. }, InFile::Path(ref input_path))
|
||||||
if p.as_ref().map_or(true, |p| p == input_path) =>
|
if path.as_ref().map_or(true, |p| p == input_path) =>
|
||||||
{
|
{
|
||||||
info!("{}: Could not optimize further, no change written", input);
|
info!("{}: Could not optimize further, no change written", input);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
@ -484,26 +486,21 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
if opts.pretend {
|
|
||||||
info!("{}: Running in pretend mode, no output", savings);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
match (output, input) {
|
match (output, input) {
|
||||||
(&OutFile::StdOut, _) | (&OutFile::Path(None), &InFile::StdIn) => {
|
(OutFile::None, _) => {
|
||||||
|
info!("{}: Running in pretend mode, no output", savings);
|
||||||
|
}
|
||||||
|
(&OutFile::StdOut, _) | (&OutFile::Path { path: None, .. }, &InFile::StdIn) => {
|
||||||
let mut buffer = BufWriter::new(stdout());
|
let mut buffer = BufWriter::new(stdout());
|
||||||
buffer
|
buffer
|
||||||
.write_all(&optimized_output)
|
.write_all(&optimized_output)
|
||||||
.map_err(|e| PngError::new(&format!("Unable to write to stdout: {}", e)))?;
|
.map_err(|e| PngError::new(&format!("Unable to write to stdout: {}", e)))?;
|
||||||
}
|
}
|
||||||
(OutFile::Path(ref output_path), _) => {
|
(OutFile::Path { path, .. }, _) => {
|
||||||
let output_path = output_path
|
let output_path = path
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|p| p.as_path())
|
.map(|p| p.as_path())
|
||||||
.unwrap_or_else(|| input.path().unwrap());
|
.unwrap_or_else(|| input.path().unwrap());
|
||||||
if opts.backup {
|
|
||||||
perform_backup(output_path)?;
|
|
||||||
}
|
|
||||||
let out_file = File::create(output_path).map_err(|err| {
|
let out_file = File::create(output_path).map_err(|err| {
|
||||||
PngError::new(&format!(
|
PngError::new(&format!(
|
||||||
"Unable to write to file {}: {}",
|
"Unable to write to file {}: {}",
|
||||||
|
|
@ -983,19 +980,6 @@ fn is_fully_optimized(original_size: usize, optimized_size: usize, opts: &Option
|
||||||
original_size <= optimized_size && !opts.force
|
original_size <= optimized_size && !opts.force
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_backup(input_path: &Path) -> PngResult<()> {
|
|
||||||
let backup_file = input_path.with_extension(format!(
|
|
||||||
"bak.{}",
|
|
||||||
input_path.extension().unwrap().to_str().unwrap()
|
|
||||||
));
|
|
||||||
copy(input_path, &backup_file).map(|_| ()).map_err(|_| {
|
|
||||||
PngError::new(&format!(
|
|
||||||
"Unable to write to backup file at {}",
|
|
||||||
backup_file.display()
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
fn copy_permissions(metadata_input: &Metadata, out_file: &File) -> PngResult<()> {
|
fn copy_permissions(metadata_input: &Metadata, out_file: &File) -> PngResult<()> {
|
||||||
let readonly_input = metadata_input.permissions().readonly();
|
let readonly_input = metadata_input.permissions().readonly();
|
||||||
|
|
|
||||||
57
src/main.rs
57
src/main.rs
|
|
@ -25,6 +25,7 @@ use oxipng::RowFilter;
|
||||||
use oxipng::StripChunks;
|
use oxipng::StripChunks;
|
||||||
use oxipng::{InFile, OutFile};
|
use oxipng::{InFile, OutFile};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use std::ffi::OsString;
|
||||||
use std::fs::DirBuilder;
|
use std::fs::DirBuilder;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
#[cfg(feature = "zopfli")]
|
#[cfg(feature = "zopfli")]
|
||||||
|
|
@ -60,11 +61,12 @@ fn main() {
|
||||||
.help("Back up modified files")
|
.help("Back up modified files")
|
||||||
.short('b')
|
.short('b')
|
||||||
.long("backup")
|
.long("backup")
|
||||||
|
.hide(true)
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("recursive")
|
Arg::new("recursive")
|
||||||
.help("Recurse into subdirectories")
|
.help("Recurse into subdirectories and optimize all *.png/*.apng files")
|
||||||
.short('r')
|
.short('r')
|
||||||
.long("recursive")
|
.long("recursive")
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
|
|
@ -102,13 +104,6 @@ fn main() {
|
||||||
.long("preserve")
|
.long("preserve")
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
.arg(
|
|
||||||
Arg::new("check")
|
|
||||||
.help("Do not run any optimization passes")
|
|
||||||
.short('c')
|
|
||||||
.long("check")
|
|
||||||
.action(ArgAction::SetTrue),
|
|
||||||
)
|
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("pretend")
|
Arg::new("pretend")
|
||||||
.help("Do not write any files, only calculate compression gains")
|
.help("Do not write any files, only calculate compression gains")
|
||||||
|
|
@ -256,7 +251,7 @@ fn main() {
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("timeout")
|
Arg::new("timeout")
|
||||||
.help("Maximum amount of time, in seconds, to spend on optimizations")
|
.help("Maximum amount of time, in seconds, to spend on optimizations (currently of limited use due to the shift away from zlib)")
|
||||||
.value_name("secs")
|
.value_name("secs")
|
||||||
.long("timeout")
|
.long("timeout")
|
||||||
.value_parser(value_parser!(u64)),
|
.value_parser(value_parser!(u64)),
|
||||||
|
|
@ -298,6 +293,11 @@ Heuristic filter selection strategies:
|
||||||
)
|
)
|
||||||
.get_matches_from(std::env::args());
|
.get_matches_from(std::env::args());
|
||||||
|
|
||||||
|
if matches.get_flag("backup") {
|
||||||
|
eprintln!("The --backup flag is no longer supported. Please use --out or --dir to preserve your existing files.");
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
let (out_file, out_dir, opts) = match parse_opts_into_struct(&matches) {
|
let (out_file, out_dir, opts) = match parse_opts_into_struct(&matches) {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(x) => {
|
Err(x) => {
|
||||||
|
|
@ -353,10 +353,10 @@ fn collect_files(
|
||||||
out_dir: &Option<PathBuf>,
|
out_dir: &Option<PathBuf>,
|
||||||
out_file: &OutFile,
|
out_file: &OutFile,
|
||||||
recursive: bool,
|
recursive: bool,
|
||||||
allow_stdin: bool,
|
top_level: bool, //explicitly specify files
|
||||||
) -> Vec<(InFile, OutFile)> {
|
) -> Vec<(InFile, OutFile)> {
|
||||||
let mut in_out_pairs = Vec::new();
|
let mut in_out_pairs = Vec::new();
|
||||||
let allow_stdin = allow_stdin && files.len() == 1;
|
let allow_stdin = top_level && files.len() == 1;
|
||||||
for input in files {
|
for input in files {
|
||||||
let using_stdin = allow_stdin && input.to_str().map_or(false, |p| p == "-");
|
let using_stdin = allow_stdin && input.to_str().map_or(false, |p| p == "-");
|
||||||
if !using_stdin && input.is_dir() {
|
if !using_stdin && input.is_dir() {
|
||||||
|
|
@ -376,15 +376,27 @@ fn collect_files(
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let out_file = if let Some(ref out_dir) = *out_dir {
|
let out_file =
|
||||||
let out_path = Some(out_dir.join(input.file_name().unwrap()));
|
if let (Some(out_dir), &OutFile::Path { preserve_attrs, .. }) = (out_dir, out_file) {
|
||||||
OutFile::Path(out_path)
|
let path = Some(out_dir.join(input.file_name().unwrap()));
|
||||||
|
OutFile::Path {
|
||||||
|
path,
|
||||||
|
preserve_attrs,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(*out_file).clone()
|
(*out_file).clone()
|
||||||
};
|
};
|
||||||
let in_file = if using_stdin {
|
let in_file = if using_stdin {
|
||||||
InFile::StdIn
|
InFile::StdIn
|
||||||
} else {
|
} else {
|
||||||
|
// Skip non png files if not given on top level
|
||||||
|
if !top_level && {
|
||||||
|
let extension = input.extension().map(|f| f.to_ascii_lowercase());
|
||||||
|
extension != Some(OsString::from("png"))
|
||||||
|
&& extension != Some(OsString::from("apng"))
|
||||||
|
} {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
InFile::Path(input)
|
InFile::Path(input)
|
||||||
};
|
};
|
||||||
in_out_pairs.push((in_file, out_file));
|
in_out_pairs.push((in_file, out_file));
|
||||||
|
|
@ -459,10 +471,15 @@ fn parse_opts_into_struct(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let out_file = if matches.get_flag("stdout") {
|
let out_file = if matches.get_flag("pretend") {
|
||||||
|
OutFile::None
|
||||||
|
} else if matches.get_flag("stdout") {
|
||||||
OutFile::StdOut
|
OutFile::StdOut
|
||||||
} else {
|
} else {
|
||||||
OutFile::Path(matches.get_one::<PathBuf>("output_file").cloned())
|
OutFile::Path {
|
||||||
|
path: matches.get_one::<PathBuf>("output_file").cloned(),
|
||||||
|
preserve_attrs: matches.get_flag("preserve"),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
opts.optimize_alpha = matches.get_flag("alpha");
|
opts.optimize_alpha = matches.get_flag("alpha");
|
||||||
|
|
@ -474,18 +491,10 @@ fn parse_opts_into_struct(
|
||||||
opts.fast_evaluation = matches.get_flag("fast");
|
opts.fast_evaluation = matches.get_flag("fast");
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.backup = matches.get_flag("backup");
|
|
||||||
|
|
||||||
opts.force = matches.get_flag("force");
|
opts.force = matches.get_flag("force");
|
||||||
|
|
||||||
opts.fix_errors = matches.get_flag("fix");
|
opts.fix_errors = matches.get_flag("fix");
|
||||||
|
|
||||||
opts.check = matches.get_flag("check");
|
|
||||||
|
|
||||||
opts.pretend = matches.get_flag("pretend");
|
|
||||||
|
|
||||||
opts.preserve_attrs = matches.get_flag("preserve");
|
|
||||||
|
|
||||||
opts.bit_depth_reduction = !matches.get_flag("no-bit-reduction");
|
opts.bit_depth_reduction = !matches.get_flag("no-bit-reduction");
|
||||||
|
|
||||||
opts.color_type_reduction = !matches.get_flag("no-color-reduction");
|
opts.color_type_reduction = !matches.get_flag("no-color-reduction");
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||||
filter.insert(RowFilter::None);
|
filter.insert(RowFilter::None);
|
||||||
options.filter = filter;
|
options.filter = filter;
|
||||||
|
|
||||||
(
|
(OutFile::from_path(input.with_extension("out.png")), options)
|
||||||
OutFile::Path(Some(input.with_extension("out.png"))),
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_it_converts(
|
fn test_it_converts(
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||||
filter.insert(RowFilter::None);
|
filter.insert(RowFilter::None);
|
||||||
options.filter = filter;
|
options.filter = filter;
|
||||||
|
|
||||||
(
|
(OutFile::from_path(input.with_extension("out.png")), options)
|
||||||
OutFile::Path(Some(input.with_extension("out.png"))),
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add callback to allow checks before the output file is deleted again
|
/// Add callback to allow checks before the output file is deleted again
|
||||||
|
|
@ -518,8 +515,10 @@ fn preserve_attrs() {
|
||||||
#[cfg(feature = "filetime")]
|
#[cfg(feature = "filetime")]
|
||||||
let mtime_canon = RefCell::new(filetime::FileTime::from_unix_time(0, 0));
|
let mtime_canon = RefCell::new(filetime::FileTime::from_unix_time(0, 0));
|
||||||
|
|
||||||
let (output, mut opts) = get_opts(&input);
|
let (mut output, opts) = get_opts(&input);
|
||||||
opts.preserve_attrs = true;
|
if let OutFile::Path { preserve_attrs, .. } = &mut output {
|
||||||
|
*preserve_attrs = true;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "filetime")]
|
#[cfg(feature = "filetime")]
|
||||||
let callback_pre = |path_in: &Path| {
|
let callback_pre = |path_in: &Path| {
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||||
filter.insert(RowFilter::None);
|
filter.insert(RowFilter::None);
|
||||||
options.filter = filter;
|
options.filter = filter;
|
||||||
|
|
||||||
(
|
(OutFile::from_path(input.with_extension("out.png")), options)
|
||||||
OutFile::Path(Some(input.with_extension("out.png"))),
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_it_converts(
|
fn test_it_converts(
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||||
filter.insert(RowFilter::None);
|
filter.insert(RowFilter::None);
|
||||||
options.filter = filter;
|
options.filter = filter;
|
||||||
|
|
||||||
(
|
(OutFile::from_path(input.with_extension("out.png")), options)
|
||||||
OutFile::Path(Some(input.with_extension("out.png"))),
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_it_converts(
|
fn test_it_converts(
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ fn optimize_from_memory_apng() {
|
||||||
fn optimize() {
|
fn optimize() {
|
||||||
let result = oxipng::optimize(
|
let result = oxipng::optimize(
|
||||||
&"tests/files/fully_optimized.png".into(),
|
&"tests/files/fully_optimized.png".into(),
|
||||||
&OutFile::Path(None),
|
&OutFile::None,
|
||||||
&Options::default(),
|
&Options::default(),
|
||||||
);
|
);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
@ -47,7 +47,7 @@ fn optimize() {
|
||||||
fn optimize_corrupted() {
|
fn optimize_corrupted() {
|
||||||
let result = oxipng::optimize(
|
let result = oxipng::optimize(
|
||||||
&"tests/files/corrupted_header.png".into(),
|
&"tests/files/corrupted_header.png".into(),
|
||||||
&OutFile::Path(None),
|
&OutFile::None,
|
||||||
&Options::default(),
|
&Options::default(),
|
||||||
);
|
);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
|
@ -57,7 +57,7 @@ fn optimize_corrupted() {
|
||||||
fn optimize_apng() {
|
fn optimize_apng() {
|
||||||
let result = oxipng::optimize(
|
let result = oxipng::optimize(
|
||||||
&"tests/files/apng_file.png".into(),
|
&"tests/files/apng_file.png".into(),
|
||||||
&OutFile::Path(None),
|
&OutFile::None,
|
||||||
&Options::from_preset(0),
|
&Options::from_preset(0),
|
||||||
);
|
);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||||
filter.insert(RowFilter::None);
|
filter.insert(RowFilter::None);
|
||||||
options.filter = filter;
|
options.filter = filter;
|
||||||
|
|
||||||
(
|
(OutFile::from_path(input.with_extension("out.png")), options)
|
||||||
OutFile::Path(Some(input.with_extension("out.png"))),
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_it_converts(
|
fn test_it_converts(
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||||
filter.insert(RowFilter::None);
|
filter.insert(RowFilter::None);
|
||||||
options.filter = filter;
|
options.filter = filter;
|
||||||
|
|
||||||
(
|
(OutFile::from_path(input.with_extension("out.png")), options)
|
||||||
OutFile::Path(Some(input.with_extension("out.png"))),
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_it_converts(
|
fn test_it_converts(
|
||||||
|
|
@ -295,7 +292,7 @@ fn issue_92_filter_5() {
|
||||||
let input = "tests/files/issue-92.png";
|
let input = "tests/files/issue-92.png";
|
||||||
let (_, mut opts) = get_opts(Path::new(input));
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
opts.filter = [RowFilter::MinSum].iter().cloned().collect();
|
opts.filter = [RowFilter::MinSum].iter().cloned().collect();
|
||||||
let output = OutFile::Path(Some(Path::new(input).with_extension("-f5-out.png")));
|
let output = OutFile::from_path(Path::new(input).with_extension("-f5-out.png"));
|
||||||
|
|
||||||
test_it_converts(
|
test_it_converts(
|
||||||
input,
|
input,
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||||
filter.insert(RowFilter::None);
|
filter.insert(RowFilter::None);
|
||||||
options.filter = filter;
|
options.filter = filter;
|
||||||
|
|
||||||
(
|
(OutFile::from_path(input.with_extension("out.png")), options)
|
||||||
OutFile::Path(Some(input.with_extension("out.png"))),
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_it_converts(
|
fn test_it_converts(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue