Voorbeeld van strings: ASCII-afbeeldingen

Flash Player 9 of hoger, Adobe AIR 1.0 of hoger

Dit voorbeeld van een ASCII-tekening laat een aantal kenmerken zien van het werken met de klasse String in ActionScript 3.0, waaronder het volgende:

  • De methode split() van de klasse String wordt gebruikt om waarden te extraheren van een door tekens gescheiden tekenreeks (afbeeldingsinformatie in een door tabs gescheiden tekstbestand).

  • U kunt verschillende tekenreeksmanipulatietechnieken, waaronder split(), samenvoeging en het extraheren van een deel van de tekenreeks met substring() en substr(), gebruiken om de eerste letter van ieder woord in de titels van afbeeldingen een hoofdletter te geven.

  • De methode getCharAt() wordt gebruikt om één teken uit een tekenreeks op te halen (om vast te stellen welk ASCII-teken overeenkomt met een bitmapwaarde voor grijstinten).

  • Tekenreekssamenvoeging wordt gebruikt om de weergave van een ASCII-tekening met één teken tegelijk op te bouwen.

De term ASCII-tekening verwijst naar de tekstweergave van een afbeelding, waarbij de afbeelding in kaart wordt gebracht door een raster van lettertypetekens met vaste tekenbreedte, zoals Courier New-tekens. De volgende afbeelding toont een voorbeeld van een ASCII-tekening die door de toepassing wordt geproduceerd:

ASCII-tekening - een afbeelding die met teksttekens wordt gerenderd
De ASCII-tekening van de afbeelding wordt rechts weergegeven.

Zie www.adobe.com/go/learn_programmingAS3samples_flash_nl als u de toepassingsbestanden voor dit voorbeeld wilt downloaden. De toepassingsbestanden van ASCIIArt vindt u in de map Samples/ASCIIArt. De toepassing bestaat uit de volgende bestanden:

Bestand

Beschrijving

AsciiArtApp.mxml

of

AsciiArtApp.fla

Het hoofdtoepassingsbestand in Flash (FLA) of Flex (MXML)

com/example/programmingas3/asciiArt/AsciiArtBuilder.as

De klasse met de hoofdfunctionaliteit van de toepassing, waaronder het extraheren van metagegevens van een afbeelding uit een tekstbestand, het laden van de afbeeldingen en het beheren van het omzettingsproces van afbeelding in tekst.

com/example/programmingas3/asciiArt/BitmapToAsciiConverter.as

Een klasse die de methode parseBitmapData() biedt voor het omzetten van afbeeldingsgegevens in een versie String.

com/example/programmingas3/asciiArt/Image.as

Een klasse die een geladen bitmapafbeelding weergeeft.

com/example/programmingas3/asciiArt/ImageInfo.as

Een klasse die metagegevens vertegenwoordigt voor een ASCII-tekening (zoals titel, afbeeldingsbestands-URL, enzovoort).

image/

Een map met de afbeeldingen die door de toepassing worden gebruikt.

txt/ImageData.txt

Een door tabs gescheiden tekstbestand met informatie over bestanden die door de toepassing moeten worden geladen.

Door tabs gescheiden waarden extraheren

In dit voorbeeld wordt de standaardmethode gebruikt om toepassingsgegevens apart van de toepassing zelf op te slaan. Wanneer gegevens worden gewijzigd (bijvoorbeeld, als een andere afbeelding wordt toegevoegd of de titel van een afbeelding wijzigt), is het niet nodig het SWF-bestand opnieuw te maken. In dit geval worden de metagegevens van de afbeelding, inclusief de titel van de afbeelding, de URL van het daadwerkelijke afbeeldingsbestand en een aantal waarden die worden gebruikt om de afbeelding te manipuleren, opgeslagen in een tekstbestand (het bestand txt/ImageData.txt in het project). De inhoud van het tekstbestand is als volgt:

FILENAME    TITLE    WHITE_THRESHHOLD    BLACK_THRESHHOLD 
FruitBasket.jpg    Pear, apple, orange, and banana    d8    10 
Banana.jpg    A picture of a banana    C8    20 
Orange.jpg    orange    FF    20 
Apple.jpg    picture of an apple    6E    10

Het bestand gebruikt een specifieke door tabs gescheiden indeling. De eerste regel (rij) is een rij met koptekst. De resterende regels bevatten de volgende gegevens voor iedere te laden bitmap:

  • De bestandsnaam van de bitmap.

  • De weergavenaam van de bitmap.

  • De bitmapdrempelwaarden voor wit en voor zwart. Dit zijn hexadecimale waarden waarboven en waaronder een pixel wordt beschouwd als compleet wit of compleet zwart.

Zodra de toepassing start, wordt de klasse AsciiArtBuilder geladen, waarmee de inhoud van het tekstbestand wordt geparseerd. Zo wordt de 'stapel' met afbeeldingen gemaakt die wordt weergegeven. Dit gebeurt met behulp van de volgende code uit de methode parseImageInfo() van de klasse AsciiArtBuilder:

var lines:Array = _imageInfoLoader.data.split("\n"); 
var numLines:uint = lines.length; 
for (var i:uint = 1; i < numLines; i++) 
{ 
    var imageInfoRaw:String = lines[i]; 
    ... 
    if (imageInfoRaw.length > 0) 
    { 
        // Create a new image info record and add it to the array of image info. 
        var imageInfo:ImageInfo = new ImageInfo(); 
 
        // Split the current line into values (separated by tab (\t) 
        // characters) and extract the individual properties: 
        var imageProperties:Array = imageInfoRaw.split("\t"); 
        imageInfo.fileName = imageProperties[0]; 
        imageInfo.title = normalizeTitle(imageProperties[1]); 
        imageInfo.whiteThreshold = parseInt(imageProperties[2], 16); 
        imageInfo.blackThreshold = parseInt(imageProperties[3], 16); 
        result.push(imageInfo); 
    } 
}

De gehele inhoud van het tekstbestand wordt opgenomen in één instantie String, de eigenschap _imageInfoLoader.data. Wanneer u de methode split() met het teken voor een nieuwe regel ("\n") gebruikt als parameter, wordt de instantie String verdeeld in een Array (lines) waarvan de elementen de individuele regels van het tekstbestand zijn. Vervolgens gebruikt de code een lus om met iedere regel te werken (behalve de eerste, omdat die alleen kopteksten bevat en geen daadwerkelijke inhoud). Binnen de lus wordt de methode split() nogmaals gebruikt om de inhoud van de ene regel te verdelen in een set waarden (het object Array met de naam imageProperties). De parameter die in dit geval bij de methode split() wordt gebruikt is het tab-teken ("\t"), omdat de waarden in iedere regel door tab-tekens worden afgebakend.

Methoden String gebruiken om afbeeldingstitels te normaliseren

Een van de ontwerpbesluiten voor deze toepassing is dat alle afbeeldingstitels worden weergegeven met een standaardindeling, met de eerste letter van ieder woord als hoofdletter (behalve een paar woorden die normaal gesproken niet met een hoofdletter worden geschreven in titels). In plaats van aan te nemen dat het tekstbestand titels bevat die op de juiste manier zijn opgemaakt, maakt de toepassing de titels op terwijl ze uit het tekstbestand worden geëxtraheerd.

In het vorige codevoorbeeld wordt, als onderdeel van het extraheren van waarden voor metagegevens van afzonderlijke afbeeldingen, de volgende coderegel gebruikt:

        imageInfo.title = normalizeTitle(imageProperties[1]);

In deze code wordt de titel van de afbeelding van het tekstbestand aan de methode normalizeTitle() doorgegeven voordat deze in het object ImageInfo wordt opgeslagen:

private function normalizeTitle(title:String):String 
{ 
    var words:Array = title.split(" "); 
    var len:uint = words.length; 
    for (var i:uint; i < len; i++) 
    { 
        words[i] = capitalizeFirstLetter(words[i]); 
    } 
     
    return words.join(" "); 
}

Bij deze methode wordt de methode split() gebruikt om de titel in afzonderlijke woorden te verdelen (gescheiden door het spatieteken), waarna elk woord wordt doorgegeven aan de methode capitalizeFirstLetter(). Vervolgens wordt de methode join() van de klasse Array gebruikt om de woorden te combineren, zodat ze weer één tekenreeks vormen.

Met de methode capitalizeFirstLetter() wordt dus van de eerste letter van elk woord een hoofdletter gemaakt:

    /** 
     * Capitalizes the first letter of a single word, unless it's one of 
     * a set of words that are normally not capitalized in English. 
     */ 
    private function capitalizeFirstLetter(word:String):String 
    { 
        switch (word) 
        { 
            case "and": 
            case "the": 
            case "in": 
            case "an": 
            case "or": 
            case "at": 
            case "of": 
            case "a": 
                // Don't do anything to these words. 
                break; 
            default: 
                // For any other word, capitalize the first character. 
                var firstLetter:String = word.substr(0, 1); 
                firstLetter = firstLetter.toUpperCase(); 
                var otherLetters:String = word.substring(1); 
                word = firstLetter + otherLetters; 
        } 
        return word; 
    }

Voor het Engels geldt dat het eerste teken van woorden in een titel geen hoofdletter krijgt als het een van de volgende woorden betreft: 'and', 'the', 'in', 'an', 'or', 'at', 'of' of 'a'. (Dit is een vereenvoudigde versie van de regels.) Voor het uitvoeren van deze logica, gebruikt de code eerst een instructie switch om te controleren of het woord een van de woorden is die geen hoofdletter mogen krijgen. Als dat het geval is, springt de code buiten de instructie switch. Als het woord wel een hoofdletter moet krijgen, worden de volgende stappen doorlopen:

  1. De eerste letter van het woord wordt met substr(0, 1) opgehaald, waarbij een subtekenreeks wordt opgehaald dat met een teken op index 0 begint (de eerste letter in de tekenreeks, zoals aangegeven door de eerste parameter 0). De subtekenreeks is één teken lang (aangeduid door de tweede parameter 1).

  2. Dat teken krijgt een hoofdletter met de methode toUpperCase().

  3. De overige tekens van het oorspronkelijke woord worden met substring(1) opgehaald, waarbij een subtekenreeks wordt opgehaald dat op index 1 begint (de tweede letter) tot het einde van de tekenreeks (aangeduid door de tweede parameter van de methode substring() weg te laten).

  4. Het uiteindelijke woord wordt gemaakt door de eerste letter die net een hoofdletter heeft gekregen, te combineren met de overige letters via tekenreekssamenvoeging: firstLetter + otherLetters.

ASCII-tekeningtekst genereren

De klasse BitmapToAsciiConverter biedt functionaliteit voor het omzetten van een bitmapafbeelding in de ASCII-tekstrepresentatie ervan. Dit proces wordt uitgevoerd door de methode parseBitmapData() en wordt hier gedeeltelijk weergegeven:

    var result:String = ""; 
     
    // Loop through the rows of pixels top to bottom: 
    for (var y:uint = 0; y < _data.height; y += verticalResolution) 
    { 
        // Within each row, loop through pixels left to right: 
        for (var x:uint = 0; x < _data.width; x += horizontalResolution) 
        { 
            ... 
 
            // Convert the gray value in the 0-255 range to a value 
            // in the 0-64 range (since that's the number of "shades of 
            // gray" in the set of available characters): 
            index = Math.floor(grayVal / 4); 
            result += palette.charAt(index); 
        } 
        result += "\n"; 
    } 
    return result;

Deze code definieert eerst een instantie String met de naam result, die wordt gebruikt om de ASCII-versie van de bitmapafbeelding te maken. Vervolgens worden de afzonderlijke pixels van de bronbitmapafbeelding doorlopen. Bij het gebruik van verschillende kleurmanipulatietechnieken (hier weggelaten voor bondigheid), zet de code de rode, groene en blauwe waarden van een afzonderlijke pixel om in één grijsschaalwaarde (een getal van 0 tot 255). Vervolgens wordt de waarde omgezet in een waarde in de 0-63-schaal door de waarde door 4 te delen (zoals in het codevoorbeeld wordt getoond). Deze bewerkte waarde wordt opgeslagen in de variabele index. (De 0-63-schaal wordt gebruikt, omdat het 'palet' van beschikbare ASCII-tekens die deze toepassing gebruikt, 64 tekens bevat.) Het palet met tekens wordt gedefinieerd als een instantie String in de klasse BitmapToAsciiConverter:

// The characters are in order from darkest to lightest, so that their 
// position (index) in the string corresponds to a relative color value 
// (0 = black). 
private static const palette:String = "@#$%&8BMW*mwqpdbkhaoQ0OZXYUJCLtfjzxnuvcr[]{}1()|/?Il!i><+_~-;,. ";

Omdat de variabele index bepaalt welk ASCII-teken in het palet overeenkomt met de huidige pixel in de bitmapafbeelding, wordt dat teken opgehaald uit het palet String via de methode charAt(). Vervolgens wordt het teken toegevoegd aan de String-instantie result via de toewijzingsoperator voor samenvoegen (+=). Verder wordt aan het eind van elke rij met pixels een teken voor een nieuwe regel samengevoegd met het eind van de String-instantie result, zodat tekstomloop wordt afgedwongen voor de regel en een nieuwe regel met 'tekenpixels' wordt gemaakt.