是的,我知道.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的情况下操作它?如果不是 - 我再问一次 - 为什么?这是安全原因吗?他们害怕我能用这些像素做什么?
谢谢!
答案 0 :(得分:2)
简答:
否。
没那么久答案:
你可以用some hacks来实现它,但那会很痛苦。
说明:
根据{{3}},getImageData
返回一个TypedArray,其中包含画布'图像数据,而不是指向实时imageData的指针作为可修改对象。
要在画布上绘画,您必须使用fill
,stroke
,drawImage
或putImageData
等方法;每次迭代数组时,会更不明白,实际的画布图像会被修改。
每次拨打getImageData
时,都会创建一个新的TypedArray
(请注意选择实际类型the specs),并使用当前数据填充canvasImage的。这样,您可以调用此方法,对ArrayBuffer进行不同的更改,而无需将实际图像修改为画布(因此您可以存储它,或者再次调用该方法)。
至于为什么返回的ImageData的缓冲区在每次调用时都不一样,我认为这是因为"像素必须作为非预乘的alpha值返回",但对于表演,它们确实存储它是预乘的。您可以从Firefox源代码中看到is up to the UA去预复制操作,它实际上填充了一个新的Uint8ClampedArray。 此外,它避免检查自上次调用以来canvasImage是否已被修改,并确保始终获取其当前的ImageData。