⚠️ これは 非公式の翻訳サイトです。ImageMagick Studio LLC とは無関係です。正確な情報は 原文(https://usage.imagemagick.org/anim_mods/index.html) を参照してください。

ImageMagick 使用例 -- アニメーションの加工

ImageMagick 使用例 前書きと索引
アニメーションの単純な加工

このページには GIF アニメーションを扱う実用的な例が含まれています。これらの例を理解しようとする前に、アニメーションの基礎を読んで理解し、少なくともGIF アニメーションの最適化の全体的な扱い方に目を通しておくことを強くお勧めします。


アニメーションの単純な加工

まず重要な点

処理が完了していない中間のアニメーション、特に半透明の扱いカラー最適化をまだ行っていない画像を、直接 GIF に保存してはいけません。もし GIF に保存するという大きな失敗をしてしまえば、結果のアニメーションを悪化させてしまうだけです。なぜなら IM は、限られた GIF 形式に画像を収めるために存在する色数を減らすカラー量子化を自動的に実行してしまうからです。それだけではなく、各フレームを他のすべてのフレームとは完全に別々に処理するため、異なる色選択やディザパターンが生じます。それはつまり、その後のあらゆる処理、特にフレーム最適化を、それだけ難しくしてしまうということです。これはリサイズされた GIF アニメーションや、多色のオーバーレイ・アンダーレイを追加したアニメーションでは特に重要で、これらは多くの余分な色を追加しかねません。段階を踏んでアニメーションを加工したい場合は、IM の内部形式である MIFF を一時ファイル形式として使うか、編集する各フレームに個別の PNG 形式画像を使うとよいでしょう。色の問題が起きないと確信できるまでは、最終的な GIF 保存だけは行わないでください。繰り返します...

GIF を中間ファイル形式として使ってはいけません。MIFF か PNG 画像を使いましょう。

注釈 - 全フレームに著作権表示を加える

IM バージョン 6.2.6 以降、画像の上に注釈を付けるで詳しく説明したのと同じように、単純に "[-annotate](https://imagemagick.org/command-line-options/#annotate)" するだけでアニメーションに注釈を付けられます。例えば、ここではアニメーションの基礎で作成したprevious dispose アニメーションに注釈を付けます。 |

  magick canvas_prev.gif -gravity center \
          -fill black     -annotate +1+1 "Copyright" \
          -fill white     -annotate +0+0 "Copyright" \
          annotate.gif
  gif_anim_montage annotate.gif annotate_frames.gif

[IM Output]

[IM Output]

これが機能する理由は、"[-annotate](https://imagemagick.org/command-line-options/#annotate)" がテキストを画像の仮想キャンバスに対して相対的に配置し、実際の画像データに対して相対的に配置しないからです。そのため、各フレーム上のテキストの位置はアニメーション画像にとって正しくなります。ただしバージョン 6.2.6 より前では、"[-annotate](https://imagemagick.org/command-line-options/#annotate)" は他の多くの画像演算子と同様に、情報やオーバーレイを実際の画像に対して相対的に配置し、サブフレームが持つページや仮想キャンバスのオフセットを無視していました。1つ警告しておくと、このようにアニメーションに対して、まず結合(coalesce)せずに描画すると、アニメーション既存の最適化スキームのために、いくつかの異常な効果が生じることがあります(次の例の組を参照)。そのため(そして見ていくように)、まず結合(coalesce)することで既存のフレーム最適化や透明度最適化を取り除いておくことをお勧めします。

描画 - 結合(coalesce)済みアニメーションを加工する

さて、"[-annotate](https://imagemagick.org/command-line-options/#annotate)" は各フレームの仮想キャンバスに対して相対的にテキストを配置しますが、他の多くの画像演算はそうではありません。これにはすべての "[-draw](https://imagemagick.org/command-line-options/#draw)" 演算が含まれ、これらは実際の画像に対してのみ描画を行い、より大きなキャンバス上で持つかもしれないオフセットを完全に無視します。例えば、ここではprevious dispose アニメーションの左上隅近くに洒落た緑の円を描きます。 |

  magick canvas_prev.gif -fill LimeGreen -stroke SeaGreen \
          -draw 'circle 35,35 20,30'  draw_circle_fail.gif
  gif_anim_montage draw_circle_fail.gif draw_circle_fail_frames.gif

[IM Output]

[IM Output]

ご覧の通り、"[-draw](https://imagemagick.org/command-line-options/#draw)" は、画像が一部となっているより大きな仮想(ページ)キャンバスではなく、「実際の画像」に対して相対的に円を描きました。結果は、この種の状況にありがちなように... 混乱状態です。これに対する単純な解決法は、まず描画前にアニメーションを結合(coalesce)し、その後で GIF アニメーションを再最適化することです。詳細はアニメーションの最適化を参照してください。 |

  magick canvas_prev.gif -coalesce \
          -fill LimeGreen -stroke SeaGreen -draw 'circle 35,35 20,30' \
          -layers Optimize  draw_circle.gif
  gif_anim_montage draw_circle.gif draw_circle_frames.gif

[IM Output]

[IM Output]

IM のアニメーション最適化器が、実際には描画された部分を上書きしないと判断したことに注目してください。これは実際のサブフレーム画像そのものに描画した場合よりも最適です。この方法を使えば、好きなどんな種類の注釈、著作権表示、ウォーターマークでも重ねられます。もちろん、アニメーションの全フレームに実際に画像を重ねるには、特別なレイヤー合成技術を使う必要があるかもしれません。本当に上手くなれば、アニメーションの統合を行って、アニメーションの上にアニメーション化された著作権表示を重ねることさえできます。 | _この「coalesce-optimize(結合してから最適化)」の技術は、アニメーションを扱うほとんどの演算で、特に IM の最適化器とともに機能しますが、画像に対してあまりにも劇的な変化を与える演算、例えば大きな色変化やシェーディング、半透明を伴うものでは、結果のアニメーションがあまり上手く最適化されないことがあります。

例えば、ほとんどの "[-resize](https://imagemagick.org/command-line-options/#resize)" 演算は、大きな色変化のためにその後でとても下手にしか最適化されないアニメーションを生み出しがちです。これに対する解決法は下記のアニメーションのリサイズを参照してください。

_
---|---

フレーム単位 - 1フレームずつ加工する

IM の画像リスト・シーケンス演算子を使うと、アニメーションの各フレームを別々に加工できます。コツは、各フレームを括弧の中に取り出し、加工し、元の画像を加工後のものと置き換えることです。例えば、ここではアニメーションの中に著作権ウォーターマークとしてテキストを、それ自体アニメーションとして加え、除去をさらに難しくします。アニメーションを完全に台無しにしないよう、半透明の色も使いました。 |

  magick canvas_prev.gif -coalesce -gravity center \
          -font Ravie -pointsize 24 -fill '#FFF8' -stroke '#0008' \
          \( -clone 0 -annotate 0 'This'        \) -swap 0 +delete \
          \( -clone 1 -annotate 0 'This'        \) -swap 1 +delete \
          \( -clone 2 -annotate 0 'image'       \) -swap 2 +delete \
          \( -clone 3 -annotate 0 'is'          \) -swap 3 +delete \
          \( -clone 4 -annotate 0 'Copy\nright' \) -swap 4 +delete \
          -layers OptimizeFrame   frame_mod.gif
  gif_anim_montage frame_mod.gif frame_mod_frames.gif

[IM Output]

[IM Output]

括弧を使って、"[-annotate](https://imagemagick.org/command-line-options/#annotate)" 演算の効果をアニメーションの1フレームの単純な「クローン」だけに限定していることに注目してください。加工された画像は、SwapDelete 演算子を使って画像シーケンスの本来の位置に戻されます。 "[-swap](https://imagemagick.org/command-line-options/#swap)" 演算子での単一番号の使い方は IM v6.3.4-3 で追加されました。これ以前は、正しく動作させるために "-swap 3" を "-swap -1,3" と指定する必要がありました。
個々のフレームを加工するこの技術は、画像アニメーションを操作する上で出会う最も重要な技術の1つになるでしょう。また、1番目と2番目の両方の画像に同じテキストを実際に追加したことにお気づきでしょう。上のアニメーションの1番目の画像はゼロディレイ中間フレームで、これは残りのアニメーションの背景を定義するために使われます。つまり、あまりに速く過ぎ去るのでユーザーには通常見えませんし、見えることを意図されてもいません。したがって、上のアニメーションの最初の2つの実フレームは、別々の2フレームではなく、単一の可視フレームとみなすべきです。ゼロでない時間ディレイを持つフレームが、「表示」フレームシーケンスの最後のフレームです。同様に、他の高速で動くアニメーションでも、変更をある程度の時間見えるようにするには、いくつものフレームを加工する必要があるかもしれません。全フレームに描画された静的な注釈の場合は、これは問題になりません(上記の前の注釈の例を参照)。これは GIF アニメーションに関する重要な点につながります。

加工しようとする前にアニメーションを研究しましょう。
それが最終結果に大きな違いをもたらすことがあります。

切り抜き - アニメーションの領域を限定する

IM は "[-crop](https://imagemagick.org/command-line-options/#crop)" 画像演算が、実際の画像ではなく画像の仮想キャンバスに対して相対的に正しく機能するよう努めてきました(IM バージョン 6.1.1 以降)。これにより、これまで直接は不可能だったことができるようになります。例えば GIF アニメーションの画像を切り抜いても、すべてのアニメーションで期待通りに機能させられます。 |

  magick canvas_prev.gif -crop 50x50+3+30  cropped.gif
  gif_anim_montage cropped.gif cropped_frames.gif

[IM Output]

[IM Output]
ご覧の通り、切り抜きは単一画像の切り抜きの場合と同じように機能し、適切なオフセットとページサイズを保持するので、関係する領域が縮小されても画像データは依然として正しく配置されます。ご覧の通り、これは全体の仮想キャンバスサイズを変更しませんでした! | フレーム最適化された GIF アニメーションから切り抜きオフセットを除去するために "[+repage](https://imagemagick.org/command-line-options/#repage)" を使ってはいけません。そうすると、サブフレームを仮想キャンバス上に配置するのに必要なフレームオフセットも除去されてしまい、後のフレームが正しくアニメーションするのにそれに頼っているかもしれません。
---|---
ただし上記の "[-crop](https://imagemagick.org/command-line-options/#crop)" 演算は警告メッセージを生成しました...

[IM Text]

これは、アニメーションのフレームの1つの切り抜きが、そのフレームに使われるサブフレームのオーバーレイ画像を外したためです。つまり、1つのフレームが、アニメーションから切り抜かれた領域を更新しなかったのです。その結果、そのフレームには実際の画像が含まれていません! これを補うために、IM は警告メッセージを生成するだけでなく、すべてを整合させ、そのフレームに付随する「delay」や「disposal」メソッドを保持するために、アニメーション内のプレースホルダとして特別な「欠落画像」を生成します。そのプレースホルダをそのまま残しても、好きなように修正しても構いません。この場合、アニメーションが期待通りに動くには「欠落画像」が必要です。ただし複数の連続した欠落画像が生成された場合は、"[-layers](https://imagemagick.org/command-line-options/#layers)" メソッドの「[RemoveDups](anim_opt.html#removedups)」を使って、おそらく1つの欠落画像にまとめられます。とはいえ、注意とアニメーションの研究はやはりお勧めします。(これのより詳細な例は下記のアニメーションを分割するを参照してください。)

キャンバスも切り抜く - アニメーションのビューポート切り抜き

通常の切り抜きが元画像の仮想キャンバスを保持したのと同様に、アニメーションの切り抜きも保持しました。この場合、これはおそらく意図したものではありません。このため、IM バージョン 6.2.4-5 で、"[-crop](https://imagemagick.org/command-line-options/#crop)" の引数に特別なフラグ「!」が追加されました。このフラグは、個々の画像フレームを切り抜くだけでなく、画像に関するページやキャンバスの情報も同じ領域に調整させます。これは「ビューポート切り抜き」として知られ、結果は切り抜き引数のサイズと位置の「窓」または「ビューポート」を通して画像を見ているかのようになります。仮想キャンバスのサイズが切り抜き領域のサイズに設定されるだけでなく、整合性を保つためにアニメーションの各フレームのオフセットも調整されます。(キャンバス/ページ調整を伴うビューポート切り抜きを参照)。例えば、先ほどの切り抜きを繰り返しますが、「!」フラグを使ってキャンバス情報も切り抜いてみましょう... |

  magick canvas_prev.gif -quiet -crop 50x50+3+30\!  crop_viewport.gif
  gif_anim_montage crop_viewport.gif crop_viewport_frames.gif

[IM Output]

[IM Output]
| !」文字は "csh" のような一部の UNIX シェルでは特別な意味を持つため、引用符の中に置いた場合でもバックスラッシュでエスケープしなければなりません。IM はジオメトリ引数内のバックスラッシュを無視するので、常にバックスラッシュを付けても害はありません。
---|---
ご覧の通り、結果はアニメーション画像を切り抜く際におそらく本当に達成したかったものに近くなっています。前の切り抜きの試みで生成された欠落画像についての警告メッセージを IM に出さないよう依頼するために、"[-quiet](https://imagemagick.org/command-line-options/#quiet)" 設定を含めたことに注目してください。警告は実際には当てはまらないので、アニメーションを切り抜く際にはこれをお勧めします。ビューポート切り抜きでは、キャンバス領域を拡大したり、キャンバス内のすべてを再配置することさえできます。ただし、切り抜き領域の一部または完全に外側にある画像は、その領域内に現れる部分だけを表示するように切り詰められてしまうので危険です。最後に1つだけ警告しておきます。「ビューポート切り抜き」を使うとき、フレーム画像は「ビューポート」に与えられたオフセットとは負の方向に移動します。これは非論理的に見えるかもしれませんが、切り抜き演算子のオフセットはビューポートの位置であって、画像そのものを直接再配置するものではないことを思い出せば理解できます。

境界トリミング - キャンバスサイズの自動補正

前の演算と同様に、アニメーションのトリミングは厄介になり得ます。アニメーションが単純なクリアフレームアニメーションで構成されている場合は、アニメーション内のすべての個々のフレームの最大境界を割り出すだけで、アニメーションをトリミングできます。IM v6.3.4-8 以降は、「TrimBounds」レイヤーメソッドを使ってこれをとても簡単に行えます。

  magick anim_bgnd.gif -layers TrimBounds anim_trim_bounds.gif

[IM Output] [IM Output]

このバージョンより前の IM のユーザーでも同じことができますが、2段階の手順を踏む必要があります(これは他の不要な処理も行います)。これを行うには、レイヤー統合(merge)を使ってアニメーションの全フレームを単一レイヤーに統合し、そのレイヤーのサイズとオフセットを IM に報告させます...

  magick anim_bgnd.gif -layers merge -format '%wx%h%X%Y' info:

[IM Text]

これで全フレームの境界が分かったので、このサイズにアニメーション全体をビューポート切り抜きするだけです。

  magick anim_bgnd.gif -crop 89x77+5+10! anim_trim_crop.gif

[IM Output] [IM Output]

アニメーションから静的な背景もトリミングしたい場合は、レイヤー統合(merge)の手順を使う前に、フレーム最適化されたアニメーションから最初のフレームを削除するのが一番です。そして返された境界を、元のアニメーションに対するビューポート切り抜きに使えます。

フレームの再配置

似たような関連演算に「relative repage(相対的なリページ)」演算子があります。これはアニメーションの個々のサブフレームレイヤーすべてに与えられたオフセットを加え、キャンバス全体に対して相対的にそれらの位置を調整できるようにします。"[-repage](https://imagemagick.org/command-line-options/#repage)" 演算を相対的にするには、その引数に「!」フラグも加えます。例えば、ここではアニメーションの2番目以降のフレームを30ピクセル下と右にずらし、最初の「背景」フレームを通常の「+0+0」位置に戻します。 |

  magick canvas_prev.gif -repage 0x0+30+30\! \
           \( -clone 0 -repage +0+0 \) -swap 0,-1 +delete \
           repage_offset.gif

  magick identify repage_offset.gif

[IM Output]
| [IM Text]


| 上記のアニメーションは Windows Internet Explorer バージョン 8 では失敗します(最初の2フレームしか表示されません)。これは、フレームがアニメーションキャンバスの境界を超えて画像を描こうとするたびに起こります。
---|---
どの画像も「切り抜かれ」たり切り詰められたりしていないことに注目してください。元の背景画像に対して相対的に、位置だけが変更されており、画像が「キャンバス外」に移動された場合でもそうです。よろしければ、これらの新しい境界に合わせてキャンバスを拡張することもできます。キャンバスサイズを直接調整するか... |

  magick repage_offset.gif -repage 130x130  repage_canvas.gif

[IM Output]
境界トリムのレイヤーメソッドを使えば、「境界外」に配置されることになった画像を含むよう、アニメーションの境界をちょうど十分なだけ自動的に拡張できます... |

  magick repage_offset.gif -layers TrimBounds repage_bounds.gif

[IM Output]
| _"[-repage](https://imagemagick.org/command-line-options/#repage)" を使って画像を左や上に、特に小さなキャンバスで移動させると、GIF アニメーションでは失敗しがちです。この形式は基本的に負の画像オフセットを使えません。

そのためには、「ビューポート切り抜き」も適用するか、「境界トリム」を使ってすべてのオフセットをより大きな正のキャンバスへシフトする方がよいかもしれません。どちらの方法も、すべての画像フレームに正のオフセットを保証します。

PNG と MNG 形式は負のオフセットを扱えますが、多くの Web ブラウザやその他のプログラムはそうしたオフセットを理解できず、奇妙な効果を生み出すかもしれません。例えば、ある バージョンの "Firefox" Web ブラウザは、負のオフセットを持つ PNG を表示しようとすると極端に大きな画像を生成します。_
---|---

アニメーションの逆再生 - アニメーションを逆向きに動かす、または循環させる

IM v6.3.3 以降、"[-reverse](https://imagemagick.org/command-line-options/#reverse)" 画像シーケンス演算子が追加されました(Reverse 演算子に詳細があります)。これにより、結合(coalesce)済みのアニメーションシーケンスの順序をとても簡単に逆にできます。例えば、ここでは「手で k を描く」アニメーションを、描かれていく逆にしてみます! |

  magick script_k.gif -coalesce -reverse \
          -quiet -layers OptimizePlus  -loop 0 reversed.gif

[IM Output]
上記には "[-loop](https://imagemagick.org/command-line-options/#loop)" オプションを再度追加しなければなりませんでした。これは最初の画像に付加する必要があるのですが、その画像が今や最後の画像になっているからです! 結果はタイミングの調整も必要かもしれませんが、ご覧の通り、これで文字が「描き消されて」いきます! フレーム最適化が存在すると画像の順序に依存するため、逆にする前に必ず画像シーケンスを "[-coalesce](https://imagemagick.org/command-line-options/#coalesce)" してください。それらの最適化を先に取り除く方がよいでしょう。

パトロールサイクル - 両端を行ったり来たりさせる

似た技術として、逆順のフレームをアニメーションの末尾に加えることで、結果のアニメーションが元のアニメーションの最初と最後のフレームの間を循環するようにする方法があります。それは2点間を巡回する歩哨が往復するのに少し似ているので、「パトロールサイクル」と呼ばれます。ここでは画像の複製演算子(IM v6.6.8-7 で追加)を使って、(逆順の)余分なフレームを生成します。 |

  magick script_k.gif -coalesce   -duplicate 1,-2-1 \
          -quiet -layers OptimizePlus  -loop 0 patrol_cycle.gif

[IM Output]
アニメーションの全画像をただコピーしたのではなく、元のシーケンスの一番最初と一番最後の画像のコピーを飛ばしたことに注目してください。もし全画像をコピーしていたら、最初と最後の画像が期待の2倍の時間表示され、アニメーションファイルが必要以上に大きくなってしまいます。とはいえ、アニメーションの開始と終了にあるゼロディレイ中間フレームには再び気をつけるべきで、これらは予期しない問題を引き起こすことがあります。基本的に、まずアニメーションを研究せずにこれを行うと、トラブルを招くことになります。また、結果をより良く最適化できるよう、最適化を改善するために、順方向と逆方向のサイクルの間に余分なゼロディレイ中間フレームをいくつか加える必要さえあるかもしれません。これらの余分なフレームは、アニメーションがループするときに通常リセットされるため、元のアニメーション最適化には恐らく用意されていませんでした。これらの余分なフレームがアニメーションの最適化と改善にどう役立つかの詳細は、フレーム更新の分割を参照してください。こちらはクローン演算子を使って複製フレームを生成する古い方法です。 |

  magick script_k.gif -coalesce \( -clone -2-1 \) \
          -quiet -layers OptimizePlus  -loop 0 patrol_cycle_2.gif

[IM Output]

カラーモーフィング - 2つの画像間でアニメーション変化させる

"[-morph](https://imagemagick.org/command-line-options/#morph)" 演算子は特に興味深い演算子です。これは画像のリストを取り、それらの間に余分なフレームを挿入して、ある画像から次の画像への滑らかな色変化を行います。ただしこの演算子は、ピクセルの色を加工して一連のブレンド画像を作るだけなので、真の「モーフ」ではありません。映画のような真の「モーフ」では、画像内のオブジェクトの輪郭を別の画像内のオブジェクトへ変形させる画像の歪みも伴います。例えば、ここではバラの画像とその上下反転した形の間の余分なフレームを生成するためにカラーモーフを使い、パトロールサイクルを作ります。 |

  magick -delay 20 rose: \( +clone -flip \)  -morph 5 \
          -duplicate 1,-2-1  rose_flip.gif

[IM Output]
全画像が同じディレイを持つため、これは特に良くありません。その結果、アニメーションがサイクルの2つの端点の間で決して「休止」したり止まったりしないように見えます。より良い解決法は、元の画像とその「反転」した形で休止を持たせることです。ただしそれには、元の画像のディレイをモーフィングの画像とは異なるよう調整する必要があります。 |

  magick rose: \( +clone -flip \)  -morph 5 -set delay 10 \
          \( -clone 0 -set delay 240 \) -swap 0 +delete \
          \( +clone   -set delay 240 \) +swap   +delete \
          -duplicate 1,-2-1 rose_flip_pause.gif

[IM Output]
ご覧の通り、良いアニメーションを生成するにはタイミングのディレイがとても重要になり得て、アニメーションをちょうど良い地点で「休止」させられます。IM v6.6.9 以降は、画像のインデックスに基づいて計算するFX パーセントエスケープを使ってディレイを設定できます。ここでの FX 式は、画像のインデックスが最初(t=0)でも最後(t=n-1)でもないなら10のディレイを使い、そうでなければより大きな値を使う、と言っています。 |

  magick rose: \( +clone -flip \)  -morph 5 \
          -set delay '%[fx:(t>0&&t<n-1)?10:240]' \
          -duplicate 1,-2-1    rose_flip_anim.gif

[IM Output]
ある画像から別の画像へ「モーフィング」したり「トランジション」したりする様々な方法の全範囲については、Fred Weinhaus 氏の "[transitions](http://www.fmwconcepts.com/imagemagick/transitions/)" と "[fxtransitions](http://www.fmwconcepts.com/imagemagick/fxtransitions/)" の ImageMagick シェルスクリプトを参照してください。そのサンプルページには、スクリプトがアニメーションを生成するのに使う基本アルゴリズムが含まれています。

リサイズモーフィング - サイズをアニメーション変化させる

カラーモーフ演算子は、実際には2つの画像間で色のブレンドを行うだけでなく、同時に画像のリサイズも行います。例えば、ここではサイズが異なり、さらにアスペクト比も異なる2つの画像に "[-morph](https://imagemagick.org/command-line-options/#morph)" を使います。 |

  magick rose: medical.gif -morph 10 \
          -layers TrimBounds -set dispose previous -coalesce \
          -background black -alpha remove \
          -set delay '%[fx:(t>0&&t<n-1)?10:60]' \
          -duplicate 1,-2-1  -loop 0  morph_resize.gif

[IM Output]
最初の行だけがリサイズモーフを行います。実際の画像を見れば、各フレームのサイズが異なっていることが分かるでしょう! 次の2行が画像を同じサイズに「埋め」、使われない部分を黒で埋めます。具体的には、画像の順序が問題にならないよう演算が設計されています。残りはパトロールサイクルと関連するタイミングディレイを設定するだけです。「リサイズ」は左上隅からのみ行われます。執筆時点では、カラーモーフ演算子はレイヤーオフセットや、その他の空間的なモーフィング(歪みを伴うモーフィング)を理解しません。そのため、リサイズを中央寄せにしたい場合は、後のセクションで示すもっと複雑な技術を使う必要があるかもしれません。こちらは似た例で、今度は同じ画像のより小さなバージョンで画像をリサイズします(アスペクト比は保持されます)... |

  magick rose: \( +clone -resize 10 \) -morph 10 \
          -layers TrimBounds -set dispose previous -coalesce \
          -background black -alpha remove \
          -set delay '%[fx:(t>0&&t<n-1)?10:60]' \
          -duplicate 1,-2-1  -loop 0  morph_resize_self.gif

[IM Output]
「中間」の画像が、おそらく本来あるべきよりもぼやけていることに注目してください。これは、より大きな画像がより小さくリサイズされるだけでなく、より大きくリサイズされた小さな画像と色のブレンドも行われているためです。

ワイプ - ある画像から別の画像へワイプを作る

これは実はとても簡単にできます。新しい画像の「薄片」を重ねるだけです。これらは単純なタイル切り抜きを使って直接生成されます。例えば、ここではある画像からその上下反転バージョンへ「ワイプ」し、そして面白半分に元へ戻すワイプもします。 |

  magick rose: \( -clone 0 -flip -crop 3x0 \) \
                \( -clone 0 -crop 3x0 \) \
                -set delay 10 -loop 0  wipe.gif

[IM Output]
こちらは IM フォーラムの GeeMack 氏によるバージョンで、4方向すべてからのワイプを実装しています... |

  magick -size 100x60 -delay 100 \
      gradient:green-yellow gradient:blue-purple \
      gradient:orange-white gradient:red-black \
      -write mpr:stack -delete 0--1 \
      \
      mpr:stack'[0]' \( mpr:stack'[1]' -set delay 5 -crop 4x0 \) \
      mpr:stack'[1]' \( mpr:stack'[2]' -set delay 5 -crop 0x4 \) \
      mpr:stack'[2]' \( mpr:stack'[3]' -set delay 5 -crop 4x0 -reverse \) \
      mpr:stack'[3]' \( mpr:stack'[0]' -set delay 5 -crop 0x4 -reverse \) \
      -loop 0 wipe_all.gif

[IM Output]

アニメーション歪み - 画像インデックスに基づいて複数画像を歪ませる

多くの演算子は引数にパーセントエスケープを使えます。これはつまり、処理される各画像ごとに少し異なる動作をするよう、演算子を実際に加工できるということです。この方法では、まず画像の複製を行ってバラ画像の同一コピーを30個(または好きなだけ)作ります。そして画像のインデックス「%[fx:t]」とリスト内の画像数「%[fx:n]」に基づいて歪み値を計算するFX パーセントエスケープを使って、各画像を別々に加工します。例えば、ここでは計算された量だけ画像を平行移動させます。 |

  magick rose: -duplicate 29  -virtual-pixel tile \
          -distort SRT '0,0 1, 0, %[fx:w*t/n],%[fx:h*t/n]' \
          -set delay 10 -loop 0     rose_diagonal_roll.gif

[IM Output]
そしてここではインデックスに応じて画像を回転させますが、画像インデックスが0(最初の画像)の場合はより長い休止を生成します。 |

  magick rose: -duplicate 29  -virtual-pixel Gray \
          -distort SRT '%[fx:360*t/n]' \
          -set delay '%[fx:t==0?240:10]' -loop 0     rose_rotate.gif

[IM Output]
画像インデックス(「t」)は「0」から「n-1」までの値を持つので、式「%[fx:t/n]」は「0.0」から「1.0」のすぐ手前までの値を持つことに注目してください。これは上記のような繰り返しまたは循環するアニメーションには完璧ですが、ある画像から新しい画像へのトランジションを生成するにはあまり良くないかもしれません。その場合、最終フレームに乗数「1.0」を持たせたいので、式「%[fx:t/(n-1)]」を使います。これは、「%[fx:...]」計算で画像インデックスを使って今や簡単にできることの、ほんの一例にすぎません。より複雑な歪みで何が可能になるか想像してみてください。画像インデックス計算を使わなければ、上記は各フレームを個別に生成する外部シェルループと、フレームを集めて最終アニメーションを形成する別の手順が必要だったでしょう。そうしたループするシェルスクリプトの例は単純なワープ画像アニメーションにありますが、これはそれらの演算子が引数にパーセントエスケープを使えないからです。 | IM v6.6.9-0 より前では、「%p」「%n」「%[fx:t]」「%[fx:n]」のような画像インデックスを伴うパーセントエスケープFX パーセントエスケープは壊れていました。通常それらは「0」か「1」のいずれかという役に立たない値を返すだけで、現在の画像シーケンス内の実際のインデックスや画像数を返しませんでした。
---|---

ラベルを付加する - アニメーション全体にラベルを加える

いつも通り、画像にラベルを実際に付加する方法はいくつかあります。例えば、初期の背景キャンバスを持つアニメーションや、前のフレームに新しい色を重ねるだけのアニメーションでは、画像の最初のフレームにラベルを付加するだけで済みます。他のフレームはそれを除去しません。ここでは "[-splice](https://imagemagick.org/command-line-options/#splice)" で余分なスペースを少し加え、その中に "[-annotate](https://imagemagick.org/command-line-options/#annotate)" でテキストを描きます。 |

  magick canvas_prev.gif \
          \( -clone 0 -coalesce -gravity South -background white \
             -splice 0x18 -annotate 0 'Label First' \) \
          -swap -1,0 +delete   label_first.gif

[IM Output]
ただしこれは一部のアニメーションでしか機能しません。各フレームが表示された後にすべてのピクセルをクリアまたは置換する一般的なクリアフレームアニメーションでは機能しません。すべてのアニメーションで機能するより一般的な方法には、まずアニメーションを "[-coalesce](https://imagemagick.org/command-line-options/#coalesce)" して、最適化されていない結合済みアニメーションにする必要があります。そうすれば、再最適化する前に、結合済みのすべてのフレームにラベルを加えられます。 |

  magick canvas_prev.gif -coalesce \
          -gravity South -background white -splice 0x18 \
          -annotate 0 'A Better Label' \
          -layers Optimize labeled_anim.gif

[IM Output]
"[-annotate](https://imagemagick.org/command-line-options/#annotate)" を使って追加した余分なスペースにテキストを描く代わりに、合成メソッド(次のセクションを参照)を使ってそのスペースに画像を合成できます。そうすれば、アニメーションに加えるもっと洒落たラベルを準備できます。もちろん、これを行うと一部のアニメーション、特にクリアフレームアニメーションがその後あまり上手く最適化されなくなることがありますが、それがラベルを加える代償です。その種のアニメーションに対する1つの解決法は、クリアフレームアニメーションを説明したセクションで示したように、ラベルを含む「初期背景キャンバス」を先頭に付けることです。また、アニメーションにラベルを加えると多くの余分な色が追加される結果になることに注意してください。これは GIF の色数の上限を超えかねないので、アニメーションのカラー最適化も行う準備をしておく必要があるかもしれません。これは可能なら避けるのが一番の、とても難しい作業です(参照: カラー最適化)。これはどんなアニメーションへのどんな一般的な加工でも問題になり得ます。

透明を除去する - 単色の背景を加える

Web で見つかる多くのアニメーションは透明な背景を持っています。これらはとても便利で、存在するかもしれない背景パターンを気にせずに Web ページに配置できます。ただし、アニメーションを処理するとき、特に "[-resize](https://imagemagick.org/command-line-options/#resize)" や "[-blur](https://imagemagick.org/command-line-options/#blur)" のような他の画像演算子を適用するときには、そうしたアニメーションは問題を抱えます。一般的な解決法は画像から透明を除去することで、通常は何らかの形で特定の色、例えば Web ページの背景として使われる特定の色の上に重ねます。[IM Output] 例えば、ここには見えない手で描かれているかのように文字「K」が描かれる単純な透明オーバーレイアニメーションがあります。この GIF アニメーションは透明で描かれており、前のフレームに画像を重ねるだけ(ピクセルを追加するだけで、決して除去しない)なので、背景色(または画像)を設定する単純な方法は、それをアニメーションの最初のフレームにだけ加えることです。他のすべてのフレームは背景に透明色を含むので、結果に影響しません。ここでは平坦化(flatten)演算子を使って、アニメーションの最初のフレームを「LimeGreen」背景色の上に重ねます。単一の画像に適用するだけで、アニメーション全体ではないので、これに "[-flatten](https://imagemagick.org/command-line-options/#flatten)" を使えます。 |

  magick script_k.gif \( -clone 0 -background LimeGreen -flatten \) \
          -swap 0,-1 +delete      script_k_flatten_0.gif

[IM Output]
元の最初のフレームがわずか1ピクセルのサイズだったことにも注意するのが重要です。平坦化(flatten)演算子は背景に色を付けただけでなく、そのフレームをフルサイズに拡張しました。つまり、フレームを「埋めた」のです。ただし、アニメーションの最初のフレームだけが色付けされたことに注意してください。この方法は、(このアニメーションが含む重い最適化のような)あらゆる最適化が保持されるので推奨されます。最初のフレームに色を付けるのは、すべての GIF アニメーションで機能するわけではありません。単純なオーバーレイアニメーションでのみ機能します。アニメーションから透明を除去する一般的な方法には、まずアニメーションを "[-coalesce](https://imagemagick.org/command-line-options/#coalesce)" して、それからアルファ除去演算子を使って全フレームから実際に透明を除去する必要があります。今度はこれを「Tomato」背景色を使って行いましょう。 |

  magick script_k.gif -coalesce   -background Tomato -alpha remove \
          -layers Optimize   script_k_alpha_rm.gif

[IM Output]
もちろん、結果の最適化は元のものほど最適にならないかもしれませんが、アニメーションにはもう透明が一切含まれません。副作用として、アニメーション内のあらゆる「[Background](anim_basics.html#background)」dispose 設定が、フレーム最適化の処理によって、透明がもはや問題でなくなるので「[None](anim_basics.html#none)」か「[Previous](anim_basics.html#previous)」のいずれかに変換されています。 | アルファ除去は IM v6.7.5 で追加されました。お使いの IM バージョンがより古い場合は、境界(border)演算子の副作用を使うなどの代替方法を使う必要があります。これやその他の方法の詳細は透明を除去するを参照してください。
---|---
背景画像やパターンを下敷きにするようなより複雑な背景処理は、これまで見てきた単純な加工よりも、はるかに複雑なアニメーションの取り扱いを必要とします。これが次に見ていくことです。


複数画像のアルファ合成

次のレベルのアニメーション処理では、既存のアニメーションの上または下に単一の静的画像を合成できる必要があります。つまり、一般的なアルファ合成です。2つの別々の画像集合を統合する場合は、これはさらに厄介になります。IM v6.3.3-7 より前では、複数リストの合成は、特別に設計された API スクリプトか、アニメーションの個々のフレームを保存して統合するシェルスクリプトを使ってしか不可能でした。どちらもあまり良い技術ではありませんでしたが、それが可能なすべてでした。それが、今や変わったのです。

画像の描画 - 画像のリストに画像を描画する

"[-draw](https://imagemagick.org/command-line-options/#draw)" 演算子には、画像のリストの上に_ソース_画像を合成する能力があります。これはまた、IM v6.3.3-7 より前に "[mogrify](basics.html#mogrify)" コマンドで、または複数画像に対して使えた唯一の複数画像アルファ合成メソッドでもあります。このアルファ合成技術がこれほど重要だった理由は、現在の画像リストとは別の引数として画像を指定できたからです。つまり、"[-draw](https://imagemagick.org/command-line-options/#draw)" の引用符で囲まれたMagick ベクターグラフィック言語の中で、です。その歴史的重要性のため、特にまだ古いバージョンの IM を持つユーザーのために、その使い方を詳しく示します。例えば、ここではバラの画像をアニメーション全体に重ねます。 |

  magick canvas_prev.gif -coalesce \
          -gravity NorthEast  -draw 'image over 5,5 0,0 "rose:"' \
          -layers Optimize   draw_over.gif

[IM Output]
これにより、外部の_ソース_画像を現在の画像シーケンスのすべての画像の上に合成できます。これはほとんどの目的には十分です。例えば、「[Dst_Over](compose.html#dstover)」合成メソッドを使えば、画像を静的な背景としてアニメーションの「下」に配置することもできます。例えば、ここでは "netscape:" 組み込み画像を「下敷き」にしますが、どんな外部画像ファイルでも構いません... |

  magick script_k.gif -coalesce \
              -draw 'image DstOver 0,0 0,0 "netscape:"' \
          -layers Optimize   script_k_netscape.gif

[IM Output]
アニメーションのサイズが変わっていないことに注目してください。アルファ合成の最終サイズを定義するのは_デスティネーション_画像だからです。より大きなキャンバスを作りたい場合は、背景を収めるためにアニメーションのサイズとオフセットを適切に調整する必要がありました。例えば、結合(coalesce)する前にアニメーションの相対リページを使います。 |

  magick script_k.gif  -repage 100x100+20+20\!   -coalesce \
              -draw 'image DstOver 0,0 0,0 "granite:"' \
          -layers Optimize   script_k_granite.gif

[IM Output]
また、すでに読み込み・作成・加工された画像を使いたい場合は、その画像の「読み込みソース」を提供するために MPR: メモリプログラムレジスタを使う必要があります。 |

  magick -size 53x54 xc:SkyBlue -fill DodgerBlue \
          -draw 'circle 26,27 24,8' -write mpr:bgnd +delete \
          \
          script_k.gif -coalesce \
          -draw 'image DstOver 0,0 0,0 "mpr:bgnd"' \
          -layers Optimize   script_k_mpr_bg.gif

[IM Output]
それが、Draw によるアルファ合成メソッドの限界あたりです。アニメーション画像を、サイズが分からない_デスティネーション_画像の「上」に重ねることはできませんし、2つの別々の複数画像シーケンスを統合する方法もありません。それが、こうなるまでは...でした。

レイヤー合成 - 画像リストのアルファ合成

IM v6.3.3-7 で、2つの完全に別々の画像集合を合成できる "[-layers](https://imagemagick.org/command-line-options/#layers)" メソッド「**Composite**」が追加されました。(短い要約は画像のレイヤー化、レイヤー合成を参照してください)これをコマンドラインで行うには、最初の_デスティネーション_画像のリストが終わり、重ねられる_ソース_画像のリストが始まる場所を定義する特別な「[null:](files.html#null)」マーカー画像が必要です。しかしそれがこの方法の唯一の本当の複雑な点です。では、画像の集合から影の集合を作り、その影画像の上に元の画像を重ねて、試してみましょう... |

  magick script_k.gif -coalesce  coalesced_k.gif

  magick coalesced_k.gif  -background black -shadow 100x3+2+5 \
          -background SkyBlue -alpha remove    shadows_k.gif

  magick shadows_k.gif  null:  coalesced_k.gif \
          -layers Composite          compose_shadow.gif

  gif_anim_montage compose_shadow.gif compose_shadow_frames.gif

[IM Output]
[IM Output]
[IM Output]

[IM Output]

上記の例はとても重要なので、詳しく説明します。まず、アニメーションに存在するかもしれない最適化を取り除いて、GIF 最適化が処理を妨げることなく、本格的な処理の準備ができるよう、アニメーションの結合済みバージョンを生成します。次に、結合済みアニメーションからアニメーション化された影画像を作り、透明を除去します。GIF は半透明の影を扱えないからです。これが、元のアニメーションの「下」に加えたいアニメーションです。これは同じ数のフレームを持ち、元のアニメーションと同じタイミングさえ持っています。この対応関係は重要なので、忘れないでください。さて、2つのアニメーションまたはレイヤーシーケンスを読み込みますが、その間に特別な「[null:](files.html#null)」画像セパレータを加え、ImageMagick が1つのシーケンスが終わり次のシーケンスが始まる場所を分かるようにします。この画像セパレータは、次の重要な "-layer composite" 演算によって自動的に除去されます。他の API は、特別なセパレータを持つ単一のシーケンスではなく、別々の画像の「Wand」を使えるはずです。レイヤー合成は、これら2つのアニメーションまたは画像シーケンスがあたかも複数画像のシーケンスではなく単純な単一画像であるかのように行われます。各画像のペア、1つのデスティネーションと1つのソースが合成され、統合(合成)されたシーケンスの画像を生成します。最終結果として、元のアニメーションシーケンスに影が加わり、GIF 最適化、または直接の使用の準備ができます。
さて、上記のすべての手順を1つのコマンドで行えます。ただし、元のシーケンスのコピーを作るのに単純に "[-clone](https://imagemagick.org/command-line-options/#clone)" を使うことはできません。なぜなら、シーケンスに何個の画像があるかを本当には知らない(し知りたくない)からです。代わりに、画像のリスト全体を保存するために MPR: メモリプログラムレジスタを使えます。これは現在メモリにある画像シーケンス全体のスナップショットを撮り、後でそれを再び読み込むようなものです。結果は次のようなコマンドになりますが、私は異なる色の背景を使いました。 |

  magick script_k.gif -coalesce -write mpr:images \
          -background black  -shadow 100x3+2+5 \
          -bordercolor Wheat -border 0 \
          null:    mpr:images    -layers Composite \
          magick composite_shadow.gif

[IM Output]
このバージョンは実際にはより良く機能します。影(shadow)演算子が生成するオフセット情報を失わなかったからです(GIF は負のオフセットを保存できないので、ゼロにリセットします)。上記で、中間画像に GIF ではなく MIFF ファイル形式を使えばこれを修正できますし、次の例で見るように "[-geometry](https://imagemagick.org/command-line-options/#geomtry)" 合成オフセットを使っても修正できます。基本的にこれらの例は、レイヤー合成演算子が実際には個々の仮想キャンバスオフセット("[-page](https://imagemagick.org/command-line-options/#page)" 設定)を理解し、レイヤー平坦化(flatten)や、さらに良くはレイヤー統合(merge)演算子が扱うのと同じようにそれらを扱うことを示しています。しかしレイヤー合成演算子は、合成画像シーケンス全体の配置を制御する合成ジオメトリ("[-geometry](https://imagemagick.org/command-line-options/#geometry)" オフセット、デフォルトはゼロ)の使用も理解します。そのグローバルなオフセットに対する "[-gravity](https://imagemagick.org/command-line-options/#gravity)" の効果さえも理解します。例えば... 元の「K」アニメーションを、生成された影アニメーションの「南(South)」に重ねてみましょう... |

  magick shadows_k.gif  null:  coalesced_k.gif  \
          -geometry +0-10 -gravity South  -layers Composite \
          magick composite_south.gif

[IM Output]
上記はまた、通常の2画像のアルファ合成と同様に、最終出力画像のサイズを制御するのはデスティネーション画像シーケンスであり、あらゆる合成オーバーレイはデスティネーションキャンバス画像にクリップされることを示しています。そのため、すべてのデスティネーション画像が最終結果を収められるよう十分大きいことを確認すべきです。 | "[-geometry](https://imagemagick.org/command-line-options/#geometry)" のリサイズ機能は厳密には合成演算の一部ではなく、現在の画像シーケンスの最後の画像をリサイズするだけです。そのため、複数画像のレイヤー合成で使うと期待通りには動作しません。詳細はリサイズジオメトリを参照してください。
---|---
基本的にレイヤー合成は通常の合成にとてもよく似ています。
実に単純です。単純と言いましたか?
レイヤー合成の詳細......上記で見たように、コマンドライン版の "[-layers](https://imagemagick.org/command-line-options/#layers) Composite" は、現在の画像リストで見つかった最初の「[null:](files.html#null)」画像を、2つのリストを分けるマーカーとして使います。2つの画像リストが分離され、「null:」が破棄されてから、2つのリストが一度に2画像ずつアルファ合成されます。マーカーには特別な「[null:](files.html#null)」画像ソースから生成された画像のみが使え、見つからなければエラーが報告されます。現時点ではこの「[null:](files.html#null)」マーカー画像をパイプライン(少なくともこの時点では)から読み込むことはできず、必要なときに生成するだけです。レイヤー合成はまた、単純な2画像のアルファ合成よりもむしろ複雑です。画像リストの画像の仮想キャンバスも考慮されるからです。通常、アルファ合成は配置の目的では仮想キャンバスのサイズやオフセットを無視し、画像の実際のサイズだけを使います。この特別なレイヤーメソッドは、2つの画像シーケンスを揃えるために、ジオメトリ配置のために仮想キャンバスの情報を使います。そのために、サブフレームが持つあらゆる仮想キャンバスオフセットも、通常の "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 調整された "[-geometry](https://imagemagick.org/command-line-options/#geometry)" 合成オフセットに加えられて、画像オーバーレイの位置を算出します。"[-geometry](https://imagemagick.org/command-line-options/#geometry)" 合成オフセットへの "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 調整を算出するのには、各リストの最初の画像の仮想 "[-page](https://imagemagick.org/command-line-options/#page)" キャンバスサイズのみが使われます。後の画像のキャンバスサイズは無視され、個々の仮想 "[-page](https://imagemagick.org/command-line-options/#page)" オフセットだけが算出された "[-geometry](https://imagemagick.org/command-line-options/#geometry)" オフセットに加えられます。言い換えれば、"[-layers](https://imagemagick.org/command-line-options/#layers) Composite" は「レイヤー」や「アニメーション」のアルファ合成と、そうした画像リストの特別な要件のために設計されています。注意点...とはいえ、重ねる画像リストには依然として注意する必要があります。例えば、_デスティネーション_リストの画像が、重ねられる_ソース_画像を収めるのに十分大きくない、または不正確に配置されていると、重ねられる画像はクリップされるか、デスティネーション画像を完全に外してしまいます。このため、より小さな_ソース_画像を重ねる前に、_デスティネーション_画像をフルキャンバスサイズに結合(coalesce)するのが良い考えです。例えば、下記の横並びアニメーション連結の例を参照してください。そこではキャンバスサイズを拡張して連結する画像のためのスペースを設ける必要がありました。また、_ソース_画像リストが GIF アニメーションの場合は、サブフレームが圧縮最適化や凝ったフレーム最適化のようなものから綺麗になっていることを確認する必要があるかもしれません。さもないと問題が起きるかもしれません。一方、クリアフレームアニメーション結合済みアニメーションは、何の問題もなく直接「[Composite](#composite)」できます。ただ、レイヤー合成は画像に存在するかもしれない既存のGIF 廃棄(disposal)メソッドを理解しないことを覚えておいてください。とはいえ、廃棄(dispose)メソッドフレームディレイ反復ループの上限のような_デスティネーション_GIF アニメーションのメタデータは保持します。その唯一の例外は下記の特別なケースで挙げます。

単一画像合成 - 単一の画像で画像を合成する

通常、長さの等しい2つの画像のリストが、どちらかの画像リストが尽きるまで、一度に1つの画像ペアずつ合成されます。どちらの画像リストも繰り返されません。合成は単に止まります。追加された合成を伴う、元の_デスティネーション_画像リストだけが残ります。「[null:](files.html#null)」セパレータ画像と、すべての_ソース_画像が現在の画像リストから削除されます。 このレイヤーメソッドへの API インターフェースでは、2つの別々の画像リストを生成でき、結果の画像リストを生成するのに使った両方の入力画像リストを削除するのはあなたに委ねられるべきです。「[null:](files.html#null)」セパレータは必要ないはずです。
ただし、リストの一方が単一の画像しか含まない場合は、その画像が他方のリストのすべての画像に対して合成されます。その単一画像が_ソース_画像であろうと_デスティネーション_画像であろうと関係ありません。このメソッドは他方の画像リストに対して合成を行い、たとえその画像が_デスティネーション_画像であっても、単一画像ではなく_画像リスト_の GIF メタデータを保持します。この「単一画像に対する合成」はレイヤー合成の特別なケースで、アニメーションに背景を加える(次を参照)、またはアニメーションに静的なオブジェクトを挿入するのにとても便利です。

静的背景 - より大きな背景の上に合成する

例えば、この特別な単一画像レイヤー合成メソッドを使うと、アニメーションを静的な背景の上に合成できます... |

  magick -size 100x100 plasma:fractal null: \( script_k.gif -coalesce \) \
              -gravity Center   -layers Composite \
          -layers Optimize   magick composite_background.gif

[IM Output]
背景画像が_デスティネーション_なので、アニメーションの最終サイズを定義しますが、すべてのメタデータ(ディレイ、ラベル、コメントなど)はソース画像リストから来ます。通常、その情報はデスティネーション画像リストから来ます。これは画像合成中にソース画像がメタデータ情報を提供する唯一のときです。また、レイヤー合成は "[-gravity](https://imagemagick.org/command-line-options/#gravity)" を理解するので、あなた自身が計算する必要なく画像が適切に中央寄せされることに注目してください。ただし、ソースフレームがオフセットを含む場合は、それらも gravity で定義された位置に加えられ、すべてのサブフレームの相対位置が正しく保たれます。アニメーション "[script_k.gif](../static/img/images/script_k.gif)" は実際には一種のオーバーレイアニメーションなので、アニメーションに静的な背景を加える代替方法があることに注目してください。例については上記の透明を除去するのセクションを参照してください(単色の上に、ですが、どんな画像でも構いません)。これはより単純なクリアフレームアニメーションについても同様です。その場合は、まずアニメーションを結合(coalesce)する必要さえなく、背景画像の上に直接合成できます。ただし、その後で使われている「dispose」メソッドを "[-set](https://imagemagick.org/command-line-options/#set)" する必要があるかもしれませんし、より良くは完全結合済みアニメーション最適化する必要があるかもしれません。一方、他のあらゆる種類の最適化されたアニメーションは、その "[-coalesce](https://imagemagick.org/command-line-options/#coalesce)" 演算と、すべてのアニメーションフレームでの完全な合成を必要とします。そのため、すべての GIF アニメーションが正しく扱われることを確実にするには、おそらく上記の方法を使う方がよいでしょう。


輝くものすべて...

グリッターアニメーション

上記のレイヤー合成メソッドは、グリッターのような単純なアニメーションの生成をかなり簡単にします。まず、処理する画像を覆うのに十分大きなグリッターが必要です。ここでは、いくつかのランダムスペックル画像から3画像のグリッターアニメーションを生成します。まずこれは純粋な透明の上の生の白黒グリッターで、3つの色チャンネルを白黒のチャンネル画像に分離することで3フレームのグリッターを生成します。これは基本的に、他のあらゆる種類のグリッターを生成するための生の出発点です。「30%」しきい値は、フレームあたりに「点」がいくつあるかを制御します。 |

  magick -size 100x100 xc: +noise Random -separate \
          null: \( xc: +noise Random -separate -threshold 30% -negate \) \
              -compose CopyOpacity -layers composite \
          -set dispose background -set delay 20 -loop 0   glitter_overlay.gif

[IM Output]
この「生の」グリッターから、「[Screen](compose.html#screen)」アルファ合成を使って重ね、一部の色だけを明るくして、特定の色のグリッターを生成できます。ここでは境界平坦化メソッド(上記)を使います。ただの無地の色... |

  magick glitter_overlay.gif \
          -compose Screen -bordercolor GoldenRod -border 0x0  glitter_gold.gif

[IM Output]
レイヤー合成を使えば、単一の画像、あるいは複数の画像を使って、変化のある色付き背景を提供することもできます。例えば、ここでは3つのフラクタルプラズマ画像を生成して、グリッターパターンにわずかにランダム化された色付けを提供します。 |

  magick glitter_overlay.gif null: -size 100x100 \
          plasma:red-firebrick plasma:red-firebrick  plasma:red-firebrick \
          -compose Screen -layers composite    glitter_plasma.gif

[IM Output]
もちろん、他にもたくさんのグリッターのスタイルや動きのパターンがあります。WWW からそうしたグリッタータイルをたくさん見つけてダウンロードできます。このようなグリッターを画像に適用するには、いくつかの異なる方法があります。通常は、グリッターを特定の形状や背景にマスクします。これには、透明な形状(DstInを使って合成)を使えます。

  magick -size 100x100 -fill white -background none -font Candice \
          -gravity center -pointsize 90 label:A   glitter_mask_trans.gif
  magick glitter_plasma.gif null: glitter_mask_trans.gif -alpha set \
          -compose DstIn -layers composite        glitter_masked_trans.gif

[IM Output] [IM Output]

または、白黒のマスク画像(CopyOpacityを使って合成)を使います。

  magick -size 100x100 -fill white -background black -font Candice \
          -gravity center -pointsize 90 label:A    glitter_mask.gif
  magick glitter_plasma.gif null: glitter_mask.gif -alpha off \
          -compose CopyOpacity -layers composite   glitter_masked.gif

[IM Output] [IM Output]

さて、マスクされた領域ができたので、通常はマスクされたグリッターを元の画像の上に重ねることで画像を完成させます。ただし、ここでは背景を下敷きにし、境界を上に重ねます。 |

  magick glitter_masked.gif -size 100x100 \
          null: gradient:gold1-gold4 -compose DstOver -layers composite \
          null: \( -fill none -background none -stroke white -strokewidth 2 \
                   -font Candice -gravity center -pointsize 90 label:A \) \
              -compose over -layers composite      glittered_letter.gif

[IM Output]
この最後の例は、最終画像からすべての透明を除去し、グリッターのかかった領域の周りに滑らかな境界を重ねることで、あらゆる GIF 透明の問題も片付けました。 | 上記では、処理の個々の段階を magick display で表示できるよう GIF 形式画像を使ったかもしれませんが、実際には、すべての段階を1つのコマンドにまとめるか、MIFF のようなより良い中間画像ファイル形式を使うでしょう。つまり、完了するまで GIF 形式が持つ固有の問題を避けるためにそうするのです。
---|---

グリッタータイル - 「画像の穴」による下敷き

述べたように、WWW で利用できる事前準備されたアニメーション化グリッタータイル画像はたくさんあります(「glitter tiles」で検索してみてください)。1つの情報源は IM Studio のユーザー scri8e 氏と彼の Web サイト Moons Stars です。ただし、ほとんどのグリッタータイルはかなりひどい見た目だったり、速すぎたりすると私は感じることに気をつけてください。 この例では、小さな星のパターンが入った青いグリッタータイルを見つけて加工しました。IM ウィザードにきらめく衣装を与えて、本当に魔法のように見せるのに役立つと思いました。既存の画像にグリッターをかける、おそらく最も簡単な方法は、グリッターパターンをマスクで切り抜こうとするのではなく、画像に穴を開けることです。ただしこれは、最初から透明を含まない画像でしか機能しません。あるいは、画像から透明を除去し、完了したら元の透明を再付加することもできます。では、IM 使用例のロゴを取り、色の置換を使って画像のすべての青い部分を切り抜きましょう。ウィザードに透明マントを与えるようなものです ;-)

  magick logo.gif -alpha set -fuzz 33% -transparent blue logo_holed.gif

[IM Output] [IM Output]

青色をどれだけ除去すべきかを調整するためにファズ係数を使っていることに注目してください。ただし、これはエイリアスのかかった縁を生むので、画像の領域を切り抜く良い方法ではないことに気をつけてください。しかし、単純なぼかしの効いた切り抜き機能は今のところまだ利用できません。さて、穴(またはたくさんの穴)のある画像ができました。次の手順はグリッタータイル画像を下敷きにすることです。問題は、上記のタイルが小さすぎて、画像全体を覆えないことです! 以下は、複数画像のグリッタータイルをタイル状に並べる巧妙な技術を使います。ただし、画像を完全に覆えるよう、元の画像より大きなサイズを与える必要があります。 |

  magick glitter_blue.gif -virtual-pixel tile \
          -set option:distort:viewport 180x180 -distort SRT 0 \
          glitter_blue_tiled.gif

[IM Output]
では、上記のタイル状に並べたグリッターを「穴あき」画像の下に置いて、ウィザードに新しい服を着せましょう。 |

  magick logo_holed.gif null: glitter_blue_tiled.gif \
          -compose DstOver -layers composite \
          -loop 0 -layers Optimize logo_glittered.gif

[IM Output]
もちろん、これらの手順をすべて1つのコマンドで行えます。ここでは穴の生成を、2つの別々の特定部分を持つウィザードのマントだけに限定します。 |

  magick logo.gif -alpha set -fuzz 10% -fill none \
          -draw 'matte 120,150 floodfill  matte 150,120 floodfill' \
          null: \( glitter_blue.gif -virtual-pixel tile \
            -set option:distort:viewport 300x300 -distort SRT 0 \) \
          -compose DstOver -layers composite \
          -loop 0 -layers Optimize logo_glitter_cloak.gif

[IM Output]
上記の穴は、色の置換のために画像から実際の点と色を選ぶMatte Fill 描画プリミティブを使って作られました。これはつまり、元々行ったほど高いファズ係数を使う必要がないということです。比較対象の色が、選択された特定の領域から来ているからです。また、タイル状に並べる画像の正確な寸法を知る必要なく完全に覆えるよう、より大きなタイリング「ビューポート」を使いました。 | _一般歪み演算子とその特別な「viewport」オプション(IM 6.3.6-0 で追加)を使うことで、歪みパターンを他の特別な方法で加工する機会も得られます。例えば「遠近感」のある見た目を与えたり、パターンを非矩形の角度に回転させたりです。これを行うと、タイリングがそれほど均一な見た目にならないよう強化できます。

いくつかの例についてはアフィンタイリングを参照してください。_
---|---

スパークル - ほぼ透明なグリッターを重ねる

前述の2つのグリッターアニメーション技術の大きな問題は、それが全か無かの種類の置換であることです。画像の元のシェーディングや背景を使うことができません。また、グリッターはマスクされた領域に完全に制限されます。関係する領域の境界を超えて広がることはできません。そのため、前の例のウィザードの「帽子」のような一部の小さな領域は、グリッターをあまり上手く扱えません。スパークルは異なり、追加されるアニメーションがほぼ透明です。その結果、元の画像が依然として透けて見えます。そうしたアニメーションは通常、2つの方法のいずれかで画像に追加されます。アニメーションオーバーレイそのものが透明であるか、画像を明るくすべき場所に白い「火花」のある黒い背景の形であるかです。

作成中

こちらはほぼ透明な「スパークル」オーバーレイの例です。ここに例 ご覧の通り、この形を使うとカラフルなスパークルオーバーレイができます。これの大きな問題は、(通常そうであるように)保存に GIF アニメーションが使われたため、オーバーレイが激しくエイリアスされることです。つまり、重ねられた画像の見た目を滑らかにする半透明のピクセルを一切含めません。もし含んでいたら、最終結果のスパークルの周りにひどい黒いハローが出てしまうでしょう。これをウィザードにマスクして重ねてみましょう。ここに例 もう1つのスパークルの形は、黒い背景の上の白いスパークル(グレースケール画像)です。これらはマスクされ、画像を明るくしてスパークルを加えるよう重ねられます。例えば... ここに例 スパークルの最も良い点の1つは、スパークルがゆっくり現れてから消える一連のフレームを生成できることです。これはかなり複雑になり得ますが、行うのはそれほど難しくありません。ここに例

フレアとスターのアニメーションを加える

グリッターが単一の明るい点で構成され、スパークルが画像の一部の領域を覆えるのに対し、フレアは通常個別に追加されます。「フレア」は基本的に、ほんの一瞬だけ広い領域を覆うように閃く点です。「スター」は似ていますが、覆い方がより「光線」状の明るさの形です。これらは通常、特定の点から「種付け」されますが、結果はしばしば、少なくとも一瞬は種付けの領域をはるかに超えて広がります。例えば、特定の領域にマスクで限定されたフレアは、とても間抜けで不自然に見えます。フレアのより難しい側面は、良い「種」の点を見つけることと、複数のフレアのタイミングを適切にとることです。

作成中

私が作りたい最後の例... ウィザードの杖を「スパークル」が登っていき、
そしてフレアし、ある領域の上で多数の小さなスパークルフレアへと溶けていく。
そしてその一連の動きが繰り返される。

アニメーションのリサイズ

アニメーションのリサイズの問題

GIF アニメーションをリサイズする最大の問題は、"[-resize](https://imagemagick.org/command-line-options/#resize)" 演算子が、結果の画像を(リサイズ後に)できるだけ理想に近くするよう特別に設計されていることです。これは、画像内の色を統合したりたくさんの追加の色を生成したりして、見た目を良くすることで行われます。結果の画像は、限られた GIF ファイル形式に保存するには理想から程遠いものです。GIF の限られたカラーテーブルでは、これはリサイズされた画像で重い色の削減を引き起こします。単一の GIF 画像ではそれほど悪くありませんが、GIF アニメーションでは、削減された色集合のデフォルトのエラー補正ディザリングが、フレーム間の「ディザノイズ」という問題と、ひいては最終ファイルサイズのための悪いフレーム最適化を生み出します。透明色も使われている場合はさらに悪くなり、これは Web ページに使われる典型的な GIF アニメーションでよくある慣行です。透明はまた、本来は必要としないアニメーションのための圧縮最適化技術にもよく使われます。何が起きるかというと、"[-resize](https://imagemagick.org/command-line-options/#resize)" がオーバーレイ画像に半透明のピクセルを生成します。そして画像が GIF ファイル形式に保存し戻されるとき、これらのピクセルは完全に透明か完全に不透明のいずれかに変換され、どちらも結果のアニメーションに大きな色の歪みを生み出します。何らかの形の最適化(フレーム、透明、または LZW)が使われると、透明の効果が基本的に悲惨にリサイズされた GIF アニメーションという結果になります。それが、事実です。なので、それと付き合っていく必要があるでしょう。"[-sample](https://imagemagick.org/command-line-options/#sample)" を使うことで "[-resize](https://imagemagick.org/command-line-options/#resize)" を避けたとしても、まずアニメーションを "[-coalesce](https://imagemagick.org/command-line-options/#coalesce)" しなければ依然として大きな問題を抱えます。

アニメーションのリサイズ手法

上で示したように、GIF アニメーションのリサイズには深刻な問題があり、そのどれも簡単には解決できません。解決法はまた、そもそもリサイズされた画像がどんな種類だったか、漫画のようなものか、実世界のビデオ画像かに、一般的に依存します。こちらは私が知っている、または寄稿された手法です...

リサイズを避ける

可能であれば、リサイズしないでください。例えば、必要なスペースに収まるよう、アニメーションをただ切り詰めるためにキャンバスまたはビューポート切り抜きできます。あるいは、そもそも GIF アニメーションを正しいサイズで生成できます。どちらの技術も通常は最良の選択肢ではありませんが、できるなら検討してください。多くの問題と髪をかきむしる苦労から救ってくれます。

直接のリサイズ

述べたように、"[-resize](https://imagemagick.org/command-line-options/#resize)" を直接使うと、各フレームの色数か、半透明の色のいずれかで問題が起きます。例えば、これはとてもひどくなります... |

  magick script_k.gif -resize 20x20 script_k_direct.gif

[IM Output]
[IM Output]
さて、これはあまり上手くいきませんでした。それは元の画像が重いフレーム最適化を持っているからです。アニメーションの各「フレーム」は同じサイズではなく、"[-resize](https://imagemagick.org/command-line-options/#resize)" は各フレーム画像を他の画像とは完全に別々にリサイズします。つまり、上記は実際のフレーム画像をリサイズしたのであって、アニメーションの仮想キャンバスを与えられたサイズにリサイズしたのではありません。実は、結果のアニメーションが、示された空白の領域だけよりもっと「めちゃくちゃ」にならなかったことに驚いています。これがアニメーションのリサイズについての最初の点につながります。まず、すべてのフレームが完全に定義され、すべての最適化が除去されていることを確認してください。言い換えれば、リサイズしようとする前にアニメーションを結合(coalesce)してください。例えば... |

  magick script_k.gif -coalesce  -resize 20x20  script_k_direct2.gif

[IM Output]
[IM Output]
次の問題は透明色のものです。上記の結果を見ると、より小さなアニメーションの縁がひどくエイリアスされている(「階段状」になっている)のが分かるでしょう。それは、GIF が "[-resize](https://imagemagick.org/command-line-options/#resize)" 演算子が生成した半透明の色を保存できないからです。アニメーション化されたオブジェクト内の色も、新しい色を生み出すよう統合されていますが、それは通常、縁のエイリアスほどはひどくありません。

平坦化を伴うリサイズ、一般的な解決法

GIF サムネイルを生成するときの最良の考えは、透明の問題を完全に避けることです。つまり、アニメーションのリサイズの前か後にアニメーションを平坦化します。そうすれば、リサイズされた画像の縁の「アンチエイリアス」を失わずに済みます。実際、ほとんどの良い GIF アニメーション Web サイトは、GIF アニメーションのサムネイルを生成するときにまさにそうしているのを見つけました。もちろん、サムネイルはその後、特定の色付き背景での使用、通常は「白」、でも時には「黒」、または「シルバー」(Web ページのグレー)に制限されますが、最後のものは最近ではあまり一般的ではありません。例えば、ここではこの Web ページに適した背景色で、より小さなサムネイルを作ります。 |

  magick script_k.gif -coalesce \
          -bordercolor LightSteelBlue -border 0 \
          -resize 20x20  -layers Optimize   script_k_thumbnail.gif

[IM Output]
[IM Output]
これが一般的な GIF サムネイル処理に推奨される解決法です。他のどの方法も、人間による制御か、とても洗練された GIF サムネイル処理ロジックのいずれかを必要とします。

カラーテーブルの破裂

(このセクションの最初で述べたように)最大の問題は、画像に膨大な数の余分な色が生成されることで、特に線や隣接する色領域の縁の近くで生成されます。画像の縁の周りに、半透明の色のリサイズハローも出ます。これがひいては、単純な最小限の色のアニメーションに必要なカラーテーブルのサイズを拡大し、それがひいては、リサイズされた単純なアニメーションが保存されるときにより大きなファイルサイズを意味します。さらに悪いことに、リサイズされたアニメーションの各フレームが、おそらく異なる色集合を生成し、「サムネイル化」されたアニメーションのファイルサイズをさらに拡大します。カラー量子化の後、元のアニメーションと同じ特定の色をもはや持たないかもしれないという問題もあります(参照: 量子化は色を保持しない)。つまり、純粋な白の単純な領域を持つ代わりに、今や少し白っぽくない領域を持つかもしれません。

Sample を使ったリサイズ

リサイズ時に余分な色を生成するのを避ける最も単純な方法は、アニメーションをリサイズするのではなく "[-sample](https://imagemagick.org/command-line-options/#sample)" することです。これはアニメーションの現在の色を保持し、新しいサイズでアニメーションを簡単に再最適化できるようにします。 |

  magick script_k.gif -coalesce  -sample 20x20  script_k_sample.gif

[IM Output]
[IM Output]
ただし、これは機能するものの、基本的に画像からピクセルの行と列を除去しているので、その過程で画像データ、ひいては品質を失います。漫画のような画像では、これはしばしば「点々とした」境界や、欠落または歪んだディテールを残します。リサイズがアニメーションの元のサイズの50%を超える場合は、上記のケースのように、結果はしばしばかなりひどくなります。特にテクスチャや他の色パターンがアニメーションに使われているときはそうです。多くの GIF アニメーションライブラリが、ネット中からコピーしたそうしたひどい sample でリサイズされたアニメーションで埋め尽くされているのも不思議ではありません。そういったゴミを片付けてくれればと私はよく思いますが、それは提供される GIF の数を減らすことを意味し、それがひいては利用可能な GIF 数のマーケティング統計を減らし、広告部門はそれを好みません。その結果、ひどい GIF アニメーションがありふれています。

Liquid Resize を使ったリサイズ

上記の Sample メソッドを使うのに似た方法として、Seam Carving としても知られる Liquid Rescale を使う方法があります。これも、関係する画像から丸ごとのピクセルを除去または追加しますが、画像の複雑さをできるだけ多く保持する方法でそうしようとします。上記のリンクを見て、より良いリサイズ画像を生成するためにそれをどう使えるかを確認してください。残念ながら、現時点ではこれを一般的なアニメーション画像に使う方法はありません。これは画像の複雑さの理解を持たず、リスケーリングのメソッドを抽出してアニメーションの各フレームに一貫した方法で適用することが現在できないからです。願わくは、これが将来のどこかの時点で変わってほしいものです。

リサイズして色を復元する

アニメーションを Sample すると、ピクセルの行と列が除去されるだけで、細い線やその他の重要なディテールが除去される可能性があります。しかし "[-resize](https://imagemagick.org/command-line-options/#resize)" を使ってピクセルを統合すると、GIF 形式には多すぎる新しい色を生み出します。なので明らかな解決法は、"[-resize](https://imagemagick.org/command-line-options/#resize)" を行い、その後でカラーマップを使って、元のアニメーションの色を使ってリサイズされたアニメーションの色を復元することです。

FUTURE: 元のカラーテーブルを復元する例

これにはローカルカラーテーブルを生成しないという追加の利点があります。ただし、結果は「ディザノイズ」を避けるためにディザをオフにした方が良いかもしれません。これは、大きく滑らかに色付けされた領域を持つ漫画のような画像では特に当てはまります。

FUTURE: ディザなしでカラーテーブルを復元する例

フルカラー最適化

ひどい sample 化されたサムネイルが気に入らない場合は、リサイズされた GIF アニメーションのフルカラー最適化を行うという見通しに直面します。アニメーションに保持させたい「新しい」色がちょうど何かを整理するためです。ただしこれは、ほとんどのアニメーションではしばしばそれほど悪くありませんが、ビデオから GIF アニメーションへの変換のような、より複雑なアニメーションでは大きな労力になり得ます。つまり、漫画のようなアニメーションを扱っている場合は、今や激しくアンチエイリアスされた線と縁を持つことになります。透明な背景を伴うアニメーションでは、これもリサイズのアンチエイリアス機能によって生じる、アニメーションの縁の周りの半透明のピクセルを適切に扱う必要もあります。これを扱うのに使える多くの方法については、GIF ブール透明のセクションを参照してください。

大きなリサイズ縮小

大きなアニメーションをはるかに小さなアニメーションにリサイズしようと計画するとき、アニメーションの重要な部分が消えてしまう問題に直面します。これは実は、アニメーションだけでなく静的な画像でも問題です。これに対する既知の解決法については線画のリサイズを参照してください。
さらなる提案、アイデア、技術は大歓迎です。


複数のアニメーションを統合する

以前にも言いましたが、アニメーションを統合するときには特に重要になります...

扱っているアニメーションについて、できる限り多くを知りましょう!

"[gif2anim](../static/img/scripts/gif2anim)" スクリプトはこの目的に理想的です。その姉妹スクリプト "[anim2gif](../static/img/scripts/anim2gif)" も、元の設定を使ってアニメーションを再作成するためにここでよく使われます。(このスクリプトの基本的な使い方はアニメーションリスト情報を参照してください。)アニメーションがどう機能するかの知識なしに、それらを様々な方法で統合するのはほとんど不可能です。これを行うプログラム(これらの例の究極の目標)を開発できます。しかし、そうしたプログラムはしばしばとても複雑で、予期しない結果を生み出すことがあります。このため、これらの例に依然として従うべきです。アニメーションがどう扱われ統合されるべきかについて、大きな洞察を与えてくれるからです。

直列(時間方向)の連結

ある1つのシーケンスが別のシーケンスに時間方向で続くよう、2つの GIF アニメーションを連結するのは IM では単純です。基本的にコマンドラインに並べるだけで、互いに続きます。しかし、見た目ほど簡単ではないかもしれません。例えば、Web をいくらか探した後、文字が描かれるアニメーションをいくつか見つけました(まあ、この例のために盗んで大幅に加工しました)。さて、これらの画像を、誰かが「OK」という単語を書いているかのように、1つのアニメーションが完了すると次のが始まるよう結合したいと思います。こちらが文字、「アニメーションシーケンス」、そしてこれら2つのアニメーションの内部の詳細です。 | |

  gif2anim -n script_o.gif
  gif2anim -n script_k.gif

| [IM Text]

| | [IM Text]

[IM Output]
[IM Output]
これらのシーケンスは空のキャンバスから始まり、そのキャンバスにゆっくりとピクセルを追加・加工するだけです。前のフレームで追加されたピクセルを、除去・クリア・透明化することは決してありません。ただし、私たちの目的では、それらがそうするかどうかは問題ではありません。結果にほとんど影響しないからです。アニメーションのフレーム数も、この演算に影響しません。知ることが重要なのは、フレームのタイミングです。これが問題を生み出すことがあるからです。特に、最初の、この場合は最後のフレームのタイミングディレイに注目してください。この技術はとても一般的で、アニメーションがクリアして再開する前に、最終結果を見る時間を視聴者に与えます。時間方向の連結を行うときに私たちに問題を引き起こすのは、これらのディレイとフレームです。また、「k」アニメーションがアニメーションシーケンスの中ほどに少しディレイを持つことにも注目してください。このディレイは、このアニメーションの最初の筆運びと2番目の筆運びの終わりを表しています。このディレイも保持する必要があり、つまりアニメーションのすべての時間シーケンスを一定の値に変えることはできない、ということです。上記に示されていないことですが、両方のアニメーションの最初のフレームは実は空白のキャンバスです。おそらく2番目のアニメーションのそのキャンバスは時間の無駄として捨てたいでしょうが、1番目のアニメーションでは開始ディレイとして保持すべきです。さて、2つのアニメーションを調べたので、1つが時間的に他に続くよう結合してみましょう。アニメーションの時間方向の連結は実はとても単純な演算で、ただ2つのアニメーション画像をコマンドラインに並べるだけです。では、それをただ試してみましょう... |

    magick script_o.gif script_k.gif   script_ok_try1.gif

[IM Output]
さて、結果は完璧から程遠いものでした。文字は正しい順序で描かれますが、互いに重なっています! それだけでなく、1番目の「o」アニメーションが2番目の「k」アニメーション(53ピクセル)より細い(40ピクセル)ので、最後の「k」文字の一番最後の部分が、その小さなフレーミングのキャンバスサイズによってクリップされてしまいます。2番目のアニメーションの位置は、上で示したように相対リページを使って動かせます。この再配置の方法は、そのアニメーションに存在するかもしれない既存のオフセットを保持し、それらすべてを単一の関連したグループとして移動させるだけです。この場合、これは高度に最適化されたアニメーションなので、ほぼすべてのフレームが既存のオフセットを持っています。このずらした位置に対応し、2番目のアニメーションが「クリップ」されるのを避けるために、アニメーション全体のキャンバスサイズも拡大する必要があります。最初のアニメーションまたはフレームを読み込む前にキャンバスサイズを変更すると、アニメーションが動くキャンバス領域が拡大され、「K」がクリップされるのを防ぎます。 |

    magick -page 90x54 script_o.gif \
            \( script_k.gif -repage +37+0\! \)   script_ok_try2.gif

[IM Output]
結果は大幅な改善です。ただし、文字の描画の間のディレイが今やはっきりと目立ちます。私たちが欲しいのは、1番目の「O」アニメーションの最後のフレームのもっと小さなディレイです。見えない画家がペンを再配置しているように見えるくらいの大きさで十分です。これを行うために、1番目のアニメーションのその最後のフレームのコピーを作り、"[-set](https://imagemagick.org/command-line-options/#set)" 演算子を使ってそのフレームだけのディレイを変更します。そして元の加工していない画像を削除することで、そのフレームを画像シーケンスに再追加します。また、文字の描画の間に良いディレイを設定したので、2番目のアニメーションの初期の空白のキャンバス(初期の開始ディレイを表すだけ)は今や冗長なので、問題なくそのフレームを削除できます。もしこのフレームが実際に画像の一部を含んでいたら、除去する代わりにそのディレイを調整する必要があったかもしれません。 |

    magick -page 90x54 script_o.gif \( +clone -set delay 20 \) -delete -2 \
            \( script_k.gif -delete 0 -repage +37+0\! \)     script_ok.gif

[IM Output]
これで2つのアニメーションの直列(時間方向)の連結が完了し、これら2つの特定のアニメーションに関連したすべての小さな問題が修正されました。私が個々のフレームやそのタイミングディレイのすべてをグローバルに変更しようとしなかったことに注目してください。つまり、目標を達成しつつ、元のアニメーションをできるだけ多く保持しました。これは重要です。すべてのアニメーションがフレーム間で一定のタイミングディレイを使うわけではなく、これを変えるとアニメーションがとてもひどく見えることがあるからです。

横並びの連結(時間同期)

両方のアニメーションを横並びに連結したいけれど、アニメーションの両方の部分を同時にアニメーションさせたいとします。これはそれほど簡単ではありません。アニメーションも一緒に機能するよう、2つのアニメーションの各フレームペアを一緒に連結(または合成)する必要があるからです。これを行う本当の問題は、IM コマンドラインが単一の画像シーケンスでしか動作しないことです。2つの別々の画像シーケンスを保持し、それらをループして3番目に連結できる API の贅沢を持っていません。この連結を行う基本的な技術は3つ思いつきます。始める前に、まず2つのアニメーションを研究し、時間シーケンスやアニメーションの他の詳細を確認すべきです。"[gif2anim](../static/img/scripts/gif2anim)" スクリプトはこれに適しており、生成される ".anim" ファイルは後で役立ちます。 | |

  gif2anim -n bag_left.gif
  gif2anim -n bag_right.gif

| [IM Text]

| | [IM Text]

[left]
[right]
情報の要約を見れば、2つのアニメーションがまったく同じ数のフレームと、ほぼまったく同じ時間シーケンスを持つことが分かるでしょう。ここで重要なのはタイミングの類似性で、アニメーションがすでに「時間同期」されていると言えます。ただし、タイミングは正しいかもしれませんが、アニメーションは完全結合(coalesce)ではなくフレーム最適化されています。しかし、キャンバス領域の高さは同じなので、2つのフレームを横並びに連結するのが実用的です。実は、このアニメーションはひどく「分割」されており(次の例の組のアニメーションの分割を参照)、「猫」のアニメーションが2つに切られ、元のものが失われました。他の加工により、ごくわずかなタイミングの違いが生じ、それが分割をより明白にしただけでした。これは gmabrys 氏が IM フォーラムでの議論で私に提示した問題ですが、彼が出した実際の問題ははるかに、はるかにひどいものでした。[left][right] さて、ブラウザは通常、別々の各 GIF 画像を、何の同期もなくアニメーションさせます。そのため、2つのアニメーションが互いに非同期になり、チェーンソー大虐殺の一部だったように見える「猫」を生み出すことがあります。ブラウザのページに2つのアニメーションを横並びに置いた右側で、この効果を見られるかもしれません。特に遅いリンク経由で遠いサーバーにいる場合はそうです。では、それらを1つの、適切に同期されたアニメーション画像へと連結することを試みましょう。

別々のファイルを連結する

最も単純な方法は、2つのアニメーションを結合(coalesce)し、それらを別々の画像ファイル、1フレームにつき1画像に分離することです。その後、別々の画像を適切に連結(またはその他の方法でフレームを加工)できます。完了したら、新しいフレームを使ってアニメーションを再構築できます。ただしこれには、この処理中にとても簡単に失われかねないアニメーションについての多くの追加情報を保存する必要があります。 |

  # アニメーションを結合済みフレーム(プラス ".anim" ファイル)に分離する
  gif2anim -c bag_left.gif
  gif2anim -c bag_right.gif

  # 分離されたフレームを一緒に連結する
  for i in `seq -f '%03g' 1 11`; do \
    magick bag_left_$i.gif bag_right_$i.gif +append bag_append_$i.gif; \
  done

  # アニメーションを再構築する(".anim" ファイルの一方を使う)
  anim2gif -c -b bag_append  bag_left.anim

  # クリーンアップ
  rm -f bag_left.anim bag_right.anim
  rm -f bag_{left,right,append}_???.gif

[IM Output]
ご覧の通り、これはかなり込み入った処理で、多くの個別の一時画像を生成し、そのため完了時にかなりの片付けを必要とします。もちろん、上記をデバッグしている場合は、個別の一時ファイルが、処理で何が間違っているのかを把握するのを容易にします。これはまた、"[gif2anim](../static/img/scripts/gif2anim)" スクリプトと、その逆である "[anim2gif](../static/img/scripts/anim2gif)" スクリプトが、アニメーションを分離してメタデータを保存し、後で GIF アニメーションを再構築する力も示しています。基本的に、それらをスクリプトに直接コード化する必要なく、アニメーションの元のタイミングを保持できます。最終画像もまだ再最適化する必要がありますが、この場合は、すべてのフレームの間でたくさんのことが同時に起きるので、得られる最適化はごくわずかでしょう。

レイヤー合成

より良い技術は、複数画像リストのレイヤー合成を使ってアニメーションを重ねることです。これは一方の画像集合を拡大し、他方の集合を重ねてそれらを結合するだけです。実際、これは通常の "[-append](https://imagemagick.org/command-line-options/#append)" 演算子が内部で行うことなので、それほど違いはありません。ここでは、キャンバスをどれだけ大きくするかを IM に伝え、それを "[-coalesce](https://imagemagick.org/command-line-options/#coalesce)" を使って埋めます。そして他方の結合済みアニメーションを適切なオフセットで重ねます。 |

  magick bag_left.gif -repage 97x92 -coalesce \
          null: \( bag_right.gif -coalesce \) \
          -geometry +50+0 -layers Composite    bag_append.gif

[IM Output]
もちろん、上記の技術は、最終アニメーションがちょうどどれだけ大きくなるか、そして重ねるアニメーションに必要なオフセットを知る必要があることを意味します。しかし処理は速く、とても良く機能し、スクリプト化されたコマンドは画像を事前に読んでその情報を割り出せます。より普遍的なアニメーション連結の方法を作るには、連結の最終サイズとオフセットを自動的に割り出すための凝った画像処理を行う必要があります。アニメーションを事前に読まずにこれを行うには、いくつかの輪をくぐり抜ける必要がありますが、単一コマンドの一般的なアニメーション連結は可能です。まず、各アニメーションの最初の結合済みフレームを連結して、ちょうど良いサイズのキャンバスを作り、それをクリアします。1番目のアニメーションを結合し、このキャンバスの左半分に重ね、それから2番目のアニメーションを結合し、オフセットの必要を避けるために "-gravity East" で右端の半分に配置するよう重ねます。 |

  magick bag_left.gif'[0]' -coalesce \( bag_right.gif'[0]' -coalesce \) \
          +append -channel A -evaluate set 0 +channel \
          bag_left.gif -coalesce -delete 0 \
          null: \( bag_right.gif -coalesce \) \
          -gravity East  -layers Composite    bag.gif

[IM Output]
こうして、2つの時間同期されたアニメーションを一緒に連結する一般的な技術ができました。

二重連結、連結 - またはアニメーションフォントの連結

アニメーションの連結を終える前に、もう1つお見せしたい技術があります。この技術は、複数のアニメーションを同時に連結できますが、存在したすべてのタイミング情報を失うという代償があります。しばしば(常にではありませんが)それらのタイミングは大きな損失ではありません。基本的に、各アニメーションのすべてのフレームを単一の画像へ垂直に連結し、そしてアニメーション全体を2つの単純な画像として連結または重ねます。これは2本のフィルムストリップを横並びにテープで貼り合わせて、より幅広いフィルムストリップを作るようなものです。 |

  magick \( bag_left.gif  -coalesce -append \) \
          \( bag_right.gif -coalesce -append \) \
          +append  -crop x92 +repage \
          -set delay 30     bag_dbl_append.gif

[IM Output]
これは一時ファイルを一切必要としませんでしたが、最初に述べたように、すべての元の時間ディレイが失われています。この例では、すべてのアニメーションディレイをただ一定の値に設定し、妥当な、ただし異なる結果を生み出しました。また、アニメーションを再構築するには、元のアニメーションのフレームの高さを知って、幅広くなった「フィルムストリップ」を正しく分割(タイル切り抜き)する必要がありました。"[gif2anim](../static/img/scripts/gif2anim)" スクリプトを使ってそれらのタイミングを復元することは可能ですが、そうするとこの方法を使う目的が一種台無しになり、それなら個々のフレームを一時ファイルとして連結する、最初のアニメーション連結技術をただ使う方がよいでしょう。アニメーションを単純な画像として連結しているので、一連のアニメーション全体を一度にすべて連結でき(さらに幅広い「フィルムストリップ」を生み出します)、それがこの技術をこれほど便利なものにしています。例えば、すべて同じタイミングを使うアニメーションフォントに使えます。ただし、多くのアニメーションフォントは同じフレーム数を持つものの、アニメーション化された文字を非同期にするために、通常は各文字でわずかに異なるタイミングを持つことを見つけました(なぜそれが望ましいのかの理由はアニメーションの分割を参照してください)。一方、ネオンサインは同期されたアニメーションタイミングを持つべきなので、それを例として使います...

  magick \( neon_h.gif -coalesce -append \) \
          \( neon_e.gif -coalesce -append \) \
          \( neon_l.gif -coalesce -append \) \
          \( neon_l.gif -coalesce -append \) \
          \( neon_o.gif -coalesce -append \) \
          +append  -crop x60 +repage  -set delay 100  neon_hello.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

タイミングと結果のアニメーションのループ数を調整して、もう少し凝ったこともできます。

  magick neon_h.gif'[0]' neon_e.gif'[0]' neon_l.gif'[0]' neon_l.gif'[0]' \
          +append \( +clone \) -append \
          \( neon_o.gif -coalesce -append \)    +append \
          \( +clone \) -append \( +clone \) -append \( +clone \) -append \
          -crop x60 +repage   -set delay 3 \
          \( -clone 0  -set delay 300 \) -swap 0,-1 +delete \
          \( -clone 1  -set delay  10 \) -swap 1,-1 +delete \
          \( +clone    -set delay 200 \) +swap      +delete \
          -quiet -layers OptimizeFrame   neon_hell.gif

[IM Output]

最初の2行は、サインの「常に点灯している」部分(以前アニメーション化された各文字の最初のフレーム)を作ります。この後、最後の「壊れた」文字が追加され、アニメーション全体が数回二重化されて約16フレームを生み出します。タイミングは、最初と最後のフレームが長い期間表示される一方、残りのフレームが本当に速く過ぎ去る("-delay 10")ように、望む効果を完成させるよう設定されます。実は、この GIF アニメーションは、関係するフレーム数に対しておそらく思うよりはるかに小さく最適化されます。基本的に IM GIF 最適化器は、「O」アニメーションを1フレームおきに再度重ねるだけでよく、「Previous」廃棄(disposal)を使って前の点灯した「O」を復元するだけでよいと見つけました。そのため、アニメーションは基本的な点滅する最適化されていない「hello」画像より約50%大きいだけです。自分で確認してみてください。ネオンアニメーションを改善できますか? もっとリアルにできますか? GIF アニメーションに音がないのは残念です。

アニメーションを分割する

さて、アニメーションを再結合したので、Web サーバーで使うために、個々の部分が互いに干渉せずに別々にアニメーションできるよう、正しく分割することを試みましょう。これは実はかなり難しく、私は処理を完全に自動化しようとはしません。とはいえ、これを行える WWW 上のツールはあります。まず、アニメーションのどの部分が全期間を通じて変化するかを見つけるために、アニメーションを研究する必要があります。そのために、あるフレームから次のフレームへの差分を見つけ、それらをすべて、アニメーションされている領域と完全に静的なままの領域を示すマップへとまとめる必要があります。これは厄介です。基本的に、アニメーションの各フレーム間の「[Difference](compose.html#difference)」画像を見つけるために複数画像アルファ合成が使われます。これらのグレースケールの差分画像が一緒にまとめられ、それからチャンネルが分離されてやはり一緒にまとめられます。最後のしきい値が、アニメーションのどのフレーム間のゼロでない変化も、純粋な白にします。結果は、画像が変化したどこにでも白がある黒い画像で、変化の領域を浮き彫りにします。

  magick   bag.gif   -coalesce  -set delay 0 \
          -bordercolor red -border 0 -alpha off    null: \
          -duplicate 1,1--2 -compose difference -layers composite \
          +delete -compose plus -background black -flatten \
          -separate -flatten -threshold 0 bag_areas.gif

[IM Output] [IM Output]

さて、このアニメーションは少なくとも3つの領域に分けられることが分かります。上部の「猫」の領域、左の小さな「熊」、右の羽ばたく「翼」です。すべて単純な直交(垂直または水平)の切れ目です。では、アニメーションのいくつかの単純なビューポート切り抜きで、これをただ行いましょう。 |

  magick bag.gif -coalesce  -crop 97x39+0+0\!   bag_cat.gif
  magick bag.gif -coalesce  -crop 50x54+0+39\!  bag_bear.gif
  magick bag.gif -coalesce  -crop 47x54+50+39\! bag_wing.gif

| [IM Output]

[IM Output] | [IM Output]
これら3つの画像は、ブラウザによって一緒に表示でき、「テキサスチェーンソー大虐殺」のような見た目になりません。サブアニメーションが他のサブアニメーションの境界を横切る地点がないからです。さて技術的には、アニメーションされていない領域をアニメーションされた領域から分離するよう、あといくつか切れ目を入れて、このアニメーションを約6つ以上の領域に分割できますが、そうしても最適化からはあまり得られないでしょう。実際に行うのは、Web ページを複雑にし、ユーザーがダウンロードするファイルを増やすだけです。さて、より大きなアニメーションとは違い、これらのより小さな領域は互いにかなり独立してアニメーションします。これらの単純なサブアニメーションのタイミングを、結果に悪影響を与えることなく変更して、他のサブアニメーションから完全に非同期にすることさえできます。結果は、より良い、繰り返しの少ないアニメーション画像です(下記を参照)。「跳ねる熊」と「羽ばたく翼」を研究すると、単純な2フレームのサイクルを形成し、それがただ数回繰り返されて、波打つ猫のタイミングに合っていることが分かるでしょう。そのため、これらのアニメーションを単純化するために、余分な繰り返しを捨てられます。また、「猫」の最初の2フレームもまったく同じです。ただし「熊」や「翼」とは違い、その一方をただ除去することはできません。各フレームが、猫が存在しない状態で「熊」と「翼」がアニメーションできるよう、時間ディレイを含んでいるからです。これらの重複フレームを正しく除去するには、"[-layer](https://imagemagick.org/command-line-options/#layers)" メソッドの「[RemoveDups](anim_opt.html#removeDups)」を使って、結合済みアニメーション内のそうした重複フレームを見つけ、そのタイミングを統合する必要があります。こちらが、サブアニメーションの全体的な非同期化を改善するためのタイミング変更を伴う、3つの分離されたアニメーションすべての最終的な最適化です。3つのアニメーションすべてを、ちょうど表示されるべきように、ページに横並びに表示もしました。 |

  magick bag_cat.gif -layers RemoveDups \
                           -quiet  -layers Optimize  bag_cat_opt.gif
  magick bag_bear.gif -delete 2--1 -set delay 47 \
                                   -layers Optimize  bag_bear_opt.gif
  magick bag_wing.gif -delete 2--1 -set delay 33 \
                                   -layers Optimize  bag_wing_opt.gif

| [IM Output]

[IM Output] | [IM Output]
最後にまとめると、元の(ひどく分割された)2つの画像は合計 [IM Text] バイトで、これは連結バージョンとほぼ同じです。アニメーションを正しく分割した後は、サブアニメーションの良い最適化が可能になり、3画像にわたって合計 [IM Text] バイトになります。かなり良い節約です。

離れた変化のフレーム分割

作成中

透明を伴わず(固定背景)、しかし部分間のタイミング同期を保持して、「遠く離れた2つの変化するオブジェクト」のフレーム更新を分割する例。それから透明の背景で繰り返す(「クリア」されたピクセルを生成するために「OptimizePlus」が必要)。一般的な例はフレームアクションの分割を参照してください。

時間的に不揃いなアニメーションを統合する

2つのアニメーションを同期して動くよう統合できる前に、すべてのアニメーションを同じ数のフレームを使い、同じ時間ディレイの集合を使うようにする必要があります。統合がどれだけ難しいかは、アニメーションのタイミングがどれだけ不揃いかに本当に依存します。時間ディレイが基本的に一定なら、それらを単純に無視して、後でタイミングを修正できます。2フレームのアニメーションと6フレームのアニメーションを統合する際に時間を無視できる例が、IM フォーラムの議論で挙げられました。また、全体のサイクル時間が大きく異なる場合は、一方のアニメーションが他方のサイクル時間を埋めるよう2、3回ループするように物事を調整する必要があるかもしれません。基本的に重要なのはタイミングです。

おそらく次のようなものです... * + アニメーションを共通の全体ループサイクル時間に合わせて割り出し、調整する * + フレーム最適化を取り除くために両方のアニメーションを結合(coalesce)する。 * * フレーム時間ディレイを、アニメーションの開始からの経過時間に変換する。 * * 時間同期するために適切にフレームを二重化する。 * * 開始からの経過時間をフレーム時間ディレイに戻す。 * + 結合済みの時間同期されたフレームを、望むように重ねる。 * + 最適に統合し、あらゆる「ゼロディレイ」フレームを除去する。 * + 新しいアニメーションを再最適化する。

「*」の部分は、ほぼ同じ全体サイクル時間長を持つ2つのアニメーションを時間同期するための、単一の新しい "[-layer](https://imagemagick.org/command-line-options/#layers)" メソッドにできるかもしれません。

作成中

例、時間的に不揃いだが、同じサイクル時間...

例えば、次の時間ディレイを持つ3フレームの2つのアニメーションがあるとします
    10  10  10
    5    5  20

両方のアニメーションはすでに30時間単位の長さなので、それは問題ではありません。

さて、上記を各フレームが現れるべき時間インデックスに変換します...
そしてフレームが現れる全体のタイムラインを示します...
   0        10    20   |__ 両方のアニメーションが30で
   0   5    10         |   終了またはループすることに注意

これから、それらを一致させるためにいくつかの余分なフレームを挿入する
必要があることが分かります。1番目のアニメーションの最初のフレームは
時間インデックス5で繰り返される必要があります

0->5  10  20
0  5  10

そして2番目のアニメーションの最後のフレームも時間インデックス20で
二重化される必要があります

0->5  10  20
0  5  10->20

上記の矢印「->」は、同じフレームが次の時間インデックスに
ただ繰り返される(二重化される)ことを意味します。それらは実際には
同じ画像です。

さて、両方のアニメーションのフレームのタイミングが同じになったので、
フレームを単純に統合(合成)して、4フレームの長さの最終アニメーションを
得られます。

したがって4フレームは次の時間ディレイを持ち
5  5  10  10
これは依然として30時間単位(ループサイクルあたりの全体時間)に
足し合わされます。

現在の開発状況....

IM は時間ディレイ情報の収集("gif2anim" の '-t' オプションを試してください)
とアニメーションの構築を手伝えますが、IM は2つの別々の結合済み
アニメーションに必要な時間同期を実行できません。これは将来、特別な
組み込みオプションになるかもしれません。

つまり、2つの時間的に不揃いなアニメーションを2つの時間同期された
アニメーションに変えるために、適切な結合済みアニメーションのフレームを
自分で割り出して二重化する必要があります。

アニメーションを時間同期したら、新しい "-layers Composite" メソッドを
使って、2つの時間同期されたアニメーションをとても簡単に重ねたり統合
したりできます。

ただし上記はすべて、2つのアニメーションの全体ループ時間が少なくとも
おおよそ等しいか、大きな懸念ではないことを前提としています。


**簡略化された解決法**

簡略化された限定的な解決法が、(顔文字のような)速く変化するアニメーション
に使うために [IM フォーラムで議論](https://magick.imagemagick.org/viewtopic.php?p=50325)されました。

この解決法は、各アニメーションを取り、アニメーションが固定フレームレートを
持つよう拡張します。つまり、すべてのフレームが二重化され、各フレームが
一定の6センチ秒ずつ表示されるようにします。そのため、22cs のディレイを
持つ1フレームは、4 × 6cs フレーム(合計24cs)に置き換えられるかもしれません。

この後、短いアニメーションが複数回ループされて2つのアニメーションが
最終的に同じ長さになるよう、アニメーションがさらに加工されます。
つまり、2つのアニメーションが、時間とフレーム数の両方の点で同じ全体
長さにされます。

両方のアニメーションが同じフレームレートと同じ長さを持つようになると、
[レイヤー合成](#composite)を使って2つのアニメーションを正しい位置で
統合・重ねられます。

結果はその後、[重複フレームの除去](anim_opt.html#removedups)を使って
余分な不要なフレームを除去し(適切なタイミング調整を伴う)、保存前に
他の[最適化](anim_opt.html#intro)を適用して最適化できます。

構成要素のアニメーションをすべて固定フレーム長の形で持つこの方法は、
アニメーションライブラリに特によく適しています。


-----
作成する他の例....
  * 動く2つの等しい時間のアニメーションを単一のアニメーションに重ねる
    (踊る蝶、周回する原子、または鳥?)
    これは素直なレイヤー合成のはずです。

  * 動くアニメーションを固定背景に重ねる。
    (時間に伴ってアニメーションを直線的に変位させる)

  * 異なる数のフレームだが一定の時間ディレイを持つ2つのアニメーションを
    重ねる(参照: [IM フォーラムの議論](https://magick.imagemagick.org/viewtopic.php?t=12573))。

  * 時間的に不揃いな2つのアニメーションを重ねる(上記で概説したように)

  * 単純なアニメーション化された図形を、アニメーション化された背景に重ねる。
    (完全なアニメーション統合)