├── .cargo └── config ├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── mod.js ├── rust-toolchain ├── src └── lib.rs ├── test.html └── wasm ├── package.json ├── snippets └── wasm-bindgen-rayon-7afa899f36665473 │ └── src │ └── workerHelpers.no-bundler.js ├── wasm_image_decoder.d.ts ├── wasm_image_decoder.js ├── wasm_image_decoder_bg.wasm └── wasm_image_decoder_bg.wasm.d.ts /.cargo/config: -------------------------------------------------------------------------------- 1 | [target.wasm32-unknown-unknown] 2 | rustflags = ["-C", "target-feature=+atomics,+bulk-memory,+mutable-globals"] 3 | 4 | [unstable] 5 | build-std = ["panic_abort", "std"] 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasm-image-decoder" 3 | version = "0.0.5" 4 | edition = "2018" 5 | 6 | [lib] 7 | crate-type = ["cdylib"] 8 | 9 | [dependencies] 10 | wasm-bindgen = "0.2" 11 | wasm-bindgen-rayon = {version = "1.0.3", features = ["no-bundler"]} 12 | console_error_panic_hook = "0.1.6" 13 | image = "0.24.5" 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 josephrocca 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wasm Image Decoder 2 | 3 | Decodes images using Rust's `image` crate compiled to WebAssembly. By default it uses 4 threads (though some decoders are single-threaded) since it doesn't seem to get much faster if I add any more. You can edit `mod.js` to change the number of threads. 4 | 5 | Works in the browser and in Deno. 6 | 7 | **Note**: This can only be used within a Web Worker due to wasm not supporting blocking/waiting operations when executed in the main thread ([related comment](https://github.com/GoogleChromeLabs/wasm-bindgen-rayon/pull/7#issuecomment-828569860)). You can use [`comlink`](https://github.com/GoogleChromeLabs/comlink) to make it easy to use this module from the main thread. 8 | 9 | (**Edit:** The following paragraph applies for v0.0.5 - I haven't tested later versions) As of writing it's about 3x slower than native Rust. Drawing the image to an `OffscreenCanvas` and then extracting the image data is the same speed as native Rust, so use that if your JS runtime has it available. The communication overhead between JS and the wasm module is negligible, so the slowness is probably due to missing functionality and lack of optimisation in wasm runtimes (e.g. thread/simd/etc. optimisations), so the performance should improve with time. 10 | 11 | ## File Formats Supported 12 | 13 | It supports decoding PNG, JPEG, WEBP, GIF, BMP, ICO, TGA, and several others, but some formats don't have full support as of writing (Dec 2022). [See here](https://github.com/image-rs/image/tree/v0.24.5#supported-image-formats) for the support table. Check the [latest image-rs readme](https://github.com/image-rs/image) to see if there is increased support, and if so you can follow the build instructions below to build a version of this library that supports the new formats. 14 | 15 | ## Demo 16 | 17 | ```js 18 | import decode from "https://deno.land/x/wasm_image_decoder@v0.0.7/mod.js"; 19 | let input = await fetch("https://i.imgur.com/LYVUrUf.jpg", {referrer:""}).then(r => r.arrayBuffer()); // empty referrer header because imgur blocks requests from 127.0.0.1 20 | // let input = await Deno.readFile("./image.png"); 21 | let result = decode(input); // `decode` accepts an ArrayBuffer or a Uint8Array 22 | console.log(result); // {width, height, data} where data is a Uint8Array array of RGBA values like [R,G,B,A,R,G,B,A,R,G,B,A,...] 23 | ``` 24 | 25 | ## Build 26 | ``` 27 | git clone https://github.com/josephrocca/wasm-image-decoder 28 | cd wasm-image-decoder 29 | cargo install wasm-pack 30 | wasm-pack build --target=web --out-dir=wasm 31 | ``` 32 | Basic `wasm-pack` tutorial here: https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_wasm 33 | 34 | If it fails with "unable to build with the standard library", you'll need to run 35 | ``` 36 | rustup component add rust-src 37 | ``` 38 | -------------------------------------------------------------------------------- /mod.js: -------------------------------------------------------------------------------- 1 | import init, {initThreadPool, decode} from "./wasm/wasm_image_decoder.js"; 2 | await init(); 3 | await initThreadPool(4); 4 | 5 | export default function(arrayBufferOrUint8Array) { 6 | let input = arrayBufferOrUint8Array; 7 | if(input.constructor === ArrayBuffer) { 8 | input = new Uint8Array(input); 9 | } 10 | let result = decode(input); 11 | let data = result.slice(0, -4); 12 | let widthBytes = result.slice(-4); 13 | let width = (widthBytes[0] << 24) + (widthBytes[1] << 16) + (widthBytes[2] << 8) + (widthBytes[3] << 0); 14 | let imageData = { 15 | width, 16 | height: (data.length/4) / width, 17 | data, 18 | }; 19 | return imageData; 20 | }; 21 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly-2022-04-07 -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | use image::io::Reader as ImageReader; 3 | use std::io::Cursor; 4 | use console_error_panic_hook; 5 | 6 | pub use wasm_bindgen_rayon::init_thread_pool; 7 | 8 | #[wasm_bindgen] 9 | pub fn decode(bytes: Vec) -> Vec { 10 | console_error_panic_hook::set_once(); 11 | 12 | let img_buf = ImageReader::new(Cursor::new(bytes)).with_guessed_format().unwrap().decode().unwrap().into_rgba8(); 13 | let width = img_buf.width(); 14 | let mut data = img_buf.into_raw(); 15 | // add width bytes to end (a u32 as four u8 values): 16 | data.push((width >> 24) as u8); 17 | data.push((width >> 16) as u8); 18 | data.push((width >> 8 ) as u8); 19 | data.push((width >> 0 ) as u8); 20 | data 21 | } -------------------------------------------------------------------------------- /test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | wasm image decoder 6 | 7 | 8 | 55 | 56 | -------------------------------------------------------------------------------- /wasm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wasm-image-decoder", 3 | "version": "0.0.5", 4 | "files": [ 5 | "wasm_image_decoder_bg.wasm", 6 | "wasm_image_decoder.js", 7 | "wasm_image_decoder.d.ts" 8 | ], 9 | "module": "wasm_image_decoder.js", 10 | "types": "wasm_image_decoder.d.ts", 11 | "sideEffects": false 12 | } -------------------------------------------------------------------------------- /wasm/snippets/wasm-bindgen-rayon-7afa899f36665473/src/workerHelpers.no-bundler.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | // This file is kept similar to workerHelpers.js, but intended to be used in 15 | // a bundlerless ES module environment (which has a few differences). 16 | 17 | function waitForMsgType(target, type) { 18 | return new Promise(resolve => { 19 | target.addEventListener('message', function onMsg({ data }) { 20 | if (data == null || data.type !== type) return; 21 | target.removeEventListener('message', onMsg); 22 | resolve(data); 23 | }); 24 | }); 25 | } 26 | 27 | waitForMsgType(self, 'wasm_bindgen_worker_init').then(async data => { 28 | const pkg = await import(data.mainJS); 29 | await pkg.default(data.module, data.memory); 30 | postMessage({ type: 'wasm_bindgen_worker_ready' }); 31 | pkg.wbg_rayon_start_worker(data.receiver); 32 | }); 33 | 34 | // Note: this is never used, but necessary to prevent a bug in Firefox 35 | // (https://bugzilla.mozilla.org/show_bug.cgi?id=1702191) where it collects 36 | // Web Workers that have a shared WebAssembly memory with the main thread, 37 | // but are not explicitly rooted via a `Worker` instance. 38 | // 39 | // By storing them in a variable, we can keep `Worker` objects around and 40 | // prevent them from getting GC-d. 41 | let _workers; 42 | 43 | export async function startWorkers(module, memory, builder) { 44 | const workerInit = { 45 | type: 'wasm_bindgen_worker_init', 46 | module, 47 | memory, 48 | receiver: builder.receiver(), 49 | mainJS: builder.mainJS() 50 | }; 51 | 52 | _workers = await Promise.all( 53 | Array.from({ length: builder.numThreads() }, async () => { 54 | // Self-spawn into a new Worker. 55 | // The script is fetched as a blob so it works even if this script is 56 | // hosted remotely (e.g. on a CDN). This avoids a cross-origin 57 | // security error. 58 | let scriptBlob = await fetch(import.meta.url).then(r => r.blob()); 59 | let url = URL.createObjectURL(scriptBlob); 60 | const worker = new Worker(url, { 61 | type: 'module' 62 | }); 63 | worker.postMessage(workerInit); 64 | await waitForMsgType(worker, 'wasm_bindgen_worker_ready'); 65 | URL.revokeObjectURL(url); 66 | return worker; 67 | }) 68 | ); 69 | builder.build(); 70 | } 71 | -------------------------------------------------------------------------------- /wasm/wasm_image_decoder.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * @param {Uint8Array} bytes 5 | * @returns {Uint8Array} 6 | */ 7 | export function decode(bytes: Uint8Array): Uint8Array; 8 | /** 9 | * @param {number} num_threads 10 | * @returns {Promise} 11 | */ 12 | export function initThreadPool(num_threads: number): Promise; 13 | /** 14 | * @param {number} receiver 15 | */ 16 | export function wbg_rayon_start_worker(receiver: number): void; 17 | /** 18 | */ 19 | export class wbg_rayon_PoolBuilder { 20 | free(): void; 21 | /** 22 | * @returns {string} 23 | */ 24 | mainJS(): string; 25 | /** 26 | * @returns {number} 27 | */ 28 | numThreads(): number; 29 | /** 30 | * @returns {number} 31 | */ 32 | receiver(): number; 33 | /** 34 | */ 35 | build(): void; 36 | } 37 | 38 | export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; 39 | 40 | export interface InitOutput { 41 | readonly decode: (a: number, b: number, c: number) => void; 42 | readonly __wbg_wbg_rayon_poolbuilder_free: (a: number) => void; 43 | readonly wbg_rayon_poolbuilder_mainJS: (a: number) => number; 44 | readonly wbg_rayon_poolbuilder_numThreads: (a: number) => number; 45 | readonly wbg_rayon_poolbuilder_receiver: (a: number) => number; 46 | readonly wbg_rayon_poolbuilder_build: (a: number) => void; 47 | readonly wbg_rayon_start_worker: (a: number) => void; 48 | readonly initThreadPool: (a: number) => number; 49 | readonly memory: WebAssembly.Memory; 50 | readonly __wbindgen_add_to_stack_pointer: (a: number) => number; 51 | readonly __wbindgen_malloc: (a: number) => number; 52 | readonly __wbindgen_free: (a: number, b: number) => void; 53 | readonly __wbindgen_realloc: (a: number, b: number, c: number) => number; 54 | readonly __wbindgen_thread_destroy: () => void; 55 | readonly __wbindgen_start: () => void; 56 | } 57 | 58 | export type SyncInitInput = BufferSource | WebAssembly.Module; 59 | /** 60 | * Instantiates the given `module`, which can either be bytes or 61 | * a precompiled `WebAssembly.Module`. 62 | * 63 | * @param {SyncInitInput} module 64 | * @param {WebAssembly.Memory} maybe_memory 65 | * 66 | * @returns {InitOutput} 67 | */ 68 | export function initSync(module: SyncInitInput, maybe_memory?: WebAssembly.Memory): InitOutput; 69 | 70 | /** 71 | * If `module_or_path` is {RequestInfo} or {URL}, makes a request and 72 | * for everything else, calls `WebAssembly.instantiate` directly. 73 | * 74 | * @param {InitInput | Promise} module_or_path 75 | * @param {WebAssembly.Memory} maybe_memory 76 | * 77 | * @returns {Promise} 78 | */ 79 | export default function init (module_or_path?: InitInput | Promise, maybe_memory?: WebAssembly.Memory): Promise; 80 | -------------------------------------------------------------------------------- /wasm/wasm_image_decoder.js: -------------------------------------------------------------------------------- 1 | import { startWorkers } from './snippets/wasm-bindgen-rayon-7afa899f36665473/src/workerHelpers.no-bundler.js'; 2 | 3 | let wasm; 4 | 5 | const heap = new Array(32).fill(undefined); 6 | 7 | heap.push(undefined, null, true, false); 8 | 9 | function getObject(idx) { return heap[idx]; } 10 | 11 | let heap_next = heap.length; 12 | 13 | function dropObject(idx) { 14 | if (idx < 36) return; 15 | heap[idx] = heap_next; 16 | heap_next = idx; 17 | } 18 | 19 | function takeObject(idx) { 20 | const ret = getObject(idx); 21 | dropObject(idx); 22 | return ret; 23 | } 24 | 25 | const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); 26 | 27 | cachedTextDecoder.decode(); 28 | 29 | let cachedUint8Memory0 = new Uint8Array(); 30 | 31 | function getUint8Memory0() { 32 | if (cachedUint8Memory0.buffer !== wasm.memory.buffer) { 33 | cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); 34 | } 35 | return cachedUint8Memory0; 36 | } 37 | 38 | function getStringFromWasm0(ptr, len) { 39 | return cachedTextDecoder.decode(getUint8Memory0().slice(ptr, ptr + len)); 40 | } 41 | 42 | function addHeapObject(obj) { 43 | if (heap_next === heap.length) heap.push(heap.length + 1); 44 | const idx = heap_next; 45 | heap_next = heap[idx]; 46 | 47 | heap[idx] = obj; 48 | return idx; 49 | } 50 | 51 | let WASM_VECTOR_LEN = 0; 52 | 53 | function passArray8ToWasm0(arg, malloc) { 54 | const ptr = malloc(arg.length * 1); 55 | getUint8Memory0().set(arg, ptr / 1); 56 | WASM_VECTOR_LEN = arg.length; 57 | return ptr; 58 | } 59 | 60 | let cachedInt32Memory0 = new Int32Array(); 61 | 62 | function getInt32Memory0() { 63 | if (cachedInt32Memory0.buffer !== wasm.memory.buffer) { 64 | cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); 65 | } 66 | return cachedInt32Memory0; 67 | } 68 | 69 | function getArrayU8FromWasm0(ptr, len) { 70 | return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len); 71 | } 72 | /** 73 | * @param {Uint8Array} bytes 74 | * @returns {Uint8Array} 75 | */ 76 | export function decode(bytes) { 77 | try { 78 | const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); 79 | const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc); 80 | const len0 = WASM_VECTOR_LEN; 81 | wasm.decode(retptr, ptr0, len0); 82 | var r0 = getInt32Memory0()[retptr / 4 + 0]; 83 | var r1 = getInt32Memory0()[retptr / 4 + 1]; 84 | var v1 = getArrayU8FromWasm0(r0, r1).slice(); 85 | wasm.__wbindgen_free(r0, r1 * 1); 86 | return v1; 87 | } finally { 88 | wasm.__wbindgen_add_to_stack_pointer(16); 89 | } 90 | } 91 | 92 | const cachedTextEncoder = new TextEncoder('utf-8'); 93 | 94 | const encodeString = function (arg, view) { 95 | const buf = cachedTextEncoder.encode(arg); 96 | view.set(buf); 97 | return { 98 | read: arg.length, 99 | written: buf.length 100 | }; 101 | }; 102 | 103 | function passStringToWasm0(arg, malloc, realloc) { 104 | 105 | if (realloc === undefined) { 106 | const buf = cachedTextEncoder.encode(arg); 107 | const ptr = malloc(buf.length); 108 | getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); 109 | WASM_VECTOR_LEN = buf.length; 110 | return ptr; 111 | } 112 | 113 | let len = arg.length; 114 | let ptr = malloc(len); 115 | 116 | const mem = getUint8Memory0(); 117 | 118 | let offset = 0; 119 | 120 | for (; offset < len; offset++) { 121 | const code = arg.charCodeAt(offset); 122 | if (code > 0x7F) break; 123 | mem[ptr + offset] = code; 124 | } 125 | 126 | if (offset !== len) { 127 | if (offset !== 0) { 128 | arg = arg.slice(offset); 129 | } 130 | ptr = realloc(ptr, len, len = offset + arg.length * 3); 131 | const view = getUint8Memory0().subarray(ptr + offset, ptr + len); 132 | const ret = encodeString(arg, view); 133 | 134 | offset += ret.written; 135 | } 136 | 137 | WASM_VECTOR_LEN = offset; 138 | return ptr; 139 | } 140 | /** 141 | * @param {number} num_threads 142 | * @returns {Promise} 143 | */ 144 | export function initThreadPool(num_threads) { 145 | const ret = wasm.initThreadPool(num_threads); 146 | return takeObject(ret); 147 | } 148 | 149 | /** 150 | * @param {number} receiver 151 | */ 152 | export function wbg_rayon_start_worker(receiver) { 153 | wasm.wbg_rayon_start_worker(receiver); 154 | } 155 | 156 | /** 157 | */ 158 | export class wbg_rayon_PoolBuilder { 159 | 160 | static __wrap(ptr) { 161 | const obj = Object.create(wbg_rayon_PoolBuilder.prototype); 162 | obj.ptr = ptr; 163 | 164 | return obj; 165 | } 166 | 167 | __destroy_into_raw() { 168 | const ptr = this.ptr; 169 | this.ptr = 0; 170 | 171 | return ptr; 172 | } 173 | 174 | free() { 175 | const ptr = this.__destroy_into_raw(); 176 | wasm.__wbg_wbg_rayon_poolbuilder_free(ptr); 177 | } 178 | /** 179 | * @returns {string} 180 | */ 181 | mainJS() { 182 | const ret = wasm.wbg_rayon_poolbuilder_mainJS(this.ptr); 183 | return takeObject(ret); 184 | } 185 | /** 186 | * @returns {number} 187 | */ 188 | numThreads() { 189 | const ret = wasm.wbg_rayon_poolbuilder_numThreads(this.ptr); 190 | return ret >>> 0; 191 | } 192 | /** 193 | * @returns {number} 194 | */ 195 | receiver() { 196 | const ret = wasm.wbg_rayon_poolbuilder_receiver(this.ptr); 197 | return ret; 198 | } 199 | /** 200 | */ 201 | build() { 202 | wasm.wbg_rayon_poolbuilder_build(this.ptr); 203 | } 204 | } 205 | 206 | async function load(module, imports) { 207 | if (typeof Response === 'function' && module instanceof Response) { 208 | if (typeof WebAssembly.instantiateStreaming === 'function') { 209 | try { 210 | return await WebAssembly.instantiateStreaming(module, imports); 211 | 212 | } catch (e) { 213 | if (module.headers.get('Content-Type') != 'application/wasm') { 214 | console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); 215 | 216 | } else { 217 | throw e; 218 | } 219 | } 220 | } 221 | 222 | const bytes = await module.arrayBuffer(); 223 | return await WebAssembly.instantiate(bytes, imports); 224 | 225 | } else { 226 | const instance = await WebAssembly.instantiate(module, imports); 227 | 228 | if (instance instanceof WebAssembly.Instance) { 229 | return { instance, module }; 230 | 231 | } else { 232 | return instance; 233 | } 234 | } 235 | } 236 | 237 | function getImports() { 238 | const imports = {}; 239 | imports.wbg = {}; 240 | imports.wbg.__wbg_new_abda76e883ba8a5f = function() { 241 | const ret = new Error(); 242 | return addHeapObject(ret); 243 | }; 244 | imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { 245 | const ret = getObject(arg1).stack; 246 | const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 247 | const len0 = WASM_VECTOR_LEN; 248 | getInt32Memory0()[arg0 / 4 + 1] = len0; 249 | getInt32Memory0()[arg0 / 4 + 0] = ptr0; 250 | }; 251 | imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { 252 | try { 253 | console.error(getStringFromWasm0(arg0, arg1)); 254 | } finally { 255 | wasm.__wbindgen_free(arg0, arg1); 256 | } 257 | }; 258 | imports.wbg.__wbindgen_object_drop_ref = function(arg0) { 259 | takeObject(arg0); 260 | }; 261 | imports.wbg.__wbindgen_throw = function(arg0, arg1) { 262 | throw new Error(getStringFromWasm0(arg0, arg1)); 263 | }; 264 | imports.wbg.__wbindgen_module = function() { 265 | const ret = init.__wbindgen_wasm_module; 266 | return addHeapObject(ret); 267 | }; 268 | imports.wbg.__wbindgen_memory = function() { 269 | const ret = wasm.memory; 270 | return addHeapObject(ret); 271 | }; 272 | imports.wbg.__wbindgen_object_clone_ref = function(arg0) { 273 | const ret = getObject(arg0); 274 | return addHeapObject(ret); 275 | }; 276 | imports.wbg.__wbg_static_accessor_URL_2c9da2bf037bbb2f = function() { 277 | const ret = import.meta.url; 278 | return addHeapObject(ret); 279 | }; 280 | imports.wbg.__wbg_startWorkers_271dd75b3837d2b0 = function(arg0, arg1, arg2) { 281 | const ret = startWorkers(takeObject(arg0), takeObject(arg1), wbg_rayon_PoolBuilder.__wrap(arg2)); 282 | return addHeapObject(ret); 283 | }; 284 | 285 | return imports; 286 | } 287 | 288 | function initMemory(imports, maybe_memory) { 289 | imports.wbg.memory = maybe_memory || new WebAssembly.Memory({initial:22,maximum:16384,shared:true}); 290 | } 291 | 292 | function finalizeInit(instance, module) { 293 | wasm = instance.exports; 294 | init.__wbindgen_wasm_module = module; 295 | cachedInt32Memory0 = new Int32Array(); 296 | cachedUint8Memory0 = new Uint8Array(); 297 | 298 | wasm.__wbindgen_start(); 299 | return wasm; 300 | } 301 | 302 | function initSync(module, maybe_memory) { 303 | const imports = getImports(); 304 | 305 | initMemory(imports, maybe_memory); 306 | 307 | if (!(module instanceof WebAssembly.Module)) { 308 | module = new WebAssembly.Module(module); 309 | } 310 | 311 | const instance = new WebAssembly.Instance(module, imports); 312 | 313 | return finalizeInit(instance, module); 314 | } 315 | 316 | async function init(input, maybe_memory) { 317 | if (typeof input === 'undefined') { 318 | input = new URL('wasm_image_decoder_bg.wasm', import.meta.url); 319 | } 320 | const imports = getImports(); 321 | 322 | if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { 323 | input = fetch(input); 324 | } 325 | 326 | initMemory(imports, maybe_memory); 327 | 328 | const { instance, module } = await load(await input, imports); 329 | 330 | return finalizeInit(instance, module); 331 | } 332 | 333 | export { initSync } 334 | export default init; 335 | -------------------------------------------------------------------------------- /wasm/wasm_image_decoder_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephrocca/wasm-image-decoder/c200c663e8d6376298ea2bade07ab981ce9bb7c2/wasm/wasm_image_decoder_bg.wasm -------------------------------------------------------------------------------- /wasm/wasm_image_decoder_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export function decode(a: number, b: number, c: number): void; 4 | export function __wbg_wbg_rayon_poolbuilder_free(a: number): void; 5 | export function wbg_rayon_poolbuilder_mainJS(a: number): number; 6 | export function wbg_rayon_poolbuilder_numThreads(a: number): number; 7 | export function wbg_rayon_poolbuilder_receiver(a: number): number; 8 | export function wbg_rayon_poolbuilder_build(a: number): void; 9 | export function wbg_rayon_start_worker(a: number): void; 10 | export function initThreadPool(a: number): number; 11 | export const memory: WebAssembly.Memory; 12 | export function __wbindgen_add_to_stack_pointer(a: number): number; 13 | export function __wbindgen_malloc(a: number): number; 14 | export function __wbindgen_free(a: number, b: number): void; 15 | export function __wbindgen_realloc(a: number, b: number, c: number): number; 16 | export function __wbindgen_thread_destroy(): void; 17 | export function __wbindgen_start(): void; 18 | --------------------------------------------------------------------------------