canvas - Check if all pixels in a region are all empty in Javascript? -
i have 2d canvas things drawn , want know if pixels in region (rect - x,y,w,h) empty/fully transparent? know can done getimagedata there faster way? writing simple java script image packer , wish exclude empty images final sheet.
the way read pixels use getimagedata()
, can speed sort of checks using different view default uint8clampedarray
, example uint32array
allows read single pixel per iteration:
function isempty(ctx, x, y, w, h) { var idata = ctx.getimagedata(x, y, w, h), // needed usual ... u32 = new uint32array(idata.data.buffer), // reads 1x uint32 instead of 4x uint8 = 0, len = u32.length; while(i < len) if (u32[i++]) return false; // if !== 0 return false, not empty return true // empty, ok }
however, cannot used check transparency though. if pixel transparent there may color data present in other channels. example, produce invisible pixel: rgba(255,128,0,0)
, isempty()
report area non-empty if pixel isn't visible.
to check cases you'll have check alpha channel only, , modify above use , mask filter out color data, or, shift alpha channel bits over, pushing other bits out - in either case after non-0 values.
as in little-endian (lsb) format (as on main stream computers nowadays), components in order abgr (0xaabbggrr
) can either:
u32[i] & 0xff000000
or use shift (sign not matter in case, prefer use unsigned shift (>>> rather >>) when deal unsigned numbers begin with):
u32[i]>>>24
performance wise there little difference, guess anding faster if anything:
anding
function istransparent(ctx, x, y, w, h) { var idata = ctx.getimagedata(x, y, w, h), // needed usual ... u32 = new uint32array(idata.data.buffer), // reads 1x uint32 instead of 4x bytes = 0, len = u32.length; while(i < len) if (u32[i++] & 0xff000000) return false; // not transparent? return true // transparent, ok }
bit-shifting
function istransparent(ctx, x, y, w, h) { var idata = ctx.getimagedata(x, y, w, h), // needed usual ... u32 = new uint32array(idata.data.buffer), // reads 1x uint32 instead of 4x bytes = 0, len = u32.length; while(i < len) if (u32[i++]>>>24) return false; // not transparent? return true // transparent, ok }
update:
speed tricks
if know data you're checking of @ least size, lets 2x2 pixels, can improve speed skipping every other pixel, every other line:
while(i < len) if (u32[(i += 2)]>>>24) return false; // skips every 2. pixel
for lines, need 2 iterators:
while(i < len) { var endline = + width, p = i; // p in case deal odd widths while(p < endline) if (u32[(p += 2)]>>>24) return false; // skip every 2. pixel += width * 2; // skip line }
Comments
Post a Comment