ImageMagick 使用例 -- アニメーションの基礎
- Dispose None - 各フレームを順番に重ねる
- Dispose Previous - 背景キャンバスを保持する
-
Dispose Background - 背景に消去する
-
Identify - アニメーションに関する情報
- Adjoin - 個々のフレーム画像に分割する
- Coalesce - フレームを完全に埋める
- Frame Montage - 「gif_anim_montage」スクリプト
- List Information - 既存のアニメーションを再構築する
- Disposal Images - フレームの GIF 破棄形態
- Deconstruct - フレーム間の差分領域を報告する
-
Frame Comparisons - より詳細なフレーム差分
- オーバーレイアニメーション
- 消去フレームアニメーション
-
ループの終わり - アニメーションが停止するとき ゼロディレイの中間フレーム これらの例は、前のページ 複数画像のレイヤー の続きですが、複数の画像を重ねて単一の画像を生成するのではなく、ここでは各画像を短い時間だけ表示することで、画像のアニメーションを生成します。次の節では、アニメーション、とりわけ GIF アニメーションの複雑さを基本的に理解できるようにします。アニメーションを生成するために使われる基本的な方法と、既存のアニメーションを調べてその仕組みを理解する方法を見ていきます。後のアニメーションに関する各節へ進む前に、まず読んでおくことをお勧めします。
GIF アニメーションとアニメーションのメタデータ
ImageMagick が画像リストを出力するときの既定の扱いは、複数ページの画像を生成することです。ただし GIF 画像フォーマットの場合は、これは「GIF アニメーション」という特別な形になります。 |
magick -delay 100 -size 100x100 xc:SkyBlue \
-page +5+10 balloon.gif -page +35+30 medical.gif \
-page +62+50 present.gif -page +10+55 shading.gif \
-loop 0 animation.gif
![[IM Output]](../static/img/anim_basics/animation.gif)
こちらはより高度な「きらめき」の例で、シェルスクリプト「[star_field](../static/img/scripts/star_field) 」を使っています。このスクリプトは、私が ランダムな星空 を生成する実験から発展させたものです。 |
star_field 70x46 stars1.gif
star_field 70x46 stars2.gif
star_field 70x46 stars3.gif
magick rose: -compose Screen \
\( -clone 0 stars1.gif -composite \) \
\( -clone 0 stars2.gif -composite \) \
\( -clone 0 stars3.gif -composite \) \
-delete 0 -set delay 25 -layers Optimize rose_sparkle.gif
rm stars[123].gif
![[IM Output]](../static/img/anim_basics/rose_sparkle.gif)
基本的には、適切なサイズのランダムな星空を 3 つ生成し、それらを IM 組み込みの「rose:」画像の上に「[Screen](compose.html#screen)」アルファ合成を使って重ね、指定した星のパターンで画像を明るくします。その全体を IM の汎用 GIF アニメーション最適化機能に通します。上記は、まだ紹介していない高度な IM 機能を使っているため複雑に見えるかもしれませんが、結果は比較的単純でありながらうまく最適化された 3 フレームのアニメーションです。単純なシェルスクリプトを使って作成された、より複雑なアニメーションについては 歪みアニメーション も見てみてください。GIF アニメーションで使うために特別に作られた IM 設定がいくつかあり、それらを知ることが GIF アニメーションの世界への第一歩です… [**-dispose**](https://imagemagick.org/command-line-options/#dispose) {method}
| 以降の画像が、それまでの GIF アニメーションの結果に対して何をすべきかを指定します。有効なオプションは「Undefined」「[None](#none)」「[Previous](#previous)」「[Background](#background)」です。(設定の説明は以下を参照)
[**-loop**](https://imagemagick.org/command-line-options/#loop) {number} | GIF アニメーションが停止するまでに画像シーケンスを巡回する回数。これは出力時の「画像書き込み」設定なので、コマンドラインのどこにでも設定できますが、最後に設定されたものだけが使われます。通常はこれは既定でゼロ(無限ループ)に設定されますが、読み込まれたいずれかの画像が異なる値を持っていれば、この設定はその画像の値に設定されます。そのため、GIF アニメーションを作成するときは、すべての画像を読み込んだ後で必ず「[-loop](https://imagemagick.org/command-line-options/#loop)」を設定することをお勧めします。詳しくは以下の ループの終わり を参照してください。
[**-delay**](https://imagemagick.org/command-line-options/#delay) {time} | この設定が定義された後で読み込まれたり作成されたりする画像を描画した後に一時停止する時間遅延(100 分の 1 秒単位)を設定します。「x」によるスケーリング(1 秒あたりのティック数で指定)を指定することで、時間遅延に別のスケールを指定できます。たとえば「10x1」は 1 秒のティックが 10 個、「10x100」は 100 分の 1 秒のティックが 10 個です。基本的に「x」は分数の「/」記号と等価です。たとえば「1x160」を指定すると、毎秒 160 フレームに適したディレイが設定されます。 | | GIF アニメーションのディレイは、正しく動作させるために 100 分の 1 秒単位で指定しなければならず、これが既定の時間単位である理由です。「x」係数は、MNG や AVI のような、より動画に近いフォーマットを生成するために多く使われます。
---|---
[**-set**](https://imagemagick.org/command-line-options/#set) dispose {method}
[**-set**](https://imagemagick.org/command-line-options/#set) delay {time}
| 前述のオプション設定は、そのオプションが与えられた 後に 新しく作成されたり読み込まれたりする画像に画像属性を設定しますが、「[-set](https://imagemagick.org/command-line-options/#set)」オプションは演算子であり、現在の画像シーケンスに すでに あるすべての画像に画像属性を設定できます。これにより、画像を読み込んだり変更したりした後で、アニメーション全体、あるいは単一のフレームだけにわたって設定を変更できます。
[**-page**](https://imagemagick.org/command-line-options/#page) {w}x{h}+{x}+{y}
| これは、これから読み込む画像のオフセット位置を設定できます。これは設定オプションなので、与えた配置情報はその設定の後に続く画像にのみ適用されます。すでにメモリに読み込まれた画像には影響しません。指定されない場合、または「[+page](https://imagemagick.org/command-line-options/#page)」で無効にした場合は、読み込まれる画像のオフセットが保持されます。画像にオフセットがなければ、作業キャンバスまたは「ページ」の左上隅である「+0+0」に配置されます。幅「x」高さを指定することで、より大きな作業キャンバスを定義するためにも使えます。シーケンスの最初の画像のページ幅と高さの設定だけが GIF アニメーション全体のキャンバスサイズの設定に使われ、他のすべてのページサイズ設定はアニメーションが最終的に書き出されるときに無視されます。GIF アニメーションが読み込まれると、キャンバスサイズはアニメーション内のすべてのフレームに設定されます。MNG アニメーションはフレームのオフセットを保存できますが、キャンバスサイズは保存しません。最初の画像のサイズがアニメーション全体のキャンバスサイズを定義します。 | | _GIF 画像フォーマットは、キャンバス上の画像に負のオフセットを指定できません。負のオフセットを使おうとすると、その画像(またはアニメーションフレーム)が GIF ファイルに書き出されるときに IM はそれをゼロにリセットします。
画像キャンバスより大きい正のオフセットはまったく問題ありませんが、その結果、表示時に画像がキャンバスの描画領域に現れないことがあります。GIF アニメーション表示プログラムがこれをどう扱うかは未定義です。注意が必要です。_
---|---
[**-repage**](https://imagemagick.org/command-line-options/#repage) {w}x{h}+{x}+{y}
| これは「[-page](https://imagemagick.org/command-line-options/#page)」とまったく同じですが、設定ではなく画像演算子である点が異なります。つまり、これを使うと、すでにメモリに読み込まれた画像やアニメーションフレームの「ページ配置情報」を変更したりリセットしたりできます。より単純な「[+repage](https://imagemagick.org/command-line-options/#repage)」形式は、現在の画像シーケンスの各フレームの「ページ配置情報」を、ゼロオフセットとその画像の実際のサイズにリセットするだけです。この操作は、アニメーションから個々のフレームを抽出するときに不可欠です(以下の Adjoin の例 を参照)。ただし「[+repage](https://imagemagick.org/command-line-options/#repage)」は各画像に格納された多くの配置情報を破壊するので、後で再利用するためにこの情報を別ファイルに抽出しておくべきでしょう。以下の アニメーションリスト情報 を参照してください。
重要な点
処理がまだ終わっていない中間的なアニメーションを、直接 GIF に保存しては いけません。アニメーションを一連の別々の処理ステップで作業したい場合は、一時的なファイルフォーマットとして IM 内部フォーマットの MIFF を使えます。もう一度言います…
GIF を中間ファイルフォーマットとして使わず、代わりに MIFF を使ってください
もし GIF に保存するという大きな間違いを犯してしまうと、IM が存在する色数を減らすために自動的に 色の量子化 を行うため、結果のアニメーションを悪化させてしまうだけです。それだけでなく、IM はそれを各フレームごとに他のすべてのフレームとは完全に独立して行うため、その後の処理、とりわけ GIF 最適化がそれだけ難しくなります。これを解決するのは複雑な多段階の問題であり、次の節 アニメーションの最適化 で取り上げます。
フレームの破棄方法
GIF アニメーションを作成する人がまず手こずるのが「[-dispose](https://imagemagick.org/command-line-options/#dispose)」設定です。これは複雑な設定なので無理もありません。さらに悪いことに、多くの Web ブラウザを含む多くのアニメーションプログラムは、GIF 破棄のメタデータ設定を常に正しく扱うとは限りません。しかし、適切な破棄方法を使うことは、アニメーションがどれだけうまく動作し、最適化されるかに大きな違いをもたらします。ImageMagick で最初に覚えておくべきことは、ほとんどすべての特別なアニメーションオプションが画像読み込み用の設定だということです。つまり、それらは設定が与えられた後に読み込まれる画像に適用されます。「[-loop](https://imagemagick.org/command-line-options/#loop)」設定だけが、通常アニメーションが完成した後、アニメーションを保存する直前に使われます。「[-dispose](https://imagemagick.org/command-line-options/#dispose)」の基本的な役割は、画像が「[-delay](https://imagemagick.org/command-line-options/#delay)」時間だけ表示された 後に、その画像をどのように除去するかを定義することです。つまり、そのフレームの画像を読み込む 前に、画像の「[-dispose](https://imagemagick.org/command-line-options/#dispose)」と「[-delay](https://imagemagick.org/command-line-options/#delay)」の設定を与える必要があります。しかしその動作は、その画像が表示された後に適用されます。これは少し直感に反しますが、IM が画像を扱う方法では理にかなっています。これを覚えておけば、問題は起きないはずです。これらのオプションの「プラス」形式は、IM の他のほとんどの設定と同様に、読み込まれる画像に設定が適用されないようにします。つまり、設定を指定しなければ、フレーム画像は(もしあれば)画像とともに読み込まれた設定を引き続き使います。これは、さらなる処理のために GIF アニメーションを読み込みたいときに重要になることがあります。あるいは、ある GIF アニメーションを別のものに統合するとき(最も難しいアニメーション技術)にも重要です。
Dispose None - 各フレームを順番に重ねる
GIF アニメーションの既定の「[-dispose](https://imagemagick.org/command-line-options/#dispose)」設定は「**Undefined**」で、ほとんどのアニメーションプログラムはこれを「**None**」破棄設定と同じように扱います。基本的にこれは、この特定のフレームが重ねたものをそのまま残すようコンピュータに指示します。より正確には「何もしない」です。ただし、アニメーションシーケンスの最後では、ループして繰り返す前に、キャンバス全体が常に消去されることに注意してください。たとえば、こちらが標準的な「None 破棄」アニメーションです… |
magick -delay 100 -dispose None \
-page 100x100+5+10 balloon.gif \
-page +35+30 medical.gif \
-page +62+50 present.gif \
-page +10+55 shading.gif \
-loop 0 anim_none.gif
![[IM Output]](../static/img/anim_basics/anim_none.gif)
この破棄技術は、無地または模様付きの背景に描かれたアニメーションのように、いかなる形の透明性も含まないアニメーションに最適です。 |
magick -dispose none -delay 100 \
-size 100x100 xc:SkyBlue +antialias \
-fill DodgerBlue -draw 'circle 50,50 15,25' \
-page +5+10 balloon.gif \
-page +35+30 medical.gif \
-page +62+50 present.gif \
-page +10+55 shading.gif \
-loop 0 canvas_none.gif
![[IM Output]](../static/img/anim_basics/canvas_none.gif)
この技術は、アニメーションに見える色を追加することしかできない点に注意してください。アニメーションの一部を再び実際に透明にすることは決してできません。(以下の オーバーレイアニメーション を参照)。透明性も扱うには、他の種類の破棄方法のいずれかを使う必要があります。
Dispose Previous - 背景キャンバスを保持する
「**Previous**」破棄方法は比較的単純です。現在の画像が終わったら、その画像が重ねられる前の状態にキャンバスを戻します。直前のフレーム画像も「Previous」破棄方法を使っていた場合は、結果はそのフレームの前の状態と同じになります… 以下同様…。たとえばこのアニメーションでは、後続の各フレームは、「[None](#none)」破棄設定を持つ最初のフレームに戻ってから、そのフレームに関連付けられた画像を重ねます。結果として、各フレーム画像がそのフレームの表示時間だけ重ねられる背景キャンバスになります… |
magick -dispose none -delay 0 \
-size 100x100 xc:SkyBlue +antialias \
-fill DodgerBlue -draw 'circle 50,50 15,25' \
-dispose previous -delay 100 \
-page +5+10 balloon.gif \
-page +35+30 medical.gif \
-page +62+50 present.gif \
-page +10+55 shading.gif \
-loop 0 canvas_prev.gif
![[IM Output]](../static/img/anim_basics/canvas_prev.gif)
最初の画像に使われた「[-dispose](https://imagemagick.org/command-line-options/#dispose)」方法「[None](#none)」に注意してください。これは重要です。そうしないと、「previous」フレームが、最初のフレームの前にあった元の空のキャンバスまでずっと戻ってしまいます。また、上記のアニメーションでは「[-delay](https://imagemagick.org/command-line-options/#delay)」に「0」を使ったことにも注意してください。これは、最初のフレームをこの「背景キャンバス」に重ねる前に待たないことを指示します。これがないと、上に何も乗っていないキャンバス画像だけが表示される短いディレイが見えてしまいます。もちろん、後続の画像にはやはりもっと長い「[-delay](https://imagemagick.org/command-line-options/#delay)」を設定する必要があります。さもないと、それらは一瞬で現れて消えてしまい、ついでに視聴者の CPU サイクルを大量に消費します。「Previous」破棄方法の使用は、一部の Web ブラウザ、特に遅いマシンで、わずかなちらつきや一時停止を起こしやすいことがあります。最近ではめったに見られませんが、ちらつき自体はまだ存在しており、私はこれをバグだと考えています。詳しくは以下の ゼロディレイフレーム を参照してください。dispose previous スタイルのアニメーションを使うものはほとんどありません。その理由は、コンピュータにとって最適化が非常に難しいからです。問題は、コンピュータが背景画像にするためにどのフレームを選ぶべきかということです。最適な画像を見極めるのは人間にとっては簡単ですが、コンピュータが決めるのは難しいのです。アニメーションで使うのに最適な背景画像は、現在の例のように、そもそも表示されることを意図していないことさえあり、そのため最適化されていないバージョンのそのアニメーションには存在しないこともあります。
Dispose Background - 背景に消去する
最初の 2 つの「[-dispose](https://imagemagick.org/command-line-options/#dispose)」方法は比較的単純ですが、「**Background**」はおそらく最も理解しにくいものです。特定のフレームの時間遅延が終わると、そのフレームによって重ねられた領域が消去されます。キャンバス全体ではなく、重ねられた領域だけです。それが終わると、結果として得られたキャンバスがアニメーションの次のフレームに渡され、そのフレームの画像によって重ねられます。たとえばここでは、各フレームを次のフレームで置き換えるだけです。 |
magick -delay 100 -dispose Background \
-page 100x100+5+10 balloon.gif \
-page +35+30 medical.gif \
-page +62+50 present.gif \
-page +10+55 shading.gif \
-loop 0 anim_bgnd.gif
![[IM Output]](../static/img/anim_basics/anim_bgnd.gif)
何が起きているかをはっきり見せるために、アニメーションに初期キャンバス画像を加えて、「Background」が実際にどのようにそのフレームをアニメーション表示から「破棄」するかを見てみましょう。 |
magick -delay 100 -dispose none \
-size 100x100 xc:SkyBlue +antialias \
-fill DodgerBlue -draw 'circle 50,50 15,25' \
-dispose background \
-page +5+10 balloon.gif \
-page +35+30 medical.gif \
-page +62+50 present.gif \
-page +10+55 shading.gif \
-loop 0 canvas_bgnd.gif
![[IM Output]](../static/img/anim_basics/canvas_bgnd.gif)
見てのとおり、重ねられた各フレームが破棄されると、次の画像が重ねられる前に、そのフレームの領域が透明に消去されます。これがこの GIF 破棄方法の重要性です。なぜなら、これは GIF アニメーションがアニメーションのフレーム履歴に関係なく任意のピクセルを消去できる唯一の方法だからです。ピクセルを消去する他の唯一の方法は、「[Previous](#previous)」を使って、それらのピクセルが透明だったフレームに戻ることです。しかしそれはアニメーションシーケンスの履歴を知っていることに依存するため、コンピュータが最適化するのがはるかに難しくなります。 | _重ねられた領域を透明色に消去するのではなく、この破棄は GIF アニメーションに格納された「背景」色メタデータ設定に消去すべきだという考え方もあります。実際、古い「Netscape」ブラウザ(バージョン 2 と 3)はまさにそうしていました。しかしそれは「Previous」破棄方法を正しく実装することにも失敗していました。
一方で、初期キャンバスもフォーマットの「背景」色から設定されるべきですが、それも行われていません。しかし、すべての最新の Web ブラウザは、最後に重ねられた領域だけを透明に消去します。そのため、これが今では受け入れられた慣行であり、IM が今従っているものです。_
---|---
| _IM バージョン 6.2.6-1 より前は、IM の「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」と「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」の操作は、すべての主要な Web ブラウザのように「Background」破棄を使ってピクセルを透明にするアニメーションを扱えませんでした。例と詳細については アニメーションのバグ を参照してください。
ただし、これらの機能はピクセルの消去が適用されない、または意図されていない場合には問題なく動作しました。これは現在「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」については修正されており、GIF アニメーションのフレーム最適化機能としての「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」の使用を置き換えるために「[-layers](https://imagemagick.org/command-line-options/#layers) [OptimizeFrame](anim_opt.html#optframe)」方法が作られました。_
---|---
アニメーションを調べる
GIF アニメーションの基礎、その種類、最適化、扱い方の技術へと進む前に、既存のアニメーションを調べるための技術がいくつか必要です。
Identify - アニメーションに関する情報
さて、アニメーションは個々のフレームそれぞれに詰め込まれた多くの情報から成ります。この情報の一部は、既定の IM「[identify](basics.html#identify)」コマンドを使って見ることができます。
magick identify canvas_prev.gif
| 上記のような出力が見られなかった場合、あなたの IM は少々古いので、インストール済みの ImageMagick を最新バージョンに本当にアップグレードすべきです。そうしないと、IM の GIF アニメーションの扱いと制御に関する多くの新しい進歩を見逃すことになります。
---|---
見てのとおり、2 番目以降のフレームに実際に保存された画像はわずか 32x32 ピクセルですが、すべてのフレームは 100x100 ピクセルの「仮想キャンバス」上に、その大きなキャンバス上の「仮想オフセット」とともに配置されています。存在するさまざまなメタデータをもっと見るには、より特殊な パーセントエスケープ書式 を使って IM に出力させる必要があります。
magick identify -format "%f canvas=%Wx%H size=%wx%h offset=%X%Y %D %Tcs\n" \
canvas_prev.gif
これにより、キャンバスサイズ、画像サイズ、オフセットだけでなく、個々のフレームに使われた破棄方法と時間遅延もはっきりと示されます。最初のフレームが、後続の「Previous」破棄方法を正しく使うために必要だった異なる破棄方法と時間遅延を持っていることに注意してください。
Adjoin - アニメーションをフレームに分割する
さて、上で見たように、ImageMagick は既定で、ファイルフォーマットが許す場合は複数の画像を 1 つのファイルに保存しようとします。しかし、複数画像リストの書き込み で議論したように、IM では「[+adjoin](https://imagemagick.org/command-line-options/#adjoin)」設定を使って、各画像を別々の個別画像としてディスクに保存するよう指示できます。たとえばここでは、GIF アニメーションの 1 つを読み込んで、アニメーションシーケンス内の個々のフレーム画像を出力します。
magick canvas_prev.gif -scene 1 +adjoin frame_%03d.gif
上記の実際の画像を調べてみると、ほとんどの Web ブラウザはより大きな 100x100 の領域を表示し、その上に各サブフレームが現れますが、実際には、表示される実際の画像のほとんどは、前の「identify」コマンドで示されたとおり、実際にはわずか 32x32 ピクセルにすぎないことがわかります。つまり、領域のほとんどは、何も描かれていない単なるキャンバスであり、画像の「ページ配置情報」または「仮想キャンバス」として知られているものです。アニメーションの最初の画像がそのより大きな「キャンバス」を定義し、他のすべてのフレームがこのより大きなキャンバス上の「オフセット」位置を定義します。この追加情報は、「[+adjoin](https://imagemagick.org/command-line-options/#adjoin)」設定によって保存されたフレームに保持されます。そのため、GIF アニメーションを簡単に再構築できます。各別々のフレーム画像にページ情報が保持されるだけでなく、ディレイ、ループ、GIF 破棄の設定も保持されます。 つまり、アニメーションを再構築するには、すべての画像を読み込むだけでよいのです。 |
magick frame_???.gif anim_rebuilt.gif
![[IM Output]](../static/img/anim_basics/anim_rebuilt.gif)
ただし、ときにはこのページ配置情報を保持したくない場合もあります。たとえば、個々のフレームを他のプロジェクトで使いたい場合です。「[+repage](https://imagemagick.org/command-line-options/#repage)」オプションを使ってページサイズとオフセットをリセットし、「仮想キャンバス」情報を取り除いて、実際の画像だけを残せます。
通常、アニメーションのサブ画像を抽出するときは、編集や表示に干渉しないようにするため、画像のディレイと破棄の設定も一般にリセットします。たとえばここでは、不要な仮想キャンバスとオフセットを取り除き、タイミングのディレイと破棄をリセットします。
magick canvas_prev.gif +repage -set delay 0 -set dispose None \
+adjoin repage_%03d.gif
もちろん、そのメタデータを捨ててしまうなら、そのデータを記録して編集する何らかの方法が必要です。サブ画像を抽出し、アニメーションのメタデータを、アニメーションを再構築するために使える形で保存するスクリプトについては、(下記の) アニメーションリスト情報 を参照してください。
Coalesce - フレームを完全に埋める
しかし、サブフレームの形でアニメーションを見ることは、通常、典型的なアニメーションではあまり役に立ちません。ひとつには、高度に最適化されたアニメーションは、それらがどう組み合わさるかが視覚的にまったくわからないまま、たくさんの非常に小さな部品から成りえます。また、アニメーション全体のファイルサイズを減らすために 圧縮最適化 のために加えられた多くの他の「ノイズ」も含みえます。たとえば、このアニメーションが実際に何をしたのかを、アニメーションの個々のサブフレームを見るだけで把握するのは非常に難しいです。
magick script_k.gif +repage +adjoin script_k_%02d.gif
「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」操作は基本的に、前のフレームが正しく 破棄 され、次のサブフレームが重ねられた後にアニメーションがどう見えるべきかちょうどそのとおりの画像に変換します。つまり、各フレームが前の「破棄された」フレームに対する重ね合わせの変更だけを表すアニメーションシーケンスの代わりに、この演算子はアニメーションシーケンスというより、本物のフィルムストリップのように、各時点でのアニメーションの完全なビューを作成します。合体アニメーション として知られるそのようなシーケンスは、調べる、編集する、変更する、再最適化することがはるかに簡単です。たとえばここでは、上で示したのと同じ「紛らわしい」アニメーションシーケンスのモンタージュを生成しますが、今回はシーケンスを「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」して、実際に何が起きているかを見られるようにします。 |
montage script_k.gif -coalesce \
-tile x1 -frame 4 -geometry '+2+2' \
-background none -bordercolor none coalesce_k_montage.gif
見てのとおり、結果はアニメーションのフィルムストリップのようになっており、前の部品がどう組み合わさって手描きの文字「K」を形成するかをはっきり見ることができます。IM バージョン 6.2.6 から、「magick montage」コマンドは「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」の使用を理解するようになり、上で示したとおり、アニメーションフレームの「フィルムストリップ」のような画像を作成できるようになりました。このバージョンには coalesce の修正も含まれており、GIF アニメーションの作業はすべて、少なくともこのバージョン(あるいはもっと良いのは最新バージョン)であるべきです。 |
アニメーションを調べるためのさらに優れたモンタージュ技術については、次の例の節で紹介します。 |
|---|---|
合体アニメーション における 合体画像シーケンス の「[-dispose](https://imagemagick.org/command-line-options/#dispose)」設定は、実際には無関係です。ただし、ユーザーの安心のために、「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」演算子は各フレームの「[-dispose](https://imagemagick.org/command-line-options/#dispose)」設定を「[None](#none)」または「[Background](#background)」のいずれか適切なものに設定するので、合体画像シーケンスは(上で示したように)正しくアニメーションし続けます。 |
_「[Background](#background)」破棄を持つフレームは、次のフレームが正しく表示されるために少なくとも 1 つ以上のピクセルを消去する必要があったことを意味します。 |
そのため、「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」が「[Background](#background)」破棄を加えたアニメーションは、単純な オーバーレイアニメーション (下記参照)として保存できないことを意味します。
技術的には、合体画像シーケンスのすべての破棄設定を「[Background](#background)」または「[Previous](#previous)」のいずれかに設定して、消去フレームアニメーション (下記参照)を生成できます。ただし、すべてのアニメーションがその形でうまく最適化されるわけではありません。_
---|---
「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」演算子には、アニメーション以外の用途もいくつかあります。これらの用途の例については Coalesce と段階的な平坦化 を参照してください。
アニメーションフレームモンタージュ - 「gif_anim_montage」スクリプト
「[+adjoin](https://imagemagick.org/command-line-options/#adjoin)」演算子はアニメーションから実際の画像を抽出でき、「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」は結果のアニメーションフレームを見られますが、どちらの方法もアニメーションに関する多くの情報を省いてしまいます。アニメーション画像を非常に注意深く操作することで、実際のフレームだけでなく、より大きなキャンバス上でのそれらのフレームの配置も示すように、フレームを表示できます。こちらがそのようなアニメーション表示方法の 1 つです。
magick -dispose Background script_k.gif -alpha set \
-compose Copy -bordercolor black -border 1x1 -compose Over \
-coalesce -bordercolor none -frame 4x4+2+2 \
-bordercolor none -border 2x2 +append script_k_parts.gif
ここでは、アニメーションがどう機能するかをはっきり見ることができます。各サブフレーム画像は、それまでのすべての重ね合わせに追加するように配置されています。結果はゆっくりと成長していく絵です。各フレームはまた、それが配置される「仮想キャンバス」よりもずっと小さくなっています。私は GIF アニメーションの開発とデバッグの際にこの表示技術をよく使うので、それをシェルスクリプト「[gif_anim_montage](../static/img/scripts/gif_anim_montage) 」に変換し、アニメーション内の各フレームの上に上記の詳細の一部を列挙するように拡張しました。
gif_anim_montage script_k.gif script_k_frames.gif
ペンがページから持ち上げられて配置し直されるかのように一時停止するために、さまざまなフレームで使われているタイミングの変化に注意してください。可変タイミングのアニメーションは最も興味深いものの一部になりえますが、後の IM 例ページで見るように、扱うのもより難しくなります。「[gif_anim_montage](../static/img/scripts/gif_anim_montage)」スクリプトには特別なオプション「-u」もあり、これは合体アニメーションの半透明のコピーを下敷きにします。これにより、新しいサブフレームが表示されるアニメーションをどう変更するかを見ることができます。
gif_anim_montage -u script_k.gif script_k_frames.png
もちろんこれには半透明のピクセルがあるので「PNG」画像フォーマットが必要でした。あるいは、そのスクリプトが提供する多くの「背景」オプションのいずれかを使って、アニメーションの結果のまとめ画像に GIF や JPEG フォーマットさえ使えます。他のオプションでは、使う行数や列数を定義したり、さまざまな不透明の背景を設定したり、既定の黒の代わりに赤い箱を使ったりできます。このスクリプトは、IM 例の次の数ページで多く使われます。提案やコメントを歓迎します。
アニメーションリスト情報 - アニメーションを構築するために使われたオプション
述べたように、「[+adjoin](https://imagemagick.org/command-line-options/#adjoin)」と「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」、そして「[+repage](https://imagemagick.org/command-line-options/#repage)」はすべて、GIF アニメーションを抽出して見るのに役立つ方法です。しかし、これらはすべてその過程で元のアニメーションに関する情報を破壊します。フレーミング、時間遅延、フレーム破棄などのこの追加情報は、IM「magick identify」コマンドに「[-verbose](https://imagemagick.org/command-line-options/#verbose)」オプションを付けて使えば見ることができます。しかし私は、そしておそらく他のほとんどのユーザーも、このコマンドの出力が圧倒的で、実際には直接使えるものではないと感じます。そこで、私が書いた別の特別なシェルスクリプトが出番です。「[gif2anim](../static/img/scripts/gif2anim) 」スクリプトは、アニメーションの個々のフレームを分離するだけでなく、それらの画像からアニメーションを再構築するために必要となる IM「magick」オプションが正確に何かも割り出します。「[gif2anim](../static/img/scripts/gif2anim)」は、IM オプションの観点からアニメーションの要約を生成する、アニメーションの逆アセンブラだと考えることができます。たとえば、これまで使ってきたアニメーション例をデコードして、それを作成するために使われた元の「magick」設定と、使われた個々の画像を復元してみましょう… |
gif2anim canvas_prev.gif
既定では、「[gif2anim](../static/img/scripts/gif2anim)」スクリプトは個々の画像と「.anim」オプションファイルに同じベースファイル名を使います。そのため、上記コマンドで生成されるアニメーションシーケンスファイルは「[canvas_prev.anim](https://usage.imagemagick.org/anim_basics/canvas_prev.anim)」と名付けられ、個々のフレーム画像は「[canvas_prev_001.gif](../static/img/anim_basics/canvas_prev_001.gif)」から「[canvas_prev_005.gif](../static/img/anim_basics/canvas_prev_005.gif)」となります。結果をもっと詳しく調べると、私がこの GIF アニメーションを最初に作成したときに使った元のオプションを実際にうまく再現できたことがわかります(参照: Dispose Previous アニメーション)。また、実際にアニメーションを生成するのには重要ではありませんが、調べやすくするため、重ねられたフレームのサイズとタイミングもコメントとして列挙されます。結果をファイルに保存する代わりに、「-l」フラグを使ってアニメーションシーケンスオプションを画面に列挙するだけにもできます。つまり、保存したり、アニメーションの個々のフレーム画像を保存したりするのではなく、アニメーションシーケンスファイルを出力するだけです。
gif2anim -l canvas_prev.gif
「.anim」ファイルと個々のフレーミング画像があれば、補完的なスクリプト「[anim2gif](../static/img/scripts/anim2gif) 」を使ってアニメーションを再構築できます。 |
anim2gif canvas_prev.anim
![[IM Output]](../static/img/anim_basics/canvas_prev_anim.gif)
「[anim2gif](../static/img/scripts/anim2gif)」は既定で「_anim.gif」という接尾辞を付けて GIF アニメーションを再作成します。生成された結果の「[canvas_prev_anim.gif](../static/img/anim_basics/canvas_prev_anim.gif)」アニメーションが、元のアニメーションとまったく同じように見え、動作することがわかります。このスクリプトは単に、「アニメーションシーケンスファイル」で使われた特別な文字列「BASENAME」を置き換え、すべてのコメントを取り除き、残った convert オプションを「magick」コマンドに渡すだけです。言い換えれば、上記のファイルをコメント付きの一種の「convert」スクリプトとして扱います。特別な文字列が使われた理由は、こうすることで「.anim」ファイル自体の名前とは異なるベースファイル名を指定できるようになるからです。そうすれば、元のものの変更版など、まったく別のフレーム画像のセットを使って、古いものから別のアニメーションを再作成できます。これは非常に便利な機能で、より複雑なアニメーション処理で使われます。(例については アニメーションを横並びで連結する を参照)。「[gif2anim](../static/img/scripts/gif2anim)」と同様に、「[anim2gif](../static/img/scripts/anim2gif)」スクリプトにも、アニメーションを処理・変更するのに役立つかなりの数の便利なオプションがあります。これらのオプションの一部は後で使われます。たとえば アニメーションの連結 を参照してください。また「.anim」ファイルはプレーンテキストなので、これを使ってデコードしたアニメーションの画像を取り、タイミング、位置、アニメーションの繰り返し区間などの GIF のメタデータを調整したり、アニメーションに新しいフレームや画像を加えたりできます。結局のところ、私が IM 例に関わるずっと前に、これらのスクリプトを書いたそもそもの理由がこれでした。当面、「[gif2anim](../static/img/scripts/gif2anim)」は、アニメーションシーケンスを調べて、何が起きているか、フレーム間にどんなタイミングが適用されているかを見るのに最も役立つでしょう。
Dispose Images - フレームの GIF 破棄形態
この特別な「[-layers](https://imagemagick.org/command-line-options/#layers)」方法「**Dispose**」は、時間遅延が終わって GIF 破棄方法が適用された 後、しかし次のフレームの画像が重ねられる 前 に、フレームがどう見えるべきかを示します。言い換えれば、これは GIF「[-dispose](https://imagemagick.org/command-line-options/#dispose)」方法設定が実際にフレームに対して何をするかを正確に示し、アニメーションで何がうまくいっていないかを正確に把握できるようにします。たとえば、こちらが私たちの 3 つの 破棄方法の例アニメーション のそれぞれが、個々のフレームの破棄方法が適用された後にどう見えるかです。これらのアニメーションはそれぞれ、「[None](#none)」の「[-dispose](https://imagemagick.org/command-line-options/#dispose)」設定で設定された「キャンバス画像」と、それに続いて重ねられてさまざまな GIF 破棄方法で破棄される 4 つの小さい画像から成ることを思い出してください。「[None](#none)」破棄アニメーション…
magick canvas_none.gif -layers Dispose canvas_none_dispose.gif
gif_anim_montage canvas_none_dispose.gif canvas_none_dispose_frames.gif
「[Previous](#previous)」破棄アニメーション…
magick canvas_prev.gif -layers Dispose canvas_prev_dispose.gif
gif_anim_montage canvas_prev_dispose.gif canvas_prev_dispose_frames.gif
「[Background](#background)」破棄アニメーション…
magick canvas_bgnd.gif -layers Dispose canvas_bgnd_dispose.gif
gif_anim_montage canvas_bgnd_dispose.gif canvas_bgnd_dispose_frames.gif
上記を調べれば、3 つの GIF 破棄方法のそれぞれが、そのフレームの重ねられた画像をどのようにアニメーションから消去するかを正確に見ることができます。これら 3 つのアニメーションの最初のフレームは常に「None」の破棄に設定されているので、変化しないまま残ることに注意してください。重要なのは、後続のフレームでの破棄方法の効果です。 |
「-layers Dispose」操作は、破棄フレームの「合体」シーケンスを生成するだけです。破棄設定自体はリセットしないため、結果は正しくアニメーションしないことがあります。上記を正しくアニメーションさせるには、すべての破棄方法を「previous」または「background」に設定するか、保存前にアニメーションを最適化します。 |
|---|---|
| _GIF 破棄方法が適用された後の最後のフレームの見た目は、通常 GIF アニメーションには影響しません。なぜなら、アニメーションが繰り返す(ループする)前にキャンバス全体が完全に消去されるからです。アニメーションがループせずシーケンスの最後で停止する場合は、最後のフレームの破棄は適用されません。 |
言い換えれば、上で示したような(破棄後の)最後のフレームの見た目、あるいは最後のフレームの実際の破棄設定さえも、GIF アニメーションには何の影響もありません。IM は、アニメーションの フレーム最適化 の際に適切な破棄方法を割り出そうとするとき、一般にこれを前のフレームと同じに設定します。_
---|---
Deconstruct - フレーム間の差分領域を報告する
ImageMagick でアニメーションを最適化し、結果をより小さく、ダウンロードもアニメーションも速くする伝統的な方法は、その「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」形態を「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」することです。これはもう推奨されません。代わりに 汎用 GIF 最適化 を使うべきです。この演算子は、合体された画像シーケンス(実際に表示されたときに見えるアニメーションフレーム)を取り、2 番目以降の画像を前の画像と比較します。そして、その画像を、変化したピクセルの最小の矩形領域で置き換えます。色の変化(重ね合わせ)であれ消去(消去)であれ、いかなるピクセルの変化もカウントされます。これは非常に単純で、典型的な オーバーレイアニメーション については、そのアニメーションに最適な フレーム最適化 を生成します。ただし、オーバーレイアニメーション は「[None](#none)」破棄方法のみを使います。たとえば、上で生成した 合体された previous アニメーション(これはたまたま オーバーレイアニメーション を形成します)を取り、それを「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」演算子に通してみましょう。 |
magick canvas_prev.gif -coalesce coalesce.gif
magick coalesce.gif -deconstruct deconstruct.gif
gif_anim_montage coalesce.gif coalesce_frames.gif
gif_anim_montage deconstruct.gif deconstruct_frames.gif
![[IM Output]](../static/img/anim_basics/deconstruct.gif)
![[IM Output]](../static/img/anim_basics/deconstruct_frames.gif)
「previous 破棄アニメーション」は、思い出していただければ、各フレームを最後の previous 破棄でないフレーム、この場合は初期の背景キャンバスに消去します。見てのとおり、「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」は、ある合体フレームから次のフレームへ変化した領域を返しました。結果として、特別な破棄設定を必要としない、最適化された オーバーレイアニメーション になります。これは私が最初に始めた手作業で生成したアニメーションほど最適ではありませんが、それ自体は役立ちます。 残念ながら「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」は GIF アニメーションの「[-dispose](https://imagemagick.org/command-line-options/#dispose)」設定をまったく理解しません。その結果、上で作成した(左に示す)「background 破棄」アニメーションのように、あるフレームから次のフレームへピクセルを消去するアニメーションでこれを試すと、ひどく失敗します。 | ![[IM Output]](../static/img/anim_basics/canvas_bgnd.gif)
---|---
ここでは、今示したアニメーションを取り、「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」と「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」のサイクルに通します。 |
magick canvas_bgnd.gif -coalesce -deconstruct deconstruct_erase.gif
![[IM Output]](../static/img/anim_basics/deconstruct_erase.gif)
見てのとおり、「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」は徐々にアニメーションを破壊します。基本的に「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」は、画像レイヤー間の差分を単に見つけるように設計されています。アニメーションを正しく最適化するようには決して設計されておらず、以前に重ねられたピクセルを消去(消去または透明化)するためにさまざまな破棄技術を使う必要があるアニメーションでは失敗します。
Frame Comparisons - より詳細なフレーム比較
IM v6.2.6-2 で、いくつかの追加の GIF フレーム比較方法が加えられました。これらはアニメーションを適切に最適化するために内部的に必要でしたが、コマンドラインや他の API インターフェースで利用できるようにするのに十分役立つと判断されました。
Compare_Any
「[-layers](https://imagemagick.org/command-line-options/#layers)」方法「**CompareAny**」は、実は「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」とまったく同じです。実際、「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」演算子は「CompareAny」方法の機能的なエイリアスにすぎません。もう一度、「background 破棄」アニメーションの「deconstruct」または「CompareAny」の実際の画像結果を見てみましょう。
magick canvas_bgnd.gif -coalesce canvas_bgnd_coal.gif
gif_anim_montage canvas_bgnd_coal.gif canvas_bgnd_coal_frames.gif
magick canvas_bgnd_coal.gif -layers CompareAny magick compare_any.gif
gif_anim_montage compare_any.gif compare_any_frames.gif
見てのとおり、2 番目以降の画像は、新しいピクセル色の重ね合わせであれ、古いピクセルの透明への消去であれ、変化したすべてのピクセルを含む最小の矩形領域です。
Compare_Clear
「[-layers](https://imagemagick.org/command-line-options/#layers)」方法「**CompareClear**」は、あるフレームから次のフレームへ消去する必要があったすべてのピクセルを含む最小の矩形領域を示します。
magick canvas_bgnd_coal.gif -quiet -layers CompareClear compare_clear.gif
gif_anim_montage compare_clear.gif compare_clear_frames.gif
最初のフレームと 2 番目のフレームの間ではピクセルが消去されなかったため、特別な Missed Image が生成されたことに注意してください。「[-quiet](https://imagemagick.org/command-line-options/#quiet)」設定は、この画像についていかなる警告も出さないよう IM に指示するために使われました。後続のフレームがすべて「missed」画像になる場合、その GIF アニメーションはピクセルを決して消去せず、そのアニメーションは オーバーレイアニメーション に分類できます。
Compare_Overlay
最後の「[-layers](https://imagemagick.org/command-line-options/#layers)」比較方法「**CompareOverlay**」は、前のフレーム以降に重ねられた(追加または色が変化したが消去はされていない)ピクセルの領域を返します。
magick canvas_bgnd_coal.gif -layers CompareOverlay magick compare_overlay.gif
gif_anim_montage compare_overlay.gif compare_overlay_frames.gif
| これは IM 固有の「ChangeMask」アルファ合成方法に似ています。ただし、それは変化した矩形領域ではなく、画像を変化させたピクセルだけを返します。透明性の最適化 も参照してください。 | 「[-layers](https://imagemagick.org/command-line-options/#layers)」比較方法も、「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」演算子も、使われる画像の GIF 破棄方法を見たり変更したりはしません。結果は単なる画像のリストであり、それ自体がアニメーションとして使われることは想定されていません。 |
|---|---|
| _これらの演算子は合体された画像シーケンスで動作するように設計されていますが、エラーを出さずに非合体の画像レイヤーのシーケンスも受け付けます。 |
この場合、フレームが比較される前に、各フレームは「[Copy](compose.html#copy)」アルファ合成方法を使って前の重ねられたフレームの上に重ねられます。このアルファ合成方法は、レイヤー内のあらゆる透明性が、出力先の画像にも追加されることを保証します。これがないと、上記は合体された画像シーケンスで透明に消去されるピクセルを見つけられません。
これは、GIF アニメーションを表示するのに必要な「破棄/重ね合わせ」サイクルを扱うために「[-coalesce](https://imagemagick.org/command-line-options/#coalesce)」演算子が使う、より普通の「[Over](compose.html#over)」合成方法とは異なることに注意してください。
_
---|---
アニメーションの種類
見つかる GIF アニメーションのほとんどは、いくつかの基本的なアニメーションの種類に分類されます。これらの種類について知ることで、そのアニメーションがあるフレームから別のフレームへどう表示されるかを理解でき、アニメーションの扱いや変更で近道ができるようになります。
合体アニメーション
オーバーレイアニメーション
「オーバーレイアニメーション」とは、アニメーションの各フレームが、現在表示されているアニメーションに新しいピクセルを重ねるだけのものです。言い換えれば、アニメーションのどの時点でも、ピクセルを透明に消去する必要がありません。個々のフレームは、背景として、または最適化の一部として透明性を含みえますが、ピクセルを透明に戻すことは決してありません。もちろん、透明性がまったく使われていなければ、そのアニメーションは確実に単純なオーバーレイアニメーションに変換できます。これはおそらく最も単純な種類の フレーム最適化 アニメーションであり、クライアントによる特別な扱いを必要としません。ユーザーに示される各フレームは、単に前のすべてのフレームを「平坦化」した画像と見なせます。「[None](#none)」GIF 破棄方法のみを使うアニメーションは、すべて「オーバーレイアニメーション」です。たとえば前の例は、「完全な合体アニメーション」であるだけでなく、「オーバーレイアニメーション」でもありますが、そのような「完全な合体アニメーション」がすべて「オーバーレイアニメーション」というわけではありません。あるアニメーションがオーバーレイアニメーションになりえるかどうかは、合体 アニメーションに対して「[CompareClear](#compareclear)」レイヤー方法を使い、2 番目以降の画像がすべて「missed 画像」かどうかを確認することでテストできます。つまり、あるフレームから次のフレームへ、消去または削除する必要のあるピクセルがないということです。実際、あるアニメーションが変更なしでオーバーレイアニメーションになりえるなら、IM「[coalesce](#coalesce)」演算子はすべてのフレームに「[None](#none)」破棄方法のみを使います。そうでない場合、「[coalesce](#coalesce)」は少なくとも一部のフレームに「[Background](#background)」破棄を使ったことになります。これにより、「オーバーレイのみ」の能力をテストする別の方法も得られます。オーバーレイアニメーションは透明性を使えますが、透明な背景の上に動く部分を持ちません。たとえば、手描きの文字「K」のアニメーションはオーバーレイアニメーションです。なぜなら、各部分は透明な背景上に既存の部分を追加または変更するだけだからです。それは(最初のフレームの一部を除いて)結果の画像に新しい透明性を決して加えません。 |
![]() |
![]() |
|---|---|---|
とはいえ、動く物体がオーバーレイアニメーションで扱えないというわけではありません。ただ、透明性を必要とせずに動く部分の古い位置も「消去」できるよう、透明でない背景が必要になるというだけです。たとえば、この「世界をフォルダにダウンロードする」アニメーションのフレームを見てください… |
もちろん、元の背景を重ねることで古い部分を「消去」する必要があるということは、重ねられるサブ画像が一般により大きくなり、それゆえ GIF アニメーションファイルサイズも一般により大きくなることを意味します。残念ながら、IM の フレーム最適化 演算子を使うと、より小さい GIF ファイルサイズを見つけようとする過程で、「合体オーバーレイアニメーション」を「オーバーレイアニメーション」でないものに変えてしまうことができ、おそらくそうしてしまうでしょう。しかし、フレーム最適化 を使う代わりにアニメーションに Deconstruct を使えば、アニメーションが単純な「オーバーレイアニメーション」のまま残ることを保証できますが、それはアニメーションが本当に「オーバーレイアニメーション」である場合に限ります。アニメーションが「オーバーレイアニメーション」でない場合、Deconstruct 操作はひどく失敗することがあります(上記の Deconstruct を参照)。多少の人間の技があれば、オーバーレイアニメーションをさらにうまく最適化できます。たとえば フレーム更新の分割 を使い、アニメーションの「オーバーレイのみ」要件を壊さずに何らかの 圧縮最適化 を適用するなどです。通常、「オーバーレイアニメーション」は透明性をまったく表示しません(最適化の一部として使えますが、表示しません)。そして、透明性が表示されないなら、そのアニメーションは確実に「オーバーレイアニメーション」です。なぜ「オーバーレイアニメーション」がそれほど重要なのでしょうか?それは、この種類のアニメーションに限定されたソフトウェアが世の中にあるからです。これははるかに扱いが簡単です。なぜなら、透明性を扱ったり、GIF 破棄方法を扱うために前のフレームを保存したりする必要がなく、重ね合わせだけが行われるからです。そのようなソフトウェアはまれですが、存在します。
消去フレームアニメーション
アニメーションが「Previous」または「Background」GIF 破棄のみを使う場合、非常に特別な種類のアニメーションが得られます。「Background」破棄のみが使われる場合、アニメーションのすべてのフレームは表示され、次のフレームが表示される前に消去されることに注意してください。また、「[Previous](#previous)」のみが使われる場合、次のフレームが表示される前にアニメーションは常に初期の消去されたキャンバスに戻され、同じ効果になります。これら 2 つの破棄設定の混合のみを使う場合も同じことが起こります。つまり、これらの破棄方法のみを使うアニメーションは、表示されるべきものの完全なコピーであるフレームを持ちます。つまり、フレームはその時点でユーザーに表示されるすべてを含みます。だからといって、そのアニメーションが「完全な合体アニメーション」であるとは限りません。サブフレームはアニメーションの仮想キャンバス領域よりずっと小さいことがあり、そのフレームの外側のすべては透明(または背景)と見なされ、重要なものは何も含みません。たとえば、この走るウサギのアニメーションを見てください… |
![]() |
![]() |
|---|---|---|
それぞれすべてのサブフレームが、表示される完全な画像であることに注意してください。それ以上でもそれ以下でもありません。また、どのフレームも実際にはアニメーションの仮想キャンバス全体を使う必要がないことに注意してください。そして最後に、すべてのフレームの破棄が「[Previous](#previous)」に設定されていることに注意してください。これは、以下で見る理由により、使うのにより論理的な破棄設定です。すべての破棄設定は、しかし、最終結果を変えずに「[Background](#background)」破棄、またはその 2 つの任意の混合に設定することもできました。より良い名前がないので、私はそのようなアニメーションを「消去フレームアニメーション」と呼んでいますが、「Previous または Background 破棄アニメーション」と呼ばれているのも見たことがあります。アニメーションがこの種類でない唯一の場合は、アニメーション内の少なくとも 1 つの空でないフレームが「[None](#none)」または「Undefined」(同じこと)破棄方法を使った場合です。このアニメーションは非常に特別です。なぜなら、オーバーレイアニメーション とは違って、アニメーションシーケンス内のどこでも、任意の量の透明性の消去を扱えるからです。しかしまた、任意の静的な背景画像の上に非常に素早く重ねることもできます。これを行うには、「消去フレームアニメーション」の定義を少し厳しくする必要があります。具体的には、すべての破棄が「[Previous](#previous)」に設定されていることを確認する必要があります(私たちの例ではすでにそうなっています)。それができれば、(ゼロディレイの)画像を先頭に付けて背景を下敷きにするだけです。 たとえば、ウサギを草の上に置いてみましょう… |
magick bunny_grass.gif bunny_anim.gif -loop 0 bunny_on_grass.gif
![[IM Output]](../static/img/anim_basics/bunny_on_grass.gif)
見てのとおり、これは非常に単純なので、多くのアプリケーションがこの種類の GIF アニメーションを使って、より大きな物体に記号やその他の指標(ファイルのロック、スマイリー、星など)を加えます。そのような GIF アニメーションをアニメーション表示するのも簡単です。なぜなら、アプリケーションは領域を何らかの単純な一定の背景画像に消去し、シーケンスの次のフレームを重ねるだけでよいからです。破棄を計算したり、静的で変化しない背景表示以外の「前の」表示を追跡したりする必要がありません。これが、「[Previous](#previous)」破棄が 消去フレームアニメーション に推奨される破棄である理由でもあります。GIF アニメーションの特別な部分集合にすぎない オーバーレイアニメーション とは違って、すべてのアニメーションは 消去フレームアニメーション として保存できます。アニメーションを 合体 し、必要なら周囲の透明な縁を トリミング してフレーム最適化し、破棄をリセットするだけです。
magick any_animation.gif -coalesce -trim \
-set dispose previous cleared_frame_animation.gif
その背景の上でアニメーションの位置を変えることさえできます… |
magick bunny_grass.gif \( bunny_anim.gif -repage 0x0+5+15\! \) \
-loop 0 bunny_on_grass2.gif
![[IM Output]](../static/img/anim_basics/bunny_on_grass2.gif)
そのため、消去フレームアニメーション は通常、透明な背景の上の、小さく、絶えず変化または移動する物体から成ります。これらは Web ページ上で直接使えたり、アニメーション化された記号として使えたり、他のアニメーションと統合してはるかに複雑なアニメーションを生成できたりします。要約すると、この種類のアニメーションは、より大きく複雑なアニメーションを作成するための、アニメーション化された部品のライブラリで使うのに良いスタイルです。
しかし、GIF アニメーションにこのように背景を加えることには問題があります。前の例を見れば、おそらく、その速く動くアニメーションに、目立つ気になる一時停止があったことに気づいたでしょう。つまり、アニメーションがループして背景画像が再読み込みされるとき、ウサギが一瞬消えたのです。(参照: ゼロディレイフレーム の注釈)。ただしこれは、表示される物体にアニメーション化された記号を加えるためにこの技術を使うアプリケーションにとっては問題ではありません。なぜなら、それらはとにかくその「中間」フレームを表示しないからです。そのため、GIF アニメーションに透明でない背景を加えるなら、単純な 消去フレームアニメーション を オーバーレイアニメーション に変換するのが一般に良い考えです。つまり、初期キャンバスを与えるのではなく、その背景をアニメーションのすべてのフレームに加えるのです。これは、上記のアニメーションを 合体 してから ゼロディレイ の背景フレームを削除するか、または元のアニメーションを 静的背景 の上に レイヤー合成 することで行えます。たとえば…
|
magick bunny_grass.gif \( bunny_anim.gif -repage 0x0+5+15\! \) \
-coalesce -delete 0 -deconstruct -loop 0 bunny_bgnd.gif
gif_anim_montage bunny_bgnd.gif bunny_bgnd_frames.gif
これで、すべてのフレームが等しくうまく表示され、背景がリセットされる際に一時停止が見えなくなります。ただし、アニメーションは今や、アニメーション物体の動きによって背景が「再描画」される オーバーレイアニメーション になっているので、おそらくファイルサイズが少し大きくなっています。上記の結果の最適化の続きについては 透明性の最適化 を参照してください。 | _IM フォーラムのメンバー el_supremo、Pete が、MagickWand 相当のスクリプト 消去フレームを背景の上に置く例 を寄稿しています。
この例は IM フォーラム MagickWand で消去フレーム GIF アニメーションを作成する でも詳しく議論されています。
混合破棄アニメーション - 複数背景のアニメーション
単一の GIF アニメーション内でさまざまな破棄方法を混ぜることを妨げるものは何もありません。実際、消去フレームアニメーション に背景を加えることは、まさにそれを行います。破棄方法を混ぜて使うことは私たち人間にとってそれほど単純ではありませんが、そうすることで非常に複雑なアニメーション表示を生成できます。一般に、それらは特定のアニメーションのための自動 フレーム最適化 の一部として作成されます。ただ、その結果は、特定の目的のための前述のアニメーション種類のように直接使えるわけではないことを覚えておいてください。実際、一部の GIF 処理プログラムが「混合破棄アニメーション」を適切に扱わなくても驚かないでください。それには、利用できる GIF 最適化ツールの一部も含まれます。「混合破棄アニメーション」の典型的な例は、アニメーションの背景に半永久的だが一時的に静的な変化を起こす小さな動く物体です。ボールがレバーに当たるのが一例でしょう。
_単純な例を求む_
同様に、より大きな透明な表示上の 2 つの非常に小さな動く物体が関わるアニメーションは、各物体が別々のアニメーションフレームを使って動くように破棄技術を混ぜることでしかうまく最適化できません。
将来、
研究用のより複雑なアニメーション。
* 半透明のキャンバスから始める
* 少しだけ「previous」破棄を走らせる
* 1 フレームを新しい「キャンバス」として残す
* さらに previous アニメーション
* その「追加」を新しいキャンバスとして設定した「background」破棄を使って消去する
* 開始点まで続ける
このアニメーションは、IM の破棄方法だけでなく
さまざまなブラウザの破棄方法も徹底的にテストするはずです。
もしこのようなアニメーションの IM 例を寄稿していただけるなら、あなたの名前とホームページへのリンクをここに載せられます!
ループの終わり - アニメーションが停止するとき
アニメーションを永遠にループさせないのは良い考えだとよく見なされます。なぜなら、アニメーションがアニメーションし続けている間、クライアントマシンは絶えず働かなければならないからです。そのため、アニメーションが実際に何回ループするかを考えるのは良い考えです。基本的に…
アニメーションにループ制限を加えましょう(現実的なら)
これは特に、Web ページの上部にロゴとして使われる大きなアニメーションの場合に当てはまります。アニメーションが実行される全体の時間にもよりますが、大きなロゴには通常 10〜30 ループで十分です。そして、ユーザーに優しくするために、そのようなすべてのアニメーションにループ制限を加えるべきです。「[-loop](https://imagemagick.org/command-line-options/#loop)」の保存設定が 0 だと、永遠にループすることを意味します。これは通常使われるもので、小さいアニメーションには問題ありません。ただし、一部のブラウザは、アニメーションが何らかの内部ループ制限(多くの場合 256 ループ)に達すると停止を強制します。IM 例では、アニメーションがページのどこにでも現れうるため、私は一般に「0」の「[-loop](https://imagemagick.org/command-line-options/#loop)」保存設定、つまり「永遠にループ」を使ってきました。これは、ユーザーがページを読み込んでから、ある特定の GIF アニメーションを実際に見てそれについて読むまでに、しばらく時間がかかることがあるという意味です。もしより少ない「ループ」回数を使えば、アニメーションはそれが実証すべきことをもはや行わなくなり、その効果を失ってしまいます。トップレベルのフラッシュページの上にある大きなアニメーションには、通常の GIF アニメーションの既定値である「1」の「[-loop](https://imagemagick.org/command-line-options/#loop)」が使えます。これは、アニメーションを一度だけ実行してから停止することを意味します。そこで、これが極めて重要な問いに私たちを導きます… どこで停止する? 古い「Netscape」ブラウザのような一部のブラウザは、アニメーションの最初のフレームを再表示しました。しかし、ほとんどの最新のブラウザは、そのフレームの無用な 破棄 設定を無視して、最後のフレームで停止するだけです。ただし、特定のアプリケーションが何をするかはアプリケーション次第です。真の標準が存在しないからです。実は「loop」メタデータの使用自体も非標準で、古い「Netscape」ブラウザが実装し、それ以降のすべてのブラウザがコピーしただけのものです。このため、アニメーションを停止させたい特定のフレーム、たとえば会社名やロゴが載ったフレームがあるなら、そのフレームをアニメーションの最初と最後の両方のフレームにするのが良い考えです。ただし、それらのフレームのどちらかには「ゼロディレイ」を与えて、アニメーションの全体のループ時間の長さに影響しないようにすべきです。というわけで、要約すると…
ループ制限する場合、「停止」フレームを最初と最後の両方のフレームとして加えましょう。
ゼロディレイの中間フレーム
消去フレームアニメーション に関して、「ゼロディレイ」を持つフレームの使用はすでに見ました。また、Previous と Background の破棄 を説明するためにもそれらを使いました。これらの特別なフレームは、実はおそらく人々が思っているよりもずっと一般的です。それらは、(私が上で使ってきたような)アニメーションに背景「キャンバス」を先頭に付ける方法を表すだけではありません。それらは、フレーム倍化 や フレーム更新の分割 のような、より複雑な フレーム最適化 技術の一部にも不可欠です。もう 1 つの(PNG フォーマット以前の非常に古い)用途は、256 色制限を超える色を含む静的 GIF 画像を作成できるようにすることでした! つまり、各フレームが 256 色を提供し、次のフレームが次の 256 色のセットを提供し、すべてゼロディレイで、最後にループなしです。これを指摘してくれた、議論 量子化されていない GIF を作成する の TLUL に感謝します。これらの「ゼロディレイの中間フレーム」は、ユーザーに表示されることを意図していません。それらは、それらがなければ不可能、またはより良く最適化される特別な効果を GIF 画像に作り出すために使われるだけです。要約すると…
ゼロディレイフレームは中間フレームであり、
ユーザーに見えることを意図していません。
ImageMagick は、自動の「OptimizePlus」の一部としてアニメーションにそのようなフレームを作成するだけでなく、「RemoveZero」レイヤー方法を使ってそれらを取り除く方法も提供します。それらに注意してください。なぜなら、それらはしばしばアニメーションの扱いを複雑にするからです。さて、それらが重要だとして、それがどうした? なぜなら、多くのアプリケーションがそれらを好まない、または誤って扱うからです。それらは、何らかの理由であなたが意図的にアニメーションに加えたときでさえ、「ゼロディレイフレーム」を悪いものと見なします。こちらが、「間違ったことをする」と私が知っている、または聞いたことのあるアプリケーションの要約です… Gimp | 「ゼロディレイフレーム」を保存しません。ゼロ時間遅延を持つどのフレームにも常に最小の時間遅延を加えます。:-(
---|---
FireFox | そのようなフレームにわずかな非ゼロの一時停止を与えます。これはおそらく、時間遅延がまったくないアニメーションがコンピュータのすべての CPU サイクルを使い果たすのを防ぐためです。しかし「firefox」は、アニメーションに全体の非ゼロの表示時間があっても、その制限を緩めません。
Internet Explorer | 最小の時間遅延が 6 センチ秒で、これより小さいディレイを無視します。Internet Explorer バージョン 8 はまた、いずれかの画像フレームが最初のフレームによって設定されたアニメーション境界を超えて広がると失敗します(直ちにループを再開します)。これは私なら重大なバグに分類します。
一方、ImageMagick の「RemoveZero」レイヤー方法は正しいことを行い、すべての画像が「ゼロ時間遅延」を持つ場合はどのフレームも取り除きません。実際、このレイヤー方法は、時間遅延がまったくないアニメーションを見ると警告を出します。これがもう 1 つの経験則に私たちを導きます…
「ディレイ」がまったくない GIF(ループ)アニメーションを決して保存しないこと
そうすることは非常に悪い習慣であり、上記のほとんどの「バグのある」アプリケーションが、本来すべきことではなく、するべきでないことをする理由です。もし見かけたら所有者に苦情を言いましょう。また、ゼロディレイフレームを正しく扱うよう、アプリケーション開発者にも苦情を言いましょう。たとえそれが、そのフレームをまったく表示せず、次に表示するフレームの準備として使うだけだとしても。なんといっても、それらは ゼロ の時間だけ画面に表示されるのですから!
![[IM Text]](../static/img/anim_basics/identify_prev.txt.gif)
![[IM Text]](../static/img/anim_basics/identify_prev_more.txt.gif)
![[IM Output]](../static/img/anim_basics/frame_001.gif)
![[IM Output]](../static/img/anim_basics/frame_002.gif)
![[IM Output]](../static/img/anim_basics/frame_003.gif)
![[IM Output]](../static/img/anim_basics/frame_004.gif)
![[IM Output]](../static/img/anim_basics/frame_005.gif)
![[IM Output]](../static/img/anim_basics/repage_000.gif)
![[IM Output]](../static/img/anim_basics/repage_001.gif)
![[IM Output]](../static/img/anim_basics/repage_002.gif)
![[IM Output]](../static/img/anim_basics/repage_003.gif)
![[IM Output]](../static/img/anim_basics/repage_004.gif)
![[IM Output]](../static/img/anim_basics/script_k_00.gif)
![[IM Output]](../static/img/anim_basics/script_k_01.gif)
![[IM Output]](../static/img/anim_basics/script_k_02.gif)
![[IM Output]](../static/img/anim_basics/script_k_03.gif)
![[IM Output]](../static/img/anim_basics/script_k_04.gif)
![[IM Output]](../static/img/anim_basics/script_k_05.gif)
![[IM Output]](../static/img/anim_basics/script_k_06.gif)
![[IM Output]](../static/img/anim_basics/script_k_07.gif)
![[IM Output]](../static/img/anim_basics/script_k_08.gif)
![[IM Output]](../static/img/anim_basics/script_k_09.gif)
![[IM Output]](../static/img/anim_basics/script_k_10.gif)
![[IM Output]](../static/img/images/script_k.gif)
![[IM Output]](../static/img/anim_basics/coalesce_k_montage.gif)
![[IM Output]](../static/img/anim_basics/script_k_parts.gif)
![[IM Output]](../static/img/anim_basics/script_k_frames.gif)
![[IM Output]](../static/img/anim_basics/script_k_frames.png)
![[IM Text]](../static/img/anim_basics/canvas_prev.anim.gif)
![[IM Output]](../static/img/anim_basics/canvas_prev_001.gif)
![[IM Output]](../static/img/anim_basics/canvas_prev_002.gif)
![[IM Output]](../static/img/anim_basics/canvas_prev_003.gif)
![[IM Output]](../static/img/anim_basics/canvas_prev_004.gif)
![[IM Output]](../static/img/anim_basics/canvas_prev_005.gif)
![[IM Output]](../static/img/anim_basics/canvas_none_dispose_frames.gif)
![[IM Output]](../static/img/anim_basics/canvas_prev_dispose_frames.gif)
![[IM Output]](../static/img/anim_basics/canvas_bgnd_dispose_frames.gif)
![[IM Output]](../static/img/anim_basics/canvas_bgnd_coal_frames.gif)
![[IM Output]](../static/img/anim_basics/compare_any_frames.gif)
![[IM Output]](../static/img/anim_basics/compare_clear_frames.gif)
![[IM Output]](../static/img/anim_basics/compare_overlay_frames.gif)
![[IM Output]](../static/img/images/smoke_skull_frames.gif)
![[IM Output]](../static/img/images/smoke_skull_anim.gif)
![[IM Output]](../static/img/images/dl_world_anim.gif)
![[IM Output]](../static/img/images/dl_world_frames.gif)
![[IM Output]](../static/img/images/bunny_frames.gif)
![[IM Output]](../static/img/images/bunny_anim.gif)
![[IM Output]](../static/img/anim_basics/bunny_bgnd.gif)
![[IM Output]](../static/img/anim_basics/bunny_bgnd_frames.gif)