Everyday Pieces ::
  • Webサービス
  • ブログパーツ
  1. ホーム
  2. プログラミング

GIFをparseするjsなライブラリ(3)

2017年3月6日 プログラミング gif.js

 前々回でも書いていましたが、
アニメGIFを再現する際の
disposalMethodなる処理がよく分からず、
放っておいたままでした(^_^;)

 改めてさらに調査して試してみたら
うまく行った感じになったので、
それについてまとめてみたいと思います。

 こちらによると、
Disposal Method は0~3の4種類がある模様です。

Disposal Method
0 - No disposal specified.
The decoder is not required to take any action.
1 - Do not dispose. The graphic is to be left in place.
2 - Restore to background color.
The area used by the graphic must be restored to the background color.
3 - Restore to previous. 
The decoder is required to restore the area overwritten 
by the graphic with what was there prior to rendering the graphic.

 上記のように仕様が書かれているようですが、
実装するにはどうしたらよいのかがよく分からない感じです。

 こちらのページでは、
実際に0~3の値を指定して具体的なちがいを説明しています。
ところがGIFをダウンロードしてdisposalMethodの値を確認してみると、
0,1は良いのですが、
「2」となっているのは実際には3で、
「3」となっているのは実際には7が入っていました。
ということで残念ながら間違っている感じです。

 ところで、
disposalMethodはアニメGIFを再現するにあたっての、
現フレームから次フレームへ移行する際の
「後始末方法」を指示しているようです。
実装時には先頭以外の各フレームを描画する直前で対処することになりそうです。
値としては0~7を指定できるのですが、4~7は未定義っぽい?

 いろいろ調べた結果、
こちらのページを見つけました。
ページの右端に表示されてる5つのフレームを使って、
disposalMethodのちがいによる効果を説明しています。
2つのアニメGIFのdisposalMethodは、
それぞれ順に各フレームで
左:1,2,2,2,2
右:1,3,3,3,3
となっていました。





 これによって次のことが分かりました。
Disposal Method:
0) 特に何もしない。
1) 処理時には何もしないが、
 ”no disposal”という形でフレームの内容を覚えておく。
 一番最近に処理したのを1つだけ覚えておけばよい。
2) 全体を背景色でいったん塗りつぶす。
 ここで言う「背景色」はGIFヘッダでの設定を指しているのでは無く、
 描画側が設定する背景色を指します。
 通常は rgba(0,0,0,0) になるので、
 描画する範囲の既存の状態が背景色となります。
 特に意識しなくても問題ないと思います。
 たいていの場合はhtmlのbodyカラーが背景色になるはずです。
3) 2と同様に全体を背景色でいったん塗りつぶし、
 覚えておいた”no disposal”なフレームがあればそれを描画する。

 思ったより複雑ですね。
仕様書を読んだだけじゃ分からんンわ・・・(^_^;)

 ということで、
ライブラリを更新しました。
諸般の都合で一部の仕様が変わります(^_^;)
Gif.createFrameImages()は以下のように変わります。
第1引数にはCanvasの’2d’なコンテキストを渡します。
第2引数にtrueを渡すと、
あらかじめレンダリングしたイメージを生成します。
通常はこれが使いやすいかと思われます。
falseを渡した場合は、
GIF内のイメージのままで返します。
前フレームからの差分イメージになっていることがあります。
第3引数にfalseを渡すと、
canvasContext.putImageData()向けのイメージを生成します。
trueを渡すと、
canvasContext.drawImage()向けのイメージを生成します。

 サンプルなソースコードの例は以下のように変わります。

function animateGIF(arrayBuffer,canvas) {
    var gif,context,frames,idx,delay,lastTime;

    gif = new Gif();
    gif.onparse = function() {
        start();
    };
    gif.onerror = function(e) {
        alert(e);
    };
    gif.onprogress = function(e) {
        console.log('Parsing...' + ((100 * e.loaded / e.total)|0) + '%');
    };
    gif.parse(arrayBuffer);

    function start() {
        canvas.width = gif.header.width;
        canvas.height = gif.header.height;
        context = canvas.getContext('2d');
        frames = gif.createFrameImages(context,true); // pre-rendering
        idx = 0;
        delay = 0;
        draw(); // first draw
        if (frames.length > 1) {
            setTimeout(function() {
                lastTime = performance.now();
                tick(lastTime);
            },0);
        }
    }

    function draw() {
        var frame;
        frame = frames[idx];
        delay += frame.delay * 10; // 1/100sec to millisec
        context.putImageData(frame.image,frame.left,frame.top);
    }

    function tick(time) {
        var delta;
        delta = time - lastTime;
        lastTime = time;
        delay -= delta;
        if (delay <= 0) {
            idx = (idx+1) % frames.length;
            draw();
        }
        requestAnimationFrame(tick);
    }
}

 拙作のライブラリを使って、
作ってみたツールはこちらから試せます。
ライブラリのダウンロードも行えます。

関連記事
自サイトの壁紙を自動生成するようにしてみた(実験的) GIFをparseするjsなライブラリ(4) GIFをparseするjsなライブラリ(2) GIFをparseするjsなライブラリ JavaScriptのクラスの書き方の考察

コメントする キャンセル

アドレスが公開されることはありません。が付いている欄は必須項目です。

投稿ナビゲーション

目の動きが人間らしさを生むVRなアバター
アニメGIF⇒パラパラ漫画(JS版)

カテゴリー

WordPress つぶやき トピック プログラミング

タグ

AS3 enchant.js FamilyTreeVis Flash Geolocation gif.js kinect Linux MMD MoneyTrackNote notifier.js OpenCV PDFカレンダー RISC-V three.js セキュリティ テーマ自作 ブログパーツ 動物 動画 麻雀

アーカイブ

© katwat