how to pass multiple data in array as a transferable object

792 views Asked by At

to pass single images to a worker thread I do something like the following

    var image = ctx.getImageData(0, 0, data.width, data.height)); 

    var tData = new Uint8ClampedArray(data.width*data.height*4); 
    tData.set(image.data);

    let message = {function: "my function", buffer: tData.buffer}

    worker.postMessage(message, [tData.buffer]);

This works fine for single images, but now I want to send variable number of images using a loop. The sending of multiple arrays is permitted in the specification (eg. worker.postMessage(message, [array1, array2]);) but then you cannot dynamically alter the number of images.

let imageDataArray=[];

for(let i=0;i<images.length;i++){   

    var tData = new Uint8ClampedArray(data.width*data.height*4); 

    tData.set(images[i].data);

    imageDataArray.push(tData.buffer);
}

let message = {function: "my function", buffer: imageDataArray}

worker.postMessage(message, [imageDataArray]);

but it is just not working correctly since the data type is not transferable. Is there a proper way to do this?

Uncaught TypeError: Failed to execute 'postMessage' on 'Worker': Value at index 0 does not have a transferable type.
1

There are 1 answers

0
ejectamenta On

The last line should be (note: no square brackets needed).

worker.postMessage(message, imageDataArray);

Then in the worker the data is accessed like

let imageIndex = 0;
let buf = event.data.buffer[imageIndex];
let image = new Uint8Array(buf);

// do something with image
// ....

// return it back
postMessage(event.data, event.data.buffer);

then in the calling function it needs to be accessed by array index

var image = new Uint8ClampedArray(event.data.buffer[imageIndex]);

then you can use it like

let imageData = ctx.getImageData(0, 0, width, height);

imageData.data.set(image);

// write the data to the canvas
ctx.putImageData(imageData, 0, 0);

Not all browsers support multiple images so you should check compatibility first by doing a dummy test with a array argument to the worker.