Referência única de BitmapData

É importante otimizar o uso da classe BitmapData pela reutilização de ocorrências sempre que possível. O Flash Player 10.1 e o AIR 2.5 introduzem um novo recurso para todas as plataformas chamado referência única de BitmapData. Quando criamos ocorrências BitmapData de uma imagem incorporada, uma versão única do bitmap é utilizada para todas as ocorrências de BitmapData. Se um bitmap for modificado posteriormente, recebe seu próprio bitmap exclusivo na memória. A imagem incorporada pode ser da biblioteca ou uma tag [Embed].

Nota: O conteúdo existente também se beneficia deste novo recurso, visto que o Flash Player 10.1 e o AIR 2.5 reutilizam bitmaps automaticamente.

Quando estiver criando uma instância de uma imagem incorporada, um bitmap associado é criado na memória. Antes do Flash Player 10.1 e do AIR 2.5, cada instância recebia um bitmap separado na memória, conforme mostrado no seguinte diagrama:

Bitmaps na memória antes do Flash Player 10.1 e do AIR 2.5

No Flash Player 10.1 e no AIR 2.5, quando várias instâncias da mesma imagem são criadas, um única versão do bitmap é usada para todas as instâncias de BitmapData. O diagrama a seguir ilustra este conceito:

Bitmaps na memória no Flash Player 10.1 e AIR 2.5

Esta abordagem reduz drasticamente a quantidade de memória usada por um aplicativo com muitos bitmaps. O código a seguir cria várias instâncias de um símbolo 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) 
    } 
}

A imagem a seguir mostra o resultado do código:

Exibir gráfico inteiro
Resultado do código para criar várias instâncias do símbolo

Com o Flash Player 10, por exemplo, a animação acima usa cerca de 1008 KB de memória. Com o Flash Player 10.1, no desktop e em um dispositivo móvel, a animação usa somente 4 KB.

O código a seguir modifica uma instância de 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);

A imagem a seguir mostra o resultado da modificação de uma instância de Star :

Exibir gráfico inteiro
Resultado da modificação de uma instância

Internamente, o tempo de execução automaticamente atribui e cria um bitmap na memória para lidar com as modificações dos pixels. Quando um método da classe BitmapData é chamado, causando modificações de pixel, uma nova ocorrência é criada na memória e nenhuma outra ocorrência é atualizada. A figura a seguir ilustra o conceito:

Resultado na memória da modificação de um bitmap

Se uma estrela é modificada, uma nova cópia é criada na memória. A animação resultante usa cerca de 8 KB na memória no Flash Player 10.1 e no AIR 2.5.

No exemplo anterior, cada bitmap está individualmente disponível para transformação. Para criar apenas o efeito lado a lado, o método beginBitmapFill() é o mais apropriado:

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

Esta abordagem produz o mesmo resultado com a criação de uma única instância de BitmapData. Para girar as estrelas continuamente, ao invés de acessar cada ocorrência Estrela, utilize um objeto Matriz que é rotacionado em cada quadro. Forneça este objeto Matriz para o método 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); 
}

Utilizando esta técnica, nenhuma repetição ActionScript será necessária para criar o efeito. O tempo de execução faz tudo internamente. A imagem a seguir mostra o resultado da transformação das estrelas:

Exibir gráfico inteiro
Resultado das estrelas girando

Com esta abordagem, atualizar o objeto BitmapData original atualiza automaticamente seu uso em outros locais do palco, o que pode ser uma técnica poderosa. Esta abordagem não permitiria, contudo, que cada estrela fosse dimensionada individualmente, como no exemplo anterior.

Nota: Quando várias instâncias da mesma imagem são usadas, o desenho depende de se há uma classe associada ao bitmap original na memória. Se nenhuma classe estiver associada ao bitmap, as imagens serão desenhadas como objetos Shape com preenchimentos de bitmap.