0

是的,我知道 .getImageData()

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

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

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

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, ...);

而这个内部本身运行新循环并复制我的 imageData。

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

谢谢!

4

1 回答 1

2

简短的回答:
没有。

没多久 答案:
你也许可以通过一些技巧来实现它,但那会很痛苦。

说明:
根据规范getImageData返回一个包含画布图像数据的 TypedArray,而不是指向作为可修改对象的实时 imageData 的指针。

要在画布上绘画,您必须使用fill、或;stroke等方法。每次遍历数组时,实际的画布图像都会被修改,这样就更没有意义了drawImageputImageData

每次调用时getImageData,都会创建一个新的TypedArray (注意实际类型的选择取决于 UA并填充 canvasImage 的当前数据。这样,您可以调用此方法,对 ArrayBuffer 进行不同的更改,而无需将实际图像修改到画布中(因此您可以存储它,或者再次调用该方法)。

至于为什么每次调用时返回的 ImageData 的缓冲区都不相同,我认为这是因为“像素必须作为非预乘 alpha 值返回”,但对于性能,它们确实将其存储为预乘。你可以在这里看到来自 Firefox 源代码的去预乘操作,它实际上填充了一个新的 Uint8ClampedArray。
此外,它避免检查自上次调用以来 canvasImage 是否已修改,并确保您始终获取其当前 ImageData。

于 2015-09-21T05:17:17.323 回答