AS3を使用して(32ビットARGB)PNG画像をチェックし、(半)透明ピクセル(returningtrue
またはfalse
)が含まれているかどうかを確認したいと思います。これを行うための最速の方法は何ですか?
2 に答える
昔、同じものを探していて、ループを使って各ピクセルをチェックしようとしました。しかし、それには多くの時間がかかり、信じられないほどの量の 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;
}
残念ながら、私が知っている唯一の方法は手動です。それを行う方法が組み込まれている可能性がありますが、私の推測では、以下で説明するのと同じ方法を使用するでしょう
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 バイト (1 バイトあたり 8 ビット)) のデータがあることに注意してください。ループが終了したら、必ずbytes.clear();
メモリのために を実行する必要があります。またbreak;
、必要なものをヒットした瞬間にループを実行する必要があります (そうしないと、画像内のすべてのピクセルをチェックするまで実行し続けます。256x256 の画像は 65,536 を実行します)比較のため)。
わかりやすくするために:
- RGBA/ARGB は 0 ~ 255 の値で測定されます
- 0 は黒 (0x000000)、255 は白 (0xffffff)
- アルファ バイトが黒くなるほど、透明になります。
- 単純なビット単位のシフトを使用して、そのバイト (ビット 24 ~ 32) の実際の値を取得し、0 ~ 255 の値に設定します。
- これは、RGB チャネルに対しても実行できます。B は
>> 0 & 255
、G は>> 8 & 255
、R は>> 16 & 255