Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web worker dealing with imageData working with Firefox but not Chrome

When I run code that deals with imageData being passed to a web worker and then back, then Firefox works great but Chrome gives "Uncaught Error: DATA_CLONE_ERR: DOM Exception 25"

Searching google suggests that older versions of Chrome used to work?

I checked some more and it seemed as if I needed to run JSON.stringify and JSON.parse on the imagedata before sending it but then it stops working everywhere. The code that works in FF 9 is:

image.js:

var myImageData = context.getImageData(0, 0, canvas.width, canvas.height).data;
var worker = new Worker("http://direct.link/helpers/worker.js");
worker.postMessage(myImageData);  
worker.onmessage = function(event) {
  var value = event.data;
  switch (value.cmd){
    case 'last':
      //doing stuff 
      break;
  default:
      //doing stuff
    });
}

worker.js:

addEventListener('message', function(event) {
  var myImageData = event.data;
  // doing stuff.
  sendItBack(colors);
});
};

    function sendItBack(colors){
    each(colors, function(index, value){
      self.postMessage(value);
    }); 
    self.postMessage({'cmd': 'last'});
    }

What method should I use in order to send this imagedata back and forth the app and the web worker?

Thanks!

EDIT:

If I copy to a regular array then Chrome starts working...

var newImageData = [];
for (var i=0,len=myImageData.length;i<len;++i) newImageData[i] = myImageData[i];

So chrome can't pass a CanvasPixelArray to a worker but it can pass a regular Array. But firefox can.

like image 689
garg Avatar asked Jan 08 '12 10:01

garg


People also ask

Are web workers supported in all browsers?

Web Workers And ES Modules #All modern browsers support running JavaScript modules via <script type="module" src="file. js"> . All modern browsers apart from Firefox also now support the worker counterpart: new Worker("./worker.

What is the difference between service worker and web worker?

What is a Service Worker? Unlike Web Workers, Service Workers have a dedicated role of being a proxy between the network and the browser and/or cache. Similar to Web Workers, they are registered in the primary JavaScript file as a dedicated worker.

What cancels a web worker?

terminate() The terminate() method of the Worker interface immediately terminates the Worker .


3 Answers

What I do is pass the entire imagedata object from the context to the worker, and not just the data:

var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);

// This works beautifully
worker.postMessage({imgData:imgData});

// But this throws the exception
worker.postMessage({imgData:imgData.data});

With this approach you're passing a few extra attributes to the worker (namely, the array's width and height), but I think this bit of extra data is better than the overhead associated with copying the entire data array.

like image 76
rodrigo-silveira Avatar answered Nov 14 '22 22:11

rodrigo-silveira


Posting this as follow up. I can reproduce your error in case anyone else can answer your question (I can't unfortunately). I've searched the Chromium issues to see if it's an outstanding bug, but not found anything. Given image processing is one of the more popular uses of WebWorkers I would hope someone can answer you quickly.

http://jsfiddle.net/gGFSJ/9/

From Chrome (asterisks added by me):

window.URL does not exist
window.WebKitURL does not exist
using window.webkitURL for URL
window.BlobBuilder does not exist
using window.WebKitBlobBuilder for BlobBuilder
***Uncaught Error: DATA_CLONE_ERR: DOM Exception 25***
data=send back.
data=to worker.
data=send back.
data=0.

From Firefox:

using window.URL for URL
window.BlobBuilder does not exist
window.WebKitBlobBuilder does not exist
window.webkitBlobBuilder does not exist
using window.MozBlobBuilder for BlobBuilder
data=send back.
data=to worker.
data=send back.
data=0.
data=send back.
data=[object Uint8ClampedArray].
like image 44
Paul Grime Avatar answered Nov 14 '22 22:11

Paul Grime


If I copy the getimagedata.data array to a regular array and then pass the array to a webworker then Chrome starts working.

var newImageData = [];
for (var i=0,len=myImageData.length;i<len;++i) newImageData[i] = myImageData[i];

So chrome can't pass a CanvasPixelArray to a worker but it can pass a regular Array. But Firefox can pass an imagedata.data directly.

like image 42
garg Avatar answered Nov 14 '22 22:11

garg