使用AS3检查PNG图像是否包含(半)透明像素

时间:2012-11-26 16:14:49

标签: actionscript-3 image-processing png pixel transparent

我想使用AS3检查(32位ARGB)PNG图像,看它是否包含任何(半)透明像素(返回truefalse)。最快的方法是什么?

2 个答案:

答案 0 :(得分:5)

很久以前我一直在寻找相同的东西,我尝试使用循环来检查每个像素。但是这花了很多时间并消耗了大量的CPU。幸运的是,我们有BitmapData.compare()方法,如果在比较的BitmapData对象中存在任何差异,它会输出Bitmapdata。

还有BitmapData.transparent属性,它实际上直接为您提供布尔值的答案。但我自己从来没有直接在加载的图像上使用它。

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;
}

答案 1 :(得分:2)

不幸的是,我知道这样做只是手动。可能有内置的方法,但我的猜测是它会使用下面描述的相同方法

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
    }
}

请记住,ByteArray将为每个像素提供32位(或4字节(每字节8位)数据)。循环结束后,你绝对应该为bytes.clear();做一个内存,你应该{@ 1}}你想要的第二个循环(否则它会一直运行,直到它检查每个像素在你的图像中。为了比较,256x256图像将运行65,536次。

为了清楚起见:

  • RGBA / ARGB的测量值为0-255
  • 0为黑色(0x000000),255为白色(0xffffff)
  • 字母字节越黑,越透明
  • 我们使用简单的按位移位来获取该字节的实际值(位24-32)并将其设置为0到255之间的值
  • 您也可以为RGB通道执行此操作。 B为break;,G为>> 0 & 255,R为>> 8 & 255