Es importante optimizar el uso de la clase BitmapData, reutilizando instancias siempre que sea posible. Flash Player 10.1 y AIR 2.5 introducen una nueva función para todas las plataformas denominada referencia única de BitmapData. Al crear instancias de BitmapData a partir de una imagen incorporada, se utiliza una sola versión del mapa de bits para todas las instancias de BitmapData. Si un mapa de bits se modifica con posterioridad, se le asigna su propio mapa de bits en memoria. La imagen incorporada puede proceder de la biblioteca o ser una etiqueta [Embed].
Nota:
el contenido existente también se beneficia de esta nueva función, ya que Flash Player 10.1 y AIR 2.5 reutiliza automáticamente los mapas de bits.
Cuando se crea una instancia de una imagen incorporada, un mapa de bits asociado se crea en memoria. Antes de Flash Player 10.1 y AIR 2.5, a cada instancia se le asignaba un mapa de bits independiente en memoria, tal y como se muestra en el siguiente diagrama:
Mapas de bits en memoria antes de Flash Player 10.1 y AIR 2.5
En Flash Player 10.1 y AIR 2.5, cuando se crean varias instancias de la misma imagen, se utiliza una sola versión del mapa de bits para todas las instancias de BitmapData. El siguiente diagrama ilustra este concepto:
Mapas de bits en memoria en Flash Player 10.1 y AIR 2.5
Con este enfoque se reduce en gran medida la cantidad de memoria que utiliza la aplicación con diversos mapas de bits. El siguiente código crea varias instancias de un 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)
}
}
La siguiente imagen muestra el resultado del código:
Con Flash Player 10, por ejemplo, la animación anterior utiliza unos 1.008 KB de memoria. Con Flash Player 10.1, en el escritorio y en dispositivos móviles, la animación solo utiliza 4 KB.
El siguiente código modifica una instancia 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);
La imagen siguiente muestra el resultado de la modificación de una instancia de
Star
:
Internamente, el motor de ejecución crea y asigna de forma automática un mapa de bits en memoria para administrar las modificaciones de píxeles. Cuando se llama a un método de la clase BitmapData, lo que implica modificaciones de píxel, se crea una nueva instancia en memoria y no se actualiza ninguna otra instancia. La siguiente figura ilustra el concepto:
Resultado en memoria de la modificación de un mapa de bits
Si se modifica una estrella, se crea una copia nueva en memoria. La animación resultante utiliza unos 8 KB en memoria con Flash Player 10.1 y AIR 2.5.
En el ejemplo anterior, cada mapa de bits está disponible individualmente para su transformación. Para crear únicamente el efecto mosaico, el método
beginBitmapFill()
es el más adecuado.
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);
Este enfoque produce el mismo resultado con sólo una única instancia creada de BitmapData. Para girar las estrellas de forma continua, en lugar de acceder a cada instancia de Star, utilice un objeto Matrix que se gire en cada fotograma. Transmita este objeto Matrix al 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);
}
Con el uso de esta técnica, no se requiere ningún bucle de ActionScript para crear el efecto. El motor de ejecución lo hace todo internamente. La siguiente imagen muestra el resultado de la transformación de las estrellas:
Con este enfoque, con la actualización del objeto de origen BitmapData original se actualiza automáticamente su uso en cualquier lugar del escenario, lo cual puede ser una técnica eficaz. Sin embargo, con este enfoque no se permitiría que se aplicara escala a cada estrella de forma individual, tal y como sucedía en el ejemplo anterior.
Nota:
al utilizar varias instancias de la misma imagen, el dibujo depende de si una clase se asocia al mapa de bits original en memoria. Si no existe ninguna clase asociada al mapa de bits, las imágenes se dibujan como objetos Shape con rellenos de mapa de bits.