PNG・GIFのパレットを読み込んだり書き換えたり他

このまえ作ったドット絵用ビューアを更新しました。更新内容は主に

  • アニメーションGIFの対応
  • PNG/GIF画像のパレット読み込み・書き換え

の二つです。実際に動いているのは、

ドット絵ビューア例

みたいなかんじです。

AS3のLoader(今まで使っていたもの)だと、PNGやGIFなどの画像を読み込んで表示がお手軽にできるのですが、アニメGIFを読み込んでも最初のフレームしか表示できなかったり、表示オブジェクトにしかならないので、パレットの情報などは得られません。

ちゃんと画像として読み込むには、URLLoaderを使って画像データをバイナリとして読み込み(ここまでは簡単)、さらにバイナリを仕様に基づいて分解してBitmapなどに変換してやる必要があります。

アニメGIFに関してはGIF Player(下のほうにVersion 0.2があります。)なるアニメGIFをバイナリから読み込んで表示できるライブラリがあったので、苦労せずして読み込めるようになりました。もっと早く気づいていればよかった。少しソースをいじれば、GIFのデコーダからパレットや背景色情報なども取得できます。

PNGに関してはデコーダクラスは今のところない(そもそもLoaderで表示できるので普通は必要ない)ようなので、

あたりを参考に、パレットを読み込んでいます。パレット形式のほかにも、フルカラーPNGの対応などを考えると大変なので、ビューア上でのPNG表示はLoaderに任せて、パレット・透過の色情報だけ取得しています。なので、そんなに難しくありません。

で、GIFもPNGもBitmapDataとパレットの情報に変換できたので、ついでにパレットの色の書き換えも実装してみました。ただし、擬似的なものでちゃんとしたパレットの変換にはなってません。だいたいこんな感じ

// 画像(BitmapData)の中の色(oldColor)を色(color)に変換する
private function transColor(b:BitmapData, oldColor:uint, color:uint):void 
{
  b.threshold(b, b.rect, new Point(), '==', oldColor, color);
}

これだと、パレット番号に関わらず同じ色のものが変換されてしまうのでよくないです。色変換前のBitmapDataとパレット情報を保存しておいて、うまくやればちゃんとパレットでの変換になるとおもいますが、そもそもビューアであってエディットツールではないのでそこまでこだわる必要も無い気がしたのでこの辺でやめておきました。(この辺で力尽きたというのもあります)

ドット絵ビューアの今後の展望

ここまできたらもはや編集出来るようにしてもいい気もしますが、やっぱり既存のドット絵エディタツールには敵う気がしないのでビューア機能を強化したいところです。あんまり機能つけすぎて重くなってもしょうがないし。

というわけで、気が向いたらそのうち実装するかもしれないアイデアメモ

  • パレットデータの保存(EDGEの.pal形式とか)
  • 網掛け表示
  • アニメーション表示いろいろ(並べて・重ねてetc...)

世界樹の迷宮II キャラクタステータスエディタつくった話

世界樹の迷宮II キャラクタステータスエディタ

つくりました。

ゲームのキャラクタのステータスをシミュレートしていじれるツールなのですが、世界樹の迷宮IIはまだ発売されていなくてデータがないので現在は判明しているスキルのみエディットできます。

このような簡単なツールはもっぱらJavaScriptで作成するのが普通で、そのほうが開発は容易だし手早くつくれます。
だというのに、わざわざFlashで作った理由は、インターフェースをある程度作りこみたかったことと、画像の生成が容易だったからです。

このツールの一番のポイントが、作成したキャラクタデータを画像化してアップロードできるという点。

こんなかんじに。
http://status.heriet.info/sq2/Elsu6eaua8Oaic6.png

これまではWeb上でツールで作ったキャラクタデータをやりとりするのに、「データ作成者がツールのURLを貼る→閲覧者がURLを開く」という流れが必要だったのでした。
しかし、画像として生成してやれば、作成者が画像を貼り付けてやることで閲覧は容易になります。(2chブラウザなどでもツールのURLよりも画像URLのほうが閲覧が楽)

あと、ちょこっとデータとか計算式を変えてやれば似たようなシステムのゲームにも対応できそうです。ネトゲとかはほとんどやらないので似たようなキャラエディットのあるゲームがどれだけあるかはわかりませんが。(少なくともデータ作れば前作にも適用できる)

ツールの開発自体は前につくったツール類の使いまわしも多く、わりと簡単にできました。部品組み合わせただけで難しいことはしてません。ソースとかも一応は配布してます。(Flex3 SDK Beta3で開発)

もう2,3ツールとか作ってスキルを上げたら、本命のゲームのほうも作り込みたいところです。

ドット絵向け簡易画像ビューア(ピクセルビューア)

ピクセルビューアとかいうやつソースとか色々公開しました。

ブラウザ上でドット絵とかの画像を閲覧するためのビューアです。

名前は適当です。解説も適当。たいして興味深いこともしてないので。いろいろ適当。しいて言えば、EDGE風のカラーピッカーは他にも使い道あるかもねってぐらい。

アップローダーの画像閲覧用に作ったやつで、あんまり汎化されてないですが、某所ではそこそこ好評頂いているようです。


画像アップローダーに画像閲覧ビューアつけたらおもしろいんじゃね?という思いのもとつくってみましたが、やっぱりおもしろいことになってます。

特に、某所はアップロードした画像の出来の良し悪しを語ったりする場所なので、わざわざ画像をダウンロードするまでもなくFlashのビューアだけで細かいところまで拡大してみたり左右反転させてデッサンの矛盾点を見つけたりできるのはよい感じ。

よくあるアップローダーだと転送量とかの問題もあるので有用ではないでしょうが、某所は閲覧数・アップロード数・ファイルサイズがたいしたことないので全然問題ではないでしょう。swf自体のサイズも少ない(約15KB)ですしね。

とまあ、こんな感じのツールが大体3,4日ぐらい(のべ1日ぐらい)で作れるので楽しいですねAS3

Flash内の表示オブジェクトをPNG画像として開く

はじめに

世界樹の迷宮風マップツールII β で実装した、マップの画面をPNG画像として開く、というお話です。

簡易なお絵かきができるようなFlashはよくありますが、描いたものをいちいちPrintScreenしたりするのも面倒ですよね。

セキュリティ的な問題だと思いますが、Flashで生成したデータはそのままファイルとしてそのまま保存はできません。せいぜい、クリップボードにテキストを貼り付けられる程度です(バイナリは無理)

ならばせめて、画像を右クリックして名前をつけて保存、ぐらいのことが出来るようにしたいと思います。

ここまでならサーバーを介して既にやっているところも多いのですが、さらに可能な限りローカルで処理を行い、できるだけサーバーの負担を軽減するようにします。

ちなみに、ActionScript3.0/Flex2 SDKで作っています。AS2まではByteArrayとかがないので下の方法では出来ません(無理やり画像化する方法はあるようです)

Step 0 〜 とりあえず実際の例を見てみる

言葉で書いていてもわかりにくいので、簡単なサンプルと使用したソースを上げておきました。どういう風に動くのかはそちらを見てみてください。IEFirefoxでは微妙に挙動がちがいます。

ちなみに、世界樹の迷宮風マップツールII β 新規マップの上部の左から6番目のアイコンからおんなじことが出来ます。(というか、これをやるために作ったので)

Step 1 〜 表示オブジェクトをPNG画像にする

では実装したコードについて順序だてて説明してきます。

まずは、DisplayObjectをBitmapDataに変換して、BitmapDataをPNGエンコードされたByteArrayに格納します。たとえばこんな感じ

import com.adobe.images.PNGEncoder;

import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.utils.ByteArray;

public function encodeDisplay(display:DisplayObject):ByteArray
{
  var bitmapData:BitmapData = new BitmapData(display.width,display.height);
  bitmapData.draw(display);
  var png:ByteArray = PNGEncoder.encode(bitmapData);
  return png;
}

BitmapData.draw()でDisplayObjectをBitmapDataに変換します。もちろん、MovieClipとかSpriteとかShapeとかはDisplayObjectを継承しているのでどれも同じ処理が使えます。BitmapData.draw()に渡せるのはIBitmapDrawableインターフェース(DisplayObjectとBitmapDataで実装されている)ですが、BitmapDataならそのままPNGエンコードすればいい話です。

BitmapDataからPNGへの変換はcom.adobe.images.PNGEncoderを使っています。使い方はソースのとおり。簡単ですね。

Step 2 〜 サーバーに送って表示させる

生成したByteArrayをサーバーにPOSTして、画像を表示させます。たとえばこんな感じ

import flash.net.URLRequest;
import flash.net.URLRequestMethod;

private static const OUTPUT_URL:String = 'サーバの送り先';

public function output(image:ByteArray,window:String = null):void
{
  request = new URLRequest();
  request.url = OUTPUT_URL;
  request.contentType = 'application/octet-stream';
  request.method = URLRequestMethod.POST;
  request.data = image;
  navigateToURL(request,window);
}

サーバー側はなんでもいいですが、例えばPHPで簡単に書けば

<?php
$png = file_get_contents('php://input');

if(isset($png)){
  header("Content-type: image/png");
  header("Cache-control: no-cache");
  
  print $png;
}
else{
  print 'no image';
}
?>

とでもしてやればいいです。実際に使う場合は、サーバ側は送られた画像が本当にPNGなのかとかスクリプトが埋め込まれてないかとかチェックする必要があります(サーバーに画像を保存するなら特に)

まあ簡単ですね。

Step 3 〜 dataスキームも使う

サーバーを介せばもうそれでいい話なんですが、あんまり負担が増えても困りものです。せっかくFlashがローカルで画像処理してくれているのだから、できれば全部ローカルで処理したいと思うのが普通ですよね。

そこで、dataスキームを使えば、サーバーを介せずにローカルだけで処理できます。dataスキームは、バイナリのデータをテキストに符号化(普通はBase64で符号化)し、URLの代わりに直接データを埋め込むことができるものです。ブラウザによってはdataスキームが実装されていませんが、FirefoxOperaなどではdataスキームを使うことが出来ます。

例えば、「data:text/plain;base64,aGVyaWV0」という文字列をブラウザのアドレスバーに貼り付けてやれば、dataスキームが使えるブラウザならば「aGVyaWV0」という文字列をBase64でデコードしたテキストが表示されるはずです。エンコードされている文字がtext/plain以外の形式でも、適宜書き換えてやればOKです。

で、要はBase64に符号化してやればいいだけなので実装も簡単です。ライブラリもあるのでそちらを使ってやれば下のようになります。

import com.dynamicflash.utils.Base64;

public function outputDataScheme(image:ByteArray,window:String = null):void
{
  var imageString:String = Base64.encodeByteArray(image);
  var url:String = 'data:image/png;base64,' + imageString;
  var request:URLRequest = new URLRequest(url);
  navigateToURL(request,window);
}

これはcom.dynamicflash.utils.Base64 を使っています。

ちなみに、標準でmx.utils.Base64Encoderというクラスもある(でもFlex2のドキュメントには載ってない)ので、そっちを使うのであれば

import mx.utils.Base64Encoder;

public function outputDataScheme(image:ByteArray,window:String = null):void
{
  var encoder:Base64Encoder = new Base64Encoder();
  encoder.encodeBytes(image);
  var imageString:String = encoder.flush();
  var url:String = 'data:image/png;base64,' + imageString;
  var request:URLRequest = new URLRequest(url);
  navigateToURL(request,window);
}

とも書けます(ちょっと使いにくい気もするけど)で、バイナリをBase64符号化したものに、先頭に「data:image/png;base64,」とくっつけてやってそれをURLとして開いてやれば、dataスキームに対応したブラウザなら画像が表示されるはずです。

でも、dataスキームに対応しているかどうかはブラウザ依存。困りますね。

Step4 〜 dataスキームとサーバーを使い分ける

仕方がないので、dataスキームが実装されているブラウザではdataスキームを使うことでサーバーの負担を減らし、どうしようもない場合はサーバーを介して表示させることにしましょう。閲覧者のブラウザがdataスキームを実装しているかどうか判別できればいいわけです。

実際に適当なデータをつかったdataスキームを読み込んで、結果正しく読み込めていれば判別できるかと思ったのですが

import flash.net.URLLoader;
import flash.net.URLRequest;

private _ableDataScheme:Boolean = false;

public function checkAbleDataScheme():void
{
  var url:String = 'data:text/plain;base64,aGVyaWV0'; 
// aGVyaWV0はherietという文字列をBASE64エンコードしたもの。対応するブラウザで直接開くと読み込める

  var request:URLRequest = new URLRequest();
  request.url = url;
  request.method = URLRequestMethod.GET;

  var loader:URLLoader = new URLLoader();
  loader.addEventListener(Event.COMPLETE,loadComplete);
  loader.load(request);
}
private function loadComplete(e:Event):void
{
  var loader:URLLoader = URLLoader(e.currentTarget);
  if(String(loader.data) == 'heriet')
    _ableDataScheme = true;
}

上のcheckAbleDataSchemeのような処理をおこなっても、URLLoaderではdata スキームに対応していないようで、対応しているブラウザで開こうとしてもIOErrorEventになってうまくいきません。

そこで、代わりにJavaScriptでブラウザのdata スキーム判別を行うコードがあったので、そいつを使います。JavaScriptでのBase64が使用できるかどうかのBoolean値を返す関数をdschk()とすれば、それをFlash側で呼び出してやればいいわけです。たとえばこんなかんじ

private var _ableDataScheme:Boolean;

public function checkAbleDataScheme():void
{
  try{
    _ableDataScheme = Boolean(ExternalInterface.call('dschk'));
  }
  catch(e:Error){
    _ableDataScheme = false;
  }
}

画像を表示させる前に、checkAbleDataScheme関数を呼び出しておいて、画像を表示させるときに_ableDataSchemeがtrueならdataスキーム、falseならサーバーに送信すればよいということになります。ただ、この方法だとHTMLから呼び出していて、かつJavaScriptが有効でないと使えないので状況が限定されるというのがやや難点です(だいたいの閲覧者は有効だとおもうのですが)

Flash側から直接、使用しているブラウザがdata スキームに対応しているかどうかわかれば一番いいんですけどね。とりあえず私の知識ではできませんでした。

Step5 〜 応用することを考える

というわけで、上では表示オブジェクトをPNGの画像として開く、という問題に限定して考えましたが、ここまで読んだ利口なみなさんならばすぐに応用例が思いつくことでしょう。

サーバーやdataスキームとして渡すデータ形式は別にPNGである必要はないし、画像ですらある必要はありません。バイナリだろうがテキストであろうが、同じような方法で渡すことが出来ます。

表示オブジェクトからJPG形式のByteArrayにするライブラリもありますし、音声なり動画なりSWFなりをFlash側で編集とか生成とかしてやれば、わりと簡単にブラウザから読み込んでダウンロードとかさせることができるのです。

世界樹の迷宮風マップツールII β公開しました

世界樹の迷宮風マップツールII βというわけで、まだβですが前のより使える程度になったので公開しました。

エディタの仕様が世界樹の迷宮IIバージョンになり、タッチペンと同じドロップ式入力・マップアップロード・マップ画像化などなどの機能も追加されてます。

マリオドット絵みたいな感じでマップがアップロードできます。これでちょっとしたマップを説明するのでも、貼り付けやすくなったかと。

あと、マップ画面のPNG画像化も実装したので、より保存しやすくなっています(攻略サイトとかブログとかに是非使ってください)

Flash画面の画像化は作っていてけっこうおもしろかったので、今度別エントリで解説でもしようかと思ってます。

まだまだ細かい部分が作りこめていないので、発売前にはできるだけ実装していきたいところです。

ゆくゆくは、汎用のFlashマップエディタみたいな感じになっていくといいですね。

世界樹の迷宮IIが発表されたので、またマッピングツール作ってたり、アイコン作ってたり

ディープメモに続き、世界樹の迷宮II メモランダムということで、また新しくサイトを立ち上げました。
前回はあんまり味気のない攻略サイトとしてやってましたが、今回はより個人サイトな色を出してみようかと考えてます。

とりあえず、世界樹の迷宮IIマッピングも新しいインターフェースになっているようなので、前に私が作ったマップツールも一から作り直しているところです。中途半端なところで開発もとまっていたところですし。

また、新しく追加する要素として、

  • マップアップロード機能
  • アイコンドロップモード(タッチペンと同じような編集モード)
  • 床色変更

などなど、その他色々考えています。

それが仕上がったら、今度はユグドラ・ユニオン用(今度PSPでリメイクされることだし)のマップとか、その他いろんなゲームにも適用できるような仕様に拡張していきたいなとも思っています。

それからマップとは別に、ドット絵修行として世界樹の迷宮の12ジョブ×9の小さめなアイコンをせっせと作ろうとしているところでもあります。現在は1日1個のペースで9キャラできてますが、飽きっぽい私が果たして全部描ききれるのか、不安でしょうがありませんね。

まあ、相変わらず需要のある・なし、を気にせずやりたいことをやっている感じな今日この頃でした。

どうみても CUFD-H が他を圧倒しています

売れ行きとかUSBメモリスレ内の人気とかいう話ではなく。

ここ1週間のUSBメモリまとめWikiの検索キーワード数ランキング(()内 検索数)Google Analytics調べ

  1. 「cufd-h」 (281)
  2. usbメモリ まとめ」 (105)
  3. usbメモリ wiki」 (99)
  4. 「usb wiki」 (55)
  5. usbメモリ」 (45)
  6. 「cufd-h2g」 (42)
  7. 「picoboost」 (33)
  8. 「cufd-h4g」 (28)
  9. usbメモリまとめ」 (28)
  10. 「cufd-h8g」 (24)

自身のサイト名を除くと、10位以内ではUSBメモリの製品名はCUFD-HとPicoBoostのみ。

CUFD-Hの人気が出る前は、PicoTurbo 一択みたいな雰囲気もあったのですが、今ではほとんど話題にも出ない感じです(代わりにPicoBoostが頑張っている)

1年後には、CUFD-Hじゃなくなっているのか、はたまた、まだまだCUFD-Hが頑張っているのか。こういう遅遅とした微妙な変化が運営していて楽しかったりするのでした。

※まあ、検索してみるとわかるけど、CUFD-Hのランクが異様に高いのは、検索して他に引っかかるサイトがあまりないせい