⚠️ Ini adalah situs terjemahan tidak resmi dan tidak berafiliasi dengan ImageMagick Studio LLC. Untuk informasi resmi, lihat halaman asli (https://usage.imagemagick.org/anim_basics/index.html).

Contoh penggunaan ImageMagick -- dasar-dasar animasi

Kata pengantar dan indeks contoh penggunaan ImageMagick
Animasi GIF dan metadata animasi
Metode disposal frame

Animasi GIF dan metadata animasi

Secara bawaan ImageMagick menangani keluaran sebuah daftar gambar dengan menghasilkan gambar multi-halaman. Namun untuk format gambar GIF, keluaran itu mengambil bentuk khusus berupa 'animasi GIF'. |

  magick -delay 100  -size 100x100 xc:SkyBlue \
          -page +5+10  balloon.gif   -page +35+30 medical.gif  \
          -page +62+50 present.gif   -page +10+55 shading.gif  \
          -loop 0  animation.gif

[IM Output]
Berikut contoh 'sparkle' yang lebih maju, memakai skrip shell "star_field ". Skrip ini saya kembangkan dari percobaan saya membangkitkan medan bintang acak. |

  star_field 70x46  stars1.gif
  star_field 70x46  stars2.gif
  star_field 70x46  stars3.gif
  magick rose:  -compose Screen \
          \( -clone 0 stars1.gif -composite \) \
          \( -clone 0 stars2.gif -composite \) \
          \( -clone 0 stars3.gif -composite \) \
          -delete 0 -set delay 25 -layers Optimize rose_sparkle.gif
  rm stars[123].gif

[IM Output]
Pada dasarnya tiga medan bintang acak dibangkitkan dengan ukuran yang tepat, lalu ditimpakan ke gambar kita, yaitu gambar bawaan IM "rose:", memakai komposisi alpha 'Screen' agar gambarnya menjadi lebih terang dengan pola bintang tersebut. Keseluruhannya lalu dijalankan melalui pengoptimal animasi GIF serba guna milik IM. Perintah di atas mungkin terlihat rumit karena memakai beberapa fitur IM tingkat lanjut yang belum saya perkenalkan, tetapi hasilnya animasi tiga frame yang relatif sederhana namun teroptimisasi dengan baik. Anda juga dapat melihat beberapa animasi yang lebih rumit, yang dibuat memakai skrip shell sederhana, pada animasi distorsi. Ada beberapa pengaturan (setting) IM tambahan yang dibuat khusus untuk animasi GIF, dan mengenalinya adalah langkah pertama memasuki dunia animasi GIF... **-dispose** {method}
| Apa yang harus dilakukan gambar-gambar berikutnya terhadap hasil sebelumnya dari animasi GIF. Opsi yang sah adalah 'Undefined', 'None', 'Previous', dan 'Background. (Penjelasan pengaturan ini ada di bawah)
**-loop** {number} | Berapa kali animasi GIF mengulang urutan gambarnya sebelum berhenti. Ini pengaturan (setting) keluaran 'penulisan gambar', jadi dapat ditaruh di mana saja pada baris perintah, meski hanya pengaturan terakhirlah yang dipakai. Biasanya nilainya nol secara bawaan (loop tak terbatas), namun bila ada gambar yang dibaca membawa nilai berbeda, pengaturan ini akan mengikuti nilai gambar tersebut. Karena itu saya menyarankan agar "-loop" selalu ditetapkan saat membuat animasi GIF, setelah semua gambar dibaca. Untuk keterangan lebih lanjut lihat Akhir dari loop di bawah.
**-delay** {time} | Menetapkan jeda (delay) waktu (dalam 1/100 detik) untuk berhenti sejenak setelah menggambar gambar-gambar yang dibaca atau dibuat setelah pengaturan ini diberikan. Anda dapat menentukan skala jeda yang berbeda dengan memberi penskalaan 'x' (dinyatakan dalam tik per detik). Misalnya '10x1' berarti 10 tik satu detik, sedangkan '10x100' berarti 10 tik seperseratus detik. Pada dasarnya 'x' setara dengan tanda pecahan '/'. Misalnya bila ditulis '1x160', jeda yang ditetapkan sesuai untuk 160 frame per detik. | | Jeda animasi GIF harus dinyatakan dalam perseratus detik agar bekerja dengan benar, dan itulah sebabnya satuan waktu tersebut menjadi bawaan. Faktor 'x' lebih banyak dipakai untuk menghasilkan format yang lebih mirip film, seperti MNG dan AVI.
**-set** dispose {method} **-set** delay {time}
| Sementara pengaturan opsi sebelumnya menetapkan atribut gambar pada gambar yang baru dibuat atau yang dibaca setelah opsi itu diberikan, opsi "-set" adalah operator yang memungkinkan penetapan atribut gambar pada semua gambar yang sudah ada di urutan gambar saat ini. Dengan begitu pengaturan dapat diubah untuk keseluruhan animasi, atau untuk satu frame saja, setelah gambar dimuat atau dimodifikasi.
**-page** {w}x{h}+{x}+{y}
| Ini memungkinkan penetapan posisi offset gambar yang akan dibaca. Karena ini opsi pengaturan (setting), geometry yang diberikan hanya berlaku bagi gambar yang menyusul setelahnya. Gambar yang sudah dibaca ke memori tidak terpengaruh. Bila tidak diberikan, atau dimatikan dengan "+page", offset gambar yang dibaca akan dipertahankan. Bila gambar tidak punya offset, gambar ditempatkan di '+0+0', yaitu pojok kiri atas kanvas kerja atau 'page'.Opsi ini juga bisa dipakai untuk mendefinisikan kanvas kerja yang lebih besar, dengan menyebutkan lebar 'x' tinggi. Hanya pengaturan lebar dan tinggi page dari gambar pertama dalam urutanlah yang dipakai untuk menetapkan ukuran kanvas animasi GIF secara keseluruhan; semua pengaturan ukuran page lainnya diabaikan saat animasi akhirnya ditulis. Saat sebuah animasi GIF dibaca, ukuran kanvas ditetapkan pada semua frame di dalamnya. Animasi MNG dapat menyimpan offset frame, tetapi tidak menyimpan ukuran kanvas. Ukuran gambar pertama menentukan ukuran kanvas seluruh animasi. | | _Format gambar GIF tidak dapat menyatakan offset negatif bagi gambar di atas kanvas. Bila Anda mencoba memakai offset negatif, IM akan mengembalikannya ke nol saat gambar (atau frame animasi) itu ditulis ke file GIF.

Offset positif yang lebih besar daripada kanvas gambar sepenuhnya boleh, tetapi bisa membuat gambarnya tidak tampak di area gambar kanvas saat ditampilkan. Bagaimana sebuah program penampil animasi GIF menangani hal ini tidak terdefinisi. Sebaiknya berhati-hati._
**-repage** {w}x{h}+{x}+{y}
| Ini persis seperti "-page", bedanya ia operator gambar dan bukan pengaturan. Artinya opsi ini bisa dipakai untuk mengubah atau mengatur ulang 'page geometry' sebuah gambar atau frame animasi yang sudah dibaca ke memori. Bentuk sederhananya, "+repage", sekadar mengatur ulang 'page geometry' semua gambar pada urutan gambar saat ini menjadi offset nol dengan ukuran gambar yang sebenarnya. Operasi ini vital ketika Anda mengekstrak frame satu per satu dari sebuah animasi (lihat contoh Adjoin di bawah). Namun "+repage" akan menghancurkan banyak informasi penempatan yang tersimpan di tiap gambar, jadi sebaiknya informasi itu juga diekstrak ke file terpisah untuk dipakai lagi nanti. Lihat Informasi daftar animasi di bawah.

Poin penting

JANGAN menyimpan animasi antara, yang pemrosesannya belum selesai, langsung ke GIF. Anda bisa memakai format internal IM yaitu MIFF sebagai format file sementara, bila ingin mengerjakan sebuah animasi dalam rangkaian langkah pemrosesan terpisah. Saya ulangi...

Jangan pakai GIF sebagai format file antara, pakailah MIFF

Bila Anda melakukan kesalahan besar dengan menyimpannya ke GIF, animasi hasilnya justru bertambah buruk, sebab IM sudah telanjur melakukan kuantisasi warna otomatis untuk mengurangi jumlah warna yang ada. Bukan cuma itu, IM melakukannya pada tiap frame secara sepenuhnya terpisah dari frame lain, sehingga pemrosesan selanjutnya, terutama optimisasi GIF apa pun, menjadi jauh lebih sulit. Mengatasi hal ini persoalan rumit dan berlapis, yang dibahas di bagian berikutnya, optimisasi animasi.


Metode disposal frame

Hal pertama yang menyulitkan orang saat membuat animasi GIF adalah pengaturan (setting) "-dispose". Ini tidak mengherankan, sebab pengaturan tersebut memang rumit. Lebih parah lagi, banyak program animasi, termasuk banyak peramban web, tidak selalu menangani metadata disposal GIF dengan benar. Meski begitu, memakai disposal yang tepat sangat menentukan seberapa baik animasi Anda bekerja dan dioptimisasi. Hal pertama yang perlu diingat pada ImageMagick adalah bahwa hampir semua opsi animasi khusus merupakan pengaturan untuk pembacaan gambar. Artinya, opsi itu berlaku pada gambar yang dibaca setelah pengaturan diberikan. Pengaturan "-loop" satu-satunya yang lazim dipakai setelah animasi selesai, tepat sebelum animasi disimpan. Tugas dasar "-dispose" adalah menentukan bagaimana sebuah gambar dihilangkan, setelah gambar itu ditampilkan selama kurun "-delay"-nya. Jadi, pengaturan "-dispose" dan "-delay" sebuah gambar harus diberikan sebelum membaca gambar untuk frame tersebut. Namun aksinya diterapkan setelah gambar itu ditampilkan. Ini agak berlawanan dengan intuisi, tetapi masuk akal dalam cara IM bekerja atas gambar. Kalau ini diingat, seharusnya tidak ada masalah. Bentuk 'plus' opsi-opsi ini, seperti kebanyakan pengaturan lain di IM, menghentikan penerapan pengaturan pada gambar mana pun yang dibaca. Artinya bila Anda tidak menyebutkan sebuah pengaturan, gambar frame akan tetap memakai pengaturan yang ikut terbaca bersama gambar itu (bila ada). Hal ini bisa menjadi penting nanti saat Anda ingin membaca sebuah animasi GIF untuk diproses lebih lanjut. Atau saat menggabungkan satu animasi GIF ke dalam animasi lain (teknik animasi yang paling sulit).

Dispose None - tiap frame ditimpakan secara berurutan

Pengaturan "-dispose" bawaan untuk animasi GIF adalah '**Undefined**', yang oleh kebanyakan program animasi diperlakukan sama dengan pengaturan disposal '**None**'. Pada dasarnya ini menyuruh komputer membiarkan begitu saja apa pun yang ditimpakan oleh frame bersangkutan. Atau lebih tepatnya, 'jangan lakukan apa-apa'. Namun perhatikan bahwa seluruh kanvas selalu dibersihkan di akhir urutan animasi, sebelum animasi mengulang dari awal. Berikut misalnya sebuah animasi 'dispose None' yang biasa... |

  magick -delay 100 -dispose None \
              -page 100x100+5+10  balloon.gif  \
              -page +35+30 medical.gif  \
              -page +62+50 present.gif  \
              -page +10+55 shading.gif  \
          -loop 0  anim_none.gif

[IM Output]
Teknik disposal ini ideal untuk animasi yang tidak melibatkan transparansi dalam bentuk apa pun, misalnya animasi yang digambar di atas latar belakang warna polos atau berpola. |

  magick -dispose none  -delay 100 \
                -size 100x100 xc:SkyBlue +antialias \
                -fill DodgerBlue -draw 'circle 50,50 15,25' \
                -page +5+10  balloon.gif  \
                -page +35+30 medical.gif  \
                -page +62+50 present.gif  \
                -page +10+55 shading.gif  \
          -loop 0  canvas_none.gif

[IM Output]
Perhatikan bahwa teknik ini hanya bisa menambahkan warna yang tampak ke sebuah animasi. Teknik ini tidak pernah bisa membuat bagian mana pun dari animasi menjadi transparan lagi. (Lihat animasi overlay di bawah). Untuk menangani transparansi juga, perlu dipakai salah satu jenis metode disposal yang lain.

Dispose Previous - mempertahankan kanvas latar belakang

Metode disposal '**Previous**' relatif sederhana. Ketika gambar saat ini selesai, kembalikan kanvas ke keadaannya sebelum gambar itu ditimpakan. Bila gambar frame sebelumnya juga memakai metode disposal 'Previous', hasilnya sama dengan keadaan sebelum frame tersebut.. dan seterusnya.. dan seterusnya.. dan seterusnya... Misalnya pada animasi ini tiap frame berikutnya akan kembali ke frame paling pertama, yang punya pengaturan disposal 'None, sebelum menimpakan gambar milik frame itu. Hasilnya kanvas latar belakang yang hanya ditimpai gambar tiap frame selama durasi gambar tersebut saja... |

  magick -dispose none  -delay 0 \
                -size 100x100 xc:SkyBlue +antialias \
                -fill DodgerBlue -draw 'circle 50,50 15,25' \
          -dispose previous -delay 100 \
                -page +5+10  balloon.gif  \
                -page +35+30 medical.gif  \
                -page +62+50 present.gif  \
                -page +10+55 shading.gif  \
          -loop 0  canvas_prev.gif

[IM Output]
Perhatikan metode "-dispose" 'None' yang dipakai pada gambar pertama. Ini penting, sebab kalau tidak, frame 'previous' akan mundur sampai ke kanvas kosong asli yang ada sebelum frame pertama. Perhatikan juga bahwa saya memakai "-delay" bernilai '0' pada animasi di atas. Ini menyatakan agar tidak menunggu sebelum menimpakan frame pertama ke 'kanvas latar belakang' ini. Tanpa itu, akan terlihat jeda singkat yang hanya menampilkan gambar kanvas tanpa apa pun di atasnya. Tentu saja saya tetap perlu menetapkan "-delay" yang lebih panjang untuk gambar-gambar berikutnya, kalau tidak semuanya akan muncul dan lenyap dalam sekejap mata, sekaligus menghabiskan banyak siklus CPU penonton. Pemakaian metode disposal 'Previous' rawan menimbulkan kedipan halus, atau jeda, pada sebagian peramban web, terutama pada mesin yang lambat. Meski kini jarang terlihat, kedipannya sendiri masih ada, dan menurut saya itu sebuah bug. Lihat frame jeda nol di bawah untuk rinciannya. Sedikit animasi yang memakai gaya dispose previous, sebabnya animasi semacam itu sangat sulit dioptimisasi komputer. Masalahnya, frame mana yang harus dipilih komputer untuk menjadi gambar latar belakang? Bagi kita manusia mudah saja menentukan gambar terbaik yang dipakai, tetapi sulit bagi komputer. Gambar latar belakang terbaik dalam sebuah animasi bahkan mungkin memang tidak dimaksudkan untuk ditampilkan, seperti pada contoh ini, sehingga bisa jadi tidak ada dalam versi animasi yang belum dioptimisasi.

Dispose Background - membersihkan hingga latar belakang

Kalau dua metode "-dispose" pertama relatif sederhana, '**Background**' mungkin yang paling sulit dipahami. Ketika jeda waktu sebuah frame berakhir, area yang ditimpai oleh frame itu dibersihkan. Bukan seluruh kanvas, hanya area yang tertimpa. Setelah itu, kanvas hasilnya diteruskan ke frame animasi berikutnya untuk ditimpai gambar frame tersebut. Di sini misalnya kita sekadar mengganti tiap frame dengan frame berikutnya. |

  magick -delay 100 -dispose Background \
              -page 100x100+5+10  balloon.gif  \
              -page +35+30 medical.gif  \
              -page +62+50 present.gif  \
              -page +10+55 shading.gif  \
          -loop 0  anim_bgnd.gif

[IM Output]
Supaya jelas benar apa yang terjadi, mari kita tambahkan gambar kanvas awal ke animasinya, sehingga terlihat bagaimana 'Background' sesungguhnya 'membuang' frame itu dari tampilan animasi. |

  magick -delay 100 -dispose none \
                -size 100x100 xc:SkyBlue +antialias \
                -fill DodgerBlue -draw 'circle 50,50 15,25' \
          -dispose background \
                -page +5+10  balloon.gif  \
                -page +35+30 medical.gif  \
                -page +62+50 present.gif  \
                -page +10+55 shading.gif  \
          -loop 0  canvas_bgnd.gif

[IM Output]
Seperti terlihat, tiap kali frame yang ditimpakan dibuang, area frame tersebut dibersihkan menjadi transparan sebelum gambar berikutnya ditimpakan. Di situlah pentingnya metode disposal GIF ini, sebab inilah satu-satunya cara animasi GIF dapat membersihkan piksel mana pun tanpa bergantung pada riwayat frame animasinya. Satu-satunya cara lain untuk membersihkan piksel adalah memakai 'Previous' agar kembali ke frame yang pikselnya masih bersih. Tapi cara itu bergantung pada pengetahuan tentang riwayat urutan animasi, yang membuatnya jauh lebih sulit dioptimisasi komputer. | _Ada pendapat bahwa alih-alih membersihkan area yang tertimpa menjadi warna transparan, disposal ini seharusnya membersihkannya menjadi warna 'background' yang tersimpan sebagai metadata di animasi GIF. Peramban "Netscape" lawas (versi 2 dan 3) memang persis begitu. Tapi peramban itu juga gagal menerapkan metode dispose 'Previous' dengan benar.

Di sisi lain, kanvas awal pun semestinya diambil dari warna 'background' milik format tersebut, dan itu juga tidak dilakukan. Namun semua peramban web modern hanya membersihkan area yang terakhir tertimpa menjadi transparan, sehingga inilah yang kini menjadi praktik yang diterima, dan yang diikuti IM sekarang._
| _Sebelum IM versi 6.2.6-1, operasi IM "-coalesce" dan "-deconstruct" tidak menangani animasi yang memakai disposal 'Background' untuk membuat piksel menjadi transparan, sebagaimana dilakukan semua peramban web utama. Lihat bug animasi untuk contoh dan rinciannya.

Fungsi-fungsi tersebut tetap bekerja baik bila tidak ada pembersihan piksel yang diterapkan atau dimaksudkan. Kini hal itu sudah diperbaiki untuk "-coalesce", dan metode "-layers OptimizeFrame' dibuat untuk menggantikan pemakaian "-deconstruct" sebagai fungsi optimisasi frame animasi GIF._


Mempelajari animasi

Sebelum kita melanjutkan ke dasar-dasar animasi GIF, jenis-jenisnya, optimisasinya, dan teknik penanganannya, kita perlu beberapa teknik untuk mempelajari animasi yang sudah ada.

Identify - informasi tentang sebuah animasi

Nah, sebuah animasi terdiri dari banyak informasi yang dipadatkan ke tiap frame. Sebagian informasi ini dapat dilihat dengan perintah IM "identify" bawaan.

  magick identify canvas_prev.gif

[IM Text]

| Bila keluaran yang Anda lihat tidak seperti di atas, IM Anda agak lawas dan sebaiknya versi ImageMagick yang terpasang dimutakhirkan ke versi terbaru. Kalau tidak, Anda akan melewatkan banyak kemajuan baru dalam penanganan dan pengendalian animasi GIF oleh IM.
Seperti terlihat, gambar sesungguhnya yang disimpan untuk frame kedua dan seterusnya hanya berukuran 32x32 piksel, tetapi semua frame duduk di atas 'kanvas virtual' 100x100 piksel dengan 'offset virtual' pada kanvas yang lebih besar itu. Untuk melihat lebih banyak potongan metadata yang ada, perlu dipakai format persen escape yang lebih khusus agar IM mengeluarkannya.

  magick identify -format "%f canvas=%Wx%H size=%wx%h offset=%X%Y %D %Tcs\n" \
           canvas_prev.gif

[IM Text]

Ini jelas menampilkan bukan hanya ukuran kanvas, ukuran gambar, dan offset, melainkan juga disposal serta jeda waktu yang dipakai tiap frame. Perhatikan bahwa frame pertama punya disposal dan jeda waktu berbeda, yang memang diperlukan agar metode disposal 'Previous' berikutnya bekerja sebagaimana mestinya.

Adjoin - memecah animasi menjadi frame

Seperti terlihat di atas, secara bawaan ImageMagick berusaha menyimpan banyak gambar ke dalam satu file bila format file itu mengizinkannya. Namun sebagaimana dibahas di menulis banyak gambar, IM mengizinkan pemakaian pengaturan "+adjoin" untuk menyuruhnya menyimpan tiap gambar ke disk sebagai gambar terpisah. Sebagai contoh, di sini kita membaca salah satu animasi GIF lalu mengeluarkan gambar tiap frame dalam urutan animasinya.

  magick canvas_prev.gif -scene 1 +adjoin  frame_%03d.gif

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

Bila gambar-gambar di atas diperiksa sungguh-sungguh, akan tampak bahwa kebanyakan peramban web menampilkan area 100x100 yang lebih besar, tempat tiap subframe muncul. Padahal sebagian besar gambar yang ditampilkan sebenarnya hanya berukuran 32x32 piksel, persis seperti yang ditunjukkan perintah 'identify' di atas. Artinya, sebagian besar area itu sekadar kanvas yang tidak digambari apa pun, yang dikenal sebagai 'page geometry' atau 'kanvas virtual' gambar tersebut. Gambar pertama animasi mendefinisikan 'kanvas' yang lebih besar itu, dan tiap frame lain mendefinisikan posisi 'offset' pada kanvas besar tersebut. Informasi tambahan ini dipertahankan pada frame yang disimpan oleh pengaturan "+adjoin". Karena itu animasi GIF-nya mudah dibangun ulang. Bukan hanya informasi page yang dipertahankan pada tiap gambar frame terpisah, melainkan juga pengaturan jeda (delay), loop, dan dispose GIF. Artinya, untuk membangun ulang animasinya Anda cukup membaca semua gambar itu. |

  magick frame_???.gif  anim_rebuilt.gif

[IM Output]
Namun kadang informasi page geometry ini justru tidak ingin dipertahankan. Misalnya bila frame satu per satu hendak dipakai untuk proyek lain. Ukuran dan offset page dapat diatur ulang memakai opsi "+repage" untuk membuang informasi 'kanvas virtual', menyisakan gambar yang sebenarnya saja.
Biasanya, saat mengekstrak subgambar animasi, pengaturan jeda (delay) dan dispose gambar juga diatur ulang agar tidak mengganggu penyuntingan dan penampilan. Sebagai contoh, di sini saya membuang kanvas virtual dan offset yang tidak diinginkan lalu mengatur ulang jeda waktu serta disposal-nya.

  magick canvas_prev.gif  +repage  -set delay 0   -set dispose None \
          +adjoin  repage_%03d.gif

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

Tentu saja bila metadata itu dibuang, diperlukan cara untuk mencatat dan menyunting datanya. Lihat informasi daftar animasi (di bawah) untuk skrip yang mengekstrak subgambar sekaligus menyimpan metadata animasi, dalam bentuk yang dapat dipakai untuk membangun ulang animasinya.

Coalesce - mengisi frame sepenuhnya

Namun melihat animasi dalam bentuk subframe biasanya kurang berguna pada animasi kebanyakan. Salah satu sebabnya, animasi yang sangat teroptimisasi bisa terdiri dari banyak potongan sangat kecil, tanpa petunjuk visual apa pun tentang bagaimana potongan itu saling melengkapi. Bisa juga ada banyak 'noise' lain yang ditambahkan demi optimisasi kompresi untuk memperkecil ukuran file animasi secara keseluruhan. Misalnya, sangat sulit menebak apa sebenarnya yang dilakukan animasi ini hanya dengan melihat subframe-nya satu per satu.

  magick script_k.gif  +repage  +adjoin  script_k_%02d.gif

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

Operasi "-coalesce" pada dasarnya mengubah sebuah gambar menjadi persis seperti tampilan animasi setelah frame sebelumnya di-dispose dengan benar dan subframe berikutnya ditimpakan. Jadi, alih-alih urutan animasi yang tiap frame-nya hanya mewakili perubahan yang ditimpakan ke frame 'ter-dispose' sebelumnya, operator ini membuat pandangan utuh atas animasi pada tiap titik, agak mirip strip film sungguhan ketimbang urutan animasi. Urutan semacam itu, yang dikenal sebagai animasi hasil coalesce, jauh lebih mudah dipelajari, disunting, dimodifikasi, dan dioptimisasi ulang. Di sini misalnya kita akan membuat montage dari urutan animasi 'membingungkan' yang sama seperti di atas, tetapi kali ini urutannya kita "-coalesce" dulu, sehingga terlihat apa yang sebenarnya terjadi. |

  montage script_k.gif -coalesce \
          -tile x1 -frame 4 -geometry '+2+2' \
          -background none -bordercolor none coalesce_k_montage.gif

[IM Output]

[IM Output]

Seperti terlihat, hasilnya mirip strip film dari animasinya, sehingga jelas bagaimana potongan-potongan sebelumnya menyatu membentuk huruf 'K' yang digambar tangan. Sejak IM versi 6.2.6, perintah "magick montage" memahami pemakaian "-coalesce", sehingga gambar frame animasi bisa disusun seperti 'strip film', persis seperti di atas. Versi ini juga memuat perbaikan untuk coalesce, jadi pekerjaan animasi GIF apa pun sebaiknya memakai setidaknya versi ini (atau lebih baik lagi versi terbaru). Teknik montage yang lebih baik lagi untuk memeriksa animasi diberikan pada bagian contoh berikutnya.
Pengaturan "-dispose" pada urutan gambar hasil coalesce sebenarnya tidak relevan di dalam animasi hasil coalesce. Namun demi ketenangan pengguna, operator "-coalesce" akan menetapkan pengaturan "-dispose" tiap frame menjadi 'None' atau 'Background' sesuai keperluan, sehingga urutan gambar hasil coalesce tetap beranimasi dengan benar (seperti di atas). _Sebuah frame dengan disposal 'Background' berarti frame berikutnya perlu membersihkan setidaknya satu piksel atau lebih agar tampil dengan benar.

Karena itu, animasi yang oleh "-coalesce" diberi dispose 'Background' berarti tidak dapat disimpan sebagai animasi overlay sederhana (lihat di bawah).

Secara teknis, semua pengaturan dispose pada urutan gambar hasil coalesce bisa ditetapkan ke 'Background' atau 'Previous' untuk menghasilkan animasi frame terhapus (lihat di bawah). Meski tidak semua animasi teroptimisasi dengan baik dalam bentuk itu._
Ada pula beberapa pemakaian operator "-coalesce" di luar animasi. Lihat komposisi coalesce dan pelapisan progresif untuk contoh pemakaian semacam itu.

Montage frame animasi - skrip "gif_anim_montage"

Operator "+adjoin" memungkinkan pengambilan gambar sesungguhnya dari sebuah animasi, dan "-coalesce" memperlihatkan frame hasil animasinya, tetapi kedua metode itu tidak menyertakan banyak informasi tentang animasi tersebut. Dengan manipulasi gambar animasi yang sangat cermat, frame dapat ditampilkan sedemikian rupa sehingga yang terlihat bukan hanya frame sesungguhnya, melainkan juga penempatan frame itu pada kanvas yang lebih besar. Berikut salah satu metode menampilkan animasi seperti itu.

  magick -dispose Background   script_k.gif  -alpha set \
          -compose Copy -bordercolor black -border 1x1 -compose Over \
          -coalesce  -bordercolor none   -frame 4x4+2+2 \
          -bordercolor none -border 2x2 +append  script_k_parts.gif

[IM Output]

Di sini jelas terlihat bagaimana animasinya bekerja. Tiap gambar subframe ditempatkan sedemikian rupa sehingga menambah semua overlay sebelumnya. Hasilnya gambar yang tumbuh perlahan. Tiap frame juga jauh lebih kecil daripada 'kanvas virtual' tempatnya ditempatkan. Saya sering memakai teknik tampilan ini selama pengembangan dan penelusuran bug animasi GIF, sehingga saya jadikan skrip shell "gif_anim_montage ", lalu saya perluas agar sekalian mendaftar sebagian rincian di atas tiap frame animasi.

  gif_anim_montage   script_k.gif   script_k_frames.gif

[IM Output]

Perhatikan variasi pewaktuan yang dipakai pada berbagai frame, yang menjeda seolah-olah pena diangkat dari kertas lalu dipindahkan. Animasi dengan pewaktuan beragam bisa termasuk yang paling menarik, tetapi juga lebih sulit ditangani, seperti akan terlihat pada halaman contoh IM berikutnya. Skrip "gif_anim_montage" juga punya opsi khusus '-u' yang melapiskan salinan semitransparan animasi hasil coalesce di bawahnya. Dengan begitu terlihat bagaimana subframe baru mengubah animasi yang ditampilkan.

  gif_anim_montage  -u  script_k.gif  script_k_frames.png

[IM Output]

Tentu saja gambar ini punya piksel semitransparan sehingga format gambar 'PNG' diperlukan, ATAU Anda bisa memakai salah satu dari banyak opsi 'background' yang juga disediakan skrip itu, sehingga format GIF atau bahkan JPEG bisa dipakai untuk gambar ringkasan animasinya. Opsi lain memungkinkan penentuan jumlah baris atau kolom yang dipakai, penetapan berbagai latar belakang tak transparan, atau pemakaian kotak merah alih-alih hitam yang bawaan. Skrip ini akan banyak dipakai pada beberapa halaman contoh IM berikutnya. Saran dan komentar dipersilakan.

Informasi daftar animasi - opsi yang dipakai untuk membangun animasi

Seperti sudah saya sebutkan, "+adjoin" dan "-coalesce", begitu pula "+repage", semuanya metode yang berguna untuk mengekstrak dan mengamati animasi GIF. Namun semuanya menghancurkan informasi tentang animasi aslinya dalam prosesnya. Informasi tambahan tentang framing, jeda waktu, dispose frame, dan sebagainya bisa dilihat memakai perintah IM "magick identify" dengan opsi "-verbose". Tapi saya, dan mungkin kebanyakan pengguna lain, merasa keluaran perintah ini terlalu banyak untuk dicerna dan tidak benar-benar langsung bisa dipakai. Di sinilah skrip shell khusus lain yang saya tulis berperan. Skrip "gif2anim " akan memisahkan frame animasi satu per satu, sekaligus mencari tahu persisnya opsi IM "magick" apa saja yang Anda perlukan untuk membangun ulang animasi itu dari gambar-gambar tersebut. Anggap saja "gif2anim" sebagai pembongkar animasi, yang menghasilkan ringkasan animasi dalam bentuk opsi IM. Sebagai contoh, mari kita bongkar contoh animasi yang sedari tadi kita pakai untuk memulihkan pengaturan "magick" asli yang dipakai membuatnya, berikut gambar-gambar yang dipakainya... |

  gif2anim canvas_prev.gif

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

Secara bawaan skrip "gif2anim" memakai nama dasar file yang sama untuk gambar satu per satu dan untuk file opsi ".anim". Karena itu file urutan animasi yang dihasilkan perintah di atas bernama "canvas_prev.anim", dengan gambar frame "canvas_prev_001.gif" sampai "canvas_prev_005.gif". Bila hasilnya diperiksa lebih teliti, akan terlihat bahwa skrip itu memang berhasil membuat ulang opsi asli yang saya pakai ketika pertama kali membuat animasi GIF ini (lihat animasi dispose previous). Selain itu, meski tidak penting bagi pembuatan animasinya sendiri, ukuran dan pewaktuan frame yang ditimpakan juga didaftar sebagai komentar agar lebih mudah dipelajari. Alih-alih menyimpan hasilnya ke file, opsi urutan animasi bisa langsung ditampilkan ke layar memakai flag "-l". Artinya, keluarkan saja file urutan animasinya, tanpa menyimpannya maupun gambar frame animasi satu per satu.

  gif2anim -l canvas_prev.gif

Dengan adanya file ".anim" beserta gambar tiap frame, skrip pelengkap "anim2gif " dapat dipakai untuk membangun ulang animasinya. |

  anim2gif canvas_prev.anim

[IM Output]
Secara bawaan "anim2gif" akan membuat ulang animasi GIF dengan akhiran "_anim.gif". Terlihat bahwa animasi "canvas_prev_anim.gif" yang dihasilkan tampak dan bekerja persis seperti animasi aslinya. Skrip ini sekadar mengganti string khusus "BASENAME" yang dipakai di dalam "file urutan animasi", membuang semua komentar, lalu meneruskan opsi convert yang tersisa ke perintah "magick". Dengan kata lain, file di atas diperlakukan sebagai semacam skrip 'convert' berkomentar. Alasan dipakainya string khusus adalah agar Anda bisa menyebutkan nama dasar file yang berbeda dari nama file ".anim" itu sendiri. Dengan begitu, sekumpulan gambar frame yang sama sekali lain, misalnya versi modifikasi dari aslinya, bisa dipakai untuk membuat animasi berbeda dari yang lama. Ini fitur yang sangat berguna dan akan dipakai pada pemrosesan animasi yang lebih rumit. (Lihat penyambungan animasi berdampingan sebagai contoh). Seperti "gif2anim", skrip "anim2gif" punya cukup banyak opsi berguna untuk membantu memproses dan memodifikasi animasi. Sebagian opsi itu akan dipakai nanti. Misalnya lihat penyambungan animasi. Selain itu, karena file ".anim" berupa teks biasa, file itu bisa dipakai untuk mengambil gambar animasi yang sudah dibongkar lalu menyetel metadata GIF-nya, seperti pewaktuan, posisi, bagian animasi yang berulang, atau menambahkan frame dan gambar baru ke sebuah animasi. Itulah sebetulnya alasan awal saya menulis skrip-skrip ini, jauh sebelum saya terlibat dengan contoh-contoh IM. Untuk sekarang, "gif2anim" paling berguna untuk memeriksa urutan animasi guna melihat apa yang sedang terjadi dan pewaktuan yang diterapkan antar-frame.

Dispose Images - bentuk dispose GIF dari tiap frame

Metode "-layers" khusus, '**Dispose**', memperlihatkan bagaimana seharusnya rupa sebuah frame setelah jeda waktunya berakhir dan metode dispose GIF diterapkan, tetapi sebelum gambar frame berikutnya ditimpakan. Dengan kata lain, ini menunjukkan persis apa yang sebenarnya dilakukan pengaturan metode "-dispose" GIF terhadap frame, sehingga Anda dapat mengetahui persis apa yang salah pada animasi Anda. Sebagai contoh, beginilah rupa masing-masing dari tiga contoh animasi metode dispose kita setelah metode dispose tiap frame diterapkan. Ingat, tiap animasi ini terdiri dari sebuah 'gambar kanvas' yang diberi pengaturan "-dispose" 'None', lalu disusul empat gambar lebih kecil yang ditimpakan lalu dibuang oleh berbagai metode dispose GIF. Animasi dispose 'None'...

  magick canvas_none.gif -layers Dispose canvas_none_dispose.gif
  gif_anim_montage canvas_none_dispose.gif canvas_none_dispose_frames.gif

[IM Output]

Animasi dispose 'Previous'...

  magick canvas_prev.gif -layers Dispose canvas_prev_dispose.gif
  gif_anim_montage canvas_prev_dispose.gif canvas_prev_dispose_frames.gif

[IM Output]

Animasi dispose 'Background'...

  magick canvas_bgnd.gif -layers Dispose canvas_bgnd_dispose.gif
  gif_anim_montage canvas_bgnd_dispose.gif canvas_bgnd_dispose_frames.gif

[IM Output]

Bila mempelajari yang di atas, akan terlihat persis bagaimana masing-masing dari tiga metode dispose GIF membersihkan animasi dari gambar yang ditimpakan frame tersebut. Perhatikan bahwa frame pertama ketiga animasi ini selalu diberi dispose 'None' sehingga tetap tak berubah. Yang penting adalah efek metode dispose pada frame-frame berikutnya. Operasi "-layers Dispose" hanya menghasilkan urutan 'hasil coalesce' dari frame disposal-nya. Operasi ini tidak mengatur ulang pengaturan disposal itu sendiri, sehingga hasilnya bisa jadi tidak beranimasi sebagaimana mestinya. Agar hasil di atas beranimasi dengan benar, tetapkan semua metode disposal ke 'previous' atau 'background', atau optimisasi animasinya sebelum disimpan.
_Rupa frame terakhir setelah metode dispose GIF biasanya tidak berpengaruh pada animasi GIF, sebab seluruh kanvas dibersihkan sepenuhnya sebelum animasi mengulang (loop). Bila animasi tidak 'loop' melainkan berhenti di akhir urutan, disposal frame terakhir tidak diterapkan.

Dengan kata lain, rupa frame terakhir (setelah disposal) seperti ditampilkan di atas, bahkan pengaturan dispose frame terakhir itu sendiri, tidak berpengaruh apa pun pada animasi GIF. IM umumnya menyetelnya sama dengan frame sebelumnya ketika mencoba menentukan metode disposal yang tepat, selama optimisasi frame sebuah animasi._

Deconstruct - melaporkan area perbedaan antar frame

Cara tradisional di ImageMagick untuk mengoptimisasi animasi, agar hasilnya lebih kecil serta lebih cepat diunduh dan dianimasikan, adalah men-"-deconstruct" bentuk "-coalesce"-nya. Cara ini tidak lagi disarankan. Sebagai gantinya pakailah pengoptimal GIF serba guna. Operator ini mengambil urutan gambar hasil coalesce (frame animasi sebagaimana benar-benar tampak saat ditampilkan), lalu membandingkan gambar kedua dan seterusnya dengan gambar sebelumnya. Gambar itu kemudian diganti dengan area persegi terkecil yang memuat piksel yang berubah. Perubahan piksel apa pun ikut dihitung, tak peduli berupa perubahan warna (overlay) atau pembersihan (penghapusan). Ini cukup sederhana, dan untuk animasi overlay pada umumnya akan menghasilkan optimisasi frame yang optimal bagi animasi tersebut. Namun sebuah animasi overlay hanya memakai metode dispose 'None' saja. Sebagai contoh, mari kita ambil animasi previous hasil coalesce yang kita buat di atas, yang kebetulan membentuk animasi overlay, lalu kita jalankan melalui operator "-deconstruct". |

  magick canvas_prev.gif   -coalesce     coalesce.gif
  magick coalesce.gif     -deconstruct   deconstruct.gif
  gif_anim_montage  coalesce.gif     coalesce_frames.gif
  gif_anim_montage  deconstruct.gif  deconstruct_frames.gif

[IM Output]
[IM Output]
[IM Output]
Kalau Anda ingat, sebuah 'animasi dispose previous' membersihkan tiap frame kembali ke frame ter-dispose terakhir yang bukan previous, dalam hal ini kanvas latar belakang awal. Seperti terlihat, "-deconstruct" mengembalikan area yang berubah dari satu frame hasil coalesce ke frame berikutnya. Hasilnya animasi overlay teroptimisasi yang tidak memerlukan pengaturan dispose khusus. Ini jauh dari seoptimal animasi buatan tangan yang saya pakai di awal, tetapi tetap berguna. Sayangnya "-deconstruct" sama sekali tidak memahami pengaturan "-dispose" animasi GIF. Akibatnya bila cara ini dicoba pada animasi yang membersihkan piksel dari satu frame ke frame berikutnya, seperti animasi 'dispose background' yang kita buat di atas (dan ditampilkan di kiri), hasilnya akan kacau. | [IM Output]
Di sini kita ambil animasi yang baru saja ditampilkan, lalu kita jalankan melalui siklus "-coalesce" dan "-deconstruct". |

  magick canvas_bgnd.gif  -coalesce  -deconstruct  deconstruct_erase.gif

[IM Output]
Seperti terlihat, "-deconstruct" perlahan-lahan merusak animasinya. Pada dasarnya "-deconstruct" dirancang sekadar untuk menemukan perbedaan antar-layer gambar. Operator ini tidak pernah dirancang untuk mengoptimisasi animasi dengan benar, dan akan gagal pada animasi yang perlu memakai berbagai teknik disposal untuk membersihkan (menghapus atau membuat transparan) piksel yang sebelumnya ditimpakan.

Perbandingan frame - membandingkan frame secara lebih rinci

Pada IM v6.2.6-2 ditambahkan sejumlah metode perbandingan frame GIF tambahan. Metode ini diperlukan secara internal demi optimisasi animasi yang benar, tetapi dianggap cukup berguna untuk disediakan pula pada baris perintah dan antarmuka API lain.

Compare_Any

Metode "-layers" '**CompareAny**' sebenarnya persis sama dengan "-deconstruct". Malah operator "-deconstruct" cuma alias fungsional bagi metode 'CompareAny'. Sekali lagi mari kita lihat hasil gambar sesungguhnya dari 'deconstruct' atau 'CompareAny' atas animasi 'dispose background'.

  magick canvas_bgnd.gif  -coalesce  canvas_bgnd_coal.gif
  gif_anim_montage canvas_bgnd_coal.gif canvas_bgnd_coal_frames.gif

  magick canvas_bgnd_coal.gif  -layers CompareAny   magick compare_any.gif
  gif_anim_montage compare_any.gif compare_any_frames.gif

[IM Output]
[IM Output]

Seperti terlihat, gambar kedua dan seterusnya adalah area persegi minimal yang memuat semua piksel yang berubah, entah berupa penimpaan warna piksel baru maupun pembersihan piksel lama menjadi transparan.

Compare_Clear

Metode "-layers" '**CompareClear**' menampilkan area persegi terkecil yang memuat semua piksel yang perlu dibersihkan dari satu frame ke frame berikutnya.

  magick canvas_bgnd_coal.gif -quiet -layers CompareClear compare_clear.gif
  gif_anim_montage compare_clear.gif compare_clear_frames.gif

[IM Output]

Perhatikan bahwa karena tidak ada piksel yang dibersihkan antara frame pertama dan kedua, sebuah gambar 'missed' khusus dihasilkan. Pengaturan "-quiet" dipakai untuk menyuruh IM tidak memberi peringatan apa pun tentang gambar ini. Bila semua frame berikutnya menjadi 'missed image', berarti animasi GIF itu tidak pernah membersihkan piksel, dan animasinya dapat digolongkan sebagai animasi overlay.

Compare_Overlay

Metode perbandingan "-layers" terakhir, '**CompareOverlay**', mengembalikan area piksel yang ditimpakan (ditambahkan atau berubah warnanya, tetapi tidak dibersihkan) sejak frame sebelumnya.

  magick canvas_bgnd_coal.gif  -layers CompareOverlay  magick compare_overlay.gif
  gif_anim_montage compare_overlay.gif compare_overlay_frames.gif

[IM Output]

Ini mirip dengan metode komposisi alpha 'ChangeMask" khas IM. Bedanya, metode itu mengembalikan hanya piksel yang mengubah gambar, bukan area persegi yang berubah. Lihat juga optimisasi transparansi. Tak satu pun metode perbandingan "-layers", maupun operator "-deconstruct", melihat atau mengubah metode dispose GIF yang dipakai gambar. Hasilnya sekadar daftar gambar, dan tidak dimaksudkan untuk dipakai sebagai animasi.
_Meski operator ini dirancang untuk bekerja dengan urutan gambar hasil coalesce, operator ini menerima urutan layer gambar yang belum di-coalesce tanpa memunculkan error.

Dalam hal ini tiap frame ditimpakan ke frame-frame yang sudah ditimpakan sebelumnya memakai metode komposisi alpha 'Copy', sebelum frame-frame itu dibandingkan. Metode komposisi alpha ini memastikan transparansi apa pun pada sebuah layer ikut ditambahkan ke gambar tujuan. Tanpa itu, cara di atas tidak akan menemukan piksel yang dibersihkan menjadi transparan pada urutan gambar hasil coalesce.

Perhatikan bahwa ini berbeda dari metode komposisi 'Over' yang lebih lazim, yang dipakai operator "-coalesce" untuk menangani siklus 'dispose/overlay' yang diperlukan guna menampilkan animasi GIF.

_


Jenis-jenis animasi

Kebanyakan animasi GIF yang Anda temui termasuk ke dalam beberapa jenis animasi dasar. Mengenali jenis-jenis ini membuat Anda paham bagaimana animasi tersebut ditampilkan dari satu frame ke frame lain, dan memungkinkan jalan pintas dalam menangani serta memodifikasinya.

Animasi hasil coalesce

'Animasi hasil coalesce ' pada dasarnya urutan gambar yang menunjukkan bagaimana seharusnya sebuah animasi tampak bagi pengguna setelah tiap siklus 'dispose/overlay'. Gambar-gambarnya persis seperti yang akan Anda lihat bila menatap 'strip film' animasi itu sungguhan. Inilah bentuk animasi yang paling sederhana dan sama sekali belum dioptimisasi. Penamaan ini berasal dari nama operator IM "-coalesce" yang dipakai untuk mengubah animasi ber-disposal GIF menjadi 'animasi hasil coalesce' yang belum teroptimisasi. Kebanyakan format video (MPEG, AVI, dan sebagainya) sebenarnya juga 'animasi hasil coalesce' menurut sifatnya. Namun format itu cenderung tidak punya piksel transparan, dan umumnya jeda waktu antar-frame-nya tetap. Sebaliknya, animasi GIF hasil coalesce bisa punya piksel transparan dan jeda waktu yang sangat beragam, dari jeda '0' yang langsung, sangat cepat, sampai sangat sangat sangat lambat. Pengaturan disposal GIF apa pun pada animasi hasil coalesce tidak punya makna, tetapi operator "-coalesce" akan menetapkan disposal yang sesuai sehingga urutan gambar hasilnya tetap bekerja sebagai animasi GIF yang sah. Format video yang selalu mengganti tiap piksel dari satu frame ke frame berikutnya umumnya cukup memakai pengaturan disposal GIF 'None' atau 'Undefined'. Berikut contoh animasi yang menurut sifatnya juga merupakan animasi hasil coalesce, berikut tampilan "gif_anim_montage" atas frame animasinya satu per satu. [IM Output] [IM Output]
Kebanyakan animasi yang tidak memuat atau memakai transparansi, dan yang menganimasikan seluruh kanvas, biasanya disimpan dan disebarkan sebagai animasi hasil coalesce.

Animasi overlay

'Animasi overlay ' adalah animasi yang tiap frame-nya hanya menimpakan piksel baru ke animasi yang sedang ditampilkan. Dengan kata lain, di titik mana pun animasi itu tak pernah perlu membersihkan piksel menjadi transparan. Frame satu per satu boleh memuat transparansi, entah sebagai latar belakang atau sebagai bagian dari optimisasinya, tetapi tak pernah mengembalikan sebuah piksel menjadi transparan. Tentu saja bila transparansi sama sekali tidak dipakai, animasinya dijamin dapat dijadikan animasi overlay sederhana. Inilah jenis animasi teroptimisasi frame yang barangkali paling sederhana, dan yang tidak memerlukan penanganan khusus dari sisi klien. Tiap frame yang ditampilkan kepada pengguna dapat dipandang begitu saja sebagai gambar 'hasil flatten' dari semua frame sebelumnya. Animasi apa pun yang hanya memakai metode disposal GIF 'None' adalah 'animasi overlay'. Contoh terakhir tadi misalnya, bukan cuma 'animasi yang sepenuhnya hasil coalesce' melainkan juga 'animasi overlay', meski tidak semua 'animasi yang sepenuhnya hasil coalesce' merupakan 'animasi overlay'. Anda bisa menguji apakah sebuah animasi dapat menjadi animasi overlay dengan memakai metode layers 'CompareClear' pada animasi hasil coalesce, lalu memeriksa apakah gambar kedua dan seterusnya semuanya 'missed image'. Artinya, tidak ada piksel yang perlu dibersihkan atau dihapus dari satu frame ke frame berikutnya. Sebetulnya, bila sebuah animasi dapat menjadi animasi overlay tanpa modifikasi, operator IM "coalesce" hanya akan memakai metode disposal 'None' untuk semua frame. Kalau tidak demikian, berarti "coalesce" memakai disposal 'Background' setidaknya pada sebagian frame. Ini memberi satu lagi cara menguji kemampuan 'hanya overlay'. Animasi overlay boleh memakai transparansi, tetapi tidak punya bagian yang bergerak di atas latar belakang transparan. Misalnya, animasi huruf 'K' yang digambar tangan adalah animasi overlay, sebab tiap bagiannya hanya menambah atau mengubah bagian yang sudah ada di atas latar belakang transparan. Animasi itu tak pernah menambahkan transparansi baru ke gambar hasilnya (kecuali sebagai bagian dari frame pertama). [IM Output] [IM Output]
[IM Output] Bukan berarti objek bergerak tak dapat ditangani animasi overlay; hanya saja diperlukan latar belakang yang tidak transparan agar posisi lama bagian yang bergerak bisa ikut 'dihapus' tanpa memerlukan transparansi. Misalnya, lihat frame animasi "mengunduh dunia ke dalam direktori" berikut...

[IM Output]

Tentu saja, karena bagian lama harus 'dihapus' dengan menimpakan latar belakang aslinya, subgambar yang ditimpakan umumnya jadi lebih besar, dan ukuran file animasi GIF-nya pun umumnya lebih besar. Sayangnya, memakai operator optimisasi frame milik IM bisa, dan besar kemungkinan akan, mengubah 'animasi overlay hasil coalesce' menjadi sesuatu yang bukan lagi 'animasi overlay', dalam usahanya mencari ukuran file GIF yang lebih kecil. Namun dengan memakai deconstruct pada animasi tersebut alih-alih optimisasi frame, Anda dapat memastikan animasinya tetap berupa 'animasi overlay' sederhana, tetapi hanya bila animasi itu memang benar-benar 'animasi overlay'. Bila bukan, operasi deconstruct bisa berantakan (lihat deconstruct di atas). Dengan sedikit keterampilan manusia, animasi overlay masih bisa dioptimisasi lebih baik, misalnya memakai memecah pembaruan frame dan menerapkan semacam optimisasi kompresi tanpa merusak syarat 'hanya overlay' animasi tersebut. Umumnya 'animasi overlay' sama sekali tidak menampilkan transparansi (transparansi boleh dipakai sebagai bagian dari optimisasi, tetapi tidak ditampilkan). Dan bila tidak ada transparansi yang ditampilkan, animasinya dijamin berupa 'animasi overlay'. Mengapa 'animasi overlay' begitu penting? Karena ada perangkat lunak di luar sana yang terbatas pada jenis animasi ini. Jenis ini jauh lebih sederhana ditangani, sebab yang dilakukan hanya penimpaan, tanpa perlu menangani transparansi atau menyimpan frame sebelumnya untuk menangani metode disposal GIF. Perangkat lunak semacam itu langka, tetapi memang ada.

Animasi frame terhapus

Ketika sebuah animasi hanya memakai disposal GIF 'Previous' atau 'Background' saja, yang Anda dapatkan adalah jenis animasi yang sangat khusus. Perhatikan, bila hanya disposal 'Background' yang dipakai, semua frame animasi ditampilkan lalu dibersihkan sebelum frame berikutnya ditampilkan. Begitu pula bila hanya 'Previous' yang dipakai: animasi selalu dikembalikan ke kanvas bersih awal sebelum frame berikutnya ditampilkan, sehingga efeknya sama. Hal serupa terjadi bila Anda memakai campuran kedua pengaturan disposal itu saja. Artinya, animasi yang hanya memakai metode disposal ini punya frame yang merupakan salinan lengkap dari apa yang akan ditampilkan. Artinya, frame tersebut memuat segala sesuatu yang akan ditampilkan kepada pengguna pada saat itu. Bukan berarti animasinya lantas menjadi 'animasi yang sepenuhnya hasil coalesce'. Sebab subframe-nya bisa jadi jauh lebih kecil daripada area kanvas virtual animasi, tetapi segala sesuatu di luar frame itu dianggap transparan (atau latar belakang) dan tidak memuat apa pun yang penting. Sebagai contoh, lihatlah animasi kelinci berlari ini... [IM Output] [IM Output]
Perhatikan bahwa setiap subframe adalah gambar lengkap yang ditampilkan. Tidak lebih, tidak kurang. Perhatikan pula bahwa tak satu pun frame benar-benar perlu memakai seluruh kanvas virtual animasi. Dan akhirnya perhatikan bahwa semua disposal frame diatur ke 'Previous', yang karena alasan yang akan Anda lihat di bawah merupakan pengaturan disposal yang lebih masuk akal. Semua pengaturan disposal itu sebenarnya bisa saja diatur ke disposal 'Background' atau campuran keduanya tanpa mengubah hasil akhirnya.Karena tak ada nama yang lebih baik, animasi semacam ini saya sebut 'animasi frame terhapus ', tetapi saya pernah pula melihatnya disebut 'animasi disposal previous atau background'. Satu-satunya keadaan yang membuat sebuah animasi bukan jenis ini adalah bila setidaknya satu frame tak kosong di dalamnya memakai metode disposal 'None' atau 'Undefined' (sama saja). Animasi ini sangat khusus, sebab ia dapat menangani pembersihan transparansi sebanyak apa pun, di mana pun dalam urutan animasinya, tidak seperti animasi overlay. Tapi ia juga bisa ditimpakan ke gambar latar belakang statis APA PUN dengan sangat cepat. Untuk itu kita perlu sedikit memperketat definisi 'animasi frame terhapus'. Khususnya, kita perlu memastikan semua disposal-nya diatur ke 'Previous' (yang pada contoh kita memang sudah begitu). Bila itu dilakukan, Anda tinggal menyisipkan sebuah gambar di depan (dengan jeda nol) sebagai lapisan latar belakang. Misalnya, mari kita taruh kelinci kita di atas rerumputan....
  magick bunny_grass.gif bunny_anim.gif -loop 0  bunny_on_grass.gif

[IM Output]
Seperti terlihat, cara ini begitu sederhana sehingga banyak aplikasi memakai animasi GIF jenis ini untuk menambahkan simbol atau penanda lain (kunci file, smiley, bintang, dan sebagainya) pada objek yang lebih besar. Menganimasikan animasi GIF semacam itu juga mudah, sebab aplikasi tinggal membersihkan areanya ke suatu gambar latar belakang tetap yang sederhana lalu menimpakan frame berikutnya dalam urutan. Tidak perlu menghitung disposal atau melacak tampilan 'previous', selain tampilan latar belakang statis yang tidak berubah. Inilah pula sebabnya disposal 'Previous' lebih disukai untuk animasi frame terhapus. Tidak seperti animasi overlay yang cuma bagian khusus dari animasi GIF, SEMUA animasi dapat disimpan sebagai animasi frame terhapus. Cukup coalesce animasinya, secara opsional trim tepi transparan di sekelilingnya untuk mengoptimisasi frame-nya, lalu atur ulang disposal-nya.

  magick any_animation.gif -coalesce -trim \
          -set dispose previous   cleared_frame_animation.gif

Animasinya bahkan dapat diposisikan ulang di atas latar belakang itu... |

  magick bunny_grass.gif \( bunny_anim.gif -repage 0x0+5+15\! \) \
          -loop 0  bunny_on_grass2.gif

[IM Output]
Karena itu animasi frame terhapus umumnya berupa objek kecil yang terus berubah atau bergerak di atas latar belakang transparan. Animasi seperti ini langsung dapat dipakai di halaman web, atau sebagai simbol beranimasi, atau digabungkan dengan animasi lain untuk menghasilkan animasi yang jauh lebih rumit. Singkatnya, jenis animasi ini cocok dipakai dalam pustaka bagian-bagian beranimasi, untuk membuat animasi yang lebih besar dan rumit.
Namun ada satu masalah dalam menambahkan latar belakang seperti ini pada animasi GIF. Kalau melihat contoh-contoh sebelumnya, Anda mungkin memperhatikan adanya jeda yang mencolok dan mengganggu pada animasi yang bergerak cepat itu. Yaitu, kelincinya lenyap sesaat ketika animasi mengulang dan gambar latar belakangnya dimuat ulang. (Lihat catatan di frame jeda nol ) Meski ini bukan masalah bagi aplikasi yang memakai teknik tersebut untuk menambahkan simbol beranimasi pada objek yang ditampilkan, sebab aplikasi itu memang tidak menampilkan frame 'antara' tadi. Karena itu, bila Anda menambahkan latar belakang tak transparan ke animasi GIF, umumnya lebih baik mengubah animasi frame terhapus yang sederhana itu menjadi animasi overlay. Yakni, tambahkan latar belakang tersebut ke setiap frame animasi, alih-alih memberi kanvas awal. Itu bisa dilakukan dengan meng-coalesce animasi di atas lalu menghapus frame latar belakang jeda nol-nya, ATAU dengan komposisi layer animasi aslinya ke atas latar belakang statis. Sebagai contoh...

|

  magick bunny_grass.gif \( bunny_anim.gif -repage 0x0+5+15\! \) \
          -coalesce -delete 0 -deconstruct -loop 0  bunny_bgnd.gif
  gif_anim_montage  bunny_bgnd.gif  bunny_bgnd_frames.gif

[IM Output]
[IM Output]

Kini semua frame tampil sama baiknya, tidak ada jeda yang terlihat saat latar belakang diatur ulang. Namun animasinya sekarang menjadi animasi overlay dengan latar belakang yang 'digambar ulang' akibat gerakan objek animasinya, sehingga ukuran file-nya mungkin sedikit lebih besar. Lihat optimisasi transparansi untuk kelanjutan optimisasi hasil di atas. | _Anggota forum IMel_supremo, Pete, menyumbangkan skrip setara dalam MagickWand, contoh frame terhapus di atas latar belakang.

Contoh ini juga dibahas rinci di Forum IM, Creating a Cleared Frame GIF Animation in the MagickWand.

_

Animasi disposal campuran - animasi berlatar belakang banyak

Tidak ada yang menghalangi Anda mencampur berbagai metode disposal dalam satu animasi GIF. Malah, menambahkan latar belakang ke animasi frame terhapus persis melakukan hal itu. Mencampur metode disposal tidak begitu sederhana bagi kita manusia, tetapi dengan begitu tampilan beranimasi yang sangat rumit dapat dihasilkan. Umumnya animasi semacam ini tercipta sebagai bagian dari optimisasi frame otomatis atas suatu animasi. Ingat saja bahwa hasilnya tidak akan langsung bisa dipakai untuk keperluan khusus sebagaimana jenis animasi sebelumnya. Malah, jangan heran bila sebagian program penangan GIF tidak menangani 'animasi disposal campuran' dengan benar. Termasuk sebagian pengoptimal GIF yang ada. Contoh khas 'animasi disposal campuran' adalah objek kecil bergerak yang menimbulkan perubahan semi-permanen namun untuk sementara statis pada latar belakang animasinya. Bola yang mengenai tuas bisa jadi salah satu contohnya.

_Dibutuhkan contoh sederhana_

Serupa itu, animasi yang melibatkan dua objek bergerak sangat kecil di atas tampilan transparan yang lebih besar hanya dapat dioptimisasi dengan baik dengan mencampur teknik disposal, sehingga tiap objek digerakkan memakai frame animasi terpisah.

FUTURE,
A more complex animation for study.
 * Start with a semi-transparent canvas
 * run a little 'previous' disposal
 * leave one frame as a new 'canvas'
 * more previous animations
 * erase that 'addition' using a 'background' disposal set as new canvas
 * continue back to start point.
This animation should thoroughly test out not only IM disposal methods
but also various browser disposal methods.

Kalau Anda mau menyumbangkan contoh IM untuk animasi semacam itu, nama dan tautan beranda Anda bisa tampil di sini!


Akhir dari loop - kapan animasi berhenti

Sering dianggap lebih baik tidak membuat animasi mengulang selamanya, sebab mesin klien harus terus bekerja selama animasi masih berjalan. Karena itu ada baiknya memikirkan berapa kali animasi Anda sebenarnya mengulang. Pada dasarnya..

Tambahkan batas loop pada animasi Anda (bila memungkinkan)

Ini terutama berlaku bagi animasi besar yang dipakai sebagai logo di bagian atas halaman web. Tergantung total waktu jalannya animasi, 10 sampai 30 loop biasanya cukup untuk logo besar. Dan sebaiknya batas loop ditambahkan pada semua animasi semacam itu, demi kebaikan pengguna Anda. Pengaturan simpan "-loop" bernilai 0 berarti mengulang selamanya. Nilai inilah yang lazim dipakai, dan itu tidak apa-apa untuk animasi kecil. Namun sebagian peramban memaksakan berhenti ketika animasi mencapai batas loop internal tertentu (sering 256 loop). Untuk contoh-contoh IM saya umumnya memakai pengaturan simpan "-loop" '0', yang berarti 'mengulang selamanya', sebab animasinya bisa muncul di mana saja pada sebuah halaman. Artinya, bisa jadi ada jeda cukup lama antara saat pengguna memuat halaman dan saat ia akhirnya melihat serta membaca tentang animasi GIF tertentu. Kalau saya memakai jumlah 'loop' yang lebih kecil, animasinya tidak lagi memperagakan apa yang seharusnya diperagakan, sehingga kehilangan daya gunanya. Untuk animasi besar pada halaman pembuka tingkat atas, "-loop" bernilai '1', yaitu bawaan normal animasi GIF, dapat dipakai. Ini berarti animasi dijalankan sekali saja lalu berhenti. Yang membawa kita ke satu pertanyaan amat penting.. Berhenti di mana? Sebagian peramban, seperti "Netscape" lawas, menampilkan lagi frame pertama animasi. Namun kebanyakan peramban modern berhenti begitu saja di frame terakhir, mengabaikan pengaturan dispose frame itu yang memang tak berguna. Apa yang dilakukan suatu aplikasi terserah aplikasinya, sebab tidak ada standar yang sesungguhnya. Sebetulnya pemakaian metadata 'loop' itu sendiri pun tidak standar, sekadar sesuatu yang diterapkan peramban "Netscape" lawas lalu ditiru semua peramban sesudahnya. Karena itu, bila ada frame tertentu yang Anda inginkan sebagai tempat animasi berhenti, katakanlah frame yang memuat nama atau logo perusahaan Anda, ada baiknya frame itu dijadikan frame pertama sekaligus frame terakhir animasi. Salah satu dari kedua frame itu sebaiknya diberi 'jeda nol', supaya tidak memengaruhi total panjang waktu loop animasinya. Jadi, ringkasnya...

Bila loop dibatasi, tambahkan frame 'berhenti' sebagai frame pertama SEKALIGUS frame terakhir.


Frame antara jeda nol

Kita sudah melihat pemakaian frame yang punya 'jeda nol' sehubungan dengan animasi frame terhapus. Saya juga memakainya untuk menjelaskan disposal previous dan background. Frame khusus ini sebenarnya jauh lebih umum daripada yang mungkin orang kira. Frame semacam ini bukan hanya cara menyisipkan 'kanvas' latar belakang di depan sebuah animasi (seperti pemakaian saya di atas), melainkan juga wajib ada pada sebagian teknik optimisasi frame yang lebih rumit, seperti penggandaan frame dan memecah pembaruan frame. Pemakaian lain (sangat lawas, dari masa sebelum format PNG) adalah agar Anda bisa membuat gambar GIF statis yang memuat lebih dari batas 256 warna! Yakni, tiap frame menyediakan 256 warna, dan frame berikutnya menyediakan 256 warna berikutnya lagi, semuanya dengan jeda nol dan tanpa loop di akhir. Terima kasih kepada TLUL dalam diskusi Creating unquantized GIFs yang menunjukkan hal ini. 'frame antara jeda nol ' ini tidak dimaksudkan untuk ditampilkan kepada pengguna. Frame ini semata dipakai untuk membuat efek khusus pada gambar GIF yang tanpanya tidak mungkin dibuat, atau tidak akan seoptimal itu. Singkatnya...

Frame jeda nol adalah frame antara,
Frame itu tidak dimaksudkan terlihat oleh pengguna.

ImageMagick bukan hanya membuat frame semacam itu di dalam animasi sebagai bagian dari 'OptimizePlus' otomatisnya, melainkan juga menyediakan cara membuangnya lewat metode layers 'RemoveZero'. Waspadai frame ini, sebab sering kali ia merumitkan penanganan animasi Anda. Baik, jadi frame ini penting, lalu kenapa? Karena banyak aplikasi tidak menyukainya, atau menanganinya secara keliru. Aplikasi itu menganggap 'frame jeda nol' sebagai hal buruk, bahkan ketika Anda sengaja menambahkannya ke animasi karena satu dan lain alasan. Berikut ringkasan aplikasi yang saya tahu atau saya dengar 'berbuat keliru'... Gimp | Tidak mau menyimpan 'frame jeda nol'; ia selalu menambahkan jeda waktu minimal pada frame mana pun yang jeda waktunya nol. :-(

FireFox | Memberi jeda kecil tak nol pada frame semacam itu. Agaknya ini supaya animasi yang sama sekali tidak punya jeda waktu tidak menghabiskan seluruh siklus CPU komputer. Tapi "firefox" tetap tidak melonggarkan pembatasan itu meski sebuah animasi punya total waktu tampil yang tidak nol.

Internet Explorer | Punya jeda waktu minimal 6 perseratus detik, dan mengabaikan jeda yang lebih kecil dari itu. Internet Explorer versi 8 juga gagal (langsung mengulang loop dari awal) bila ada frame gambar yang melampaui batas animasi yang ditetapkan frame pertama. Ini saya golongkan sebagai bug besar.
Sebaliknya, metode layers 'RemoveZero' milik ImageMagick berbuat benar dan TIDAK akan membuang frame apa pun bila SEMUA gambar punya 'jeda waktu nol'. Malah metode layers ini akan memberi peringatan bila melihat animasi yang sama sekali tanpa jeda waktu. Ini membawa kita ke satu aturan praktis lagi...

Jangan pernah menyimpan animasi GIF (yang mengulang) yang sama sekali tidak punya 'jeda'

Melakukannya merupakan praktik yang sangat buruk, dan itulah sebabnya kebanyakan aplikasi 'ber-bug' di atas berbuat seperti itu ketimbang seperti seharusnya. Protes kepada pemiliknya bila Anda menemuinya. Protes pula kepada pengembang aplikasi, supaya mereka menangani frame jeda nol dengan benar. Sekalipun itu berarti tidak menampilkan frame tersebut sama sekali, melainkan memakainya sekadar sebagai persiapan bagi frame berikutnya yang akan ditampilkan. Toh frame itu berada di layar selama waktu NOL!