javascriptperformancecanvasgetimagedataputimagedata

Why is there no reference on image data?


Yes, I know about .getImageData()

I mean, let's say, I have to change some pixels:

var imageData = ctx.getImageData(...);

Seems, this method give me completely new copy of "real" (hiden somewhere deep from me) image-data. I say that, because if you create new one:

var imgData2 = ctx.getImageData(.../*same parameters as before*/);

and compare two buffers:

imageData.data.buffer === imgData2.data.buffer; //false

So, each time it create new copy from it's bitmap. Oh my Gosh, Why? Okay, go further:

/*...apply some new changes to the imageData in a loop...*/

Nothing special above. But now, it's time to put this back:

ctx.putImageData(imageData, ...);

And this one inside itself run new loop and copy my imageData.

So much extra work! Is there a way to get actual imageData and manipulate it without get/put? And if no - I'm ask again - WHY? Is it security reasons? What they afraid I can do with that pixels?

Thank you!


Solution

  • Short answer :
    No.

    Not so long Answer :
    You may be able to achieve it with some hacks but that would be such a pain.

    Explanations :
    According to the specs, getImageData returns a TypedArray which contains the canvas' image data, not a pointer to the live imageData as a modifiable object.

    To paint on a canvas, you have to use methods such as fill, stroke, drawImage or putImageData ; that would make even less sense that each time you iterate through the array, the actual canvas image get modified.

    Each time you call getImageData, a new TypedArray (note that the choice of the actual type is up to the UA) is created and filled with the current data of the canvasImage. This way, you can call this method, make different alterations on the ArrayBuffer, without modifying the actual image into the canvas (so you can store it, or call the method again).

    As to why the buffer of the returned ImageData is not the same on each call, I think it is because "Pixels must be returned as non-premultiplied alpha values", but for performances, they do store it as premultiplied. You can see here the de-premultiplication operation from Firefox source code, which actually fills a new Uint8ClampedArray.
    Also, it avoids to check if the canvasImage as been modified since the last call, and ensure you always get its current ImageData.