先日、
アニメ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を生成できるようになれば、
パラパラ漫画な冊子を造れるようになるかも
だけど、予定は未定・・(^_^;)