2

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

4

2 回答 2

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;
}
于 2012-11-26T17:33:54.240 回答
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();循环完成后,为了记忆,你绝对应该做一个循环,你也应该break;在你达到你想要的第二个循环(否则它将继续运行,直到它检查图像中的每个像素。一个 256x256 的图像将运行 65,536次,为了比较)。

只是为了清楚起见:

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