2017-02-17 49 views
1

如何在圖像畫布算面積的透明單位像素,我寫了這個功能,但我想有一些像另一種方法帆布只得到不透明像素

ctx = getCanvasImg(); 
for (var x = selection.x2 * zoom; x > selection.x1 * zoom; x--) { 
    for (var y = selection.y2 * zoom; y > selection.y1 * zoom; y--) { 
     var pixel = ctx.getImageData(x, y, 1, 1); 
     var data = pixel.data; 
     var rgba = 'rgba(' + data[0] + ',' + data[1] + ',' + data[2] + ',' + (data[3]/255) + ')'; 
     if (data[0] == 0) { 
      countWhite++; 
     } 
    } 
} 
+0

您的解決方案有問題嗎? –

回答

5

只要抓住有需要的地區一次:

var idata = ctx.getImageData(startX, startY, widthOfArea, heightOfArea); 

統計所有不透明像素,可以重複使用,而不是Uint32Array

var data = new Uint32Array(idata.data.buffer); 

// little-endian byte order 
for(var i = 0, len = data.length, count = 0; i < len;) { 
    if (data[i++] >>> 24 === 255) count++; // shifts AABBGGRR to 000000AA, then =255? 
} 

// count = number of opaque pixels 

更新:只是爲了澄清意見:這假設little-endian CPU架構。現在大多數主流/消費設備都使用這種CPU架構,這通常不是問題。然而,如果你懷疑你的代碼會遇到big-endian系統,你必須事先檢查它,並在檢查中顛倒字節順序(對於任何使用類型數組視圖的視圖都要比8位寬,因爲它們將使用本機系統建築)。

要檢查字節序的系統上,你可以這樣做:

function isLittleEndian() { 
    return new Uint16Array(new Uint8Array([255,0]).buffer)[0] === 255 
} 

如果大端,檢查這種方式,而不是使用and面具,而不是位移位:

// big-endian byte order 
for(var i = 0, len = data.length, count = 0; i < len;) { 
    if (data[i++] & 0xff === 255) count++; // masks RRGGBBAA to 000000AA, then =255? 
} 

您始終可以使用DataView s並指定endianess,但在這種情況下,由於存在輕微的開銷,這是沒有好處的。