Almacenamiento en caché de mapas de bits

Utilice la función de almacenamiento en caché de mapas de bits para el contenido vectorial complejo, si resulta necesario.

Se puede realizar una buena optimización utilizando la función de almacenamiento en caché de mapa de bits. Esta función almacena en caché un objeto vectorial, lo representa como un mapa de bits internamente y utiliza este mapa de bits para la representación. El resultado puede ser un enorme aumento de rendimiento para la representación, pero se requiere una cantidad considerable de memoria. Utilice el almacenamiento en caché de mapas de bits para el contenido vectorial complejo, como los degradados complejos o el texto.

La activación del almacenamiento en caché de mapas de bits para un objeto animado que contiene gráficos vectoriales complejos (por ejemplo, texto o degradados) mejora el rendimiento. Sin embargo, si el almacenamiento en caché de mapas de bits está activado en un objeto de visualización como un clip de película cuya línea de tiempo se está reproduciendo, se obtiene el resultado contrario. En cada fotograma, el motor de ejecución debe actualizar el mapa de bits en caché y posteriormente redibujarlo en pantalla, lo que requiere diversos ciclos de CPU. La función de almacenamiento en caché de mapas de bits sólo supone una ventaja cuando el mapa de bits en caché se puede generar una vez y posteriormente utilizarse sin necesidad de actualizarlo.

Si se activa el almacenamiento en caché de mapas de bits para un objeto Sprite, el objeto se puede mover sin hacer que el motor de ejecución vuelva a generar el mapa de bits en caché. El cambio de las propiedades x e y del objeto no implica una regeneración. No obstante, cualquier intento de rotarlo, escalarlo o cambiar su valor alfa hace que el motor de ejecución vuelva a generar el mapa de bits en caché y, como resultado, se daña el rendimiento.

Nota: la propiedad DisplayObject.cacheAsBitmapMatrix disponible en AIR y Packager for iPhone no presenta esta limitación. Mediante la propiedad cacheAsBitmapMatrix , es posible girar, escalar, sesgar y cambiar el valor alfa de un objeto de visualización sin necesidad de regenerar el mapa de bits que active este proceso.

Un mapa de bits en caché utiliza más memoria que una instancia de clip de película normal. Por ejemplo, si el clip de película del escenario es 250 x 250 píxeles, cuando se almacena en caché utiliza alrededor de 250 KB, en lugar de 1 KB sin almacenarse en caché.

El siguiente ejemplo incluye un objeto Sprite que contiene una imagen de una manzana. La siguiente clase se añade al símbolo de la manzana:

package org.bytearray.bitmap 
{     
    import flash.display.Sprite; 
    import flash.events.Event; 
     
    public class Apple extends Sprite 
    { 
        private var destinationX:Number; 
        private var destinationY:Number; 
         
        public function Apple () 
        { 
            addEventListener(Event.ADDED_TO_STAGE,activation); 
            addEventListener(Event.REMOVED_FROM_STAGE,deactivation);     
        } 
         
        private function activation(e:Event):void  
        { 
            initPos();     
            addEventListener (Event.ENTER_FRAME,handleMovement);     
        } 
         
        private function deactivation(e:Event):void  
        { 
            removeEventListener(Event.ENTER_FRAME,handleMovement);     
        } 
         
        private function initPos():void 
        { 
            destinationX = Math.random()*(stage.stageWidth - (width>>1)); 
            destinationY = Math.random()*(stage.stageHeight - (height>>1)); 
        } 
         
        private function handleMovement(e:Event):void  
        { 
            x -= (x - destinationX)*.5; 
            y -= (y - destinationY)*.5; 
             
            if (Math.abs(x - destinationX) < 1 && Math.abs(y - destinationY) < 1) 
                initPos(); 
        } 
    } 
}

El código utiliza la clase Sprite en lugar de MovieClip porque la línea de tiempo no es necesaria para cada manzana. Para obtener un mejor rendimiento, utilice el objeto más ligero posible. A continuación, se crea una instancia de la clase con el siguiente código:

import org.bytearray.bitmap.Apple; 
 
stage.addEventListener(MouseEvent.CLICK,createApples); 
stage.addEventListener(KeyboardEvent.KEY_DOWN,cacheApples); 
 
const MAX_NUM:int = 100; 
var apple:Apple; 
var holder:Sprite = new Sprite(); 
 
addChild(holder); 
 
function createApples(e:MouseEvent):void 
{ 
    for (var i:int = 0; i< MAX_NUM; i++) 
    { 
        apple = new Apple(); 
         
        holder.addChild(apple); 
    } 
} 
 
function cacheApples(e:KeyboardEvent):void 
{ 
    if (e.keyCode == 67) 
    { 
        var lng:int = holder.numChildren; 
         
        for (var i:int = 0; i < lng; i++) 
        { 
            apple = holder.getChildAt (i) as Apple; 
             
            apple.cacheAsBitmap = Boolean(!apple.cacheAsBitmap); 
        } 
    } 
}

Cuando el usuario hace clic con el ratón, las manzanas se crean sin almacenamiento en caché. Cuando el usuario presiona la tecla C (código de tecla 67), los vectores de la manzana se almacenan en caché como mapas de bits y se muestran en pantalla. Esta técnica mejora en gran medida el rendimiento de la representación, tanto en el escritorio como en los dispositivos móviles, cuando la CPU es lenta.

No obstante, aunque el uso de la función de almacenamiento en caché de mapas de bits mejora el rendimiento de representación, puede consumir con rapidez grandes cantidades de memoria. Cuando un objeto se almacena en caché, su superficie se captura como un mapa de bits transparente () y se almacena en memoria, tal y como se muestra en el diagrama siguiente:

Objeto y su mapa de bits de superficie almacenado en memoria

Flash Player 10.1 y AIR 2.5 optimizan el uso de la memoria adoptando el mismo enfoque, tal y como se describe en Filtros y descarga dinámica de mapas de bits . Si un objeto de visualización en caché está oculto o fuera de pantalla, su mapa de bits en memoria se libera cuando no se utiliza durante un tiempo.

Nota: si la propiedad opaqueBackground del objeto de visualización se establece en un color específico, el motor de ejecución considera que el objeto de visualización es opaco. Cuando se utiliza con la propiedad cacheAsBitmap , el motor de ejecución crea un mapa de bits de 32 bits no transparente en memoria. El canal alfa se establece en 0xFF, lo cual mejora el rendimiento, ya que no se requiere ninguna transparencia para dibujar el mapa de bits en pantalla. Al evitar la mezcla alfa se agiliza aún más la representación. Si la profundidad de pantalla actual se limita a 16 bits, el mapa de bits en memoria se almacena como una imagen de 16 bits. La utilización de la propiedad opaqueBackground no activa implícitamente el almacenamiento en caché de mapas de bits.

Para ahorrar memoria, utilice la propiedad cacheAsBitmap y actívela en cada objeto de visualización en lugar de en el contenedor. La activación del almacenamiento en caché de mapas de bits en el contenedor hace que el mapa de bits final presente un tamaño mucho mayor en memoria, creando un mapa de bits transparente con dimensiones de 211 x 279 píxeles. La imagen utiliza unos 229 KB de memoria:

Ver gráfico a tamaño completo
Activación del almacenamiento en caché de mapas de bits en el contenedor

Asimismo, al almacenar en caché el contenedor, se arriesga a tener todo el mapa de bits actualizado en memoria, si alguna manzana comienza a moverse en un fotograma. La activación del almacenamiento en caché de mapas de bits en instancias independientes implica el almacenamiento en caché de seis superficies de 7 KB en memoria, que únicamente utiliza 42 KB de memoria:

Ver gráfico a tamaño completo
Activación del almacenamiento en caché de mapas de bits en instancias

Al acceder a cada instancia de la manzana mediante la lista de visualización y llamar al método getChildAt() , las referencias se almacenan en un objeto Vector para un acceso más fácil:

import org.bytearray.bitmap.Apple; 
 
stage.addEventListener(KeyboardEvent.KEY_DOWN, cacheApples); 
 
const MAX_NUM:int = 200; 
var apple:Apple; 
var holder:Sprite = new Sprite(); 
 
addChild(holder); 
 
var holderVector:Vector.<Apple> = new Vector.<Apple>(MAX_NUM, true); 
 
for (var i:int = 0; i< MAX_NUM; i++) 
{ 
    apple = new Apple(); 
     
    holder.addChild(apple); 
     
    holderVector[i] = apple; 
} 
 
function cacheApples(e:KeyboardEvent):void 
{ 
    if (e.keyCode == 67) 
    { 
        var lng:int = holderVector.length 
         
        for (var i:int = 0; i < lng; i++) 
        { 
            apple = holderVector[i]; 
             
            apple.cacheAsBitmap = Boolean(!apple.cacheAsBitmap); 
        } 
    } 
}

Se debe tener en cuenta que el almacenamiento en caché de mapas de bits mejora la representación si el contenido en caché no se gira, se escala o se modifica en cada fotograma. Sin embargo, para cualquier transformación distinta de la traslación de los ejes x e y, la representación no mejora. En estos casos, Flash Player actualiza la copia del mapa de bits almacenada en caché para cada transformación que se produzca en el objeto de visualización. La actualización de la copia en caché puede implicar una mayor utilización de la CPU, bajo rendimiento y mayor uso de la batería. Una vez más, la propiedad cacheAsBitmapMatrix en AIR o Packager for iPhone no presenta esta limitación.

El siguiente código cambia el valor alfa en el método de movimiento, lo que modifica la opacidad de la manzana en cada fotograma:

private function handleMovement(e:Event):void  
{ 
        alpha = Math.random(); 
        x -= (x - destinationX)*.5; 
        y -= (y - destinationY)*.5; 
             
        if (Math.abs(x - destinationX) < 1 && Math.abs(y - destinationY) < 1) 
            initPos(); 
}

El uso del almacenamiento en caché de mapas de bits implica una disminución del rendimiento. El cambio del valor alfa provoca que el motor de ejecución actualice el mapa de bits almacenado en caché en memoria siempre que se modifique el valor alfa.

Los filtros se basan en los mapas de bits que se actualizan siempre que se mueva la cabeza lectora de un clip de película almacenado en caché. Por lo tanto, la utilización de un filtro automáticamente establece la propiedad cacheAsBitmap en true . La siguiente figura ilustra un clip de película animado:

Clip de película animado.

Evite la utilización de los filtros en contenido animado, ya que se pueden producir problemas de rendimiento. En la siguiente figura, el diseñador añade un filtro de sombra:

Clip de película animado con el filtro de sombra.

Como resultado, si la línea de tiempo dentro del clip de película se está reproduciendo, el mapa de bits se debe regenerar. El mapa de bits también debe regenerarse si el contenido se modifica de cualquier forma distinta a una simple transformación x o y. Cada fotograma provoca que el motor de ejecución vuelva a dibujar el mapa de bits, lo que requiere más recursos de CPU, causa problemas de bajo rendimiento y consume más duración de la batería.

Paul Trani proporciona ejemplos de uso de Flash Professional y ActionScript para optimizar los gráficos con mapas de bits en los siguientes vídeos de formación: