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

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

gradle error "Cannot convert the provided notation to a File or URI" -

python - NameError: name 'subprocess' is not defined -