parent
e4cd9b85e7
commit
3a39b13acf
7 changed files with 54 additions and 139 deletions
|
|
@ -2,6 +2,7 @@
|
|||
- Minor compression improvement on interlaced images
|
||||
- Performance optimizations
|
||||
- [SEMVER_MINOR] Move default Options into a Default impl
|
||||
- [SEMVER_MINOR] Add option for setting number of threads ([#39](https://github.com/shssoichiro/oxipng/issues/39))
|
||||
|
||||
**Version 0.6.0**
|
||||
- Fix issue where output directory would not be created if it did not exist
|
||||
|
|
|
|||
11
src/lib.rs
11
src/lib.rs
|
|
@ -79,6 +79,8 @@ pub struct Options {
|
|||
/// Whether to use heuristics to pick the best filter and compression
|
||||
/// Intended for use with `-o 1` from the CLI interface
|
||||
pub use_heuristics: bool,
|
||||
/// Number of threads to use, defaults to 1.5x CPU cores, rounded down
|
||||
pub threads: usize,
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
|
|
@ -96,6 +98,10 @@ impl Default for Options {
|
|||
strategies.insert(i);
|
||||
}
|
||||
|
||||
// Default to 1 thread on single-core, otherwise use threads = 1.5x CPU cores
|
||||
let num_cpus = num_cpus::get();
|
||||
let thread_count = num_cpus + (num_cpus >> 1);
|
||||
|
||||
Options {
|
||||
backup: false,
|
||||
out_file: PathBuf::new(),
|
||||
|
|
@ -121,6 +127,7 @@ impl Default for Options {
|
|||
idat_recoding: true,
|
||||
strip: png::Headers::None,
|
||||
use_heuristics: false,
|
||||
threads: thread_count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -200,9 +207,7 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> {
|
|||
let something_changed = perform_reductions(&mut png, &opts);
|
||||
|
||||
if opts.idat_recoding || something_changed {
|
||||
// Use 1 thread on single-core, otherwise use threads = 1.5x CPU cores
|
||||
let num_cpus = num_cpus::get();
|
||||
let thread_count = num_cpus + (num_cpus >> 1);
|
||||
let thread_count = opts.threads;
|
||||
let pool = Pool::new(thread_count);
|
||||
// Go through selected permutations and determine the best
|
||||
let best: Arc<Mutex<Option<TrialWithData>>> = Arc::new(Mutex::new(None));
|
||||
|
|
|
|||
21
src/main.rs
21
src/main.rs
|
|
@ -172,6 +172,23 @@ fn main() {
|
|||
.help("Strip safely-removable metadata objects")
|
||||
.short("s")
|
||||
.conflicts_with("strip"))
|
||||
.arg(Arg::with_name("threads")
|
||||
.help("Set number of threads to use - default 1.5x CPU cores")
|
||||
.long("threads")
|
||||
.short("t")
|
||||
.takes_value(true)
|
||||
.validator(|x| {
|
||||
match x.parse::<usize>() {
|
||||
Ok(val) => {
|
||||
if val > 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("Thread count must be >= 1".to_owned())
|
||||
}
|
||||
}
|
||||
Err(_) => Err("Thread count must be >= 1".to_owned()),
|
||||
}
|
||||
}))
|
||||
.after_help("Optimization levels:
|
||||
-o 0 => --zc 3 --nz (0 or 1 trials)
|
||||
-o 1 => --zc 9 (1 trial, determined heuristically)
|
||||
|
|
@ -478,6 +495,10 @@ fn parse_opts_into_struct(matches: &ArgMatches, opts: &mut oxipng::Options) -> R
|
|||
opts.strip = png::Headers::Safe;
|
||||
}
|
||||
|
||||
if let Some(x) = matches.value_of("threads") {
|
||||
opts.threads = x.parse::<usize>().unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,43 +10,15 @@ use std::path::Path;
|
|||
use std::path::PathBuf;
|
||||
|
||||
fn get_opts(input: &Path) -> oxipng::Options {
|
||||
let mut options = oxipng::Options::default();
|
||||
options.out_file = input.with_extension("out.png").to_owned();
|
||||
options.verbosity = None;
|
||||
options.force = true;
|
||||
let mut filter = HashSet::new();
|
||||
filter.insert(0);
|
||||
let mut compression = HashSet::new();
|
||||
compression.insert(9);
|
||||
let mut memory = HashSet::new();
|
||||
memory.insert(9);
|
||||
let mut strategies = HashSet::new();
|
||||
for i in 0..4 {
|
||||
strategies.insert(i);
|
||||
}
|
||||
options.filter = filter;
|
||||
|
||||
oxipng::Options {
|
||||
backup: false,
|
||||
out_file: input.with_extension("out.png").to_owned(),
|
||||
out_dir: None,
|
||||
stdout: false,
|
||||
pretend: false,
|
||||
recursive: false,
|
||||
fix_errors: false,
|
||||
force: true,
|
||||
clobber: true,
|
||||
create: true,
|
||||
preserve_attrs: false,
|
||||
verbosity: None,
|
||||
filter: filter,
|
||||
interlace: None,
|
||||
compression: compression,
|
||||
memory: memory,
|
||||
strategies: strategies,
|
||||
window: 15,
|
||||
bit_depth_reduction: true,
|
||||
color_type_reduction: true,
|
||||
palette_reduction: true,
|
||||
idat_recoding: true,
|
||||
strip: png::Headers::None,
|
||||
use_heuristics: false,
|
||||
}
|
||||
options
|
||||
}
|
||||
|
||||
fn test_it_converts(input: &Path,
|
||||
|
|
|
|||
|
|
@ -10,43 +10,15 @@ use std::path::Path;
|
|||
use std::path::PathBuf;
|
||||
|
||||
fn get_opts(input: &Path) -> oxipng::Options {
|
||||
let mut options = oxipng::Options::default();
|
||||
options.out_file = input.with_extension("out.png").to_owned();
|
||||
options.verbosity = None;
|
||||
options.force = true;
|
||||
let mut filter = HashSet::new();
|
||||
filter.insert(0);
|
||||
let mut compression = HashSet::new();
|
||||
compression.insert(9);
|
||||
let mut memory = HashSet::new();
|
||||
memory.insert(9);
|
||||
let mut strategies = HashSet::new();
|
||||
for i in 0..4 {
|
||||
strategies.insert(i);
|
||||
}
|
||||
options.filter = filter;
|
||||
|
||||
oxipng::Options {
|
||||
backup: false,
|
||||
out_file: input.with_extension("out.png").to_owned(),
|
||||
out_dir: None,
|
||||
stdout: false,
|
||||
pretend: false,
|
||||
recursive: false,
|
||||
fix_errors: false,
|
||||
force: true,
|
||||
clobber: true,
|
||||
create: true,
|
||||
preserve_attrs: false,
|
||||
verbosity: None,
|
||||
filter: filter,
|
||||
interlace: None,
|
||||
compression: compression,
|
||||
memory: memory,
|
||||
strategies: strategies,
|
||||
window: 15,
|
||||
bit_depth_reduction: true,
|
||||
color_type_reduction: true,
|
||||
palette_reduction: true,
|
||||
idat_recoding: true,
|
||||
strip: png::Headers::None,
|
||||
use_heuristics: false,
|
||||
}
|
||||
options
|
||||
}
|
||||
|
||||
fn test_it_converts(input: &Path,
|
||||
|
|
|
|||
|
|
@ -10,43 +10,15 @@ use std::path::Path;
|
|||
use std::path::PathBuf;
|
||||
|
||||
fn get_opts(input: &Path) -> oxipng::Options {
|
||||
let mut options = oxipng::Options::default();
|
||||
options.out_file = input.with_extension("out.png").to_owned();
|
||||
options.verbosity = None;
|
||||
options.force = true;
|
||||
let mut filter = HashSet::new();
|
||||
filter.insert(0);
|
||||
let mut compression = HashSet::new();
|
||||
compression.insert(9);
|
||||
let mut memory = HashSet::new();
|
||||
memory.insert(9);
|
||||
let mut strategies = HashSet::new();
|
||||
for i in 0..4 {
|
||||
strategies.insert(i);
|
||||
}
|
||||
options.filter = filter;
|
||||
|
||||
oxipng::Options {
|
||||
backup: false,
|
||||
out_file: input.with_extension("out.png").to_owned(),
|
||||
out_dir: None,
|
||||
stdout: false,
|
||||
pretend: false,
|
||||
recursive: false,
|
||||
fix_errors: false,
|
||||
force: true,
|
||||
clobber: true,
|
||||
create: true,
|
||||
preserve_attrs: false,
|
||||
verbosity: None,
|
||||
filter: filter,
|
||||
interlace: None,
|
||||
compression: compression,
|
||||
memory: memory,
|
||||
strategies: strategies,
|
||||
window: 15,
|
||||
bit_depth_reduction: true,
|
||||
color_type_reduction: true,
|
||||
palette_reduction: true,
|
||||
idat_recoding: true,
|
||||
strip: png::Headers::None,
|
||||
use_heuristics: false,
|
||||
}
|
||||
options
|
||||
}
|
||||
|
||||
fn test_it_converts(input: &Path,
|
||||
|
|
|
|||
|
|
@ -10,43 +10,15 @@ use std::path::Path;
|
|||
use std::path::PathBuf;
|
||||
|
||||
fn get_opts(input: &Path) -> oxipng::Options {
|
||||
let mut options = oxipng::Options::default();
|
||||
options.out_file = input.with_extension("out.png").to_owned();
|
||||
options.verbosity = None;
|
||||
options.force = true;
|
||||
let mut filter = HashSet::new();
|
||||
filter.insert(0);
|
||||
let mut compression = HashSet::new();
|
||||
compression.insert(9);
|
||||
let mut memory = HashSet::new();
|
||||
memory.insert(9);
|
||||
let mut strategies = HashSet::new();
|
||||
for i in 0..4 {
|
||||
strategies.insert(i);
|
||||
}
|
||||
options.filter = filter;
|
||||
|
||||
oxipng::Options {
|
||||
backup: false,
|
||||
out_file: input.with_extension("out.png").to_owned(),
|
||||
out_dir: None,
|
||||
stdout: false,
|
||||
pretend: false,
|
||||
recursive: false,
|
||||
fix_errors: false,
|
||||
force: true,
|
||||
clobber: true,
|
||||
create: true,
|
||||
preserve_attrs: false,
|
||||
verbosity: None,
|
||||
filter: filter,
|
||||
interlace: None,
|
||||
compression: compression,
|
||||
memory: memory,
|
||||
strategies: strategies,
|
||||
window: 15,
|
||||
bit_depth_reduction: true,
|
||||
color_type_reduction: true,
|
||||
palette_reduction: true,
|
||||
idat_recoding: true,
|
||||
strip: png::Headers::None,
|
||||
use_heuristics: false,
|
||||
}
|
||||
options
|
||||
}
|
||||
|
||||
fn test_it_converts(input: &Path,
|
||||
|
|
|
|||
Loading…
Reference in a new issue