Firefox3から入るらしいAPNG(Animated PNG)。MNGみたいに複雑すぎず、アニメーションGIFと同じくらいの機能が入っており、既存のPNGと互換性を保つ。互換性というのは、既存のPNG対応アプリで何も変更することなしに普通に特定のフレームが画像として見えているということ。これは大きい。
MNGは機能を詰め込みすぎたせいでもう死んでいる。APNGはモメたようでこの後もすったもんだがあるかもしれないけど、Firefoxが強引に入れてしまうようなので、デファクトスタンダードになるかもしれない。フルカラーでアルファブレンディングもできる簡易アニメーション、というのはブラウザさえ普及すれば需要があると思います。
というわけで、APNG及びPNGについてちょっと調べつつサンプルプログラムを書いてみた。まずPNGはシグニチャがあり、その後にチャンクの形式でずらずら続く。圧縮は全部zlibのdeflate。圧縮されるチャンクの種類は少なく、IDAT(画像データ)とzTXt(圧縮テキスト)、iTXt(言語情報を入れられるテキスト情報)くらい。IDATを開くとrawなビットマップなデータが入っている。非常に単純で特別な技術も使われておらず、実装しやすいという印象。まあ難しそうなのはinterlaceのコードと、あとはアルファブレンディングみたいな画像関係の技術が入るところくらいで、それも特に疑問なく実装できそうな気がする。
非圧縮PNGの形式を用意してgzip(zlib)で圧縮しただけ、でも良かったんじゃないのかな、という感想も持ってしまうな。けっこうすごいことしてんのかなと思ってたんだけど、こんなもんだったのか。
で、APNGはチャンク「acTL」「fcTL」「fdAT」の3つを追加する拡張。普通のPNG対応(APNG非対応)アプリはacTLやfcTL、fdATなんて知らないから無視して、通常のIDAT等を使うので問題ない。これはコンテナのタイプIDに4文字テキストを使ったPNG作者のセンスが勝因だろう。テキストのほうが見た目が分かりやすく、4文字固定なら最適化で32bit intとして見る実装も可能だしね。大文字小文字に意味を持たせるというやり方も分かりやすくていい。
APNGで拡張した内容は、「acTL」はアニメーション全体の情報(フレーム数やリピート回数)、「fcTL」はフレームの情報(ディレイ時間など)、「fdAT」はフレームのデータが入る。フレーム番号の扱いが微妙な感じを受ける。fcTLとfdATにはフレーム番号がついているが、別に対応するわけではなく連番。複数のfdATが1枚のフレームを構成するようになっていて、fdAT列の区切りとしてフレームごとのfcTLがあるという感じ。1枚のフレームを構成する複数のfdATそれぞれに別個にフレーム番号を振る必要があり、その番号がfcTLも含めた連番になっている。
だからfcTLのフレーム番号を見ても何枚めのフレームなのかは判別できない。そしてacTLに入っているフレーム数というのはfcTLの個数なので、対応をつけるのがアレですな、という感じ。
よく見ると(よく見なくても分かるけど)、fdATからフレーム番号だけ削除してそのままIDATに変更すれば普通のPNGを抜き出すことができる(CRC32を計算しなおす必要はあるが、圧縮し直す必要はない)。そんな簡単にできそうなapng2pngのコンバータ。
まあでもこんなに簡単な構造ならPure-Pythonで書こうよ、という印象なので、試しに書いてみた。APNG対応のアプリもまだ少ないことだし、サンプルとして見てもらえれば幸いです。
pngtest.pyもしくは、
# cg-clone https://wtnb.mydns.jp/apngtest.git/
で取れます。
# ls apng-file.png # python /path/to/pngtest.py apng-file.png output # ls apng-file.png output-1.png output-2.png output-3.png # eog output-?.png
こんなところで。
Tkinterを使ってウィンドウを確保し、spinfox.pngがぐるぐる回るようになりました。cg-updateしてお試しあれ。インタレースAPNGはPILが対応していないので表示できません。—–