ストリングの例:ASCII アート

Flash Player 9 以降、Adobe AIR 1.0 以降

ここでは ASCII アートの例を使って、ActionScript 3.0 の String クラスの操作について次のような機能を示します。

  • String クラスの split() メソッドを使用して、文字区切りのストリング(タブ区切りテキストファイルのイメージ情報)から値を抽出します。

  • split() 、連結、および substring() substr() の使用によるストリング部分の抽出など、何とおりものストリング操作テクニックを使用して、イメージタイトルの各単語の先頭文字を大文字にします。

  • getCharAt() メソッドを使用して、ストリングから 1 文字を取得します(グレースケールビットマップ値に対応する ASCII 文字を決定します)。

  • ストリングの連結を使用して、イメージの ASCII アート表現を一度に 1 文字ずつ構築します。

ASCII アートという用語はイメージのテキスト表現を指し、イメージは Courier New 文字のような等幅フォント文字のグリッドで描画されます。次のイメージは、アプリケーションが生成した ASCII アートの例を示しています。

ASCII アート - テキスト文字を使用してレンダリングされたイメージ
ASCII アートのグラフィックを右側に示してあります。

このサンプルのアプリケーションのファイルを入手するには、 www.adobe.com/go/learn_programmingAS3samples_flash_jp を参照してください。 ASCIIArt アプリケーションのファイルは、Samples/AsciiArt フォルダーにあります。 このアプリケーションは次のファイルで構成されています。

ファイル

説明

AsciiArtApp.mxml

または

AsciiArtApp.fla

Flash(FLA)または Flex(MXML)のメインアプリケーションファイル。

com/example/programmingas3/asciiArt/AsciiArtBuilder.as

テキストファイルからのイメージメタデータの抽出、イメージのロード、イメージからテキストへの変換プロセスの管理など、アプリケーションのメイン機能を提供するクラス。

com/example/programmingas3/asciiArt/BitmapToAsciiConverter.as

イメージデータをストリングに変換するための parseBitmapData() メソッドを提供するクラス。

com/example/programmingas3/asciiArt/Image.as

ロードしたビットマップイメージを表すクラス。

com/example/programmingas3/asciiArt/ImageInfo.as

タイトル、イメージファイル URL など、ASCII アートイメージのメタデータを表すクラス。

image/

アプリケーションが使用するイメージを含むフォルダー。

txt/ImageData.txt

アプリケーションがロードするイメージに関する情報を含む、タブ区切りのテキストファイル。

タブ区切りの値の抽出

この例では、アプリケーションデータをアプリケーション自体とは別に格納する一般的な慣習に従っています。そのようにしておくと、例えば、別のイメージが追加またはイメージのタイトルが変更されたときなど、データが変更された場合に SWF ファイルを再作成する必要がありません。この場合、イメージタイトル、実際のイメージファイルの URL、およびイメージの操作に使用する一部の値を含むイメージメタデータは、テキストファイル(プロジェクトの txt/ImageData.txt ファイル)に格納されています。 実際のテキストファイルの中身は次のようになっています。

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

ファイルは特定のタブ区切り形式を使用します。 最初の行はヘッダー行です。 残りの行は、ロードするビットマップごとに次のデータを含みます。

  • ビットマップのファイル名

  • ビットマップの表示名

  • ビットマップの白しきい値および黒しきい値。 これらは 16 進値で、この値を超えた場合および下回った場合にピクセルは完全に白または黒と見なされます。

アプリケーションが起動するとすぐに、AsciiArtBuilder クラスは、AsciiArtBuilder クラスの parseImageInfo() メソッドから次のコードを使用して、表示するイメージの「スタック」を作成するためにテキストファイルの内容をロードして解析します。

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

テキストファイルのすべての内容が単一の String インスタンス _imageInfoLoader.data プロパティに含まれます。改行( "¥n" )をパラメーターとして split() メソッドを使用すると、String インスタンスは、要素がテキストファイルの各行になる Array( lines )に分割されます。次に、ループを使用して各行の操作を行います(実際の内容ではなくヘッダーのみを含む先頭行は除く)。 ループ内で、 split() メソッドをもう一度使用して、単一行の内容を値セット( imageProperties という Array オブジェクト)に分割します。各行の値はタブ文字で区切られるため、この場合の split() メソッドで使用するパラメーターはタブ文字( "¥t" )です。

ストリングメソッドの使用によるイメージタイトルの正規化

このアプリケーションの設計に関する決定事項の 1 つは、すべてのイメージタイトルを標準形式で表示し、そのとき各単語の先頭文字を大文字にします(英語タイトルで先頭大文字にしないのが一般的ないくつかの単語は除く)。 適切に整形済みのタイトルがテキストファイルに含まれると見なすのではなく、テキストファイルからの抽出時にタイトルを整形します。

以前のコードリストでは、個々のイメージメタデータ値を抽出する一部として、次のコード行が使用されています。

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

このコードでは、テキストファイルからのイメージのタイトルが、ImageInfo オブジェクトに格納される前に normalizeTitle() メソッドを介して渡されます。

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

このメソッドは split() メソッドを使用して、タイトルを(空白文字で区切られた)個々の単語に分割し、 capitalizeFirstLetter() メソッドを介して各単語を渡し、次に Array クラスの join() メソッドを使用して、単語をもう一度 1 つのストリングに結合します。

名前が示すとおり、 capitalizeFirstLetter() メソッドは実際に各単語の先頭文字を大文字にする働きがあります。

    /** 
     * 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; 
    }

英語では、タイトルの各単語が「and」、「the」、「in」、「an」、「or」、「at」、「of」、または「a」のいずれかである場合、その先頭の文字は大文字にされません。これは簡易版の規則です。このロジックを実行するために、最初に switch ステートメントを使用して、先頭を大文字にしない単語のいずれかであるかどうかを確認します。先頭を大文字にしない単語の場合は、 switch ステートメントからジャンプします。一方、先頭を大文字にする単語の場合は、次のように何ステップかでそれを行います。

  1. substr(0, 1) を使用して、単語の先頭文字を抽出します。この抽出では、第 1 パラメーター 0 が指定するストリングの先頭文字、つまりインデックス 0 の文字から開始するサブストリングを抽出します。サブストリングは、第 2 パラメーター 1 が指定する 1 文字長になります。

  2. toUpperCase() メソッドを使用して、その文字を大文字にします。

  3. substring(1) を使用して、元の単語の残りの文字を抽出します。この抽出では、インデックス 1(第 2 文字)から開始して、ストリングの末尾( substring() メソッドの第 2 パラメーターの省略が示す)までのサブストリングを抽出します。

  4. firstLetter + otherLetters の文字連結を使用して、新しく大文字にした先頭文字と残りの文字を結合することによって、最終的な単語を作成します。

ASCII アートテキストの生成

BitmapToAsciiConverter クラスは、ビットマップイメージを ASCII テキスト表現に変換する機能を提供します。 このプロセスは、次に一部を示してある parseBitmapData() メソッドが実行します。

    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;

このコードは、ビットマップイメージの ASCII アート版を作成するために使用する result という名前の String インスタンスを最初に定義します。次に、ソースビットマップイメージについて個々のピクセルのループ処理をします。 何とおりかのカラー操作テクニックを使用して(ここでは簡略化のために省略)、個々のピクセルの赤、緑、青のカラー値を単一のグレースケール値(0 から 255 までの数値)に変換します。 続いて例に示してあるように、その値を 4 で割り、0 ~ 63 スケールの値に変換します。値は、変数 index に格納されます。0 ~ 63 スケールを使用するのは、このアプリケーションで使用する利用可能な ASCII 文字の「パレット」に格納される値の数が 64 のためです。文字パレットは、BitmapToAsciiConverter クラスの String インスタンスとして定義されています。

// 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><+_~-;,. ";

index 変数は、ビットマップイメージの現在のピクセルに対応するパレット内の ASCII 文字を定義するので、この文字は charAt() メソッドを使用して palette ストリングから取得されます。続いて、連結代入演算子( += )を使用して、 result String インスタンスに追加されます。さらに、各行のピクセルの最後で result String の最後に改行文字を連結して、文字ピクセルの新しい行を作成するために行の折り返しを強制します。