Javascript 使用一个或两个循环索引像素

Javascript 使用一个或两个循环索引像素,javascript,html,canvas,Javascript,Html,Canvas,我看到一些用户使用以下两种方法在[Image Data]数组中索引一个像素: for(var i = 0; i < imageData.length; i+=4) { data[i] = r; data[i+1] = g; data[i+2] = b; data[i+3] = a; } 或者用这个方法 for(var x = 0; w < canvas.width; x++) { for(var y = 0; h < canvas.heig

我看到一些用户使用以下两种方法在[Image Data]数组中索引一个像素:

for(var i = 0; i < imageData.length; i+=4) {
    data[i] = r;
    data[i+1] = g;
    data[i+2] = b;
    data[i+3] = a;
}
或者用这个方法

for(var x = 0; w < canvas.width; x++) {
  for(var y = 0; h < canvas.height; y++) {
      var index = (x + y*canvas.width)*4;

  }
}

所以,我想知道两者之间有什么区别。另外,如果两者相同,那么哪一种最快。

这两种方法都会产生相同的结果。我假设在计算两幅图像后,它们的索引位置是相同的。唯一改变的是像素的变化顺序


就速度而言,第二个可能会更慢。首先,这是因为缓存速度,程序访问相似阵列位置的数据的速度比连续访问整个阵列位置的速度要快。此外,为了重新计算索引,编译器必须执行一些乘法运算和加法运算,而不仅仅是加法运算。要在第二个循环中获得更快的速度,请尝试切换循环的x和y,或者将x乘以canvas.height,而不是y乘以canvas.width。

这取决于您的需要:

•如果需要线性遍历所有像素,只需执行以下操作:

var pixelCount=data.length, i=0;
while (pixelCount--) {
    data[i++] = r;
    data[i++] = g;
    data[i++] = b;
    data[i++] = a;
}
•如果迭代所有像素,但需要每个点的x、y来执行某些计算,请执行以下操作:

var index=0, canvasWidth = canvas.width, canvasHeight = canvas.height ;
for(var y = 0; h < canvasHeight; y++) {
    for(var x = 0; w < canvasWidth ; x++) {        
        data[index++] = /* depends on x, y */;
        data[index++] = /* depends on x, y */;
        data[index++] = /* depends on x, y */;
        data[index++] =  /* depends on x, y */;
    }
 } 
缓存canvas.width/height以避免循环中的DOM访问尤其重要

•如果您在数据中迭代一个矩形,那么您无法避免计算索引,您可以通过使用位移位来加快索引速度:

  var startX = ?? , startY = ???, endX = ???, endY = ??? ;
  var canvasWidth = canvas.width;
  var index=0;
  for(var y = startY; y <= endY; y++) {
      for(var x = startX; x <= endX ; x++) {      
          index = ( y * canvasWidth + x ) << 2 ;   
          data[index] = ... ;
          data[index+1] = ... ;
          data[index+2] = ... ;
          data[index+3] = ... ;
      }
   }

第一种方法可能快得可以忽略不计。如果需要轻松了解正在访问的像素的x、y坐标,请使用第二种方法。没有太大的区别。我不想否决投票,但这个答案都是基于猜测,你应该提供一个jsperf或一些真实的数据来证明你的理论。