SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

定型処理を行う簡易スクリプト実行系の実装

コマンド入力に対応した画像処理アプリケーションの作成

  • X ポスト
  • このエントリーをはてなブックマークに追加

スクリプトの文字列処理

 まず、スクリプトは改行で区切られるコマンド行から構成されているので、改行ごとに分離しましょう。そして、「そのコマンド行内のコマンドと引数を取得し、実際にコマンドを処理する関数に渡す」というここまでの処理を、関数ExecScript()に記述します。

// 文字列を行ごとに区切り、コマンド名と引数に分離
public void ExecScript(String script) {

    if (script == null) {
        return;
    }

    // 改行を\nに統一
    script = script.Replace("\r\n", "\n");

    // スクリプトを改行で分離し行ごとに配列に格納
    String[] astLine = script.Split("\n".ToCharArray());

    // 各行を処理
    foreach (String stLine in astLine) {

        // 「文字列(文字列、または空)」の形式なら、コマンド行として処理
        if (stLine.IndexOf("(") > 0 && stLine.EndsWith(")")) {

            // (の前までをコマンド名として取得
            String stCommand = stLine.Substring(0, stLine.IndexOf("("));

            String stArg = null;

            // ()内に文字列があれば、引数として取得
            if (stLine.Length > stLine.IndexOf("(") + 2) {
                stArg = stLine.Substring(stLine.IndexOf("(") + 1,
                    stLine.Length - 1 - (stLine.IndexOf("(") + 1));
            }

            // コマンドを処理
            ExecCommand(stCommand, stArg);

        }

    }

}

 関数内の処理は、まず改行\nでスクリプトを各コマンド行に分離し、分離した各コマンド行からコマンド名と引数を取得して、実際にコマンドを処理するExecCommand()に渡していく、という流れになっています。今回のコマンドは

コマンド名(引数)

 という形式なので、コマンド行からコマンド名と引数の文字列を取得する処理は、次のようになります。

取得対象識別方法
コマンド名最初の(の前まで
引数最初の(の次からコマンド行末尾の)の前まで

 コマンドを処理するExecCommand()では、まず引数文字列として渡された文字列を「,」で区切り、各引数を分離します。ただし、文字列内(""の中)の「,」では区切ってはいけないので、""の内側の「,」は区切り文字と見なさないようにしました。今回引数を文字列にとるのはload()のファイルパスのみで、ファイルパスに「,」は使えないので、""内の判定はなくても(単純に「,」でSplit()し引数を分離しても)動作に支障はありません。

 引数を「,」で区切って配列astArgに格納したら、次にコマンド名を見て各コマンドの処理に振り分けます。loadであれば渡されたファイルパスをBitmapクラスのコンストラクタに渡す、mirror/upsetならBitmapクラスのRotateFlip()を呼び出す……とほとんど.NETのライブラリに「丸投げ」して行います。

 画像に対して独自の処理を行っている箇所は、各ピクセルのRGBを加算するaddRGBくらいです。addRGBの処理では、まずBitmapGetPixel()で各ピクセルの色情報(Color構造体)を取得し、その各RGB成分に指定値を加算して新しいRGBを算出します。そして、RGBの各値を0-255に丸めてから、そのRGBでColor構造体を作成し、ピクセルの値としてSetPixel()する、という流れになっています。

 ピクセルのRGBを取得し、またピクセルに書き戻すことができれば、画像処理のアルゴリズム次第で何でもできるので、各種フィルタなど自分でいろいろなコマンドを追加してみるのも良いでしょう。

アプリケーション

 実行するとフォームが作成されるので、下の方にある白いテキスト欄に

load("d:\image.jpg")

 など、適当な画像を読み込むコマンド行を書いて[実行]ボタンをクリックしてみてください。画像が読み込まれ表示されたら、

addRGB(100,-100,100)
mirror()
upset()

 などと入力し、コマンドを一通り試してみましょう。[実行]ボタンをクリックすると、スクリプトを入力したテキスト入力欄の下にあるテキスト欄にExecCommand()内で認識されたコマンド名や各引数が表示されます。

 ただし、resize()の引数にあまり大きな値を指定すると、画像の作成に失敗する可能性があるので注意してください。

まとめ

 今回のように「コマンドのみ」を実行するスクリプト実行系の実装は、意外に簡単です。そして、この種の簡易スクリプト実行系は、アプリケーションでちょっとした定型処理を行えるようにしたり、また手持ちの高度なライブラリの機能を、プログラムを新たに作ることなくテキストファイルから簡単に利用できるインターフェイス(テキストファイルのコマンドをライブラリを呼び出して処理するプログラム)を作ってみたり、と応用範囲もかなり広いと言えるでしょう。

 実際、私も数年前に簡易スクリプト実行系を試作してみてからは、自作アプリケーションにちょっとしたスクリプト実行系を組み込む機会が多くなりました。一定の「手順」を踏む処理を行うアプリケーションを開発する際は、その手順を自動化するスクリプト実行系を組み込んで利便性を高められないか、検討してみる価値はあると思います。

 簡易スクリプト実行系の実装に慣れてきたら、簡易スクリプトから変数や制御構文を持つ本格的なスクリプト実行系へと発展させていくのも、興味深い挑戦になるでしょう。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

宍戸 輝光(シシド テルミツ)

盛岡在住のプログラマ。事実上のフリーター状態から脱しつつある……と良いのですがw著者サイト:創作プログラミングの街

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/408 2006/06/13 00:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング