2017-02-17 8 views
1

Как сосчитать прозрачные пиксели области на холсте изображения, я написал эту функцию, но я предполагаю, что есть что-то вроде другого методаCanvas получить только непрозрачные пиксели

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 

Обновление: просто уточнить в отношении комментариев: это do Предположим, что архитектура с минимальным уровнем детализации. Большинство основных/потребительских устройств в настоящее время используют эту архитектуру процессора, и это обычно не проблема. Однако, если вы подозреваете, что ваш код столкнется с системами на базе большого числа, вы должны заранее проверить это и отменить порядок байтов в проверке (для чего-либо, используя типизированные массивы, более 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, однако в этом случае это не принесет пользы из-за небольших накладных расходов.