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

GIFをparseするjsなライブラリ

2017年2月19日 プログラミング gif.js

 先日、
アニメGIFからパラパラ漫画の冊子を作る
という記事を取り上げましたが、
これのJavaScript版を作ったら面白いかも、
とか思い立ちました(^_^;)

 まずは、
GIFを扱うライブラリを探してみたのですが、
個人的に良さげなのが見つかりませんでした。
というかうまく見つけられなかったのかも(^_^;)
そんなわけでこちらのjsgifを元に作ってみることにしました。
GIFフォーマットの詳細はこちらを参照しました。

 元になったコードでは、
バイナリ文字列という手法でGIFイメージを扱っていますが、
これだと読み込みがXHR限定になってしまうし、
少々トリッキーで余計な処理も必要となる感じ。

 そこで、
arrayBufferでイメージを扱うように改造しました。
responseType='arraybuffer'なXHRや、
Drag&Drop経由のFileReader.readAsArrayBuffer()で
読み込めるようになるので扱い易くなるのではないかと。

 また、
オリジナルではGIFイメージのchunk(データの塊)を走査する毎に、
指定があればコールバックを呼び出す作りになっていましたが、
直感的に扱いにくい感じだったので、
単純にparseした結果を返すように変えました。

 さらに、
canvasなコンテキストで扱うのに都合が良い
画像イメージを作成する機能を加えてみました。
ただ、透明ピクセル時に必要となるっぽい
disposalMethodなる処理が良く分かってないです(^_^;)

 なお、
GIFファイルのサイズが大きいとか、
コマ数が多かったりすると、
LZWなデコードを伴うせいか、
parseするのにそれなりな時間が掛かるようです。
WebWorkerとか使って別スレッドでやったほうが良いのかも?(^_^;)

 さて、
拙作のライブラリを使うには、
例えば以下のようにします。
GIFのイメージを読み込んだarrayBufferと
イメージを描画するためのcanvasを渡します。
アニメーションさせるにはsetTimeout()を使うのが簡便そうですが、
requestAnimationFrame()を使ってVSYNCな感じになるようにしてみました。

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

    gif = new Gif(arrayBuffer);
    if (gif.error) {
        alert(gif.error);
        return;
    }
    canvas.width = gif.header.width;
    canvas.height = gif.header.height;
    context = canvas.getContext('2d');
    frames = gif.createFrameImages(context,1);
    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
        if (idx === 0) {
            context.clearRect(0,0,context.canvas.width,context.canvas.height);
        }
        context.drawImage(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.createFrameImages()について説明します。
第1引数にはCanvasの'2d'なコンテキストを渡します。
第2引数は値によって生成されるイメージが次のようになります。
・0の場合
 canvasContext.putImageData()向けのイメージを生成します。
・1の場合
 canvasContext.drawImage()向けのイメージを生成します。
 通常はこれが使いやすいと思います。
・2の場合
 1の場合と同様ですが、あらかじめレンダリングしたイメージを生成します。
 0と1の場合は、前フレームからの差分イメージになっています。

 ということで、
ちょっとしたツールを作ってみました。
アニメGIFをドロップすると各コマに分割してダウンロードできます。
試すにはこちらからどうぞ。
ライブラリのダウンロードも行えます。

 あとはPDFを生成できるようになれば、
パラパラ漫画な冊子を造れるようになるかも
だけど、予定は未定・・(^_^;)

関連記事
自サイトの壁紙を自動生成するようにしてみた(実験的) GIFをparseするjsなライブラリ(4) アニメGIF⇒パラパラ漫画(JS版) GIFをparseするjsなライブラリ(3) GIFをparseするjsなライブラリ(2)

コメントする キャンセル

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

投稿ナビゲーション

アニメGIF⇒パラパラ漫画
SHA-1の衝突攻撃に成功

カテゴリー

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

タグ

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

アーカイブ

© Everyday Pieces ::