簡體   English   中英

從HTML5 Canvas垂直迭代像素

[英]Iterating pixels vertically from HTML5 Canvas

我試圖在圖像中找到第一個包含數據的垂直和水平行。

我很容易得到第一個水平行,因為在調用getImageData ,生成的像素數據數組是逐行水平存儲的。 我有這樣的數據:

var data = context.getImageData(0, 0, width, height).data;
var heightFirst = 0;

for (var r = 0; r <= data.length; r += 4) {
    if (data[r + 3] > 0) {
        var y = (r / width) / 4;
        heightFirst = y;
        break;
    }
}

我現在需要垂直迭代數據。 我意識到這可能是使用嵌套for循環完成的,並執行以下操作:

for (var r = 0; r <= data.length; r += 4) {
    for (var c = 0; c < canvasHeight; c++) {    
        if (data[(r + 3) + (c * width)] > 0) {

        }
    }
}

我不確定任何人可以幫助我的確切實施/計算?

編輯

正如@bobbybee和@danielpolencic所提到的,增加4 *寬度的循環將增加一個垂直列:

for (var r = 0; r <= data.length; r += (4 * width)) {
  if (data[r + 3] > 0) {
    // do whatever
  }
}

但是,這僅獲取第一列像素的信息。 我想下一步是重復上面的循環,但是增加它的列數(由於顏色數據乘以4),循環如下:

for (var c = 0; c < canvas.width; c ++) {
    for (var r = 0; r <= data.length; r += ((4 * canvas.width) + (c * 4))) {
        if (data[r + 3] > 0) {
            firstX = c;
        }
    }
}

這似乎不太正確。 我把它放在這個小提琴上 ,因為你可以看到它應該返回10,因為這是左邊的第一列,但它正在寫99到日志。 感覺我好近!

你可以在一個循環中完成所有操作,而不必完全嵌套。

現場演示

var minX = canvas.width,
    minY = canvas.height;

for (var p = 0; p <= data.length; p += 4) {
     var curX = (p / 4) % canvas.width,
         curY = ((p / 4) - curX) / canvas.width;

    /* if what we're checking is higher than our recorded minX and 
      minY skip to the next row */

    if(curX > minX && curY > minY){
        // if minY is greater than 0 continue, if its 0 it can be no less so break.
        if(minY > 0){
            p=(curY+1)*(canvas.width*4); 
        }else{
            break;
        }
    }

    if (data[p + 3] > 0) {
        if (curX < minX) {
            minX = curX;
        };

        if (curY < minY) {
            minY = curY;
        };
    }
}

以下是從單維數組中獲取x和y的公式

X = Index % Width

Y = (Index - x) / Width

在我們的例子中,由於我們正在處理分成4個分量值(r / g / b / alpha)的像素數據,我們需要將索引除以4,就像我在上面的演示中所做的那樣。

接下來我使用minXminY設置畫布的寬度和高度。 每當我們點擊一​​個像素時,我們檢查它的xy是否低於我們存儲的最低xy 如果它們較低,那么我們保持價值並繼續前進。

但是它更容易閱讀,並且使用多個循環來讀取數據的速度更快

for (var x = 0; x <= canvas.width; x++) {
  for (var y = 0; y <= canvas.height; y++) {
    if (minY < y) {
      break;
    }
    if (data[((y * canvas.width + x) * 4) + 3] > 0) {
      if (x < minX) {
        minX = x;
      }
      if (y < minY) {
        minY = y;
      }
    }
  }
}

演示獲取lastX和lastY

for (var x = 0; x <= canvas.width; x++) {
    for (var y = 0; y <= canvas.height; y++) {
        if (data[((y * canvas.width + x) * 4) + 3] > 0) {
            if (x < firstX) {
                firstX = x;
            }
            if (y < firstY) {
                firstY = y;
            }

            if (x > lastX) {
                lastX = x;
            }
            if (y > lastY) {
                lastY = y;
            }
        }
    }
}

就像@bobbybee正確指出的那樣,你的循環步驟是4 * image_width

for (var r = 0; r <= data.length; r += (4 * width)) {
    for (var c = 0; c < canvasHeight; c++) {
        if (data[r + 3] > 0) {

        }
    }
}

這可以通過一個循環來完成(這里不需要嵌套循環):

for(var y = 0; y < data.length; y += canvas.width * 4) {
    if (data[y + 3] > 0 ) { /*...*/ }
}

或擠出更快的速度:

var y = 0,
    length = data.length,     /// cache length
    width = canvas.width * 4; /// cache width

while(y < length) {
    if (data[y + 3] > 0 ) { /*...*/ }
    y += width;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM