How can I cancel image decoding in JavaScript?

162 Views Asked by At

To transform binary image data (e.g. from a file input) into a canvas image source, createImageBitmap or Image.decode can be used.

Is there a cancellable alternative to these methods?

I want to render images from a multiple file input to a canvas element, one at a time. My current approach causes severe delays, if additional decode operations are started while the previous ones still run (I am only interested in the result of the most recent one).

I found out that Image.decode can be cancelled in some browsers, by reassinging the image src. However, this does not work universally (e.g. not in Firefox).

I am open to use third party libraries, as long as they are performant (WebAssembly) and free and if they at least support the most basic image formats like JPEG and PNG.

Edit

To clarify things, I created a Codepen: https://codepen.io/Tims777/pen/bGxvgBQ

Just select a bunch (100+) of large (~20MP) JPEGs and hold down the up button for a while to torture your CPU.

1

There are 1 best solutions below

3
Tims On BEST ANSWER

Thanks to Dai I can now answer my own question:

Using a WebWorker makes for a pretty straightforward solution, since the worker can be cancelled right in the middle of execution whenever the need arises.

The worker.js itself can be as simple as this:

onmessage = function(event) {
    createImageBitmap(event.data).then(image => postMessage(image));
}

And here is my reworked update function:

function update() {
    abortController?.abort();
    abortController = new AbortController();

    if (indexInput.valueAsNumber > fileInput.files.length) return;
    const file = fileInput.files[indexInput.valueAsNumber];
    const signal = abortController.signal;

    const worker = new Worker("worker.js");
    worker.onmessage = (message) => ctx1.drawImage(message.data, 0, 0, canvas1.width, canvas1.height);
    worker.postMessage(file);
    signal.onabort = () => worker.terminate();
}