p5.js の GIF エンコード周りを読んでみる
同じ gifenc.js をベースに GIF エンコードの処理を書いている
有名ライブラリなのでなんか盗めるところがあるかも
L407 先に全フレームを書き出している
→(フレームごとにパレットを作るのでなく)グローバルパレットを作るため
WebGL では ctx.getImageData ではなく gl.readPixels を使用している
これなんだろ zk_phi.icon
L462 グローバルパレットの生成 _generateGlobalPalette
全フレームを結合したクソデカ Uint8Array を作って quantize に投げてる
同じ方法思いついていはいたけど、これでいいんだ… zk_phi.icon
画像の特性を使ったヒューリスティックなアルゴリズムだとダメな気がする
format: rgba4444、 oneBitAlpha: true になっている
このへんまじでよくわからん…
oneBitAlpha はアルファ値を 0x00 or 0xff の2値化するものっぽいが…
rgba4444 はアルファ値にも 4 bit を振るフォーマット
謎だ…
量子化後、パレットの末尾に「alpha = 0 なランダムな色」を追加している
「他のどの色とも(確率的に)被らない透明色」にしたいっぽい
パレットがすでに 256 色使っていた場合は、 256 色目を上書き
ちょっと乱暴な実装に見えなくもないが…
そしてそれを dispose のための「透過色」として使いたいらしい
今のところ謎、 quantize の時点で透過周りはいい感じになっているわけではないのか…?
L464 applyPalette 相当の処理の自前実装 (getIndexedFrame)
「元の色から量子化された色へのマッピング」のキャッシュを自前でやるためっぽい
グローバルパレットを使用するので、フレームを跨いでキャッシュを使いたいため
(誤って Math.randon() * 255 な色が選ばれてしまうことはないのか…?)
L495 フレームをエンコーダーに投げる
1フレーム目は普通に
それ以降は「前のフレームから色が変わっていないピクセル」は「ランダムな透過色」に
dispose: 1 として、変化のないフレームは全部透明にしておくことで最適化
1フレーム目では transparent や transparentIndex は未指定
2フレーム以降は transparent: true あり
transparentIndex には「ランダムな透過色」を指定
これ透過画像に対応できてる……?
しかし量子化の時にはわざわざアルファのチャンネルを用意してたりする
わがんね
通常の透過色と、最適化用の透過色は別ということなのかも