考虑此代码:
var deSaturated = deSaturate(greyscaleCtx.getImageData(0, 0, canvasWidth, canvasHeight));
iMagedata来自getimagedata帆布功能。
function deSaturate (imageData) {
var theData = imageData.data;
var dataLength = theData.length;
var i = dataLength-1;
var lightLevel;
// Iterate through each pixel, desaturating it
while ( i >= 0) {
// To find the desaturated value, average the brightness of the red, green, and blue values
theData[i] = theData[i+1] = theData[i+2] = (theData[i] + theData[i + 1] + theData[i + 2]) / 3;
// Fully opaque
theData[i+3] = 255;
// returning an average intensity of all pixels. Used for calibrating sensitivity based on room light level.
lightLevel += theData[i]; //combining the light level in the samefunction
i -= 4;
}
imageData.data = theData; //bring back theData into imageData.data - do I really need this?
var r = [lightLevel/dataLength,imageData]
return r;
}
在撰写和优化此代码期间,我发现我真的不明白JS如何对待" TheData"变量。正在使用它只是参考imagedata.data的一种简短方法,在这种情况下,我最终不需要以下代码:
imageData.data = theData
,但是我要以退化的性能(很多DOM I/O)付款?
或正在执行theData = imageData.data
实际复制原始数组(表示为Uint8ClampedArray),然后我必须将修改后的数据重新分配给imageData.data
。
我想这是基本的JavaScript,但是我在MDN和其他开发人员资源中找到了矛盾的代码示例,我真的很想正确理解这一点。
感谢您的帮助!
刚刚进行了快速测试:
var idata = ctx.getImageData(0,0,300,300);
var data = idata.data;
for(var i=0;i<data.length;i++){
data[i]=0;
}
ctx.putImageData(idata,0,0);
,并且按预期正确地将部分遮住了屏幕的一部分。但是,如果没有PutimateData,就不会发生任何事情。因此,更改数据对象,无论是否存储在不同的变量中,将反映在该Imagedata对象中。但是,在调用putimagedata之前,这不会影响画布。
所以,是的,您可以删除最终作业,并且可以根据需要工作。
但是,我会警告它是不是是一个有效的假设,即它是uint8clampedarray。是的,这就是Chrome处理它的方式(最后我检查过),这确实是官方规范使用的。但是,有些浏览器没有UINT8ClampedArray的概念,同时仍通过现已弃用的Canvaspixelarray支持画布。
因此,您保证获得的只是一些类似阵列的接口。当我尝试通过创建一个新的UINT8ClampedArray来缓存图像数据的有趣功能时,我必须以难以学习的方式学习这一点,该功能在某些浏览器中失败。
请参阅:https://developer.mozilla.org/en-us/docs/dom/canvaspixelarrare
在JavaScript中,分配了array
或object
仅分配对该数组或对象的引用 - 它不会制作数据的副本。仅当您实际创建一个新数组并将数据复制或调用某些旨在为您完成的功能时,才能制作副本。
因此,如果imageData.data
是array
,则将其分配给theData
只是为参考相同数据的快捷方式。它不会制作新的数据副本。因此,在修改了由theData
指向的数据之后,您无需将其分配回imageData.data
,因为数据只有一个副本,并且theData
和imageData.data
点已经指向了数据的同一副本。
因此,在直接回答您的问题时,这一行是不必要的:
imageData.data = theData;