Get pixel information from canvas using ArrayBuffer

1.1k views Asked by At

I have a function to read pixel information from canvas. It looks like this:

function getPx (imageData, x, y) {

    var r = imageData.data[((y * (imageData.width * 4)) + (x * 4))],
        g = imageData.data[((y * (imageData.width * 4)) + (x * 4)) + 1],
        b = imageData.data[((y * (imageData.width * 4)) + (x * 4)) + 2],
        a = imageData.data[((y * (imageData.width * 4)) + (x * 4)) + 3];

    return {
        r: r,
        g: g,
        b: b,
        a: a,
        black: (r + g + b) / 3
    };

}

This works fine but is a bit slow. From what I understand from this article https://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipulation-with-typed-arrays/ there is a much faster way to read/write imageData from the canvas using something called ArrayBuffer. I can't unfortunately get this to work. So does anyone know how to do this?

UPDATE:

I have a canvas where I want to measure some points color or alpha value, so I don't do this an all pixels. My attempts so far looks like this:

function getPx (imageData, x, y) {

    var data32 = new Uint32Array(imageData.data.buffer);
    var rv = data32[y * imageData.width + x];
    return rv;

}

This returns values and seems to be on the right way, however the values I get can look like this 4076863488 and 4244635648 and I'm not really sure how to turn them into the data I'm after.

1

There are 1 answers

0
arpo On BEST ANSWER

As @Kaiido mentioned it's slower. But for anyone else who want to elaborate on this here's my final function.

function getPx (imageData, x, y) {

    var data32 = new Uint32Array(imageData.data.buffer),
        val32 = data32[y * imageData.width + x],
        str32,
        a = 0,
        b = 0,
        g = 0,
        r = 0;

    if (val32 > 0) {
        str32 = val32.toString(16);
        a = parseInt(str32.substr(0, 2), 16);
        b = parseInt(str32.substr(2, 2), 16);
        g = parseInt(str32.substr(4, 2), 16);
        r = parseInt(str32.substr(6, 2), 16);
    }

    return {
        r: r,
        g: g,
        b: b,
        a: a,
        black: (r + g + b) / 3
    };

}

And also, it's better to put data32 = new Uint32Array(imageData.data.buffer) outside of the function if your calling this function many times with the same imageData.