Reputation: 1403
I want to use AS3 to check a (32-bit ARGB) PNG image to see if it contains any (semi) transparent pixel (returning true
or false
). What is the fastest way to do this?
Upvotes: 2
Views: 2799
Reputation: 7470
A long time ago I was looking for the same thing and I tried using loops to check for each pixel. But that took a lot of time and consumed incredible amount of CPU. Luckily we have the BitmapData.compare()
method, which outputs a Bitmapdata if there are any diferences in compared BitmapData objects.
Also there's the BitmapData.transparent
property, which actually directly gives you the answer as a Boolean. But I have never used it directly on a loaded image myself.
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Point;
var ldr:Loader = new Loader();
var req:URLRequest = new URLRequest('someImage.png');
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE,imgLoaded);
ldr.load(req);
function imgLoaded(e:Event):void {
var l:Loader = e.target.loader,
bmp:Bitmap = l.content as Bitmap,
file:String = l.contentLoaderInfo.url.match(/[^\/\\]+$/)[0];
trace(bmp.bitmapData.transparent);
// I think this default property should do it but
// in case it does not, here's another approach:
var trans:Boolean = isTransparent(bmp.bitmapData);
trace(file,'is'+(trans ? '' : ' not'),'transparent');
}
function isTransparent(bmpD:BitmapData):Boolean {
var dummy:BitmapData = new BitmapData(bmpD.width,bmpD.height,false,0xFF6600);
// create a BitmapData with the size of the source BitmapData
// painted in a color (I picked orange)
dummy.copyPixels(bmpD,dummy.rect,new Point());
// copy pixels of the original image onto this orange BitmapData
var diffBmpD:BitmapData = bmpD.compare(dummy) as BitmapData;
// this will return null if both BitmapData objects are identical
// or a BitmapData otherwise
return diffBmpD != null;
}
Upvotes: 5
Reputation: 8149
Only way I know of doing it is manually, unfortunately. There may be a built in way of doing it, but my guess is it would use the same method described below
var bytes:ByteArray = ( loader.content as Bitmap ).bitmapData.getPixels(); //that getter may be incorrect. I'd verify the property names are correct first
var bLength:Number = bytes.length; //you'll gain considerable speed by saving the length to memory rather than accessing it repeatedly
for ( var i:Number = 0; i < bLength; i++ ) {
var alpha:uint = bytes[i] >> 24 & 255;
if ( alpha > 0 && alpha < 255 ) {
//put code in here that will run if it is semi transparent
}
if ( alpha == 255 ) {
//put code in here that will run if it is entirely opaque
}
if ( alpha == 0 ) {
//put code in here that will run if it is entirely transparent
}
}
Keep in mind that the ByteArray
will have 32 bits (or 4 bytes (8 bits per byte)) of data for each individual pixel. After the loop is finished, you should definitely do a bytes.clear();
for memory sake and you should also break;
the loop the second you hit what you want (otherwise it will keep running until it checks each and every pixel in your image. A 256x256 image will run 65,536 times, for comparison's sake).
Just for clarity:
>> 0 & 255
, G is >> 8 & 255
, and R is >> 16 & 255
Upvotes: 2