UNPKG

@niivue/niimath

Version:

A javascript library to easily use the WASM build of Chris Rorden's niimath command line program written in C

88 lines (73 loc) 3.48 kB
// Load the Emscripten-generated JavaScript, which will handle the WASM binary loading. // The worker is of type "module" so that it can use ES6 module syntax. // Importantly, the emscripten code must be compiled with: -s EXPORT_ES6=1 -s MODULARIZE=1. // This allows proper module bundlers to import the worker and wasm properly with code splitting. import Module from './niimath.js'; // initialise an instance of the Emscripten Module so that // it is ready when the worker receives a message. // We keep a reference to the module so that the worker can reuse it // for all subsequent calls without having to reinitialise it (which could be slow due to the WASM loading) let mod = null Module().then((initializedMod) => { mod = initializedMod // Send a ready message once initialization is complete // so we can signal to the main thread that the worker is ready. // The Niimath.init() method will wait for this message before resolving the promise. self.postMessage({ type: 'ready' }); }) // error handler in the worker self.onerror = function (message, error) { self.postMessage({ type: 'error', message: message, error: error ? error.stack : null }); }; // unhandled promise rejection handler in the worker self.onunhandledrejection = function (event) { self.postMessage({ type: 'error', message: event.reason ? event.reason.message : 'Unhandled rejection', error: event.reason ? event.reason.stack : null }); }; const handleMessage = (e) => { try { const file = e.data.blob; const args = e.data.cmd; const outName = e.data.outName || 'out.nii'; if (!file || args.length < 1) { throw new Error("Expected a file and at least one command"); } const inName = file.name; const fr = new FileReader(); fr.readAsArrayBuffer(file); fr.onloadend = function () { const data = new Uint8Array(fr.result); // if the module is loaded and not null, // then we can proceed with the image processing if (mod) { // Create a virtual file in the Emscripten filesystem mod.FS_createDataFile(".", inName, data, true, true); // Ensure args is an array if (!Array.isArray(args)) { throw new Error("Expected args to be an array"); } // call the main niimath entry point with the arguments. // equivalent to calling `niimath <in_file.nii> <args> <out_file.nii>` from the command line const exitCode = mod.callMain(args); // read the output file from the Emscripten filesystem const out_bin = mod.FS_readFile(outName); // binary output file from niimath wasm: nii or mz3 const outputFile = new Blob([out_bin], { type: 'application/sla' }); // send a message back to the main thread with the output file, exit code and output file name self.postMessage({ blob: outputFile, outName: outName, exitCode: exitCode }); // Free virtual files mod.FS_unlink(inName); // if the input and output file names are different, then delete the output file if (inName !== outName) { mod.FS_unlink(outName); } } else { throw new Error("WASM module not loaded yet!"); } }; } catch (err) { // Send error details back to the main thread self.postMessage({ type: 'error', message: err.message, error: err.stack }); } } // Handle messages from the main thread self.addEventListener('message', handleMessage, false);