可能な限りインスタンスを再利用して、BitmapData クラスの使用を最適化することが重要です。Flash Player 10.1 および AIR 2.5 には、すべてのプラットフォームを対象に、BitmapData 単一参照と呼ばれる新機能が導入されています。埋め込み画像から BitmapData インスタンスを作成するときは、ビットマップの単一バージョンがすべての BitmapData インスタンスに使用されます。後でビットマップを変更すると、メモリ内に固有のビットマップが作成されます。埋め込み画像は、ライブラリから使用するか、[Embed] タグとすることができます。
注意:
Flash Player 10.1 および AIR 2.5 は、自動的にビットマップを再利用するので、既存のコンテンツもこの新機能を活用できます。
埋め込み画像をインスタンス化するときは、関連するビットマップがメモリ内に作成されます。Flash Player 10.1 および AIR 2.5 より前では、次の図に示すように、メモリ内でインスタンスごとに別々のビットマップが割り当てられていました。
Flash Player 10.1 および AIR 2.5 より前のメモリ内のビットマップ
Flash Player 10.1 および AIR 2.5 では、同じイメージのインスタンスが複数作成されると、すべての BitmapData インスタンスに対して、単一のビットマップが使用されます。次の図に、この概念を示します。
メモリ内のビットマップ(Flash Player 10.1 および AIR 2.5)
この手法は、ビットマップが多数含まれているアプリケーションのメモリ使用量を大幅に低減します。次のコードは、
Star
シンボルのインスタンスを複数作成します。
const MAX_NUM:int = 18;
var star:BitmapData;
var bitmap:Bitmap;
for (var i:int = 0; i<MAX_NUM; i++)
{
for (var j:int = 0; j<MAX_NUM; j++)
{
star = new Star(0,0);
bitmap = new Bitmap(star);
bitmap.x = j * star.width;
bitmap.y = i * star.height;
addChild(bitmap)
}
}
次の図は、コードの結果を示しています。
例えば、Flash Player 10 で上記のアニメーションを実行すると、約 1008 KB のメモリが使用されます。Flash Player 10.1 では、同じアニメーションをデスクトップとモバイルデバイスのどちらで実行した場合でも、わずか 4 KB のメモリしか使用されません。
次のコードでは、1 つの BitmapData インスタンスを変更します。
const MAX_NUM:int = 18;
var star:BitmapData;
var bitmap:Bitmap;
for (var i:int = 0; i<MAX_NUM; i++)
{
for (var j:int = 0; j<MAX_NUM; j++)
{
star = new Star(0,0);
bitmap = new Bitmap(star);
bitmap.x = j * star.width;
bitmap.y = i * star.height;
addChild(bitmap)
}
}
var ref:Bitmap = getChildAt(0) as Bitmap;
ref.bitmapData.pixelDissolve(ref.bitmapData, ref.bitmapData.rect, new Point(0,0),Math.random()*200,Math.random()*200, 0x990000);
次の図は、1 つの
Star
インスタンスを変更した結果を示しています。
内部的には、ランタイムがメモリ内でビットマップの割り当てと作成を自動的に行い、ピクセルの変更を処理します。BitmapData クラスのメソッドが呼び出され、ピクセルの変更につながると、メモリ内に新しいインスタンスが作成されます。それ以外のインスタンスは更新されません。次の図に、この概念を示します。
1 つのビットマップを変更した場合のメモリの結果
星を 1 つ変更すると、新しいコピーがメモリ内に作成されます。生成されるアニメーションは、Flash Player 10.1 および AIR 2.5 で約 8 KB のメモリを使用します。
上述の例では、各ビットマップは個別に変換に利用できるようになります。タイル効果のみを作成するには、
beginBitmapFill()
メソッドが最適なメソッドです。
var container:Sprite = new Sprite();
var source:BitmapData = new Star(0,0);
// Fill the surface with the source BitmapData
container.graphics.beginBitmapFill(source);
container.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
addChild(container);
この手法は、BitmapData インスタンスを 1 つ作成するだけで、同じ結果をもたらします。各 Star インスタンスにアクセスするのではなく、連続して星を回転させるには、各フレームで回転する Matrix オブジェクトを使用します。Matrix オブジェクトを
beginBitmapFill()
メソッドに渡します。
var container:Sprite = new Sprite();
container.addEventListener(Event.ENTER_FRAME, rotate);
var source:BitmapData = new Star(0,0);
var matrix:Matrix = new Matrix();
addChild(container);
var angle:Number = .01;
function rotate(e:Event):void
{
// Rotate the stars
matrix.rotate(angle);
// Clear the content
container.graphics.clear();
// Fill the surface with the source BitmapData
container.graphics.beginBitmapFill(source,matrix,true,true);
container.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
}
このテクニックを使用すると、効果を作成するために ActionScript ループは不要になります。ランタイムにより、すべてが内部的に実行されます。次の図は、星の変形の結果を示しています。
この手法では、BitmapData の元のソースオブジェクトを更新すると、ステージ上でこのオブジェクトを使用した別の表示が自動的に更新されるので、強力なテクニックになり得ます。この手法では、上述の例のように、それぞれの星を個別に拡大 / 縮小することはできません。
注意:
同じイメージのインスタンスを複数使用する場合は、メモリ内の元のビットマップにクラスが関連付けられているかどうかによって、描画方法は異なります。ビットマップに関連付けられているクラスがない場合、イメージは Shape オブジェクトとして描画され、ビットマップで塗りつぶされます。