SHOEISHA iD

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

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

特集記事

Webブラウザで動くアイコンエディタの作成

FlashとPHPで作るアイコンエディタ

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

ダウンロード ソースファイル (130.3 KB)
ダウンロード 実行ファイル (31.9 KB)

MC_PALETTEクラスの作成

 パレットを制御するクラスMC_PALETTEは、ファイル「MC_PALETTE.as」で定義します。こちらも、ムービークリップに関連付けられたクラスなので、MovieClipを継承して作ります。クラスの雛形は次のようになります。

MC_PALETTE.as
class MC_PALETTE extends MovieClip
{
    function MC_PALETTE() // コンストラクタ
    {
        onEnterFrame = onInit;
    }
    function onInit() { // 初期設定
        delete onEnterFrame;
    }
}

パレットの初期化処理

 以下が初期化を行う関数onInit()の内容です。

「MC_PALETTE.as」の初期化処理
function onInit()
{
    delete onEnterFrame;
    // パレットのタイル描画用の空のムービーを作成
    this.createEmptyMovieClip("canvas_mc", 9999);
    tile_xcount = 16;
    tile_ycount = 16;
    // カーソルムービーへの参照を設定 // ----(*1)
    select_mc       = _root.select_mc;
    // アイコン描画用のムービーへの参照を設定
    main_canvas_mc  = _root.main_canvas_mc;

    tile_width    = this._width / tile_xcount;
    changeIndex(0);
    paletteDraw();
    // パレットを選択した時のイベントを設定
    this.onPress = selectPalette;
}

 パレットのタイル描画用の空のムービーを作成したり、パレットの色を表すタイルを描画したりしています。用途が少し違うのですが、基本的にはクラスMC_CANVASとそれほど変わらないものになっています。

パレットの色設定

 それから、パレットの色情報ですが、ここでは、Array型の変数paletteに1つずつ値を指定しています。プログラムで赤緑青の色合いを計算してパレットを作ることも考えたのですが、とりあえずベタに指定しています。Webにあった色見本帳からパレットデータをもらったものです。開発方法によると思いますが、私は、あまり手をかけず、とりあえず動くものを作ってしまってから、後でじっくり改良する方法が好きなので、ベタに作りました。

「MC_PALETTE.as」のパレット色の設定
function paletteInit()
{
    palette = new Array(
    0x000000,
    0x800000,
    0x008000,
    0x808000,
    0x000080,
    // ... 永遠と続くパレットデータ

IconEditorクラス

 そして、冒頭で紹介した唯一のFlashの中に書いたコード「new IconEditor()」で生成されるクラスIconEditorを解説します。

 このクラスでは、主にPHPへアイコンデータをポストする処理を行っています。保存処理は次のように作りました。

「IconEditor.as」のポスト処理
function save(cgi_path)
{
    // アイコンのポスト用データ生成
    var res:String = "";
    var dat:Array  = main_canvas_mc.tile_array;
    var x, y;
    for (y = 0; y < main_canvas_mc.tile_ycount; y++) {
        for (x = 0; x < main_canvas_mc.tile_xcount; x++) {
            var num:Number = dat[y][x];
            var hex:String = "000000" + num.toString(16);
            res = res + hex.substr(-6, 6);
        }
    }
    // LoadVarsに値を設定
    var lv:LoadVars = new LoadVars();
    lv.mode     = "save";
    lv.x        = main_canvas_mc.tile_xcount;
    lv.y        = main_canvas_mc.tile_ycount;
    lv.da       = res;
    lv.dalen    = res.length;
    // ポスト
    var recv:LoadVars = new LoadVars();
    recv.url = cgi_path;
    recv.onLoad = function (ok)
    {
        trace(recv.result);
        if (ok && recv.result == "OK") {
            trace( '保存しました。' );
            _root.getURL(recv.url + recv.filename, "_new");
        } else {
            trace( "失敗しました。" );
        }
    }
    lv.sendAndLoad(cgi_url, recv, "POST");
}

 この関数の前半では、アイコンデータを文字列に直しています。ここでは、アイコンの1ドットを"RRGGBB"の6文字(16進数表記)で表すようにしています。Number.toString(16)は、数値を16進数に変換します。

 後半では、LoadVarsを利用してPHPへデータをポストします。ここでは、CGIから「result=OK」というメッセージが帰ってきたら、filename=xxxで指定されたページを開くようにしています。本来なら、失敗した旨をユーザーに表示すべきですが、プログラムの簡易化のため記述していません。

PHPで画像の保存処理を作る

 さて、ここまででアイコンエディタの本体ができたので、次は、サーバーサイドのPHPプログラムを見ていきましょう。まずは、ポストされたデータの解析処理を行っている部分です。

ポストされたデータの解析処理
$fname = "test.gif";
$mode = $_POST["mode"];
$da   = $_POST["da"];   # アイコンのデータ
$cols = $_POST["x"];    # アイコンの幅(px)
$rows = $_POST["y"];    # アイコンの高さ(px)

if ($mode == "save") {
  savePic($rows, $cols, $da, $fname);
  echo "result=OK&filename=$fname";
  return;
}

 PHPでは、ポストされたデータは変数$_POSTに代入されているので、特に何も解析する必要はありません。まず、使いやすいように変数に代入しています。ここでは、保存されるファイル名$fnameが、固定になっていますが、このままだと、常に同じファイル名に画像が保存されてしまいます。アイコン掲示板のように、複数のアイコンを保存しておくようなサイトでは、カウンタを利用してファイル名が重ならないように工夫する必要があるでしょう。

 そして、以下がGDライブラリを利用して、画像を保存している部分です。大まかな手順としては、まずimagecreate()関数でイメージのハンドルを得ておきます。そして、imagecolorallocate()関数で、利用したい色の番号を取得し、imagesetpixel()で点を描画します。一通り画像への描画が終わったら、imagegif()関数で画像をGIF形式で保存し、imagedestroy()関数で処理を終わります。

画像の保存処理
function savePic($rows, $cols, $da, $fname)
{
  $im = @imagecreate($cols, $rows);
  $colors = array();
  for ($y = 0; $y < $rows; $y++) {
    for ($x = 0; $x < $cols; $x++) {
      $i = $y * $rows + $x;
      $i = $i * 6;
      $pname = substr($da, $i, 6);
      if (!isset($colors[$pname])) {
        $r = hexdec(substr($da, $i + 0, 2));
        $g = hexdec(substr($da, $i + 2, 2));
        $b = hexdec(substr($da, $i + 4, 2));
        $colors[$pname] = @imagecolorallocate($im, $r, $g, $b);
      }
      $c = $colors[$pname];
      @imagesetpixel($im, $x, $y, $c);
    }
  }
  @imagegif($im, $fname);
  @imagedestroy($im);
}

 GIFでは最大256色までしか利用できないので、画像の中に各色のパレットを持っています。そこで、必要な色数だけimagecolorallocate()関数を利用して色を割り当てます。この関数の戻り値にはパレットの番号が得られるので、この番号を利用して描画を行います。

 アイコンエディタ本体(Flash側)から渡される情報は、"RRGGBB"の文字列の形式なので、この文字列をキーにしたハッシュ$colorsにパレット番号を覚えておいて、同じ色を二度割り当てないように工夫しています。

 また、FlashとPHPで受け渡すデータ形式ですが、1ドットを表すのに"RRGGBB"と6バイトも利用しています。アイコンエディタ本体からPHPにポストする前に、パレットデータとその番号に直しておけば、通信量を減らすことができます。しかし、この場合、16ドットのアイコンだと、16×16(ドット)×6(バイト)で1536バイト、32ドットのアイコンでも、32×32×6(バイト)で6144バイトなので、普通の画像ファイル1枚程度にしかなりません。それならば、頑張ってデータ量を小さくして可読性の低いデータ形式にするよりも、可読性の高いデータ形式を採用した方が良さそうです。また、"RRGGBB"の形式にしておけば、将来的にフルカラーのアイコンを編集できるように改造する際にも、データ形式を変更せずに済みます。

最後に

 このようにして、FlashとPHPでアイコンエディタを作成しました。FlashのDrawing APIと、PHPのGDライブラリを利用することで、案外手軽に作ることができたと思います。冒頭で紹介したアイコンエディタも、ウノウ(株)の開発合宿を利用して、ほぼ1日(作業人数は2人)で作ったものです。

 それから開発ツールに関してですが、アイコンエディタ程度なら、JavaScript+PHPでもできないことはないと思います。しかし、Flashを利用することで、より手軽に作ることができたと思っています。それは、Flashの描画機能に加えて、(若干癖があるものの)ActionScript2でクラスベースでの開発が行えることも大きいと考えています。

 皆さんも、本稿を参考に、何か面白いツールを作ってみてください。

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

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

もっと読む

この記事の著者

クジラ飛行机(クジラヒコウヅクエ)

ソフト企画「くじらはんど」にて、多数のフリーソフトを公開しています。日本語プログラミング言語「なでしこ」、テキスト音楽「サクラ」、日本語Wiki記法が特徴の「KonaWiki」などを公開しています。

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

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

この記事をシェア

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

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング