Riferimento singolo BitmapData

È importante ottimizzare l'uso della classe BitmapData riutilizzando le istanze il più possibile. Flash Player 10.1 e AIR 2.5 introducono una nuova funzionalità per tutte le piattaforme, denominata "riferimento singolo BitmapData". Quando si creano istanze BitmapData da un'immagine incorporata, viene utilizzata un'unica versione della bitmap per tutte le istanze BitmapData. Solo se una bitmap viene modificata in un secondo momento, viene assegnato ad essa un riferimento bitmap specifico nella memoria. L'immagine incorporata può provenire dalla libreria o da un tag [Embed].

Nota: anche i contenuti esistenti possono sfruttare questa nuova funzionalità, poiché Flash Player 10.1 e AIR 2.5 riutilizzano automaticamente le bitmap.

Quando si crea un'istanza di un'immagine incorporata, viene creata in memoria una bitmap associata. Prima di Flash Player 10.1 e AIR 2.5, a ogni istanza veniva assegnata una bitmap separata in memoria, come mostra il diagramma seguente:

Bitmap in memoria prima di Flash Player 10.1 e AIR 2.5

In Flash Player 10.1 e AIR 2.5, quando si creano più istanze della stessa immagine, viene utilizzata un'unica versione della bitmap per tutte le istanze BitmapData. Il diagramma seguente illustra questo concetto:

Bitmap in memoria in Flash Player 10.1 e in AIR 2.5

Questo approccio riduce sensibilmente la quantità di memoria utilizzata da un'applicazione che deve gestire molte bitmap. Il codice seguente crea più istanze di un simbolo 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) 
    } 
}

L'immagine seguente mostra il risultato del codice:

Visualizzazione dell’elemento grafico a dimensioni intere
Risultato del codice che crea più istanze di un simbolo

Con Flash Player 10, ad esempio, l'animazione precedente utilizza circa 1008 KB di memoria. Con Flash Player 10.1, sia su un PC desktop che su un dispositivo mobile, l'animazione utilizza solo 4 KB.

Il codice seguente modifica una singola istanza 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);

L'immagine seguente mostra il risultato della modifica di un'istanza Star :

Internamente, il runtime assegna automaticamente e crea una bitmap in memoria per gestire le modifiche dei pixel. Quando viene chiamato un metodo della classe BitmapData, con conseguenti modifiche ai pixel, viene creata una nuova istanza in memoria e non vengono aggiornate altre istanze. La figura seguente illustra questo concetto:

Risultato in memoria della modifica di una bitmap

Se si modifica una stella, ne viene creata una nuova copia in memoria. L'animazione risultante utilizza circa 8 KB in memoria con Flash Player 10.1 e AIR 2.5.

Nell'esempio precedente, ogni bitmap è disponibile per la trasformazione. Per creare solo l'effetto a piastrelle, il metodo beginBitmapFill() è quello più appropriato:

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

Questo approccio produce lo stesso risultato con una singola istanza BitmapData creata. Per ruotare le stelle continuamente, anziché accedere a ogni istanza Star, usate un oggetto Matrix che viene ruotato su ogni fotogramma. Passate questo oggetto Matrix al metodo 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); 
}

Se si usa questa tecnica, non è necessario un ciclo ActionScript per creare l'effetto. Tutte le operazioni vengono eseguite internamente dal runtime. L'immagine seguente mostra il risultato della trasformazione delle stelle:

Con questo approccio, l'aggiornamento dell'oggetto di origine BitmapData originale aggiorna automaticamente le istanze di tale oggetto in altre parti dello stage, in base a una tecnica che si presta ad applicazioni molti sofisticate. Tuttavia, questo tipo di approccio non consentirebbe il ridimensionamento di ogni singola stella, come nell'esempio precedente.

Nota: quando si utilizzano più istanze della stessa immagine, il modo in cui le immagini vengono disegnate dipende dal fatto che una classe sia associata o meno alla bitmap originale in memoria. Se nessuna classe è associata alla bitmap, le immagini vengono disegnate come oggetti Shape con riempimenti bitmap.