Bitmap-Beispiel: Animated Spinning Moon

Flash Player 9 und höher, Adobe AIR 1.0 und höher

Im Beispiel „Animated Spinning Moon“ werden anhand eines animierten, sich drehenden Monds Techniken für die Verwendung von Bitmap-Objekten und Bitmap-Bilddaten (BitmapData-Objekten) demonstriert. Mithilfe eines zweidimensionalen Bilds der Mondoberfläche als Ausgangsmaterial wird die Animation eines sich drehenden, kugelförmigen Monds erzeugt. Es werden folgende Techniken veranschaulicht:

  • Laden externer Bilder und Zugreifen auf die Bildrohdaten

  • Erstellen eines Animationseffekts durch wiederholtes Kopieren von Pixeln aus unterschiedlichen Teilen eines Quellbilds

  • Erstellen eines Bitmapbilds durch Festlegen von Pixelwerten

Die Anwendungsdateien für dieses Beispiel finden Sie unter www.adobe.com/go/learn_programmingAS3samples_flash_de . Die Dateien der Anwendung „Animated Spinning Moon“ befinden sich im Ordner „Samples/SpinningMoon“. Die Anwendung umfasst die folgenden Dateien:

Datei

Beschreibung

SpinningMoon.mxml

oder

SpinningMoon.fla

Die Hauptanwendungsdatei in Flex (MXML) oder Flash (FLA).

com/example/programmingas3/moon/MoonSphere.as

Die Klasse mit den Funktionen zum Laden, Anzeigen und Animieren des Monds.

moonMap.png

Bilddatei mit einem Foto der Mondoberfläche, die geladen und zum Erstellen des animierten, sich drehenden Monds verwendet wird.

Laden externer Bilder als Bitmap-Daten

Die erste Teilaufgabe in diesem Beispiel ist das Laden einer externen Bilddatei, die in diesem Fall ein Foto der Mondoberfläche ist. Der Ladevorgang wird mit zwei Methoden der MoonSphere-Klasse durchgeführt: dem MoonSphere() -Konstruktor, mit dem der Ladevorgang eingeleitet wird, und der imageLoadComplete() -Methode, die aufgerufen wird, wenn das externe Bild vollständig geladen wurde.

Das Laden externer Bilder entspricht dem Laden externer SWF-Dateien. In beiden Fällen wird zum Durchführen des Ladevorgangs eine Instanz der flash.display.Loader-Klasse verwendet. Der Code in der MoonSphere() -Methode, mit dem das Laden des Bilds gestartet wird, lautet wie folgt:

var imageLoader:Loader = new Loader(); 
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadComplete); 
imageLoader.load(new URLRequest("moonMap.png"));

In der ersten Zeile wird die Loader-Instanz mit dem Namen imageLoader deklariert. In der dritten Zeile wird dann der Ladevorgang tatsächlich gestartet, indem die load() -Methode des Loader-Objekts aufgerufen und eine URLRequest-Instanz übergeben wird, die die URL des zu ladenden Bilds enthält. In der zweiten Zeile wird der Ereignis-Listener festgelegt, der ausgelöst wird, wenn das Bild vollständig geladen wurde. Beachten Sie, dass die addEventListener() -Methode nicht für die Loader-Instanz selbst aufgerufen wird, sondern für die contentLoaderInfo -Eigenschaft des Loader-Objekts. Die Loader-Instanz selbst löst keine Ereignisse aus, die sich auf die zu ladenden Inhalte beziehen. Die contentLoaderInfo -Eigenschaft der Instanz enthält jedoch einen Verweis auf das LoaderInfo-Objekt, das den in das Loader-Objekt zu ladenden Inhalten zugeordnet ist (in diesem Fall das externe Bild). Dieses LoaderInfo-Objekt enthält mehrere Ereignisse mit Bezug auf den Fortschritt und den Abschluss des Ladevorgangs externer Inhalte, u. a. das complete -Ereignis ( Event.COMPLETE ), das einen Aufruf der imageLoadComplete() -Methode auslöst, wenn das Bild vollständig geladen wurde.

Während das Starten des Ladens externer Bilder einen wichtigen Teil des Gesamtvorgangs darstellt, ist es genau so wichtig, sich über die folgenden Schritte im Klaren zu sein, nachdem das Laden abgeschlossen ist. Wie im zuvor abgebildeten Code dargestellt, wird die imageLoadComplete() -Funktion aufgerufen, wenn das Bild vollständig geladen ist. In dieser Funktion erfolgen verschiedene Manipulationen der geladenen Bilddaten, die in den folgenden Abschnitten beschrieben werden. Zum Verwenden der Bilddaten muss jedoch zunächst auf sie zugegriffen werden. Beim Verwenden eines Loader-Objekts zum Laden eines externen Bilds wird das geladene Bild zu einer Bitmap-Instanz, die dem Loader-Objekt als untergeordnetes Anzeigeobjekt zugeordnet wird. In diesem Fall steht die Loader-Instanz in der Ereignis-Listener-Methode als Teil des Ereignisobjekts zur Verfügung, das der Methode als Parameter übergeben wird. Es folgen die ersten Zeilen der imageLoadComplete() -Methode:

private function imageLoadComplete(event:Event):void 
{ 
    textureMap = event.target.content.bitmapData; 
    ... 
}

Beachten Sie, dass der Ereignisobjektparameter die Bezeichnung event trägt und eine Instanz der Event-Klasse ist. Jede Instanz der Event-Klasse hat eine target -Eigenschaft, die auf das Objekt verweist, das das Ereignis ausgelöst hat (in diesem Fall die LoaderInfo-Instanz, für die wie zuvor beschrieben die addEventListener() -Methode aufgerufen wurde). Das LoaderInfo-Objekt hat wiederum eine content -Eigenschaft, die (nach Abschluss des Ladevorgangs) die Bitmap-Instanz mit dem geladenen Bitmapbild enthält. Wenn Sie das Bild direkt auf dem Bildschirm anzeigen möchten, können Sie diese Bitmap-Instanz ( event.target.content ) einem Anzeigeobjektcontainer zuweisen. (Sie können auch das Loader-Objekt einem Anzeigeobjektcontainer zuweisen). In diesem Beispiel werden die geladenen Inhalte jedoch als Quelle für Bildrohdaten verwendet und nicht direkt auf dem Bildschirm angezeigt. Daher wird in der ersten Zeile der imageLoadComplete() -Methode die bitmapData -Eigenschaft der geladenen Bitmap-Instanz ( event.target.content.bitmapData ) gelesen und in der Instanzvariablen textureMap gespeichert. Diese wird als Bilddatenquelle verwendet, um die Animation des sich drehenden Monds zu erzeugen. Dies wird als Nächstes beschrieben.

Erstellen eines Animationseffekts durch Kopieren von Pixeln

Eine einfache Definition von Animation ist die Illusion von Bewegung oder Abwechslung durch das Ändern eines Bilds über einen bestimmten Zeitraum. In diesem Beispiel besteht das Ziel darin, die Illusion eines kugelförmigen Monds zu erzeugen, der sich um seine vertikale Achse dreht. Für den Zweck dieser Animation kann jedoch der Aspekt einer sphärischen Verzerrung vernachlässigt werden. Betrachten Sie das Bild, das geladen und als Quelle der Mondbilddaten verwendet wird:

Wie Sie sehen, sind in dem Bild keine kugelförmigen Körper abgebildet. Vielmehr handelt es sich um ein rechteckiges Foto der Mondoberfläche. Da das Foto eine Aufnahme vom Mondäquator darstellt, sind die Bildbereiche am oberen und unteren Rand lang gezogen und verzerrt. Um die Bildverzerrung zu entfernen und das Bild kugelförmig erscheinen zu lassen, wird ein Verschiebungsmatrixfilter eingesetzt. Dies wird an späterer Stelle beschrieben. Da dieses Quellbild ein Rechteck ist, genügt es zum Erzeugen der Illusion einer sich drehenden Kugel, das Foto der Mondoberfläche horizontal zu verschieben.

Beachten Sie, dass das Bild eigentlich aus zwei nebeneinandergelegten Kopien des Mondoberflächenfotos besteht. Dieses Bild ist das Quellbild, aus dem wiederholt Bilddaten kopiert werden, um den Anschein von Bewegung zu erwecken. Durch das Aneinanderfügen zweier Kopien des Bilds ist es einfacher, einen ununterbrochenen Bildlaufeffekt zu erzielen. Zum besseren Verständnis wird der Animationsvorgang nun schrittweise abgehandelt.

Der Animationsvorgang wird mit zwei verschiedenen ActionScript-Objekten durchgeführt. Zunächst wird das geladene Quellbild verwendet, das im Code durch die BitmapData-Instanz mit dem Namen textureMap dargestellt wird. Wie zuvor beschrieben, wird textureMap mithilfe des folgenden Codes mit Bilddaten gefüllt, wenn der Ladevorgang des externen Bilds abgeschlossen ist:

textureMap = event.target.content.bitmapData;

Der Inhalt von textureMap ist das rechteckige Mondbild. Zusätzlich wird im Code zum Erzeugen des animierten Rotationseffekts eine Bitmap-Instanz mit dem Namen sphere verwendet, bei der es sich um das eigentliche Anzeigeobjekt handelt, mit dem das Mondbild auf dem Bildschirm angezeigt wird. Wie textureMap wird auch das sphere -Objekt mithilfe der ursprünglichen Bilddaten in der imageLoadComplete() -Methode erzeugt und gefüllt. Dies erfolgt mit dem folgenden Code:

sphere = new Bitmap(); 
sphere.bitmapData = new BitmapData(textureMap.width / 2, textureMap.height); 
sphere.bitmapData.copyPixels(textureMap, 
                         new Rectangle(0, 0, sphere.width, sphere.height), 
                         new Point(0, 0));

Wie aus dem Code ersichtlich, wird sphere instanziiert. Die bitmapData -Eigenschaft der Instanz (die Bildrohdaten, die von sphere angezeigt werden) wird mit derselben Höhe und der halben Breite von textureMap angelegt. Anders ausgedrückt, hat der Inhalt von sphere die Größe eines Mondfotos (da das Bild in textureMap aus zwei nebeneinandergelegten Mondfotos besteht). Als Nächstes wird die bitmapData -Eigenschaft mithilfe der copyPixels() -Methode mit Bilddaten gefüllt. Mit den Parametern im Aufruf der copyPixels() -Methode werden mehrere Informationen übergeben:

  • Der erste Parameter gibt an, dass die Bilddaten aus textureMap kopiert werden.

  • Der zweite Parameter, eine neue Rectangle-Instanz, legt fest, aus welchem Teil von textureMap der Bildausschnitt kopiert werden soll. In diesem Fall handelt es sich um ein Rechteck, das an der linken oberen Ecke von textureMap beginnt (angegeben durch die ersten beiden Rectangle() -Parameter 0, 0 ). Die Breite und Höhe des rechteckigen Bildausschnitts stimmen mit den Eigenschaften width und height von sphere überein.

  • Der dritte Parameter, eine neue Point-Instanz mit dem x-Wert und dem y-Wert 0 , definiert das Ziel der Pixeldaten, in diesem Fall die linke obere Ecke (0, 0) von sphere.bitmapData .

Mit dem Code werden die in der folgenden Abbildung umrandeten Pixel aus textureMap kopiert und in sphere eingefügt. Anders ausgedrückt, ist der BitmapData-Inhalt von sphere der im Folgenden markierte Teil von textureMap :

Dabei darf jedoch nicht vergessen werden, dass es sich hierbei nur um den Anfangszustand von sphere handelt, d. h. um das erste Bild, das in sphere eingefügt wird.

Nachdem nun das Quellbild geladen und sphere erstellt wurde, besteht die letzte Aufgabe der imageLoadComplete() -Methode darin, die Animation einzurichten. Die Animation wird von einer Timer-Instanz mit dem Namen rotationTimer gesteuert, die mit dem folgenden Code erstellt und gestartet wird:

var rotationTimer:Timer = new Timer(15); 
rotationTimer.addEventListener(TimerEvent.TIMER, rotateMoon); 
rotationTimer.start();

Im Code wird zunächst die Timer-Instanz mit dem Namen rotationTimer erstellt. Mit dem an den Timer() -Konstruktor übergebenen Parameter wird angegeben, dass rotationTimer das zugehörige timer -Ereignis alle 15 illisekunden auslösen soll. Anschließend wird die addEventListener() -Methode aufgerufen und festgelegt, dass beim Auftreten des timer -Ereignisses ( TimerEvent.TIMER ) die Methode rotateMoon() aufgerufen wird. Schließlich wird der Timer dann durch Aufrufen der zugehörigen start() -Methode gestartet.

Aufgrund der Parameter für rotationTimer ruft Flash Player im Abstand von etwa 15 Millisekunden die rotateMoon() -Methode der MoonSphere-Klasse auf. Auf diese Weise wird die Animation des Monds realisiert. Der Quellcode der rotateMoon() -Methode lautet wie folgt:

private function rotateMoon(event:TimerEvent):void 
{ 
    sourceX += 1; 
    if (sourceX > textureMap.width / 2) 
    { 
        sourceX = 0; 
    } 
     
    sphere.Data.copyPixels(textureMap, 
                                    new Rectangle(sourceX, 0, sphere.width, sphere.height), 
                                    new Point(0, 0)); 
     
    event.updateAfterEvent(); 
}

Mit diesem Code werden drei Aufgaben ausgeführt:

  1. Der Wert der Variablen sourceX (anfangs auf 0 gesetzt) wird um 1 erhöht.

    sourceX += 1;

    Die Variable sourceX wird verwendet, um die Position in textureMap festzulegen, ab der die Pixel kopiert und in sphere eingefügt werden. Der Code hat daher den Effekt, dass das auf textureMap angewendete Rechteck um ein Pixel nach rechts verschoben wird. In der grafischen Darstellung bedeutet dies, dass das Quellrechteck nach mehreren Animationszyklen um mehrere Pixel nach rechts verschoben ist:

    Nach einigen weiteren Zyklen hat sich das Rechteck noch weiter bewegt:

    Diese schrittweise, kontinuierliche Verschiebung der Position, ab der die Pixel kopiert werden, ist der Schlüssel zur Animation. Durch das langsame und stetige Verschieben der Quellposition nach rechts scheint sich das auf dem Bildschirm in sphere angezeigte Bild kontinuierlich nach links zu bewegen. Aus diesem Grund muss das Quellbild ( textureMap ) aus zwei Kopien des Mondoberflächenfotos bestehen. Da sich das Rechteck kontinuierlich nach rechts bewegt, befindet es sich die meiste Zeit nicht über nur einem Mondfoto, sondern überlappt die beiden Fotos.

  2. Es gibt jedoch ein Problem mit dem sich langsam nach rechts verschiebenden Rechteck. Über kurz oder lang erreicht das Rechteck den rechten Rand von textureMap . Gleichzeitig können keine weiteren Pixel des Mondfotos kopiert und in sphere eingefügt werden.

    Dieses Problem wird mit den nächsten Codezeilen gelöst:

    if (sourceX >= textureMap.width / 2) 
    { 
        sourceX = 0; 
    }

    Im Code wird überprüft, ob sourceX (der linke Rand des Rechtecks) die Mitte von textureMap erreicht hat. Wenn dies der Fall ist, wird sourceX wieder auf 0 gesetzt und so zurück zum linken Rand von textureMap bewegt. Damit beginnt der Zyklus von vorn:

  3. Nachdem der passende Wert für sourceX berechnet ist, besteht der letzte Schritt zum Erzeugen der Animation darin, die Pixel des neuen Quellrechtecks auch tatsächlich zu kopieren und in sphere einzufügen. Der dazu verwendete Code ähnelt sehr dem Code, mit dem sphere zu Beginn gefüllt wurde (weiter oben beschrieben). Der einzige Unterschied besteht darin, dass nun beim Aufrufen des Konstruktors new Rectangle() der linke Rand des Rechtecks auf sourceX gesetzt wird:

    sphere.bitmapData.copyPixels(textureMap, 
                                new Rectangle(sourceX, 0, sphere.width, sphere.height), 
                                new Point(0, 0));

Rufen Sie sich in Erinnerung, dass dieser Code alle 15 illisekunden aufgerufen wird. Während sich die Position des Quellrechtecks kontinuierlich ändert und die kopierten Pixel in sphere eingefügt werden, wird auf dem Bildschirm der Eindruck erzeugt, dass sich das in sphere dargestellte Mondfoto ständig bewegt. Anders ausgedrückt, es entsteht der Eindruck, dass der Mond sich dreht.

Erzeugen des kugelförmigen Erscheinungsbilds

Natürlich ist der Mond kein Rechteck, sondern eine Kugel. Daher muss im Beispiel das rechteckige und fortlaufend animierte Foto der Mondoberfläche in eine Kugel umgewandelt werden. Hierzu müssen zwei Schritte ausgeführt werden: Mit einer Maske werden alle Bildinhalte außerhalb eines kreisförmigen Bereichs des Mondoberflächenfotos ausgeblendet. Mit einem Verschiebungsmatrixfilter wird dann die Darstellung des Mondfotos verzerrt, um es dreidimensional erscheinen zu lassen.

Zunächst wird eine kreisförmige Maske verwendet, um alle Inhalte des MoonSphere-Objekts außer der durch den Filter erzeugten Kugel auszublenden. Mit dem folgenden Code wird die Maske als Shape-Instanz erstellt und auf die MoonSphere-Instanz angewendet:

moonMask = new Shape(); 
moonMask.graphics.beginFill(0); 
moonMask.graphics.drawCircle(0, 0, radius); 
this.addChild(moonMask); 
this.mask = moonMask;

Beachten Sie, dass die Maske über die geerbte mask -Eigenschaft direkt auf die MoonSphere-Instanz angewendet werden kann, da es sich bei dieser Instanz um ein Anzeigeobjekt handelt.

Um einen realistisch wirkenden Effekt einer sich drehenden Kugel zu erzeugen, ist es nicht damit getan, Teile des Fotos durch eine kreisförmige Maske auszublenden. Aufgrund der Art und Weise, wie das Foto der Mondoberfläche aufgenommen wurde, sind die Abmessungen nicht proportional. Die Bildteile am oberen und unteren Bildrand sind stärker verzerrt und gestreckt als die Bereiche am Äquator. Um das Mondfoto dreidimensional wirken zu lassen, wird ein Verschiebungsmatrixfilter verwendet.

Bei einem Verschiebungsmatrixfilter handelt es sich um einen Filtertyp, der zum Verzerren von Bildern eingesetzt wird. In diesem Fall wird das Mondfoto „verzerrt“, damit es realistischer wirkt. Dazu werden der obere und untere Bildteil horizontal gestaucht, der Mittelteil bleibt jedoch unverändert. Unter der Voraussetzung, dass der Filter auf einen quadratförmigen Teil des Fotos angewendet wird, entsteht durch Stauchen des oberen und unteren Bildteils ohne Einbeziehung der Bildmitte aus dem Quadrat ein Kreis. Ein Nebeneffekt der Animation dieses verzerrten Bilds besteht darin, dass sich die Bildmitte jeweils um einen größeren Pixelabstand zu bewegen scheint als die Bereiche am oberen und unteren Bildrand. Dies erzeugt die Illusion, dass es sich bei dem Kreis in Wirklichkeit um ein dreidimensionales Objekt (eine Kugel) handelt.

Der folgende Code wird verwendet, um den Verschiebungsmatrixfilter mit dem Namen displaceFilter zu erstellen:

var displaceFilter:DisplacementMapFilter; 
displaceFilter = new DisplacementMapFilter(fisheyeLens, 
                                new Point(radius, 0),  
                                BitmapDataChannel.RED, 
                                BitmapDataChannel.GREEN, 
                                radius, 0);

Der erste Parameter fisheyeLens wird als Matrixbild bezeichnet. In diesem Fall handelt es sich um ein im Programmcode erstelltes BitmapData-Objekt. Die Erstellung dieses Bilds wird unter Erstellen eines Bitmapbilds durch Festlegen von Pixelwerten erläutert. Die anderen Parameter beschreiben die Position im gefilterten Bild, ab der der Filter angewendet werden soll, sowie die zum Steuern des Verschiebungseffekts verwendeten Farbkanäle und in welchem Ausmaß sie sich auf die Verschiebung auswirken. Nachdem der Verschiebungsmatrixfilter erstellt wurde, wird er noch in der imageLoadComplete() -Methode auf sphere angewendet:

sphere.filters = [displaceFilter];

Das endgültige Bild (Maske und Verschiebungsmatrixfilter angewendet) sieht wie folgt aus:

Mit jedem neuen Zyklus der Animation des sich drehenden Monds wird der Inhalt der BitmapData-Eigenschaft von „sphere“ mit einem neuen Ausschnitt der Quellbilddaten überschrieben. Der Filter muss jedoch nicht jedes Mal erneut angewendet werden. Der Grund hierfür ist, dass der Filter nicht auf die Bitmap-Daten (die Pixelrohdaten), sondern auf die Bitmap-Instanz (das Anzeigeobjekt) angewendet wird. Beachten Sie, dass die Bitmap-Instanz nicht die tatsächlichen Bitmap-Daten enthält. Sie ist das Anzeigeobjekt, mit dem die Bitmap-Daten auf dem Bildschirm dargestellt werden. Zur Veranschaulichung: Eine Bitmap-Instanz ist wie ein Diaprojektor, mit dem Fotos auf einer Leinwand dargestellt werden, und ein BitmapData-Objekt ist das eigentliche Dia, das mit dem Diaprojektor projiziert werden kann. Filter können direkt auf ein BitmapData-Objekt angewendet werden. Dies kann damit verglichen werden, dass direkt auf das Dia gezeichnet wird, um das Bild zu verändern. Filter können jedoch auch auf beliebige Anzeigeobjekte (einschließlich Bitmap-Instanzen) angewendet werden. Dies ist vergleichbar mit dem Anbringen eines Filters vor dem Projektorobjektiv, um das auf der Leinwand dargestellte Bild zu verzerren (ohne überhaupt das Original-Dia zu verändern). Da auf die Bitmap-Rohdaten mithilfe der bitmapData-Eigenschaft einer Bitmap-Instanz zugegriffen werden kann, können Filter direkt auf die Bitmap-Rohdaten angewendet werden. In diesem Fall ist es jedoch sinnvoll, den Filter nicht auf die Bitmap-Daten, sondern auf das Bitmap-Anzeigeobjekt anzuwenden.

Weitere Informationen zum Verwenden von Verschiebungsmatrixfiltern in ActionScript finden Sie unter Anwenden von Filtern auf Anzeigeobjekte .

Erstellen eines Bitmapbilds durch Festlegen von Pixelwerten

Ein wichtiger Aspekt beim Anwenden von Verschiebungsmatrixfiltern ist, dass eigentlich zwei Bilder verwendet werden. Das eine Bild (das Quellbild) wird tatsächlich durch den Filter verändert. In diesem Beispiel ist das Quellbild die Bitmap-Instanz mit dem Namen sphere . Das andere vom Filter verwendete Bild wird als Matrixbild bezeichnet. Das Matrixbild wird nicht auf dem Bildschirm angezeigt. Stattdessen werden die Farben der einzelnen Pixel als Eingabe der Verschiebungsfunktion verwendet. Die Farbe des Pixels an einer bestimmten (x, y)-Koordinate im Matrixbild legt fest, welche Verschiebung (der physischen Position) auf das entsprechende Pixel an dieser (x, y)-Koordinate im Quellbild angewendet wird.

Daher wird für dieses Beispiel ein geeignetes Matrixbild benötigt, um mit dem Verschiebungsmatrixfilter einen Kugeleffekt zu erzeugen. Dieses Matrixbild hat einen grauen Hintergrund und stellt einen Kreis dar, der mit dem horizontalen Farbverlauf einer einzigen Farbe (Rot, von dunkel zu hell) gefüllt ist, wie im Folgenden abgebildet:

Da in diesem Beispiel nur ein Matrixbild und ein Filter eingesetzt werden, wird das Matrixbild nur einmal (in der imageLoadComplete() -Methode, d. h. nach Abschluss des Ladevorgangs des externen Bilds) erzeugt. Das Matrixbild mit dem Namen fisheyeLens wird durch Aufrufen der createFisheyeMap() -Methode der MoonSphere-Klasse erstellt:

var fisheyeLens:BitmapData = createFisheyeMap(radius);

Innerhalb der createFisheyeMap() -Methode wird das Matrixbild Pixel für Pixel mithilfe der setPixel() -Methode der BitmapData-Klasse gezeichnet. Der vollständige Code der createFisheyeMap() -Methode ist im Folgenden aufgeführt. Im Anschluss daran finden Sie eine schrittweise Erläuterung der Funktionsweise.

private function createFisheyeMap(radius:int):BitmapData 
{ 
    var diameter:int = 2 * radius; 
     
    var result:BitmapData = new BitmapData(diameter, 
                                        diameter, 
                                        false, 
                                        0x808080); 
     
    // Loop through the pixels in the image one by one 
    for (var i:int = 0; i < diameter; i++) 
    { 
        for (var j:int = 0; j < diameter; j++) 
        { 
            // Calculate the x and y distances of this pixel from 
            // the center of the circle (as a percentage of the radius). 
            var pctX:Number = (i - radius) / radius; 
            var pctY:Number = (j - radius) / radius; 
             
            // Calculate the linear distance of this pixel from 
            // the center of the circle (as a percentage of the radius). 
            var pctDistance:Number = Math.sqrt(pctX * pctX + pctY * pctY); 
             
            // If the current pixel is inside the circle, 
            // set its color. 
            if (pctDistance < 1) 
            { 
                // Calculate the appropriate color depending on the 
                // distance of this pixel from the center of the circle. 
                var red:int; 
                var green:int; 
                var blue:int; 
                var rgb:uint; 
                red = 128 * (1 + 0.75 * pctX * pctX * pctX / (1 - pctY * pctY)); 
                green = 0; 
                blue = 0; 
                rgb = (red << 16 | green << 8 | blue); 
                // Set the pixel to the calculated color. 
                result.setPixel(i, j, rgb); 
            } 
        } 
    } 
    return result; 
}

Beim Aufrufen der Methode wird dieser zunächst ein Parameter ( radius ) übergeben, der den Radius des zu erstellenden kreisförmigen Bilds angibt. Anschließend wird im Code das BitmapData-Objekt erstellt, in dem der Kreis gezeichnet werden soll. Dieses Objekt mit dem Namen result wird schließlich als Rückgabewert der Methode zurückgegeben. Wie im folgenden Codeausschnitt dargestellt, wird die BitmapData-Instanz result mit den folgenden Werten erstellt: Breite und Höhe entsprechen dem Kreisdurchmesser, keine Transparenz ( false im dritten Parameter) und Vorfüllung mit der Farbe 0x808080 (mittelgrau):

var result:BitmapData = new BitmapData(diameter, 
                                    diameter, 
                                    false, 
                                    0x808080);

Anschließend werden im Code zwei Schleifen verwendet, damit alle Pixel des Bilds einzeln durchlaufen werden. In der äußeren Schleife werden alle Bildspalten von links nach rechts durchlaufen (die Variable i enthält die horizontale Position des jeweils zu bearbeitenden Pixels). In der inneren Schleife werden alle Pixel der aktiven Spalte von oben nach unten durchlaufen (die Variable j enthält die vertikale Position des jeweils zu bearbeitenden Pixels). Der Code für die Schleifen ist im Folgenden dargestellt (der Inhalt der inneren Schleife wurde weggelassen):

for (var i:int = 0; i < diameter; i++) 
{ 
    for (var j:int = 0; j < diameter; j++) 
    { 
        ... 
    } 
}

Während in den Schleifen alle Pixel einzeln durchlaufen werden, wird für jedes Pixel ein Wert (der Farbwert dieses Pixels im Matrixbild) berechnet. Dieser Vorgang umfasst vier Schritte:

  1. Im Code wird für das aktuelle Pixel der Abstand vom Kreismittelpunkt auf der x-Achse berechnet ( i - radius ). Dieser Wert wird durch den Radius dividiert, um den Prozentwert (im Verhältnis zum Radius) und nicht den absoluten Abstand ( (i - radius) / radius ) zu erhalten. Dieser Prozentwert wird in einer Variablen mit dem Namen pctX gespeichert. Der entsprechende Wert für die y-Achse wird ebenfalls berechnet und in der Variablen pctY gespeichert, wie im folgenden Code dargestellt:

    var pctX:Number = (i - radius) / radius; 
    var pctY:Number = (j - radius) / radius;
  2. Mithilfe einer trigonometrischen Standardformel, dem Satz des Pythagoras, wird aus pctX und pctY der lineare Abstand zwischen dem Kreismittelpunkt und dem aktuellen Punkt berechnet. Dieser Wert wird in einer Variablen mit dem Namen pctDistance gespeichert, wie im Folgenden dargestellt:

    var pctDistance:Number = Math.sqrt(pctX * pctX + pctY * pctY);
  3. Anschließend wird überprüft, ob der prozentuale Abstand kleiner als 1 ist (100 % des Radius, d. h. das Pixel befindet sich innerhalb des Kreisradius). Wenn sich das Pixel innerhalb des Kreises befindet, wird ihm ein berechneter Wert (an dieser Stelle weggelassen, jedoch in Schritt 4 beschrieben) zugewiesen. Andernfalls wird der Standardfarbwert des Pixels für Mittelgrau nicht geändert:

    if (pctDistance < 1) 
    { 
        ... 
    }
  4. Für die Pixel innerhalb des Kreises wird ein Farbwert berechnet. Am Ende weist der Kreis einen roten Farbverlauf auf, der sich von Schwarz (0 % Rot) am linken Kreisrand bis zu Hellrot (100 %) am rechten Kreisrand erstreckt. Der Farbwert wird ursprünglich in drei Teilkomponenten (Rot, Grün und Blau) berechnet, wie im Folgenden dargestellt:

    red = 128 * (1 + 0.75 * pctX * pctX * pctX / (1 - pctY * pctY)); 
    green = 0; 
    blue = 0;

    Beachten Sie, dass nur der Rotanteil der Farbe (die Variable red ) tatsächlich einen Wert enthält. Die Werte für Grün und Blau (die Variablen green und blue ) sind hier zum besseren Verständnis ebenfalls aufgeführt, können jedoch weggelassen werden. Da der Zweck dieser Methode darin besteht, einen Kreis mit einem roten Farbverlauf zu erzeugen, werden keine Werte für Grün und Blau benötigt.

    Nachdem die drei Farbwertkomponenten festgelegt sind, werden sie mithilfe eines Bitverschiebungs-Standardalgorithmus in einem einzigen ganzzahligen Farbwert kombiniert, wie im folgenden Code dargestellt:

    rgb = (red << 16 | green << 8 | blue);

    Schließlich wird der berechnete Farbwert dann mit der setPixel() -Methode des BitmapData-Objekts result dem aktuellen Pixel zugewiesen:

    result.setPixel(i, j, rgb);