【问题标题】:index a pixel using one-loop or two-loops使用单循环或双循环索引像素
【发布时间】:2014-09-01 14:06:03
【问题描述】:

我看到一些用户在 [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 坐标,请使用第二种方法。差别不大。

标签: javascript html canvas


【解决方案1】:

这完全取决于您的需求:

• 如果您需要线性迭代所有像素,只需:

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] = ... ;
      }
   }

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 真的不想投反对票,但这个答案都是基于猜测,你应该提供一个 jsperf 或某种真实数据来证明你的理论。跨度>
    【解决方案3】:

    上一个答案有效,但我想我可以提供一个循环答案。

    假设我们必须在 100x100 的正方形图像中挑选像素:

    const size = 100;
    const pixels = size * size;
    
    for( let index = 0; index < pixels; index++ ){
    
        const id = ~~index;
        const x = id % size;
        const y = ~~(id / size);
    
        console.log("x:", x, "y:", y);
    
    }

    打开您的开发工具以查看完整的控制台输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      • 2020-07-20
      • 1970-01-01
      • 1970-01-01
      • 2016-09-28
      • 2023-04-05
      • 2010-12-06
      相关资源
      最近更新 更多