作者
APNG 仕様は以下のメンバーによって作られました:
- Stuart Parmenter <[email protected]>
- Vladimir Vukicevic <[email protected]>
- Andrew Smith <[email protected]>
概要
APNGは Portable Network Graphics (PNG) フォーマットの拡張であり、アニメーション画像のサポートが追加されています。これは普及しているシンプルなアニメーション画像の GIF フォーマットに取って代わることを目的に作られたもので、GIF にはない 24 bit イメージや 8 bit の透明色を扱うことができます。 APNG は MNG の簡潔な代替案であり、インターネットで一般的に使用されるアニメーション画像に適した仕様を規定します。
APNG は PNG の後方互換です。 PNG デコーダは APNG 仕様のチャンクを無視して静止画を表示します。
用語
デフォルト画像は標準の 'IDAT' チャンクに記述されます。これは APNG に対応していないデコーダが表示する画像です。
キャンバスは各フレームが表示される出力デバイスの領域です。キャンバスの内容はデコーダにとって有効である必要はありません。 PNG 仕様により、'bKGD' チャンクがあれば背景の指定が無くても 'bKGD' の色で塗りつぶされます。
出力バッファはピクセルの配列であり、PNG の 'IHDR' チャンクの幅と高さでサイズが決まります。概念的には、各フレームはキャンバスに描画する前に出力バッファ上に作成されます。出力バッファの内容はデコーダのために用意されます。出力バッファの角はキャンバスの角にマッピングされます。
完全に透過な黒とは RGB とアルファ値の全てが 0 の状態を指します。
チャンクの説明で使用される値について、unsigned int
は 32 bit 符号なし整数であり、ネットワーク上のバイトオーダーで値は 0 から 2^31)-1 に制限されます。unsigned short
は 16 bit 符号なし整数であり、ネットワーク上のバイトオーダーで値の範囲は 0 から (2^16)-1 です。byte
は 8 bit 符号なし整数であり、0 から (2^8)-1です。
エラー処理
APNG はイメージ全体を読み込む前に、すでに読み込んであるフレームを順番に描画するようにデザインされています。この方法だと実際にアニメーションが始まるまで気付かないエラーも有り得えます。デコーダがエラーを発見した場合、以降のフレームを全て破棄し、アニメーションを止め、 デフォルト画像の表示に戻ることを強く推奨します。デコーダがアニメーションを始める前にエラーに気付いた場合、デフォルト画像を表示しなければなりません。それが妥当ならば、ユーザーにエラーメッセージが表示するのも良いでしょう。
構造
APNG のデータ構造の並びは PNG 仕様で定義されているただの PNG と同様です。3 種類のチャンクを追加することでアニメーションのフレームデータを規定します。
APNG と識別するには 'IDAT ' チャンクの前に 'acTL ' チャンクが存在しなければなりません。'acTL ' チャンクの構造は後で述べます。
概念的には、再生するたびに出力バッファは '完全に透過な黒 ' で初期化しなければなりません。初期化は 'IHDR ' チャンクで幅と高さを指定された矩形を完全に塗りつぶします。
デフォルト画像をアニメーションに含める場合、'IDAT ' チャンクの前に 1 つ 'fcTL ' チャンクを置いてください。そうすることで 'fcTL ' チャンクの中でデフォルト画像がアニメーションの 1 フレーム目であることを指定します。 そうしなかった場合、デフォルト画像はアニメーションに含まれません。
以降のフレームは 'fdAT ' チャンクの中にエンコードしておきます。'fdAT ' チャンクはシーケンス番号から始まっていること以外は 'IDAT ' と同様の構造です。 各フレームの場所とレンダリング情報は 'fcTL ' チャンクに格納します。'fdAT ' チャンクと 'fcTL ' チャンクの完全な構造は後で述べます。
アニメーション全体の境界は 'IHDR' チャンクの幅と高さで決まります。デフォルト画像がアニメーションに含まれているかは関係ありません。デフォルト画像以降のフレームで描画しない範囲がある場合、完全な透明色で適切にパディングするべきです。
それぞれのフレームは何度再生しても完全に一致します。これはアプリケーションが各フレームをキャッシュするための仕様です。
チャンクシーケンス番号
'fcTL' チャンクと 'fdAT' チャンクは 4 byte のシーケンス番号を持ちます。2 種類のチャンクはシーケンスを共有します。これには APNG のシーケンスエラーを確認し、同時にエラー情報を収集する狙いがあります。PNG の仕様では補助チャンクの順序に制限はありません。
最初の 'fcTL' チャンクはシーケンス番号が 0 でなければなりません。以降の 'fcTL' チャンクと 'fdAT' チャンクにおいて、シーケンス番号の欠番や重複があってはなりません。
下の表は 2 フレーム以上で 2 つ以上の 'fdAT' チャンクを持つ場合のシーケンス番号について表しています。
1 フレーム目がデフォルト画像の場合
シーケンス番号 | チャンク |
---|---|
(none) | 'acTL' |
0 | 'fcTL'(1 フレーム目を指定) |
(none) | 'IDAT'(1 フレーム目で使う画像 / デフォルト画像) |
1 | 'fcTL'(2 フレーム目を指定) |
2 | 'fdAT'(2 フレーム目で使う画像のデータ 1) |
3 | 'fdAT'(2 フレーム目で使う画像のデータ 2) |
... | ... |
デフォルト画像をアニメーションで使わない場合
シーケンス番号 | チャンク |
---|---|
(none) | 'acTL' |
(none) | 'IDAT'(デフォルト画像) |
0 | 'fcTL'(1 フレーム目を指定) |
1 | 'fdAT'(1 フレーム目で使う画像のデータ 1) |
2 | 'fdAT'(1 フレーム目で使う画像のデータ 2) |
... | ... |
デコーダは順番を守らない APNG チャンクをエラーとして扱います。 APNG 対応の PNG エディタはシーケンス番号を正しく修正すべきです。
'acTL' : Animation Control チャンク
'acTL' チャンクは PNG 仕様の定義では補助チャンクです。それは正当な PNG の構造を守った上で、最初の 'IDAT' チャンクの前に存在しなければなりません。
'acTL' チャンクの内容は以下の通りです。
バイトオフセット | フィールド名 | フィールドの型 | 説明 |
---|---|---|---|
0 | num_frames |
unsigned int |
APNG のフレーム数 |
4 | num_plays |
unsigned int |
APNG のループ回数。0 を指定すると無限ループ。 |
num_frames
はアニメーションのトータルフレーム数を表します。これは 'fcTL' チャンクの数と一致しなければなりません。'num_frames' に 0 を指定してはなりません。1 フレームのみの APNG には 1 を指定します。この値が実際のフレーム数と異なる場合、エラーとして扱われるべきです。
num_plays
はアニメーションが何回再生すべきかを表します。0 が指定された場合、永久に再生を続けます。0 以外が指定された場合、指定された回数を再生し、最後のフレームになったらアニメーションを停止します。
'fcTL': Frame Control チャンク
'fcTL' チャンクは PNG 仕様の定義では補助チャンクです。対象フレームの 'IDAT' チャンクまたは 'fdAT' チャンクの前に存在しなければなりません。具体的には、
- デフォルト画像の場合、'fcTL' チャンクは 'IDAT' チャンクの前に存在しなければなりません。'acTL' と 'fcTL' の順番は定義していません。
- デフォルト画像を除く最初の画像(1 フレーム目か 2 フレーム目の画像)の場合、'fcTL' チャンクは全ての 'IDAT' チャンクの後に存在しなければなりません。また、対応するフレームの 'fdAT' の前に存在しなければなりません。
- 以降の全てのフレームについて、N フレーム目の 'fcTL' チャンクは N-1 フレーム目の 'fdAT' チャンクの後に存在しなければなりません。また、N フレーム目の 'fdAT' チャンクの前に存在しなければなりません。
- その他の補助チャンクは APNG チャンクの間に存在してもかまいません。その中には 'fdAT' チャンクも含まれます。
それぞれのフレームに 1 つの 'fcTL' チャンクが必要です。
バイトオフセット | フィールド名 | フィールドの型 | 説明 |
---|---|---|---|
0 | sequence_number |
unsigned int |
アニメーションチャンクのシーケンス番号、0 から始まる |
4 | width |
unsigned int |
後に続くフレームの幅 |
8 | height |
unsigned int |
後に続くフレームの高さ |
12 | x_offset |
unsigned int |
後に続くフレームを描画する x 座標 |
16 | y_offset |
unsigned int |
後に続くフレームを描画する y 座標 |
20 | delay_num |
unsigned short |
フレーム遅延の分子 |
22 | delay_den |
unsigned short |
フレーム遅延の分母 |
24 | dispose_op |
byte |
フレームを描画した後にフレーム領域を廃棄するか? |
25 | blend_op |
byte |
フレーム描画方法のタイプ |
フレームは x_offset
、y_offset
、width
、height
で定義された領域に描画します。 オフセットは負の値となってはなりません。 領域は正の値でなければなりません。 描画領域はデフォルト画像からはみ出てはいけません。
フレーム領域の制限は以下の通りです。
x_offset
>= 0y_offset
>= 0width
> 0height
> 0x_offset
+width
<= 'IHDR' widthy_offset
+height
<= 'IHDR' height
delay_num
と delay_den
で対象のフレームを何秒遅らせて表示するかを指定できます。分母 (denominator)に 0 を指定した場合、100 として扱います。 その場合、delay_num
は 1/100 秒の遅延となります。 分子 (numerator)が 0 の場合、デコーダは次のフレームをできる限り速く描画しますが、ビューアの仕様で速さに制限をかけてもかまいません。
フレームのタイミングはデコードするタイミングと表示のタイミングの両方から独立していなければなりません。これはデコーダの実装によらず同じ速さでアニメーションを表示するためです。
dispose_op
は遅延が終わった後、次のフレームをレンダリングする前に出力バッファをどうするか指定します。
dispose_op
として有効な値は以下の通りです。
値 | 定数 | 説明 |
---|---|---|
0 | APNG_DISPOSE_OP_NONE |
次のフレームを描画する前に消去しません。出力バッファをそのまま使用します。 |
1 | APNG_DISPOSE_OP_BACKGROUND |
次のフレームを描画する前に、出力バッファのフレーム領域を完全に透過な黒で塗りつぶします。 |
2 | APNG_DISPOSE_OP_PREVIOUS |
次のフレームを描画する前に、出力バッファのフレーム領域をこのフレームに入る前の状態に戻します。 |
最初の 'fcTL' チャンクの dispose_op
で APNG_DISPOSE_OP_PREVIOUS
が指定された場合、 APNG_DISPOSE_OP_BACKGROUND
のときと同様に扱います。
blend_op
は現在の出力バッファにアルファブレンドで合成するか、完全に出力バッファを入れ替えるかを指定します。
blend_op
として有効な値は以下の通りです。
値 | 定数 | 説明 |
---|---|---|
0 | APNG_BLEND_OP_SOURCE |
アルファ値を含めた全ての要素をフレームの出力バッファ領域に上書きします。 |
1 | APNG_BLEND_OP_OVER |
書き込むデータのアルファ値を使って出力バッファに合成します。このとき、PNG 仕様 への拡張 Version 1.2.0 のアルファチャンネル処理 に書いてある通り上書き処理をします。サンプルコードの 2 つ目の項目を参照してください。 |
2 つのブレンドモードは最初のフレームでは同じ結果になることに注意してください。これはどちらのブレンドモードでも出力バッファが初期化されているためです。
デフォルト画像に対する 'fcTL' チャンクには、以下の制限があります。
x_offset
とy_offset
は 0 でなければなりません。width
とheight
はIHDR
で指定された値と等しくなければなりません。
まず注意すべきなのは、どのように再生する場合でも出力バッファは完全に透過な黒で初期化するということです。これはどのように再生する場合でもアニメーションが一致することを保証します。デコーダは、結果が一致すると保証できる場合には初期化ステップを省略することができます。例えば、デフォルト画像がアニメーションに含まれており、blend_op
に APNG_BLEND_OP_SOURCE
が設定されている場合は初期化は不要です。この場合、出力バッファが完全に上書きされるからです。
'fdAT': Frame Data チャンク
'fdAT' チャンクは 'IDAT' チャンクと同じ目的のデータです。'fdAT' チャンクはシーケンス番号から始まっていること以外は 'IDAT' と同様の構造です。
各フレームには少なくとも 1 つの 'fdAT' チャンクが存在しなくてはなりません。フレーム内にある 'fdAT' チャンクの全てのデータフィールドを連結すると、圧縮された画像データになります。画像データストリームを解凍すると、PNG 画像の完全なピクセルデータになります。解凍されたデータストリームは、スキャンライン毎の開始点のフィルターバイトを含み、解凍された 'IDAT' チャンクのデータと同様です。それはデフォルト画像と同様に、'IDAT' チャンクと同じビット深度、カラータイプ、圧縮方式、フィルター方式、インタレース方式ともしあるならばパレットを利用します。
フォーマットは以下の通りです。
バイトオフセット | フィールド名 | フィールドの型 | 説明 |
---|---|---|---|
0 | sequence_number |
unsigned int |
アニメーションチャンクのシーケンス番号、0 から始まる。 |
4 | frame_data |
X bytes |
このフレームのデータ。 |
それぞれのフレームはファイルの最初の 'IDAT' チャンク以前にある必須チャンクまたは補助チャンクの指定を継承します。ただし、幅と高さは 'fcTL' チャンクの値を使用します。
'pHYs' チャンクが存在する場合、APNGの x_offset
と y_offset
はデフォルト画像と同様にスケーリングしなければなりません。概念的には、このようなスケーリングは出力バッファをキャンバスにマッピングするときに発生します。
この仕様の更新履歴
From 0.1
- anIM' 及び 'frAm' を PNG 仕様のチャンク命名規則に対応するように名前を変更。
- セクション 2 において APNG 構造のより詳細な説明を追加。
- セクション 3.2 において png の他のチャンクとの相互作用についての情報を追加。
- 'frAm' チャンクオフセットと符号付き整数への遅延を変更。
From 0.2
- MNG 'FRAM' チャンクとの衝突を避けるために 'frAm' チャンクを 'afRa' に変更。
- フォーマットの変更:IHDR..IDAT..IEND シーケンスの代わりに、0 ではないフレームが 'afRa' チャンクに保持されるように。
- アニメーションを開始すべきフレームを示すために
start_frame
を 'anIm' に追加。 - 'anIm' チャンクから
num_frames
を削除。
From 0.3
- 最近の png-list discussion より 'aCTL', 'fdAT', 'fcTL' の説明を追加。
- グローバル及びローカルのパレットと透過について説明した、セクション 4「他の PNG チャンクとの相互作用」を追加。
- より一般的なチャンクを参照するための 'oFFs' チャンクセクションを変更。
- すべてのフレームは互いにシングルチャンクでなければならない、あるいは、最初のチャンクは空データを持たなければならないことを示すために 'aDAT' の説明を更新。
- 各フレームの範囲 (x, y, width, height) は完全に親 PNG キャンバス以内に無ければならないという注意を追加。
dispose_op
の説明を修正(前ではなく、後)dispose_op
をrender_op
に変更。disposal の説明を追加、BLEND
フラグの説明を追加。- ミリ秒の整数にならない遅延を指定するために
delay_time
を 遅延分子と分母に変更。 - パレットアニメーションはサポートされていないことを明らかにするための注記を追加。
- aCTL から
start_frame
を削除。フレーム 0 には fcTL が必要。SKIP_FRAME
fCTL フラグを追加。
From 0.4
num_frames
を aCTL に再導入。sequence_number
を aDAT から fCTL に移動。- aDAT の内容を fCTL+IDATs+fEND に変更。
- 何が許可されて、何が許可されないかの明示を追加。
- PNG 仕様のチャンク命名規則に従うために aCTL を acTL に、fCTL を fcTL に、aDAT を fdAT に、fEND を feND に名称変更。
From 0.5
- IHDR と PLTE CRCs を acTl チャンクに追加。
- acTL fcTL 及び adAT をコピーセーフに。これらを acTl, fcTl 及び adAt に名称変更。
From 0.6
- fdAt チャンクを他のチャンクのコンテナではなく、IDAT チャンクの代替に変更。
- feND チャンクを削除。
- シーケンスナンバーフィールドを fdAt に追加。
- fcTl において
width
とheight
フィールドを再導入。
From 0.7
hidden
を削除。代わりに、最初のフレームだけを隠すことができ、それは fcTl の欠如で示すように。- IDAT、fcTl 及び fdAt がそれらの間に他のチャンクを持つ必要がないように変更。
From 0.8
- acTl から IHDR and PLTE のための CRCs を削除。
- acTL fcTL and adAT はコピーセーフではなくなり、それらを acTL, fcTL 及び adAT に変更。
From 0.9
render_op
を dispose_op
と blend_op
に分離。
From 0.10
- 変更無し
テストエンコーダーとサンプル画像
サンプル画像は https://littlesvr.ca/apng/ の APNG 実装ページにあります。
オープンソースのエンコーダーは 1.9 alpha 4 以降の Gecko エンジン にあります。
Mozillaの APNG エンコーダーを組み込んだオープンソースのアプリケーションはこちらにあります。 https://littlesvr.ca/apng/apngedit.html