2012年7月21日土曜日

AndroidでアニメGIF表示

AndroidでアニメGIF表示と言えば明日の鍵さんがブログ記事にしてみえましたが
もっと短いコードでそれなりに動くものを作りました。

ソースはこれ。使い方はこんな感じサンプルプロジェクト
リソースや外部ファイルのアニメGIFを android.graphics.drawable.AnimationDrawable にします。各フレームをDrawableに展開してメモリに持つので、大きな画像やフレーム数が多いファイルはOOMになるかもしれません。

アニメーションの途中で pause したり resume したりする場合はこちらのブランチを使ってください。ただし AnimationDrawable の privateメンバにアクセスするためにリフレクションを使っています。

無保証ですがちょっとした用途なら使える、、カナ? 自己責任でご自由にお使いください。(Galaxy Note と Galaxy Nexus でしか確認していませんが API Level 4(1.6)でも動くと思います)

解説(?)。

アニメーション処理は AnimationDrawable にお任せしちゃいます。 <animation-list> なXML Drawableではパラパラアニメが実現できているので、その機構をアニメGIFに応用したいのです。
android.graphics.BitmapFactory でロードしたBitmapがアニメGIFの各フレーム情報を持っていてくれたらよいのですが、ソースを追うと最後のフレームしか使っていないようです。
external/skia/src/images/SkImageDecoder_libgif.cpp
SavedImage* image = &gif->SavedImages[gif->ImageCount-1];

external/skia のように external/giflibGIFライブラリを使えばアニメGIFのパーズはできるのですが、JNIを使うのはちょっと重い。android.graphics.Movie が SkMovie を介してアニメGIFを扱えるようなので、ここから各フレームを取得することにしました。
フレームごとのdurationにアクセスできないので10msごとに setTime() して新しいフレームを探す処理がちょっと無駄ですが、ロード時だけなので長編アニメGIFでなければまぁ大丈夫かな、、と。もっとおおざっぱなアニメーションでいい場合は 10msごと ではなく 50msごと、100msごと にしてもよいと思います。

onWindowFocusChanged()をオーバーライドしてアニメーションをスタートさせないといけないのが手間と言えば手間ですが、、自動的にアニメーションさせちゃうと画面表示されていない間もアニメーションが動き続けてバッテリーを消費しちゃうのでこれはこれでよいのかな?と。


もともとはJCROMのピクトをアニメーションする、、て話で調べ始めたんですけどね^^;

0 件のコメント:

コメントを投稿