diff options
Diffstat (limited to 'vendor/jpeg-decoder/src/worker/mod.rs')
-rw-r--r-- | vendor/jpeg-decoder/src/worker/mod.rs | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/vendor/jpeg-decoder/src/worker/mod.rs b/vendor/jpeg-decoder/src/worker/mod.rs new file mode 100644 index 0000000..d6c2b10 --- /dev/null +++ b/vendor/jpeg-decoder/src/worker/mod.rs @@ -0,0 +1,128 @@ +mod immediate; +mod multithreaded; +#[cfg(all( + not(any(target_arch = "asmjs", target_arch = "wasm32")), + feature = "rayon" +))] +mod rayon; + +use crate::decoder::{choose_color_convert_func, ColorTransform}; +use crate::error::Result; +use crate::parser::{Component, Dimensions}; +use crate::upsampler::Upsampler; + +use alloc::sync::Arc; +use alloc::vec::Vec; +use core::cell::RefCell; + +pub struct RowData { + pub index: usize, + pub component: Component, + pub quantization_table: Arc<[u16; 64]>, +} + +pub trait Worker { + fn start(&mut self, row_data: RowData) -> Result<()>; + fn append_row(&mut self, row: (usize, Vec<i16>)) -> Result<()>; + fn get_result(&mut self, index: usize) -> Result<Vec<u8>>; + /// Default implementation for spawning multiple tasks. + fn append_rows(&mut self, row: &mut dyn Iterator<Item = (usize, Vec<i16>)>) -> Result<()> { + for item in row { + self.append_row(item)?; + } + Ok(()) + } +} + +#[allow(dead_code)] +pub enum PreferWorkerKind { + Immediate, + Multithreaded, +} + +#[derive(Default)] +pub struct WorkerScope { + inner: core::cell::RefCell<Option<WorkerScopeInner>>, +} + +enum WorkerScopeInner { + #[cfg(all( + not(any(target_arch = "asmjs", target_arch = "wasm32")), + feature = "rayon" + ))] + Rayon(rayon::Scoped), + #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] + Multithreaded(multithreaded::MpscWorker), + Immediate(immediate::ImmediateWorker), +} + +impl WorkerScope { + pub fn with<T>(with: impl FnOnce(&Self) -> T) -> T { + with(&WorkerScope { + inner: RefCell::default(), + }) + } + + pub fn get_or_init_worker<T>( + &self, + prefer: PreferWorkerKind, + f: impl FnOnce(&mut dyn Worker) -> T, + ) -> T { + let mut inner = self.inner.borrow_mut(); + let inner = inner.get_or_insert_with(move || match prefer { + #[cfg(all( + not(any(target_arch = "asmjs", target_arch = "wasm32")), + feature = "rayon" + ))] + PreferWorkerKind::Multithreaded => WorkerScopeInner::Rayon(Default::default()), + #[allow(unreachable_patterns)] + #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] + PreferWorkerKind::Multithreaded => WorkerScopeInner::Multithreaded(Default::default()), + _ => WorkerScopeInner::Immediate(Default::default()), + }); + + f(match &mut *inner { + #[cfg(all( + not(any(target_arch = "asmjs", target_arch = "wasm32")), + feature = "rayon" + ))] + WorkerScopeInner::Rayon(worker) => worker, + #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] + WorkerScopeInner::Multithreaded(worker) => worker, + WorkerScopeInner::Immediate(worker) => worker, + }) + } +} + +pub fn compute_image_parallel( + components: &[Component], + data: Vec<Vec<u8>>, + output_size: Dimensions, + color_transform: ColorTransform, +) -> Result<Vec<u8>> { + #[cfg(all( + not(any(target_arch = "asmjs", target_arch = "wasm32")), + feature = "rayon" + ))] + return rayon::compute_image_parallel(components, data, output_size, color_transform); + + #[allow(unreachable_code)] + { + let color_convert_func = choose_color_convert_func(components.len(), color_transform)?; + let upsampler = Upsampler::new(components, output_size.width, output_size.height)?; + let line_size = output_size.width as usize * components.len(); + let mut image = vec![0u8; line_size * output_size.height as usize]; + + for (row, line) in image.chunks_mut(line_size).enumerate() { + upsampler.upsample_and_interleave_row( + &data, + row, + output_size.width as usize, + line, + color_convert_func, + ); + } + + Ok(image) + } +} |