2

AS3を使用して(32ビットARGB)PNG画像をチェックし、(半)透明ピクセル(returningtrueまたはfalse)が含まれているかどうかを確認したいと思います。これを行うための最速の方法は何ですか?

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 バイト (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
于 2012-11-26T17:09:04.377 に答える