Reputation: 73
How to count transperent pixels of the area at image canvas, i wrote this function, but i guess there is something like a another method
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++;
}
}
}
Upvotes: 1
Views: 171
Reputation:
Just grab the area in need once:
var idata = ctx.getImageData(startX, startY, widthOfArea, heightOfArea);
To count all opaque pixels, you can iterate using a Uint32Array
instead:
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
Update: Just to clarify in regards to comments: this do assume little-endian CPU architecture. Most mainstream/consumer devices nowadays uses this CPU architecture and this is usually not a problem. However, if you suspect your code will come across big-endian systems you have to check for this in advance and reverse the byte-order in the check (for anything using typed arrays views wider than 8-bits as they will use the native systems's architecture).
To check for endianess on a system you can do this:
function isLittleEndian() {
return new Uint16Array(new Uint8Array([255,0]).buffer)[0] === 255
}
And if big-endian, check this way instead using a and
mask instead of bit-shift:
// 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?
}
You can always use DataView
s and specify endianess, however in this case that is of no benefit due to the slight overhead.
Upvotes: 4