Het in cache plaatsen van bitmaps

Gebruik, waar mogelijk, de functie voor het in cache plaatsen van bitmaps voor complexe vectorcontent.

U kunt voor een goede optimalisering zorgen door de functie voor het in de cache plaatsen van bitmaps te gebruiken. Met deze functie wordt een vectorobject in de cache geplaatst, als bitmap intern gerenderd en wordt deze bitmap voor rendering gebruikt. Het resultaat kan een enorme verhoging van de renderprestaties zijn, maar er is mogelijk een grote hoeveelheid geheugen voor nodig. Gebruik de functie voor het in cache plaatsen van bitmaps voor complexe vectorcontent, zoals complexe overgangen of tekst.

Het inschakelen van bitmapcaches voor een geanimeerd object met complexe vectorillustraties (zoals tekst of verlopen) verbetert de prestaties. Maar als het in de cache plaatsen van bitmaps·is ingeschakeld voor een weergaveobject, zoals een filmclip waarvan de tijdlijn wordt afgespeeld, krijgt u het tegenovergesteld resultaat. Voor elk frame moet de runtime de bitmap in de cache bijwerken en deze vervolgens opnieuw op het scherm tekenen. Hiervoor is een groot aantal CPU-cycli nodig. De functie voor bitmapcaching heeft alleen voordelen wanneer de bitmap in de cache eenmaal gegenereerd kan worden en vervolgens kan worden gebruikt zonder dat de bitmap hoeft te worden bijgewerkt.

Als u bitmapcaching inschakelt voor een Sprite-object, kunt u het object verplaatsen zonder dat de runtime de bitmap in de cache opnieuw hoeft te genereren. Het wijzigen van de x - en y -eigenschappen van het object leidt niet tot het opnieuw genereren van het object. Wanneer echter wordt geprobeerd het object te roteren, te schalen of de alfawaarde van het object te wijzigen, moet de runtime de bitmap in de cache opnieuw genereren. Dit heeft een nadelige invloed op de prestaties.

Opmerking: De eigenschap DisplayObject.cacheAsBitmapMatrix die beschikbaar is in AIR of Packager for iPhone, kent deze beperking niet. Als u de eigenschap cacheAsBitmapMatrix gebruikt, kunt u een weergaveobject roteren, schalen, schuintrekken en de alfawaarde van een object wijzigen zonder dat een bitmap opnieuw wordt gegenereerd.

Een in cache geplaatste bitmap kan aanzienlijk meer geheugen gebruiken dan een standaardfilmclipinstantie. Als de filmclip in het werkgebied bijvoorbeeld 250 x 250 pixels bedraagt, zal deze ongeveer 250 KB gebruiken als deze in de cache is geplaatst in plaats van 1 KB als deze niet in de cache is geplaatst.

Het volgende voorbeeld toont een Sprite-object dat een afbeelding van een appel bevat. De volgende klasse is verbonden met het symbool van de appel:

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

De code gebruikt de Sprite-klasse in plaats van de MovieClip-klasse omdat geen tijdlijn nodig is voor elke appel. Voor de beste prestaties gebruikt u het meest lichtgewichte object mogelijk. Vervolgens wordt de klasse geïnstantieerd met de volgende code:

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

Als de gebruiker op de muis klikt, worden de appels gemaakt zonder caching. Als de gebruiker op de C-toets (toetscode 67) drukt, worden de appelvectoren als bitmaps in de cache geplaatst en op het scherm weergegeven. Met deze techniek worden de renderprestaties aanzienlijk verhoogd, zowel op het bureaublad als op mobiele telefoons, wanneer de processor langzaam is.

Hoewel het gebruik van de functie voor het in cache plaatsen van bitmaps de renderprestaties verhoogt, zorgt deze functie mogelijk ook voor een hoge geheugenconsumptie. Zodra een object in de cache wordt geplaatst, wordt het oppervlak ervan vastgelegd als een transparante bitmap en in het geheugen opgeslagen, zoals weergegeven in het volgende diagram:

Object en oppervlakbitmap opgeslagen in het geheugen

Met Flash Player 10.1 en AIR2.5 wordt het geheugenverbruik geoptimaliseerd op de manier die wordt beschreven in het hoofdstuk Filters en dynamische bitmapontladingen . Als een weergaveobject is verborgen of niet zichtbaar is op het scherm en de bijbehorende bitmap in het geheugen een tijdje niet wordt gebruikt, wordt deze vrijgegeven.

Opmerking: Als de eigenschap opaqueBackground van het weergaveobject is ingesteld op een bepaalde kleur, neemt de runtime aan dat het weergaveobject ondoorzichtig is. Wanneer het object wordt gebruikt met de eigenschap cacheAsBitmap , maakt de runtime een niet-transparante 32-bits bitmap in het geheugen. Het alfakanaal wordt ingesteld op 0xFF, wat de prestaties verhoogt, omdat er geen transparantie vereist is om de bitmap op het scherm te tekenen. Als alfa-overvloeiing kan worden voorkomen, gaat de rendering nog sneller. Als de huidige schermdiepte beperkt is tot 16 bits, wordt de bitmap in het geheugen opgeslagen als een 16-bits afbeelding. Gebruik van de eigenschap opaqueBackground activeert bitmapcaching niet op impliciete wijze.

Om geheugen te besparen, gebruikt u de eigenschap cacheAsBitmap en activeert u deze op elk weergaveobject in plaats van op de container. Het in cache plaatsen van bitmaps op de container activeren zorgt ervoor dat de uiteindelijke bitmap veel meer geheugen nodig heeft omdat een transparante bitmap wordt gemaakt met afmetingen van 211 x 279 pixels. De afbeelding gebruikt ongeveer 229 KB geheugen:

Afbeelding groot weergeven
Het in cache plaatsen van bitmaps op de container activeren

Als u de container in het cachegeheugen plaatst, loopt u bovendien het risico dat de hele bitmap in het geheugen wordt bijgewerkt wanneer een appel op een frame wordt verplaatst. Als u het in cache plaatsen van bitmaps activeert op afzonderlijke instanties, worden zes oppervlakken van 7 KB in het geheugen opgeslagen, wat een totaal van 42 KB betekent.

Afbeelding groot weergeven
Het in cache plaatsen van bitmaps op instanties activeren

Als u toegang krijgt tot elke appelinstantie via de weergavelijst en de methode getChildAt() aanroept, worden referenties opgeslagen in een Vector-object voor eenvoudigere toegang:

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

Vergeet niet dat bitmapcaching tot betere rendering leidt als de cachecontent niet op elk frame wordt geroteerd, geschaald of gewijzigd. Bij elke andere transformatie behalve translatie op de X- en Y-as wordt de rendering echter niet verbeterd. In deze gevallen werkt de Flash Player de bitmapkopie in de cache bij voor elke transformatie die plaatsvindt op het weergaveobject. Het bijwerken van de kopie in de cache kan resulteren in een hoog verbruik van de processor en de batterij en in langzame prestaties. En weer geldt dat de eigenschap cacheAsBitmapMatrix die beschikbaar is in AIR of Packager for iPhone, deze beperking niet kent.

De volgende code wijzigt de alfawaarde in de bewegingsmethode waardoor de dekking van de appel op elke frame wordt gewijzigd.

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

Het in cache plaatsen van bitmaps gebruiken leidt tot verminderde prestaties. Als de alfawaarde wordt gewijzigd, wordt de runtime gedwongen de bitmap in de cache bij te werken wanneer de alfawaarde wordt gewijzigd.

Filters vertrouwen op bitmaps die worden bijgewerkt wanneer de afspeelknop van een filmclip in de cache wordt verplaatst. Als dus een filter wordt gebruikt, wordt de eigenschap cacheAsBitmap automatisch ingesteld op true . De volgende afbeelding illustreert een geanimeerde filmclip:

Filmclip met animatie

Vermijd het gebruik van filters op geanimeerde inhoud omdat dit voor prestatieproblemen kan zorgen. In de volgende afbeelding voegt de ontwerper een slagschaduwfilter toe:

Filmclip met animatie en filter voor slagschaduw

Het resultaat is dat de bitmap opnieuw gegenereerd moet worden wanneer de tijdlijn in de filmclip wordt afgespeeld. De bitmap moet ook opnieuw gegenereerd worden als de content op andere wijze wordt gewijzigd dan via een eenvoudige x- of y-transformatie. Elke frame dwingt de runtime de bitmap opnieuw te tekenen, zodat meer processorbronnen moeten worden gebruikt, de prestaties afnemen en het batterijverbruik toeneemt.

Paul Trani verschaft in de volgende educatieve video's voorbeelden van de manier waarop u met Flash Professional en ActionScript bitmaps kunt gebruiken om afbeeldingen te optimaliseren: