MC_PALETTEクラスの作成
パレットを制御するクラスMC_PALETTE
は、ファイル「MC_PALETTE.as」で定義します。こちらも、ムービークリップに関連付けられたクラスなので、MovieClip
を継承して作ります。クラスの雛形は次のようになります。
class MC_PALETTE extends MovieClip { function MC_PALETTE() // コンストラクタ { onEnterFrame = onInit; } function onInit() { // 初期設定 delete onEnterFrame; } }
パレットの初期化処理
以下が初期化を行う関数onInit()
の内容です。
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にあった色見本帳からパレットデータをもらったものです。開発方法によると思いますが、私は、あまり手をかけず、とりあえず動くものを作ってしまってから、後でじっくり改良する方法が好きなので、ベタに作りました。
function paletteInit() { palette = new Array( 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, // ... 永遠と続くパレットデータ
IconEditorクラス
そして、冒頭で紹介した唯一のFlashの中に書いたコード「new IconEditor()
」で生成されるクラスIconEditor
を解説します。
このクラスでは、主にPHPへアイコンデータをポストする処理を行っています。保存処理は次のように作りました。
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でクラスベースでの開発が行えることも大きいと考えています。
皆さんも、本稿を参考に、何か面白いツールを作ってみてください。