ImageMagick の例 --
アニメーションの変更

目次
ImageMagick の例 序文と目次
アニメーションの簡単な変更
アニメーションのアルファ合成
輝くものすべて...
アニメーションのリサイズ
複数のアニメーションのマージ
このページでは、GIFアニメーションを扱うための実用的な例を紹介します。これらの例を理解する前に、アニメーションの基本と、少なくともGIFアニメーションの最適化の全体的な取り扱いを読んで理解することを強くお勧めします。

アニメーションの簡単な変更

まず、重要な点

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

注釈- すべてのフレームに著作権表示を追加

IMバージョン6.2.6以降では、画像への注釈で詳しく説明したのと同様の方法で、単に実行することでアニメーションに「-annotate」を適用できます。たとえば、ここでは、アニメーションの基本で作成した前の破棄アニメーションに注釈を付けます。

  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」がテキストを画像の仮想キャンバスを基準にして配置し、実際の画像データを基準にして配置しないからです。そのため、各フレームのテキストの位置は、アニメーション画像に対して正しくなります。しかし、バージョン6.2.6より前では、「-annotate」は、他の多くの画像操作子と同様に、情報を配置し、オーバーレイを実際の画像を基準にして配置し、サブフレームが持つ可能性のあるページまたは仮想キャンバスのオフセットを無視していました。1つ注意すべき点は、アニメーションを最初に結合せずに、このようにアニメーションに描画すると、アニメーションの既存の最適化スキームのために、通常とは異なる効果が発生する可能性があることです (次の例のセットを参照)。したがって、既存のフレームと透明度の最適化を結合によって削除することをお勧めします。(次の例を参照)

描画- 結合されたアニメーションを変更

-annotate」は各フレームの仮想キャンバスを基準にしてテキストを配置しますが、他の多くの画像操作はそうではありません。これには、すべて「-draw」操作が含まれ、それらは実際の画像を基準にしてのみ描画し、大きなキャンバス上のオフセットを完全に無視します。たとえば、ここでは、前の破棄アニメーションの左上隅付近に、派手な緑の円を描画します。

  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」は、画像が属しているより大きな仮想 (ページ) キャンバスではなく、「実際の画像」を基準にして円を描画しました。その結果は、このような状況では典型的な、めちゃくちゃな状態になります。これに対する簡単な解決策は、描画する前に最初にアニメーションを結合し、その後で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アニメーションオプティマイザが、実際に描画された部分を上書きしないことに決めた方法に注目してください。これは、実際のサブフレーム画像自体に描画した場合よりも、実際にはより最適です。この方法を使用すると、あらゆる種類の注釈、著作権表示、または透かしを重ねることができます。もちろん、実際にはアニメーションのすべてのフレームに画像を重ねるには、特別なレイヤー合成テクニックを使用する必要がある場合があります。本当に上手くなれば、アニメーションのマージを実行して、アニメーション化された著作権表示をアニメーションに重ねることもできます。
この「結合-最適化」テクニックは、アニメーションを含むほとんどの操作で機能しますが、特にIMのオプティマイザでは、大きな色の変化やシェーディング、半透明など、画像に大幅な変更を加える一部の操作では、結果としてアニメーションをうまく最適化できない場合があります。

たとえば、ほとんどすべての「-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]
アニメーションの1つのフレームの単純な「クローン」のみに「-annotate」操作の影響を制限するための括弧の使用に注意してください。次に、修正された画像は、スワップおよび削除操作子を使用して、画像シーケンス内の適切な位置に戻されます。
-swap」操作子での単一数値の使用は、IM v6.3.4-3で追加されました。これより前では、正しく機能させるためには、「-swap 3」を「-swap -1,3」として指定する必要がありました。
個々のフレームを変更するこのテクニックは、おそらく遭遇する画像アニメーションを操作する上で最も重要なテクニックの1つになるでしょう。また、実際には、最初と2番目の両方の画像に同じテキストを追加したことにも気付くでしょう。上記のアニメーションの最初の画像は、ゼロ遅延中間フレームであり、このアニメーションの残りの部分の背景を定義するために使用されます。つまり、非常に速く点滅するため、通常はユーザーには見えず、見えるように意図されていません。したがって、上記のアニメーションの最初の2つの実際のフレームは、2つの別々のフレームではなく、1つの可視フレームとして見なす必要があります。非ゼロの遅延時間を持つフレームは、「表示」フレームシーケンスの最後のフレームです。同様に、他の高速アニメーションの場合、変更をある程度の時間表示するには、多数のフレームを変更する必要がある場合があります。これは、すべてのフレームに描画された静的な注釈には問題ありません (上記の注釈の例を参照)。これにより、GIFアニメーションに関する重要な点が浮上します。
変更を試みる前にアニメーションを調べてください。
最終結果に大きな違いが生じる可能性があります。

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

IMは、「-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」を使用しないでください。そうすると、仮想キャンバス上のサブフレームを配置するために必要なフレームオフセットも削除され、後のフレームが正しくアニメーション化するために依存する可能性があります。
上記の「-crop」操作により、警告メッセージが生成されました...
[IM Text]
アニメーション内のいずれかのフレームの切り抜きが、そのフレームに使用されるサブフレームオーバーレイ画像を逃したためです。つまり、1つのフレームが、アニメーションから切り抜かれた領域を更新しませんでした。結果として、そのフレームには実際には画像が含まれていません!これを補うために、IMは警告メッセージを生成するだけでなく、すべてを順序どおりに保ち、そのフレームに添付された「遅延」または「破棄」方法を保持するために、アニメーション内に特別な「ミスした画像」をプレースホルダーとして生成します。そのプレースホルダーをそのままにするか、好きなように修正することができます。この場合、「ミスした画像」は、アニメーションが期待どおりに実行するために必要です。ただし、複数の連続したミスした画像が生成された場合は、「-layers」メソッド「RemoveDups」を使用して、それらを単一のミスした画像にマージできる可能性があります。ただし、アニメーションの注意深い調査をお勧めします。(これの詳細な例については、下記のアニメーションの分割を参照してください。

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

通常切り抜きと同様に、アニメーションの切り抜きも元の画像の仮想キャンバスを保持しました。これは、この場合意図していることではないでしょう。このため、IMバージョン6.2.4-5では、特別なフラグ「!」が「-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」設定を含めたことに注意してください。これは、警告が実際には適用されないため、アニメーションを切り抜く場合は常に推奨されます。 ビューポート切り抜きでは、キャンバス領域を拡大したり、キャンバス内のすべてを再配置したりすることもできます。ただし、切り抜き領域の外に部分的または完全に落ちる画像は、その領域内に表示される画像の一部のみが表示されるように切り取られるため、危険です。最後の警告の言葉を1つだけ。 「ビューポート切り抜き」を使用する場合、フレーム画像は「ビューポート」に指定されたオフセットに対して負の方向に移動されます。これは、切り抜き演算子のオフセットがビューポートの位置であり、画像自体の直接的な再配置ではないことを覚えていなければ、論理的ではないように見える可能性があります。

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

前の操作と同様に、アニメーションのトリミングは難しい場合があります。アニメーションが単純なクリアされたフレームアニメーションで構成されている場合は、アニメーション内の個々のすべてのフレームの最大境界を計算するだけでアニメーションをトリミングできます。 IM v6.3.4-8以降では、「TrimBounds」レイヤーメソッドを使用してこれを非常に簡単に行うことができます。

  magick anim_bgnd.gif -layers TrimBounds anim_trim_bounds.gif
[IM Output] ==> [IM Output]
このバージョンのIMよりも前のユーザーは、同じことを行うことができますが、2段階のプロセスでのみ(他の不要な処理も実行します)。これを行うには、レイヤーマージを使用してアニメーションのすべてのフレームを単一のレイヤーにマージし、次に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]
アニメーションから静的な背景もトリミングしたい場合は、フレーム最適化されたアニメーションから最初のフレームを削除してから、レイヤーマージステップを使用することをお勧めします。次に、元のアニメーションでビューポート切り抜きに使用するために返された境界を使用できます。

フレームの再配置

同様の関連操作は、「相対的な再ページ」演算子です。これにより、アニメーションの個々のサブフレームレイヤーすべてに指定されたオフセットが追加され、キャンバス全体に対する位置を調整できます。 「-repage」操作を相対的にするには、引数に「!」フラグも追加します。たとえば、ここではアニメーションの2番目以降のフレームを下に30ピクセル、右に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」を使用して画像を左または上に移動する場合、特にキャンバスが小さい場合は、GIFアニメーションで失敗する可能性があります。この形式は基本的に負の画像オフセットを使用できません。

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

PNGおよびMNG形式は負のオフセットを処理できますが、多くのWebブラウザーやその他のプログラムはそのようなオフセットを理解できず、奇妙な効果が生じる可能性があります。たとえば、「Firefox」Webブラウザーのあるバージョンでは、負のオフセットを持つPNGを表示しようとすると、非常に大きな画像が生成されます。

アニメーションの反転- アニメーションを逆方向に実行またはサイクルさせる

IM v6.3.3以降、「-reverse」画像シーケンス演算子が追加されました(詳細については、反転演算子を参照してください)。これにより、結合されたアニメーションシーケンスの順序を非常に簡単に反転できます。たとえば、ここでは「手描きのk」アニメーションを未描画にしています!

  magick script_k.gif -coalesce -reverse \
          -quiet -layers OptimizePlus  -loop 0 reversed.gif
[IM Output]
上記の「-loop」オプションを再追加する必要がありました。これは最初の画像に添付する必要があり、現在は最後の画像になっているためです!結果はタイミング調整も必要になる可能性がありますが、ご覧のとおり、文字を「描画解除」しています! フレーム最適化が存在する場合は画像の順序に依存するため、反転する前に必ず画像シーケンスを「-coalesce」してください。最初にこれらの最適化を削除する方が良いでしょう。

パトロールサイクル- 2つの端の間を行ったり来たりするサイクル

同様の手法は、アニメーションの最後にフレームの反転順序を追加することです。これにより、結果のアニメーションが元の最初のフレームと最後のフレームの間でサイクルします。これは、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」演算子は、特に興味深い演算子です。これは、画像のリストを受け取り、それらの間に余分なフレームを挿入して、ある画像から次の画像へとなめらかな色の変化を実現します。ただし、この演算子は、ピクセルの色を変更してブレンドされた画像のシーケンスを作成するだけなので、真の「モーフ」ではありません。真の映画のような「モーフ」には、画像内のオブジェクトのアウトラインを別の画像のオブジェクトに変換するための画像の歪みも伴います。たとえば、ここでは、バラの画像とその反転した形の間の余分なフレームを生成するために、カラーモーフを使用してパトロールサイクルを作成します。

  magick -delay 20 rose: \( +clone -flip \)  -morph 5 \
          -duplicate 1,-2-1  rose_flip.gif
[IM Output]
これは特に良いとは言えません。すべての画像で遅延が同じだからです。その結果、アニメーションは、サイクルの両端の点の間で「休止」または一時停止するように見えません。より良い解決策は、元の画像とその「反転」した形で一時停止させることです。ただし、それには、元の画像の遅延を、モーフィング画像の遅延とは異なるように調整する必要があります。

  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」および「fxtransitions」ImageMagickシェルスクリプトを参照してください。サンプルページには、スクリプトがアニメーションを生成するために使用する基本的なアルゴリズムが含まれています。

リサイズモーフ- サイズのアニメーション変化

カラーモーフ演算子は、2つの画像間のカラーブレンディングだけでなく、同時に画像のリサイズも実行します。たとえば、ここでは、サイズが異なる、さらにはアスペクト比が異なる2つの画像に対して「-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パーセントエスケープを使用して、画像のインデックス「%[fx:t]」とリスト内の画像の数「%[fx:n]」に基づいて歪みの値を計算し、各画像を異なるように変更します。たとえば、ここでは、計算された量だけ画像を平行移動します。

  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」と「-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」して、最適化されていない結合されたアニメーションにする必要があります。次に、アニメーションを再最適化する前に、アニメーションのすべての結合されたフレームにラベルを追加できます。

  magick canvas_prev.gif -coalesce \
          -gravity South -background white -splice 0x18 \
          -annotate 0 'A Better Label' \
          -layers Optimize labeled_anim.gif
[IM Output]
追加された余分なスペースにテキストを描画するために「-annotate」を使用するのではなく、構成方法(次のセクションを参照)を使用して、追加されたスペースに画像を構成できます。そうすれば、アニメーションに追加するはるかに豪華なラベルを準備できます。もちろん、これを行うと、一部のアニメーションが後で最適化されない可能性があります。特にクリアフレームアニメーションはそうですが、これはラベルを追加するために支払う代償です。そのタイプのアニメーションの1つの解決策は、クリアフレームアニメーションを説明するセクションで示されているように、ラベルを含む「最初の背景キャンバス」を先頭に追加することです。また、アニメーションにラベルを追加すると、多くの追加の色が追加される可能性があることにも注意してください。これにより、GIFの色制限を超える可能性があり、アニメーションの色を最適化する準備をする必要がある場合があります。可能な限り避けるのが最善の非常に難しいタスクです(色最適化を参照)。これは、アニメーションへの一般的な変更すべてに問題となる可能性があります。

透明度の削除- 単色の背景を追加する

Web上で見つけることができる多くのアニメーションには、透明な背景があります。これらは、Webページに配置するときに、存在する可能性のある背景パターンを心配する必要がないため、非常に便利です。ただし、特に「-resize」や「-blur」などの他の画像演算子を適用する場合、このようなアニメーションには問題があります。一般的な解決策は、通常、Webページの背景として使用される特定の色など、特定の色に重ね合わせることによって、画像から透明度を削除することです。 [IM出力]たとえば、ここでは、見えない手で描かれたかのように文字「K」が描画される単純な透明なオーバーレイアニメーションがあります。このGIFアニメーションは透明度付きで描画され、前のフレームに画像をオーバーレイ(ピクセルを追加し、削除しない)するだけなので、背景色(または画像)を設定する簡単な方法は、アニメーションの最初のフレームに追加することです。他のすべてのフレームには背景の透明色が含まれているため、結果に影響しません。ここでは、フラット化演算子を使用して、アニメーションの最初のフレームを「LimeGreen」背景色にオーバーレイします。単一の画像にのみ適用しており、アニメーション全体には適用していないため、これには「-flatten」を使用できます。

  magick script_k.gif \( -clone 0 -background LimeGreen -flatten \) \
          -swap 0,-1 +delete      script_k_flatten_0.gif
[IM Output]
元の最初のフレームが単一ピクセルサイズであったことも重要です。フラット化演算子は、背景を色付けするだけでなく、そのフレームをフルサイズに拡張しました。つまり、フレームを「塗りつぶし」ました。ただし、アニメーションの最初のフレームのみが色付けされていることに注意してください。この方法は、最適化(このアニメーションに含まれる重い最適化など)が保持されるため、推奨されます。最初のフレームを色付けすることは、すべてのGIFアニメーションで機能するわけではありません。単純なオーバーレイアニメーションでのみ機能します。アニメーションから透明度を削除する一般的な方法では、まずアニメーションを「-coalesce」してから、アルファ削除演算子を使用して、実際にすべてのフレームから透明度を削除する必要があります。今回は、これを「Tomato」背景色を使用して実行してみましょう。

  magick script_k.gif -coalesce   -background Tomato -alpha remove \
          -layers Optimize   script_k_alpha_rm.gif
[IM Output]
もちろん、結果の最適化は元のものほど最適ではない可能性がありますが、アニメーションには透明度がなくなりました。追加の副作用として、アニメーションの「背景」破棄設定は、透明度が問題ではなくなったため、フレーム最適化プロセスによって「なし」または「前へ」のいずれかに変換されます。
アルファ削除は IM v6.7.5 で追加されました。お使いの IM バージョンが古い場合は、ボーダー演算子の副作用を利用するなど、別の方法を使用する必要があります。この方法やその他の方法の詳細については、透明度の削除を参照してください。
背景画像やパターンを重ねるなど、より複雑な背景処理には、これまで見てきた単純な変更よりもはるかに複雑なアニメーション処理が必要です。次はそれを見ていきましょう。

マルチイメージアルファ合成

次のレベルのアニメーション処理では、既存のアニメーションの上または下に、単一の静止画像を合成できる必要があります。つまり、一般的なアルファ合成です。2 つの別々の画像セットを結合する場合は、さらに複雑になります。IM v6.3.3-7 より前は、マルチリスト合成は、特別に設計された API スクリプト、またはアニメーションの個々のフレームを保存および結合するシェル スクリプトを使用した場合にのみ可能でした。どちらもあまり良い方法ではありませんでしたが、それが可能なすべてでした。それが今、変わりました。

画像の描画- 画像のリストに画像を描画します

-draw」演算子には、ソース画像を画像のリストの上に合成する機能があります。また、IM v6.3.3-7 より前に、「mogrify」コマンドで使用したり、複数の画像に対して使用したりできる唯一のマルチイメージ アルファ合成方法でもあります。このアルファ合成テクニックが非常に重要だった理由は、現在の画像リストへの別の引数として画像を指定できたからです。つまり、「-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」合成方法を使用すると、画像を静的な背景としてアニメーションの「下」に配置することもできます。たとえば、ここで「netscape:」組み込み画像を「下敷き」にしますが、外部の画像ファイルでもかまいません...

  magick script_k.gif -coalesce \
              -draw 'image DstOver 0,0 0,0 "netscape:"' \
          -layers Optimize   script_k_netscape.gif
[IM Output]
アニメーションのサイズは、合成先画像がアルファ合成の最終的なサイズを定義するため、変更されていないことに注意してください。より大きなキャンバスを作成する場合は、背景に対応するように、アニメーションのサイズとオフセットを適切に調整する必要がありました。たとえば、アニメーションの相対リページを、合体する前に行います。

  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 では、「-layers」メソッドである「Composite」が追加され、完全に独立した 2 つの画像セットを合成できるようになりました。(簡単な概要については、画像のレイヤー化、レイヤー合成を参照してください。)コマンドラインでこれを行うには、最初の合成先画像リストの終了位置と、オーバーレイされるソース画像リストの開始位置を定義するために、特別な「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:」画像セパレーターを追加して、ImageMagick が 1 つのシーケンスがいつ終了し、次のシーケンスがいつ始まるかを認識できるようにします。この画像セパレーターは、次に重要な「-layer composite」操作によって自動的に削除されます。他の API は、特別なセパレーターを含む単一のシーケンスではなく、別々の画像の「ワンド」を使用できるはずです。レイヤー合成は、これらの 2 つのアニメーションまたは画像シーケンスが、複数の画像のシーケンスではなく、単なる単純な単一の画像であるかのように実行されます。1 つの合成先と 1 つのソースという各画像のペアが一緒に合成され、画像の結合(合成)されたシーケンスが生成されます。最終的な結果は、元の画像シーケンスに影が追加されており、GIF の最適化、または直接使用の準備ができていることです。
これで、上記のすべてのステップを 1 つのコマンドで実行できます。ただし、「-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]
このバージョンは、影演算子が生成するオフセット情報を失わなかったため、実際にはより適切に機能します(GIF は負のオフセットを保存できないため、ゼロにリセットします)。上記では、中間画像に GIF ではなく MIFF ファイル形式を使用するか、次の例で説明するように、「-geometry」合成オフセットを使用することで、修正できます。基本的に、これらの例は、レイヤー合成演算子が個々の仮想キャンバスオフセット(「-page」)設定を実際に理解しており、レイヤーのフラット化、またはより良いのはレイヤーの結合演算子がそれらを処理する方法と同様に処理することを示しています。しかし、レイヤー合成演算子は、合成ジオメトリ(「-geometry」)オフセット(デフォルトはゼロ)の使用も理解しており、オーバーレイ画像シーケンス全体の全体的な配置を制御します。さらに、グローバルオフセットに対する「-gravity」の効果も理解しています。たとえば、生成された影アニメーションの「南」に、元の「K」アニメーションを重ねてみましょう...

  magick shadows_k.gif  null:  coalesced_k.gif  \
          -geometry +0-10 -gravity South  -layers Composite \
          magick composite_south.gif
[IM Output]
上記は、通常の 2 つの画像のアルファ合成と同様に、最終的な出力画像サイズを制御するのは合成先画像シーケンスであり、合成オーバーレイは合成先キャンバス画像にクリップされることも示しています。そのため、すべての合成先画像が最終的な結果を含めるのに十分な大きさであることを確認する必要があります。
-geometry」のリサイズ機能は、厳密には合成操作の一部ではなく、現在の画像シーケンスの最後の画像のみをリサイズします。したがって、マルチイメージレイヤー合成で使用すると、期待どおりの結果にはなりません。詳細については、サイズ変更ジオメトリを参照してください。
基本的に、レイヤー合成は通常の合成と非常によく似ています。
本当に簡単です。簡単と言いましたか?
レイヤー合成の詳細...... 上記で見たように、コマンドライン版の "-layers Composite" は、現在の画像リスト内で最初に見つかった 'null:' 画像を、2つのリストを区切るマーカーとして使用します。2つの画像リストは分離され、'null:' は破棄されてから、2つのリストが一度に2枚ずつ アルファ合成 されます。マーカーとして使用できるのは、特別な 'null:' 画像ソースから生成された画像のみです。見つからない場合はエラーが報告されます。現在、この 'null:' マーカー画像をパイプラインから読み取ることはできません (少なくとも現時点では)。必要なときに生成するだけです。レイヤー合成は、単純な2枚の画像の アルファ合成 よりもはるかに複雑で、画像リストの仮想キャンバスも考慮されます。通常、アルファ合成は位置決めの目的で仮想キャンバスのサイズとオフセットを無視し、画像の実際のサイズのみを使用します。この特別なレイヤーメソッドは、ジオメトリの位置合わせのために仮想キャンバス情報を使用し、2つの画像シーケンスを整列させます。このため、サブフレームが持つ仮想キャンバスオフセットは、通常の "-gravity" 調整後の "-geometry" 合成オフセットに追加され、画像のオーバーレイの位置が計算されます。各リストの最初の画像の仮想 "-page" キャンバスサイズのみが、"-geometry" 合成オフセットへの "-gravity" 調整を計算するために使用されます。後の画像のキャンバスサイズは無視され、個々の仮想 "-page" オフセットのみが、計算された "-geometry" オフセットに追加されます。言い換えれば、"-layers Composite" は、「レイヤー」または「アニメーション」のアルファ合成、およびそのような画像リストの特別な要件のために設計されています。注意事項...ただし、オーバーレイする画像リストには注意が必要です。たとえば、宛先リストの画像が十分に大きくない場合、またはオーバーレイされたソース画像を含めるように正しく配置されていない場合、オーバーレイされた画像はクリップされるか、宛先画像を完全に見逃す可能性があります。このため、小さいソース画像をオーバーレイする前に、宛先画像をフルキャンバスサイズに合体することをお勧めします。たとえば、横並びアニメーション追加の以下の例では、追加された画像のスペースを提供するためにキャンバスサイズを拡大する必要がありました。また、ソース画像リストがGIFアニメーションである場合は、サブフレームに圧縮最適化や高度なフレーム最適化などのものが含まれていないことを確認する必要があるかもしれません。そうしないと、問題が発生する可能性があります。一方、クリアフレームアニメーションまたは合体アニメーションは、問題なく直接 'Composite' できます。ただし、レイヤー合成は、画像に存在する可能性のある既存のGIF破棄方法を理解していないことに注意してください。ただし、宛先 GIFアニメーションのメタデータ(破棄方法フレーム遅延繰り返しループ制限など)は保持されます。ただし、これには以下に示す特別な場合における例外が1つあります。

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

通常、長さが同じ2つの画像リストが、画像リストのいずれかがなくなるまで、一度に1枚の画像ペアずつ合成されます。画像のリストが繰り返されることはありません。合成は停止します。追加された合成のみを含む元の宛先画像リストが残されます。 'null:' セパレーター画像とすべてのソース画像は、現在の画像リストから削除されます。
このレイヤーメソッドへのAPIインターフェースでは、2つの別々の画像リストを生成できます。結果の画像リストを生成するために使用された両方の入力画像リストを削除するのはあなた次第です。 'null:' セパレーターは必要ありません。
ただし、リストの1つに単一の画像のみが含まれている場合、その画像は他のリストのすべての画像に対して合成されます。その単一の画像がソース画像であるか宛先画像であるかは関係ありません。このメソッドは、他の画像リストに対して合成を実行し、単一の画像が宛先画像であっても、単一の画像ではなく、画像リストのGIFメタデータを保持します。この「単一画像に対する合成」は、レイヤー合成の特殊なケースであり、アニメーションに背景を追加したり(次を参照)、アニメーションに静的なオブジェクトを挿入したりするのに非常に役立ちます。

静的背景- より大きな背景に重ねて合成する

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


magick -size 100x100 plasma:fractal null: \( script_k.gif -coalesce \) \ -gravity Center -layers Composite \ -layers Optimize magick composite_background.gif
[IM Output]
背景画像は宛先であるため、アニメーションの最終的なサイズを定義しますが、すべてのメタデータ(遅延、ラベル、コメントなど)はソース画像リストから取得されます。通常、その情報は宛先画像リストから取得されます。これは、画像合成中にソース画像がメタデータ情報を提供する唯一のケースです。また、レイヤー合成が "-gravity" を理解しているため、自分で計算する必要なく、画像は適切に中央揃えされます。ただし、ソースフレームにオフセットが含まれている場合、これらのオフセットもgravityで定義された位置に追加されるため、すべてのサブフレームの相対位置が正しく維持されます。アニメーション "script_k.gif" は実際にはオーバーレイアニメーションの一種であるため、アニメーションに静的な背景を追加する別の方法があります。たとえば、上の透明度の削除のセクション(単色に対してですが、任意の画像にすることができます)を参照してください。同じことが、さらに単純なクリアフレームアニメーションにも当てはまります。この場合、最初にアニメーションを合体する必要さえなく、背景画像に直接合成できます。ただし、後で使用されている 'dispose' メソッドを "-set" するか、より良いことに最適化して完全に合体したアニメーションにする必要がある場合があります。ただし、他のタイプの最適化されたアニメーションでは、"-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' アルファ合成を使用して、それをオーバーレイできます。境界フラット化メソッド(上記)を使用します。ただの単色...

  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の透明度の問題も解消しました。
上記の例では、プロセスの個々のステップをマジック表示できるようにGIF形式の画像を使用しましたが、実際には、すべてのステップを単一のコマンドに結合するか、MIFFなどのより優れた中間画像ファイル形式を使用します。つまり、完了するまでGIF形式に固有の問題を回避するために行われました。

キラキラタイル- 「画像内の穴」をアンダーレイする

前述のように、WWWには、事前に準備されたアニメーションキラキラタイル画像がたくさんあります(「キラキラタイル」を検索してください)。1つのソースは、IM Studioユーザー、scri8eとそのウェブサイト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]
上記の穴は、マット塗りつぶし描画プリミティブを使用して作成されました。これは、色の置換のために画像から実際の点と色を選択します。つまり、比較色が選択した特定の領域から取得されたため、最初に使用したような高いファズファクターを使用する必要はありません。また、タイル化される画像の正確な寸法を知らなくても、完全にカバーできるように、より大きなタイル化「ビューポート」を使用しました。
一般的な歪み演算子とその特別な「viewport」オプション(IM 6.3.6-0に追加)を使用すると、歪みパターンを他の特別な方法で変更する機会も得られます。たとえば、「遠近感」を与えたり、パターンを非矩形角度に回転させたりすることができます。これを行うと、タイル張りが均一に見えないように強調することができます。

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

きらめき- ほとんど透明なグリッターを重ねる

これまでの2つのグリッターアニメーション技術の主な問題は、完全に置き換えられるか、全く置き換えられないかのいずれかであることです。画像の元の陰影や背景を使用することはできません。また、グリッターはマスクされた領域に完全に制限されています。関与する領域の境界を超えて拡張することはできません。そのため、前の例のウィザードの「帽子」のような小さな領域は、グリッターをうまく処理できません。きらめきは異なり、追加されるアニメーションはほとんど透明です。その結果、元の画像はまだ透けて見えます。このようなアニメーションは通常、次の2つの方法のいずれかで画像に追加されます。アニメーションオーバーレイ自体が透明であるか、画像が明るくなるはずの白い「スパーク」と黒の背景の形式です。
構築中
ほとんど透明な「きらめき」オーバーレイの例を次に示します。例はこちら。ご覧のとおり、この形式を使用すると、カラフルなきらめきオーバーレイを作成できます。この主な問題は、保存するためにGIFアニメーションが使用されたこと(これが典型的です)であり、オーバーレイは非常にエイリアスがかかっていることです。つまり、オーバーレイ画像の見た目を滑らかにするための半透明ピクセルを含めることはできません。もしそうすると、最終結果の「きらめき」の周りに恐ろしい黒いハローが表示されます。ウィザードにこれをマスクしてオーバーレイしてみましょう。例はこちら。もう1つの形式のきらめきは、黒い背景に白いきらめき(グレースケール画像)です。これらは、きらめきを追加するために画像を明るくするようにマスクされ、オーバーレイされます。たとえば… 例はこちら。きらめきについての最も良いことの1つは、きらめきがゆっくりと現れて消えるフレームのシーケンスを生成できることです。これは非常に複雑になる可能性がありますが、それほど難しいことではありません。例はこちら

フレアと星のアニメーションの追加

グリッターは単一の明るさの点で構成され、きらめきは画像のいくつかの領域に重ねることができますが、フレアは通常個別に加えられます。「フレア」は基本的に、ほんの一瞬だけ広い領域をカバーするために点滅する点です。「星」は似ていますが、カバレッジはより明るさの「光線」の形をしています。これらは通常特定の点から「シード」されますが、結果は多くの場合、少なくとも一時的にシード領域をはるかに超えて拡張されます。たとえば、特定の領域にマスクが制限されているフレアは、非常に馬鹿げていて不自然に見えます。フレアのより難しい側面は、適切な「シード」ポイントを見つけて、複数のフレアのタイミングを適切に調整することです。
構築中
Final example I want to create...  A 'sparkle' the travels up the wizards
wand, then flares, and dissolves into a number of small sparkle flares over an
area.  Then the sequence repeats.

アニメーションのサイズ変更

アニメーションのサイズ変更に関する問題

GIFアニメーションのサイズ変更に関する最大の問題は、"-resize"演算子が、結果の画像が(サイズ変更後)可能な限り理想に近づくように特別に設計されていることです。これは、画像の見栄えを良くするために、画像内の多数の追加の色を結合および生成することによって行われます。結果として得られる画像は、制限されたGIFファイル形式での保存には理想的とは言えません。GIFの限られたカラーテーブルでは、これにより、サイズ変更された画像でカラー削減が大幅に行われます。単一のGIF画像ではそれほど悪くはありませんが、GIFアニメーションでは、縮小されたカラーセットのデフォルトの誤差拡散ディザリングによって、フレーム間の「ディザノイズ」と、最終的なファイルサイズのフレーム最適化が悪くなるという問題が発生します。Webページで使用される典型的なGIFアニメーションで一般的な慣行である、透明色が使用されている場合はさらに悪化します。透明度は、それ以外には必要ないアニメーションの圧縮最適化技術にもよく使用されます。何が起こるかというと、"-resize"は、オーバーレイ画像に半透明のピクセルを生成します。次に、画像がGIFファイル形式に保存されると、これらのピクセルは完全に透明または完全に不透明のいずれかに変換され、結果のアニメーションに大きな色の歪みが生じます。何らかの形式の最適化(フレーム、透明度、LZWなど)が使用されている場合、透明度の効果により、基本的にサイズ変更されたGIFアニメーションが大失敗になります。それが事実です!したがって、それを受け入れる必要があります。"-resize"の使用を避け、"-sample"を使用しても、最初にアニメーションを"-coalesce"しない限り、大きな問題が発生します。

アニメーションのサイズ変更技術

上記のように、GIFアニメーションのサイズ変更には重大な問題があり、どれも簡単には解決できません。解決策は、最初にサイズ変更された画像の種類(漫画のようなものか、現実世界のビデオ画像か)によっても異なります。以下に、私が知っている、または提供された方法を示します...

サイズ変更を避ける

可能であれば、サイズ変更しないでください。たとえば、アニメーションをキャンバスまたはビューポートクロップして、必要なスペースに収まるように切り詰めることができます。または、最初に正しいサイズでGIFアニメーションを生成することもできます。どちらの手法も通常は最良のオプションではありませんが、可能であれば、多くの問題や苦労を回避できるため、検討してください。

直接的なサイズ変更

上記のように、"-resize"を直接使用すると、各フレームの色数または半透明の色に問題が発生します。たとえば、これは本当にひどいことになります...

  magick script_k.gif -resize 20x20 script_k_direct.gif
[IM Output]
==> [IM Output]
うまくいきませんでしたが、これは元の画像に重いフレーム最適化があるためです。アニメーションの各「フレーム」は同じサイズではなく、"-resize"は、他の画像とは完全に別々に各フレーム画像をサイズ変更します。つまり、上記は、アニメーションの仮想キャンバスではなく、実際のフレーム画像のサイズを変更しました。実際、結果のアニメーションが、示されている空白領域よりも「クレイジー」ではなかったことに驚いています。これにより、アニメーションのサイズ変更に関する最初のポイントが得られます。最初に、すべてのフレームが完全に定義されていること、およびすべての最適化が削除されていることを確認します。言い換えれば、サイズ変更を試みる前にアニメーションを合体させます。たとえば...

  magick script_k.gif -coalesce  -resize 20x20  script_k_direct2.gif
[IM Output]
==> [IM Output]
次の問題は、透明色の1つです。上記の結果を見ると、小さいアニメーションの端がひどくエイリアス(「階段状」)になっていることがわかります。これは、GIFが"-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"することです。これにより、アニメーションの現在の色が保持され、新しいサイズでアニメーションを簡単に再最適化できるようになります。

  magick script_k.gif -coalesce  -sample 20x20  script_k_sample.gif
[IM Output]
==> [IM Output]
しかし、この方法は機能するものの、基本的には画像からピクセル行と列を削除しているため、画像データが失われ、その結果、画質が低下します。アニメーションのような画像では、しばしば「点々」の境界線や、欠落または歪んだディテールが生じます。上記のように、リサイズがアニメーションの元のサイズの 50% を超える場合、特にテクスチャや他のカラーパターンがアニメーションで使用されている場合、結果は非常にひどいものになることがよくあります。多くの GIF アニメーションライブラリが、ネット上からコピーしたこのようなひどいリサイズされたサンプルアニメーションで満たされているのも不思議ではありません。私はよく、このようなゴミを一掃してほしいと思いますが、それは提供する GIF の数を減らすことを意味し、それがひいては利用可能な GIF の数のマーケティング統計を減らすことになり、広告部門はそれを好みません。その結果、ひどい GIF アニメーションが一般的になっています。

リキッドリサイズを使用したリサイズ

上記のサンプルメソッドを使用するのと同様の方法は、リキッドリサイズを使用することです。これは、シームカービングとしても知られています。これも、画像からピクセル全体を削除または追加しますが、画像の複雑さをできるだけ保持するように試みます。上記のリンクを見て、よりきれいにリサイズされた画像を生成する方法を確認してください。残念ながら、現時点では、画像の複雑さを理解できず、アニメーションの各フレームに一貫した方法で適用するためのリスケール方法を抽出することができないため、一般的なアニメーション画像にこれを使用する方法はありません。うまくいけば、将来のある時点でこれが変わるでしょう。

リサイズとカラーの復元

アニメーションをサンプリングすると、ピクセル行と列が削除されるだけで、細い線やその他の重要なディテールが削除される可能性があります。しかし、「-resize」を使用してピクセルをマージすると、GIF 形式では多すぎる新しい色が生成されます。したがって、明らかな解決策は、「-resize」を実行してから、カラーマップを使用することで、元のカラーを使用してリサイズされたアニメーションのカラーを復元することです。
FUTURE: example with original color table restored
これにより、ローカルカラーテーブルが生成されないという利点が加わります。ただし、ディザノイズを避けるために、ディザをオフにすると結果が良くなる可能性があります。これは、滑らかな色で覆われた大きな領域を持つアニメーションのような画像の場合に特に当てはまります。
FUTURE: non dithered color table restored example

フルカラー最適化

ひどいサンプリングされたサムネイルが気に入らない場合は、リサイズされた GIF アニメーションのフルカラー最適化を行うという見込みに直面します。アニメーションに保持させたい「新しい」色を整理するためです。ただし、これはほとんどのアニメーションではそれほど悪くはありませんが、ビデオを GIF アニメーションに変換するときのような、より複雑なアニメーションでは大変な作業になる可能性があります。つまり、アニメーションのようなアニメーションを扱っている場合、現在、アンチエイリアス処理された線やエッジが大量にあります。透明な背景を含むアニメーションの場合、リサイズのアンチエイリアス機能によって生じるアニメーションの端の周りの半透明のピクセルも適切に処理する必要があります。これを処理するために使用できる多くの方法については、GIF ブール透明度のセクションを参照してください。

大幅なリサイズ縮小

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

複数のアニメーションの結合

以前にも言いましたが、アニメーションを結合するときに特に重要になります...
作業しているアニメーションについてできる限り多くを知ってください!
gif2anim」スクリプトは、この目的に最適です。その姉妹スクリプトである「anim2gif」も、元の設定を使用してアニメーションを再作成するためにここで一般的に使用されます。(スクリプトの基本的な使用法については、アニメーションリスト情報を参照してください。)アニメーションがどのように機能するかについての知識がないと、さまざまな方法でそれらを結合することはほとんど不可能です。このようなプログラムを開発できます(これらの例の究極の目標)。ただし、そのようなプログラムは非常に複雑で、予期しない結果が生じる可能性があります。このため、これらの例は、アニメーションをどのように処理および結合する必要があるかを理解するために、引き続き従う必要があります。

連続または時間的な付加

2 つの GIF アニメーションを時間的に連結して、1 つのシーケンスが別のシーケンスに続くようにすることは、IM では簡単です。基本的には、コマンドラインにそれらをリストするだけで、それらは互いに追従します。ただし、見た目ほど簡単ではない可能性があります。たとえば、ウェブを検索した結果、いくつかの文字が描かれているアニメーションを 2 つ見つけました(この例のために盗んで大幅に修正しました)。ここで、これらの画像を結合して、1 つのアニメーションが完了すると次のアニメーションが開始するように、誰かが「OK」という単語を書いているかのようにしたいと考えています。これが文字、「アニメーションシーケンス」、およびこれら 2 つのアニメーションの内部の詳細です。

  gif2anim -n script_o.gif
  gif2anim -n script_k.gif
 
[IM Text]
[IM Text]
[IM Output]
[IM Output]
これらのシーケンスは、空のキャンバスから始まり、このキャンバスにピクセルをゆっくりと追加および変更するだけです。以前のフレームで追加されたピクセルを削除、クリア、または透明にすることはありません。ただし、結果にはほとんど影響しないため、ここでは問題になりません。また、アニメーションのフレーム数もこの操作には影響しません。重要なのは、フレームのタイミングを知ることです。これは問題を引き起こす可能性があるためです。特に、最初のフレーム、またはこの場合は最後のフレームのタイミング遅延に注意してください。この手法は非常に一般的で、アニメーションがクリアされて再開する前に、視聴者が最終結果を確認する時間を与えます。時間的な追加を行う際に問題を引き起こすのは、これらの遅延とフレームです。また、「k」アニメーションには、アニメーションシーケンスの途中にわずかな遅延があることにも注意してください。この遅延は、このアニメーションの最初のブラシストロークの終わりと 2 番目のブラシストロークを表します。この遅延も保持する必要があります。つまり、アニメーション内のすべてのタイムシーケンスを一定の値に変更することはできません。上記に示されていないことは、両方のアニメーションの最初のフレームが実際には空白のキャンバスであるということです。2 番目のアニメーションでは、無駄な時間の浪費としてそのキャンバスを廃棄したいでしょうが、最初の遅延として最初のアニメーションには保持する必要があります。2 つのアニメーションを調べたので、それらを結合して、時間的に互いに追従するようにしてみましょう。時間的なアニメーションの追加は、実際には非常に簡単な操作であり、コマンドラインで 2 つのアニメーション画像を連結するだけです。それでは、それを試してみましょう...

    magick script_o.gif script_k.gif   script_ok_try1.gif
[IM Output]
結果は完璧とはほど遠いものでした。文字は正しい順序で描画されますが、互いに重ねて描画されます!それだけでなく、最初の「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]
結果は大幅な改善です。ただし、文字の描画間の遅延が明らかに目立つようになりました。必要なのは、最初の「O」アニメーションの最後のフレームの遅延を大幅に短くすることです。見えないアーティストがペンを再配置しているように見えるのに十分な大きさです。これを行うには、最初のアニメーションの最後のフレームのコピーを作成してから、「-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」スクリプトはこの場合に適しており、生成された「.anim」ファイルは後で役立ちます。

  gif2anim -n bag_left.gif
  gif2anim -n bag_right.gif
 
[IM Text]
 
[IM Text]
[left]
[right]
情報の概要を見ると、2 つのアニメーションのフレーム数がまったく同じで、時間シーケンスもほぼ同じであることがわかります。ここで重要なのはタイミングの類似性であり、アニメーションはすでに「時間同期」されていると言えます。ただし、タイミングは正しい可能性がありますが、アニメーションは完全に結合されているのではなく、フレーム最適化されています。ただし、キャンバス領域の高さは同じであるため、2 つのフレームを並べて追加することは実用的です。実際、このアニメーションは、次の例セットで(アニメーションの分割を参照)「分割」されたため、「猫」のアニメーションが 2 つに分割され、元のものが失われました。その他の変更により、タイミングに非常にわずかな違いが生じ、分割がより明確になりました。これは、gmabrysによってIM フォーラムでのディスカッションで提示された問題でしたが、彼が提示した実際の問題ははるかに悪かったです。 [left][right]ブラウザは通常、個別の GIF 画像を同期なしでアニメーション化します。そのため、2 つのアニメーションが互いに同期しなくなる可能性があり、チェーンソー虐殺の一部であったかのように見える「猫」が作成される可能性があります。特に、低速リンクを介して遠隔サーバーに接続している場合は、右側に 2 つのアニメーションをブラウザページに並べて配置したときにこの効果を確認できる場合があります。それでは、それらを 1 つの適切に同期されたアニメーション画像にまとめてみましょう。

別々のファイルの追加

最も簡単な方法は、2つのアニメーションを結合し、それぞれを別々の画像ファイルに分割することです。画像1枚が1フレームに対応します。分割された画像は、必要に応じて結合(またはフレームを修正)できます。完了したら、新しいフレームを使用してアニメーションを再構築できます。ただし、この処理中に失われる可能性のあるアニメーションに関する多くの追加情報を保存する必要があります。

  # Separate animations into coalesced frames (plus a ".anim" file)
  gif2anim -c bag_left.gif
  gif2anim -c bag_right.gif

  # Append the separated frames them together
  for i in `seq -f '%03g' 1 11`; do \
    magick bag_left_$i.gif bag_right_$i.gif +append bag_append_$i.gif; \
  done

  # Rebuild the animation (using one of the ".anim" files)
  anim2gif -c -b bag_append  bag_left.anim

  # Cleanup
  rm -f bag_left.anim bag_right.anim
  rm -f bag_{left,right,append}_???.gif
[IM Output]
ご覧のとおり、これはかなり複雑な処理であり、多数の一時的な画像を生成するため、完了時にかなりのクリーンアップが必要です。もちろん、上記をデバッグしている場合は、個々の一時ファイルを使用すると、処理のどこに問題があるかを把握しやすくなります。また、「gif2anim」スクリプトの威力を示すとともに、「anim2gif」スクリプトが、アニメーションのメタデータを分離して保存し、後でGIFアニメーションを再構築する点で逆の関係にあることも示しています。基本的に、スクリプトに直接コーディングする必要なく、アニメーションの元のタイミングを保持できます。最終的な画像も再最適化する必要がありますが、この場合、アニメーション全体を通して同時に多くのことが発生するため、最適化はほとんど得られません。

レイヤー合成

より良い手法は、マルチイメージリストレイヤー合成を使用してアニメーションを重ね合わせることです。これは、一方の画像セットを拡大し、もう一方の画像セットを重ね合わせて結合するだけです。実際、これは通常の「-append」演算子が内部的に行っていることなので、それほど違いはありません。ここでは、キャンバスのサイズをIMに指示し、「-coalesce」を使用して塗りつぶします。次に、適切なオフセットで他の結合されたアニメーションを重ね合わせます。

  magick bag_left.gif -repage 97x92 -coalesce \
          null: \( bag_right.gif -coalesce \) \
          -geometry +50+0 -layers Composite    bag_append.gif
[IM Output]
もちろん、上記の手法では、最終的なアニメーションのサイズと、重ね合わせるアニメーションに必要なオフセットを事前に知っておく必要がありました。しかし、この処理は高速で、非常にうまく機能し、スクリプト化されたコマンドは画像を事前読み込みして、その情報を判断できます。より汎用的なアニメーション追加メソッドを作成するには、いくつかの巧妙な画像処理を行って、最終的なサイズと追加のオフセットを自動的に決定する必要があります。アニメーションを事前に読み込まずにこれを行うには、いくつかの手順を踏む必要がありますが、単一のコマンドで一般的なアニメーションの追加が可能です。まず、各アニメーションの最初の結合されたフレームを追加して、適切なサイズのキャンバスを作成し、これをクリアする必要があります。最初のアニメーションは結合され、このキャンバスの左半分に重ねられます。次に、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つ紹介したい手法があります。この手法では、複数のアニメーションを同時に追加できますが、元のタイミング情報がすべて失われるという代償があります。多くの場合(常にではありませんが)、これらのタイミングの損失は大きなものではありません。基本的に、各アニメーションのすべてのフレームを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」スクリプトを使用してこれらのタイミングを回復することは可能ですが、そうすると、このメソッドを使用する目的が損なわれるため、一時ファイルとして個々のフレームを追加することにより、最初のアニメーション追加手法を使用した方がよいでしょう。アニメーションを単純な画像として追加しているため、一連のアニメーション全体を同時に追加することができ(さらに幅の広い「フィルムストリップ」を生成)、これがこの手法を非常に有用なものにしています。たとえば、同じタイミングを使用するアニメーションフォントで使用できます。ただし、多くのアニメーションフォントのフレーム数は同じですが、通常はアニメーション化された文字を非同期にするために、各文字のタイミングがわずかに異なることがわかりました(理由についてはアニメーションの分割を参照してください)。一方、ネオンサインはアニメーションのタイミングを同期させる必要があるため、例として使用します。

  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行は、サインの「常に点灯」部分(以前にアニメーション化された各文字の最初のフレーム)を作成します。この後、最後の「壊れた」文字が追加され、アニメーション全体が2回繰り返されて、約16フレームが生成されます。タイミングは、最初と最後のフレームが長時間表示されるように、残りのフレームが非常に速く点滅する(「-delay 10」)ことで、目的の効果を完了するように設定されています。実際、このGIFアニメーションは、おそらくあなたが考えるよりも、含まれるフレーム数に対してはるかに小さく最適化されています。基本的に、IM GIFオプティマイザーは、2番目のフレームごとに「O」アニメーションを再重ね合わせるだけでよいことを発見し、「以前」の破棄を使用して、前の点灯した「O」を復元しました。したがって、アニメーションは、基本的な点滅する最適化されていない「hello」画像よりも約50%大きくなっています。自分で確認してください。ネオンアニメーションを改善できますか?よりリアルにできますか?GIFアニメーションにサウンドがないのは残念です。

アニメーションの分割

アニメーションが再び結合されたので、Webサーバーで使用するために正しく分割を試みましょう。これにより、個々のパーツが互いに干渉することなく個別にアニメーション化できます。これは実際にはかなり難しく、完全に自動化することは試みません。ただし、これを行うことができるWWW上のツールはあります。まず、アニメーション全体でアニメーションのどの部分が変化しているかを調べる必要があります。そのためには、あるフレームから次のフレームへの差異を見つけ、それらをすべてまとめて、アニメーション化されている領域と完全に静止している領域を示すマップに追加する必要があります。これはトリッキーです。基本的に、マルチイメージアルファ合成を使用して、アニメーションの各フレーム間の「」画像を見つけます。これらのグレースケール差画像は加算され、次にチャネルが分離されて加算されます。最後に、しきい値処理を行うことで、アニメーションのいずれかのフレーム間のゼロ以外の変更がすべて純粋な白になります。結果は、画像が変化した場所はすべて白く強調表示された、黒い画像になります。

  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つのフレームもまったく同じです。ただし、「クマ」と「羽」とは異なり、各フレームに「クマ」と「羽」が猫なしでアニメーション化できるように時間遅延が含まれているため、それらの1つを削除することはできません。これらの重複フレームを正しく削除するには、「-layer」メソッド「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]バイトであり、追加されたバージョンとほぼ同じです。サブアニメーションの適切な最適化を可能にするアニメーションを正しく分割した後、合計で[IM Text]バイトを3つの画像で取得します。かなり節約できます。

遠隔変更フレーム分割

構築中
透明度(固定背景)を必要とせずに、「遠く離れた2つの変化するオブジェクト」のフレーム更新を分割する例ですが、パーツ間のタイミング同期は維持されます。次に、透明度の背景で繰り返します(「最適化された」ピクセルを生成するには「OptimizePlus」が必要です)。一般的な例については、フレームアクションの分割を参照してください。

時間的に離れたアニメーションのマージ

2つのアニメーションを同期して実行するためにマージする前に、すべてのアニメーションで同じフレーム数を使用し、同じ時間遅延のセットを使用する必要があります。マージの難しさは、アニメーションのタイミングがどの程度離れているかによって異なります。時間遅延が基本的に一定である場合は、それらを無視して、後でタイミングを修正できます。2フレームアニメーションと6フレームアニメーションをマージする際に時間を無視できる例は、IMフォーラムディスカッションで示されています。また、合計サイクル時間が非常に異なる場合は、一方のアニメーションが2回または3回ループして、もう一方のアニメーションのサイクル時間を満たすように調整する必要がある場合があります。基本的に重要なのはタイミングです。
    おそらくこのような感じでしょう...
  • + アニメーションを共通の総ループサイクル時間に調整する。
  • + フレームの最適化を削除するために、両方のアニメーションを結合します。
  • * フレームの時間遅延を、アニメーションの開始からの時間に変換します。
  • * 時間を同期させるために、必要に応じてフレームを2倍にします。
  • * 開始からの時間をフレームの時間遅延に戻します。
  • + 結合された時間同期フレームを必要に応じて重ね合わせます。
  • + 最適にマージし、「ゼロ遅延」フレームを削除します。
  • + 新しいアニメーションを再最適化します。
「*」の部分は、合計サイクル時間の長さが似ている2つのアニメーションのタイミングを同期させるための単一の新しい「-layer」メソッドに変換できます。
構築中
Example, time disjoint, but same cycle time...

For example suppose you have two animations of three frame with time delays of
    10  10  10
    5    5  20

Both animations are 30 time units long already so that is not a problem.

Now magick the above to the time index when each frame should appear...
and show the overall time line at which frames appear...
   0        10    20   |__ NOTE that both animations
   0   5    10         |   end or loop at 30

From this you can see that you need to insert some extra frames to make them
match.  The first frame of the first animation needs to be repeated at time
index 5

0->5  10  20
0  5  10

And the last frame of the second animation also needs to be duplicated at
time index 20

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

The arrow '->' in the above means the same frame is just repeated (duplicated)
into the next time index. They are actually the same image.

Now that the timings of the frames in both animations are the same, you can
simply merge (composite) the frames together, to get final animation that is
4 frames long.

The four frame will thus have time delays of
5  5  10  10
which still add up to 30 time units (overall time per loop cycle)

Current state of development....

While IM can help gather time delay information (try the '-t' option for
"gif2anim") and build the animation. IM can't perform the time synchronization
needed for two separate coalesced animations.  This may become a special
built-in option.

That is, you will need figure out and double up appropriate coalesced
animation frames so as to change two time-disjoint animations into two
time-synchronized animations.

Once you have the animations time synchronized, you can then simply use the
new "-layers Composite" method, to overlay or merge the two time-synchronized
animations  together very easily.

All the above however assumes the total loop time of the two animations
are at least roughly equal, or not a major concern.


Simplified Solution

A simplified limited solution has been Discussed on IM Forums, for use with fast changing animations (similes).

The solution takes each animation and expand it so that the animation has
a fixed frame rate.  That is, all frames are duplicated so that each frame is
shown for a conatant 6 centi-seconds each.  As such one frame with a 22cs
delay may be replaced by 4 x 6cs frames (24cs total).

After this the animations are further modified so that short animations are
looped multiple times so that the two animations are finally of equal length.
That is, the two animations are made the same overall length in terms of both
time, and number of frames.

Once both animations has the same frame-rate and the same length, Layer Composition can be used to merge/overlay the two
animations, in the right position.

The result can then be optimized using Remove Duplicate Frames to remove any extra unwanted frames (with
appropriate timing adjustments and other Optimizations applied before saving.

This method of having all your component animations in a fixed frame length
form is especially well suited to animation libraries.


-----
Other example to create....
  * Overlay two moving equal time animations into a single animation
    (dancing butterflies, circling atoms, or birds?)
    This should be a straight layers composition.

  * Overlaying a moving animation on a fix background.
    (displace animation linearly with time)

  * Overlay two animations with different numbers of frames but constant time
    delays (see IM Forum Discussion).

  * Oveylay two time disjoint animations (as outlined above)

  * Overlay a simple animated figure, on an animated background.
    (full animation merge)