Make Rayon an optional dependency (#112)
On WebAssembly, Rayon does not work (thread pool fails to initialize since threads are stubbed out).
This commit is contained in:
parent
2d303f5dc2
commit
ae65e4be8d
3 changed files with 44 additions and 15 deletions
|
|
@ -32,10 +32,13 @@ byteorder = "^1.0.0"
|
|||
crc = "^1.2.0"
|
||||
itertools = "^0.7.7"
|
||||
num_cpus = "^1.0.0"
|
||||
rayon = "^1.0.0"
|
||||
zopfli = "^0.3.4"
|
||||
miniz_oxide = "0.1.2"
|
||||
|
||||
[dependencies.rayon]
|
||||
optional = true
|
||||
version = "^1.0.0"
|
||||
|
||||
[dependencies.clap]
|
||||
optional = true
|
||||
version = "^2.10.0"
|
||||
|
|
@ -62,7 +65,8 @@ binary = [
|
|||
"clap",
|
||||
"wild",
|
||||
]
|
||||
default = ["binary"]
|
||||
default = ["binary", "parallel"]
|
||||
parallel = ["rayon"]
|
||||
cfzlib = ["cloudflare-zlib-sys"]
|
||||
dev = [
|
||||
"nightly-binary",
|
||||
|
|
|
|||
34
src/lib.rs
34
src/lib.rs
|
|
@ -8,6 +8,7 @@ extern crate image;
|
|||
extern crate itertools;
|
||||
extern crate miniz_oxide;
|
||||
extern crate num_cpus;
|
||||
#[cfg(feature = "parallel")]
|
||||
extern crate rayon;
|
||||
extern crate zopfli;
|
||||
#[cfg(feature = "cfzlib")]
|
||||
|
|
@ -15,6 +16,7 @@ extern crate cloudflare_zlib_sys;
|
|||
|
||||
use image::{DynamicImage, GenericImage, ImageFormat, Pixel};
|
||||
use png::PngData;
|
||||
#[cfg(feature = "parallel")]
|
||||
use rayon::prelude::*;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::{copy, File};
|
||||
|
|
@ -277,7 +279,9 @@ impl Default for Options {
|
|||
/// Perform optimization on the input file using the options provided
|
||||
pub fn optimize(input_path: &Path, opts: &Options) -> Result<(), PngError> {
|
||||
// Initialize the thread pool with correct number of threads
|
||||
#[cfg(feature = "parallel")]
|
||||
let thread_count = opts.threads;
|
||||
#[cfg(feature = "parallel")]
|
||||
let _ = rayon::ThreadPoolBuilder::new()
|
||||
.num_threads(thread_count)
|
||||
.build_global();
|
||||
|
|
@ -356,7 +360,9 @@ pub fn optimize(input_path: &Path, opts: &Options) -> Result<(), PngError> {
|
|||
/// loaded in-memory
|
||||
pub fn optimize_from_memory(data: &[u8], opts: &Options) -> Result<Vec<u8>, PngError> {
|
||||
// Initialize the thread pool with correct number of threads
|
||||
#[cfg(feature = "parallel")]
|
||||
let thread_count = opts.threads;
|
||||
#[cfg(feature = "parallel")]
|
||||
let _ = rayon::ThreadPoolBuilder::new()
|
||||
.num_threads(thread_count)
|
||||
.build_global();
|
||||
|
|
@ -483,9 +489,11 @@ fn optimize_png(
|
|||
}
|
||||
}
|
||||
|
||||
let filters: HashMap<u8, Vec<u8>> = filter
|
||||
.par_iter()
|
||||
.with_max_len(1)
|
||||
#[cfg(feature = "parallel")]
|
||||
let filter_iter = filter.par_iter().with_max_len(1);
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let filter_iter = filter.iter();
|
||||
let filters: HashMap<u8, Vec<u8>> = filter_iter
|
||||
.map(|f| {
|
||||
let png = png.clone();
|
||||
(*f, png.filter_image(*f))
|
||||
|
|
@ -496,9 +504,11 @@ fn optimize_png(
|
|||
let added_interlacing = opts.interlace == Some(1) && original_png.ihdr_data.interlaced == 0;
|
||||
|
||||
let best_size = AtomicMin::new(if opts.force {None} else {Some(original_len)});
|
||||
let best: Option<TrialWithData> = results
|
||||
.into_par_iter()
|
||||
.with_max_len(1)
|
||||
#[cfg(feature = "parallel")]
|
||||
let results_iter = results.into_par_iter().with_max_len(1);
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let results_iter = results.into_iter();
|
||||
let best = results_iter
|
||||
.filter_map(|trial| {
|
||||
let filtered = &filters[&trial.filter];
|
||||
let new_idat = if opts.deflate == Deflaters::Zlib {
|
||||
|
|
@ -540,8 +550,18 @@ fn optimize_png(
|
|||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
});
|
||||
#[cfg(feature = "parallel")]
|
||||
let best: Option<TrialWithData> = best
|
||||
.reduce_with(|i, j| if i.1.len() <= j.1.len() { i } else { j });
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let best: Option<TrialWithData> = best.fold(None, |i, j| {
|
||||
if let Some(i) = i {
|
||||
if i.1.len() <= j.1.len() { Some(i) } else { Some(j) }
|
||||
} else {
|
||||
Some(j)
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(better) = best {
|
||||
png.idat_data = better.1;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use std::fs::File;
|
|||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::iter::Iterator;
|
||||
use std::path::Path;
|
||||
#[cfg(feature = "parallel")]
|
||||
use rayon::prelude::*;
|
||||
use atomicmin::AtomicMin;
|
||||
|
||||
|
|
@ -605,15 +606,19 @@ impl PngData {
|
|||
assert!(!alphas.is_empty());
|
||||
let alphas = alphas.iter().collect::<Vec<_>>();
|
||||
let best_size = AtomicMin::new(None);
|
||||
let best = alphas
|
||||
.par_iter()
|
||||
.with_max_len(1)
|
||||
#[cfg(feature = "parallel")]
|
||||
let alphas_iter = alphas.par_iter().with_max_len(1);
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let alphas_iter = alphas.iter();
|
||||
let best = alphas_iter
|
||||
.filter_map(|&alpha| {
|
||||
let mut image = self.clone();
|
||||
image.reduce_alpha_channel(*alpha);
|
||||
STD_FILTERS
|
||||
.par_iter()
|
||||
.with_max_len(1)
|
||||
#[cfg(feature = "parallel")]
|
||||
let filters_iter = STD_FILTERS.par_iter().with_max_len(1);
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let filters_iter = STD_FILTERS.iter();
|
||||
filters_iter
|
||||
.filter_map(|f| {
|
||||
deflate::deflate(
|
||||
&image.filter_image(*f),
|
||||
|
|
|
|||
Loading…
Reference in a new issue