aboutsummaryrefslogtreecommitdiff
path: root/vendor/jpeg-decoder/src/worker/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/jpeg-decoder/src/worker/mod.rs')
-rw-r--r--vendor/jpeg-decoder/src/worker/mod.rs128
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)
+ }
+}