Image processing & web workers 14 April 2013

tl;dr - examples (currently requires chrome):

>with web worker (should be smoother)

>without web worker


Web workers let you to take JavaScript execution off the main UI thread - which can be really useful if you are doing complex things with video

I came across a javascript qr-code reader a few days ago. When I started using it to scan from a getUserMedia stream - it worked fine, but the extra processing was blocking the ui, which was particularly noticable when you’re displaying the video.

I thought it was a pretty good candidate for taking the processing off to a web worker; which turned out pretty well.

Scanning QR code with getUserMedia

Once you’ve got the imageData from your canvas, you can run it through jsqrcode by setting attributes of the qrcode object, then call .render():

qrcode.imagedata = imagedata;
qrcode.width = imagedata.width;
qrcode.height = imagedata.height;

var content = qrcode.process();

It was pretty straightforward to pull the code into a web worker, I spent a bit of time before I realised that console.logs were making it fall over. Here’s the interface for responding to messages with the worker:

self.onmessage = function(event) {
    var imagedata = event.data;
    qrcode.imagedata = imagedata;
    qrcode.width = imagedata.width;
    qrcode.height = imagedata.height;

    var resp;
    try{
        resp = qrcode.process();
    } catch(e){
        resp = ''; // *mostly* "no code found"
    }
    postMessage(resp);
};

Back in the original page, you can creater the worker and deliver messages to it using the .postMessage function. You can optionally list Transferable objects to efficiently move them to the web worker.

var worker = new Worker("jsqrcode/worker.js"),
worker.onmessage = function(event) {
    console.log("qr code is:" + event.data);
}

// imagedata = ctx.getImageData(…)
worker.postMessage(imagedata, [imagedata.data.buffer]);

Jsqrcode is on github, as is my fork with the starts of the worker interface. You can either view source on the examples above, or view them on github.