为什么没有图像数据的参考?

Why is there no reference on image data?

是的,我知道 .getImageData()

我的意思是,比方说,我必须更改一些像素:

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

似乎,这种方法给了我 "real"(隐藏在我深处的某处)图像数据的全新副本。 我这么说,因为如果你创建一个新的:

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

并比较两个缓冲区:

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

所以,每次它从它的位图中创建新的副本。哦,天哪,为什么?好的,更进一步:

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

以上没什么特别的。但是现在,是时候把它放回去了:

ctx.putImageData(imageData, ...);

这一个在里面 运行 新循环并复制我的图像数据。

这么多额外的工作!有没有办法在没有 get/put 的情况下获取实际的 imageData 并对其进行操作?如果没有 - 我再问一次 - 为什么?是安全原因吗?他们担心我能用那些像素做什么?

谢谢!

简答:

没那么长答案:
您也许可以使用 some hacks 来实现它,但那样会很痛苦。

解释:
根据 the specsgetImageData returns 包含 canvas' 图像数据的 TypedArray,而不是指向作为可修改对象的实时图像数据的指针。

要在 canvas 上绘画,您必须使用 fillstrokedrawImageputImageData 等方法; 如果每次遍历数组时,实际的 canvas 图像都会被修改 ,那就更没有意义了。

每次调用getImageData,都会创建一个新的TypedArray(注意选择实际类型is up to the UA并填充了 canvasImage 的当前数据。这样,你就可以调用这个方法,在ArrayBuffer上做不同的改动,而不用把实际的图像修改到canvas中(这样你就可以存储它,或者再次调用这个方法)。

至于为什么每次调用返回的ImageData的缓冲区都不一样,我想是因为"Pixels must be returned as non-premultiplied alpha values",但是为了表演,他们确实把它存储为预乘的。可以从Firefox源码中看到here去预乘操作,实际上是填充了一个新的Uint8ClampedArray
此外,它避免检查 canvasImage 自上次调用以来是否已修改,并确保您始终获得其当前 ImageData。