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

Contoh penggunaan ImageMagick -- layer multi-gambar

Kata pengantar dan indeks contoh penggunaan ImageMagick
Pengantar layer
Menyambung gambar (-append)

Pengantar pelapisan gambar

Seperti yang sudah kita catat sebelumnya, ImageMagick tidak menangani satu gambar saja, melainkan sebuah urutan atau daftar gambar. Hal ini memungkinkan pemakaian IM dalam dua teknik pemrosesan gambar yang sangat khusus. Setiap gambar dalam daftar itu misalnya dapat dianggap sebagai satu frame dalam waktu, sehingga seluruh daftar dapat dipandang sebagai sebuah Animasi. Hal ini dibahas pada halaman Contoh IM yang lain. Lihat penanganan dasar animasi. Sebaliknya, setiap gambar dalam urutan itu dapat pula dianggap sebagai Layer dari setumpuk lembar transparansi. Artinya, setiap gambar mewakili satu bagian kecil dari gambar akhir. Sebagai contoh: layer pertama (paling bawah) dapat mewakili gambar latar belakang. Di atasnya bisa ada bayangan kabur yang tembus pandang. Lalu gambar layer berikutnya berisi objek yang melemparkan bayangan itu. Di atasnya lagi sebuah layer berisi teks yang tertulis di atas objek tersebut. Jadi, bisa saja ada urutan gambar atau 'layer' yang masing-masing menambahkan satu potong lagi ke sebuah gambar yang jauh lebih rumit. Setiap layer gambar dapat dipindahkan, disunting, atau diubah sepenuhnya terpisah dari layer lain, bahkan disimpan ke dalam file multi-gambar (seperti TIFF:, MIFF: atau XCF:) atau sebagai gambar-gambar terpisah untuk diproses kemudian. Dan itulah inti dari pelapisan gambar. Baru setelah semua layer gambar dibuat, kita melakukan flatten, mosaic, atau merge atas semua gambar berlapis menjadi satu gambar akhir.


Menyambung gambar

Menyambung mungkin operasi paling sederhana di antara operasi multi-gambar yang disediakan untuk menangani banyak gambar. Pada dasarnya ia menyatukan urutan gambar yang ada di memori menjadi satu kolom, atau satu baris, tanpa celah. Opsi "-append" menyambung secara vertikal, sedangkan bentuk plusnya "+append" menyambung secara horizontal. Sebagai contoh, di sini kita menyambung sekumpulan gambar huruf berdampingan untuk membentuk sebuah kata yang menarik, mirip dengan cara 'glyph' atau huruf-huruf sebuah 'font' disatukan.

  magick font_A.gif font_P.gif font_P.gif font_E.gif font_N.gif \
          font_D.gif font_E.gif font_D.gif +append  append_row.gif

[IM Output]

Contoh di atas mirip (secara sangat mendasar) dengan cara font ditangani. Tidak seperti font sungguhan, Anda tidak dibatasi hanya pada dua warna, melainkan dapat menghasilkan alfabet berwarna-warni yang menarik dari gambar tiap karakter. Banyak 'font gambar' semacam ini tersedia untuk diunduh di WWW. Satu kumpulan kecil dapat ditemukan di Anthony's Icon Library, pada Font untuk teks dan penghitung, yang juga tempat saya menemukan Font Blue Bubble di atas. Perhatikan juga bahwa operator "+append" dijalankan sebagai operasi terakhir, setelah semua gambar yang hendak disambung dimasukkan ke urutan gambar saat itu. Cara ini bagus untuk menyambungkan label ke sebuah gambar, misalnya... |

  magick rose: -background LawnGreen label:Rose \
          -background white  -append append_label.jpg

[IM Output]
Perhatikan bahwa warna "-background" dipakai untuk mengisi ruang yang tidak terisi. Tentu saja bila semua gambar sama lebarnya, tidak ada ruang tersisa untuk diisi. Sejak IM v6.4.7-1 pengaturan (setting) "-gravity" dapat dipakai untuk menentukan bagaimana gambar-gambar itu disatukan. Jadi pada penyambungan vertikal, pengaturan 'Center' akan menengahkan gambar relatif terhadap gambar hasil akhir (begitu pula pengaturan 'North' atau 'South'). |

  magick rose: -background LawnGreen label:Rose \
          -background white -gravity center -append \
          append_center.jpg

[IM Output]
Tentu saja pengaturan gravity 'East' akan meratakan gambar ke sisi kanan. |

  magick rose: -background LawnGreen label:Rose \
          -background white -gravity east -append \
          append_east.jpg

[IM Output]
Perataan vertikal serupa dapat dicapai saat memakai "+append" | _Sebelum IM v6.4.7, meratakan gambar yang disambung jauh lebih sulit dan umumnya melibatkan "-flop" untuk perataan kanan. Atau memakai "-extent" atau "-border" untuk menyesuaikan lebar gambar demi penyambungan yang rata tengah.

Sebagai contoh, perintah ini bekerja pada IM versi 6.3.2 yang lebih lama..._ | |

  magick rose: -background SkyBlue label:Rose \
          -background White -gravity center -extent 200x \
          -append -trim +repage   append_center_old.jpg

[IM Output]
Anda juga dapat memakai beberapa operasi append sekaligus dalam satu perintah tanpa konflik atau kerancuan mengenai hasilnya (hal ini tidak berlaku sebelum IM v6). |

  magick font_{0,0,6,1,2}.gif +append  dragon_long.gif \
          -background none   -append   append_multi.gif

[IM Output]
Kita menyambung tiap baris gambar, lalu menyambungkan gambar yang lebih besar di bawahnya. Ini sangat sederhana dan lugas. Dengan memakai tanda kurung, angka-angkanya saja dapat disambung setelah gambar yang lebih besar. Sebagai contoh, di sini semua angka disambung lebih dulu, sebelum disambungkan secara vertikal ke gambar naga yang dibaca sebelum angka-angka tadi. |

  magick dragon_long.gif  '(' font_{0,0,6,2,9}.gif +append ')' \
          -background none   -append   append_parenthesis.gif

[IM Output]
| Tanda kurung pada contoh di atas harus dikutip, atau di-escape dengan backslash ('\') bila dipakai pada shell UNIX; jika tidak, shell akan menafsirkannya sebagai sesuatu yang sama sekali berbeda.
| Karena hanya dua gambar yang terlibat, kita sebenarnya bisa memakai "+swap" atau "-reverse" saja alih-alih tanda kurung.

Menyambung larik gambar

Cara ini dapat Anda lanjutkan untuk membuat larik gambar utuh, dan menyusunnya menurut baris atau menurut kolom. |

  magick \( font_1.gif font_2.gif font_3.gif +append \) \
          \( font_4.gif font_5.gif font_6.gif +append \) \
          \( font_7.gif font_8.gif font_9.gif +append \) \
          \( -size 32x32 xc:none  font_0.gif +append \) \
          -background none -append   append_array.gif

[IM Output]
Secara teknis tanda kurung yang pertama tidak diperlukan, karena belum ada gambar yang dibaca, tetapi hal itu membuat keseluruhannya tampak seragam dan memperlihatkan maksud perintahnya, yaitu membuat larik gambar. Lihat juga mode konkatenasi montage untuk cara lain membuat larik gambar berukuran sama. | _Operator "-append" hanya menyambung gambar yang sebenarnya, dan tidak memanfaatkan ukuran kanvas virtual (page gambar) maupun offset gambar. Namun informasi kanvas virtual tampaknya ditinggalkan dalam keadaan aneh: ukuran kanvasnya dijumlahkan dan offsetnya diisi nilai yang tidak terdefinisi.

Hal ini bisa dianggap bug, dan berarti gambar masukan atau gambar hasilnya perlu direset kanvas virtualnya memakai "+repage" sebelum disimpan, atau sebelum gambar itu dipakai pada operasi yang menganggap informasi ini penting.

Keadaan ini mungkin akan diperbaiki pada pengembangan operasi ini di kemudian hari. Karena itu berhati-hatilah, terutama bila menyambung ulang gambar hasil pemangkasan tile._

Menyambung dengan tumpang tindih

Di Forum IM ada pengguna yang menanyakan cara sederhana untuk Append images with some overlap. Banyak solusi ditawarkan. Yang berikut salah satu yang paling sederhana, dengan besar tumpang tindih ditulis di satu tempat saja. |

  magick granite: rose: -gravity east -background none \
          \( -clone 1 -chop 30x0 \) \( -clone 0,2 +append \) \
          -delete 0,2 +swap -composite append_overlap.gif

[IM Output]
Cara di atas tidak memerlukan perhitungan posisi gambar apa pun (yang biasanya melibatkan ukuran gambar) seperti pada solusi yang lebih umum. Lihat Menangani layer gambar di bawah. Yang dikerjakannya adalah memotong bagian yang tumpang tindih, lalu menyambungkan hasilnya ke gambar pertama sehingga diperoleh ukuran gambar akhir. Gambar aslinya kemudian dikomposisikan (dengan gravity) di atasnya untuk menghasilkan tumpang tindih yang sebenarnya. Cara ini mudah diubah untuk tumpang tindih vertikal, bahkan untuk tumpang tindih dari kanan ke kiri.

Menyambung dengan smush

Cara lain untuk menyambung gambar adalah dengan smush. Operator "-smush" bekerja mirip operator append (lihat di atas), tetapi ia menerima argumen berapa banyak ruang (atau anti-ruang) yang Anda inginkan di antara gambar-gambar itu. Sebagai contoh, mari kita pakai untuk mengerjakan contoh sebelumnya dengan lebih sederhana. |

  magick granite: rose: -background none -gravity Center \
          +smush -20 smush_overlap.png

[IM Output]
Cara itu bekerja dengan sangat baik, meski bukan itu yang sebenarnya menjadi tujuan operator ini, dan kemungkinan besar jauh lebih lambat. Yang sebenarnya dimaksudkan oleh smush adalah mendekatkan 'gambar bentuk' sedekat mungkin. Sebagai contoh, di sini saya membuat huruf 'A' dan 'V' lalu men-'smush' keduanya dengan jarak sesempit mungkin. |

  magick -background none -pointsize 72 \
          -fill red label:A -fill blue label:V \
          +smush 0 smush_append.png

[IM Output]
Perhatikan bagaimana kedua huruf itu disambung jauh lebih rapat daripada yang dapat dilakukan append, dengan memanfaatkan ruang kosong pada 'bentuk' gambar. Celah pada contoh di atas disebabkan oleh piksel tepi hasil anti-aliasing dari kedua huruf. Itulah yang dirancang untuk dikerjakan "-smush", meski memerlukan banyak perhitungan sehingga jauh lebih lambat daripada append (lihat di atas). Argumennya adalah offset bagi posisi akhir itu, biasanya bernilai positif untuk menghasilkan celah, tetapi boleh negatif untuk membuat tumpang tindih. |

  magick -background none -pointsize 72 \
          -fill red label:A -fill blue label:V \
          +smush -15 smush_offset.png

[IM Output]
Gambar dapat terpotong dengan cara yang tidak terdokumentasi bila dipakai nilai negatif yang sangat besar.


Komposisi banyak pasang gambar

Komposisi adalah operasi tingkat rendah yang dipakai untuk menggabungkan dua gambar. Hampir semua teknik pelapisan pada akhirnya menyusut menjadi penggabungan gambar dua per dua, sampai tersisa satu gambar saja. Jadi mari kita mulai dengan melihat berbagai cara melakukan komposisi tingkat rendah atas pasangan gambar.

Menggunakan perintah composite

Cara tradisional untuk menggabungkan dua gambar dengan ImageMagick adalah lewat perintah "magick composite". Perintah ini hanya bisa menggabungkan dua gambar sekaligus, lalu menyimpan hasil tiap operasi ke sebuah file. Tentu saja hal itu tidak menghalangi Anda memakainya untuk melapiskan banyak gambar, satu gambar setiap kali... |

  magick -size 100x100 xc:skyblue composite.gif
  magick composite -geometry  +5+10 balloon.gif composite.gif composite.gif
  magick composite -geometry +35+30 medical.gif composite.gif composite.gif
  magick composite -geometry +62+50 present.gif composite.gif composite.gif
  magick composite -geometry +10+55 shading.gif composite.gif composite.gif

[IM Output]
| _Karena semua gambar masukan dibaca oleh ImageMagick SEBELUM gambar keluaran dibuka, keluarannya dapat dituliskan ke salah satu gambar masukan. Dengan begitu gambar yang sama dapat diolah berulang kali, seperti di atas, tanpa masalah.

Jangan lakukan ini dengan format gambar lossy seperti "JPEG", karena error format bersifat kumulatif dan gambar dasarnya akan cepat memburuk._
Anda juga dapat mengubah ukuran gambar yang ditimpakan sekaligus menempatkannya memakai pengaturan "-geometry". |

  magick -size 100x100 xc:skyblue comp_resize.gif
  magick composite -geometry 40x40+5+10  balloon.gif comp_resize.gif comp_resize.gif
  magick composite -geometry      +35+30 medical.gif comp_resize.gif comp_resize.gif
  magick composite -geometry 24x24+62+50 present.gif comp_resize.gif comp_resize.gif
  magick composite -geometry 16x16+10+55 shading.gif comp_resize.gif comp_resize.gif

[IM Output]
Perintah "magick composite" juga punya beberapa kelebihan lain: cara gambar digambarkan ke latar belakang dapat dikendalikan dengan opsi "-compose", dan posisi relatifnya dipengaruhi pengaturan "-gravity". Gambar timpaan juga dapat di-"-tile" sehingga ia menutupi gambar latar belakang tanpa perlu menentukan batas tile. Hal ini hanya tersedia saat memakai "magick composite". Kerugian besar cara ini adalah Anda memakai beberapa perintah, dan IM harus menuliskan gambar kerjanya, entah ke pipeline atau ke disk, agar perintah berikutnya membacanya lagi. Untuk contoh lain pemakaian perintah "magick composite" dalam menimpakan gambar ke gambar lain, lihat "Anotasi dengan menimpakan gambar" dan "Penempatan gambar memakai gravity".

Operator composite pada convert

Operator "-composite" tersedia di dalam perintah "magick". Untuk keterangan lebih lanjut lihat komposisi gambar dalam IM. Dengan ini hal yang sama seperti di atas dapat dikerjakan, tetapi seluruhnya dalam satu perintah. |

  magick -size 100x100 xc:skyblue \
          balloon.gif  -geometry  +5+10  -composite \
          medical.gif  -geometry +35+30  -composite \
          present.gif  -geometry +62+50  -composite \
          shading.gif  -geometry +10+55  -composite \
          compose.gif

[IM Output]
Perintah ini mula-mula membuat gambar kanvas berwarna "skyblue", lalu melapiskan tiap gambar berikutnya ke kanvas itu pada posisi yang diberikan. Nah, "-geometry" adalah operator yang sangat khusus: ia tidak hanya menetapkan posisi timpaan bagi operasi "-composite" berikutnya, tetapi juga mengubah ukuran ("-resize") gambar terakhir (dan hanya gambar terakhir) dalam urutan gambar saat itu. |

  magick -size 100x100 xc:skyblue \
          balloon.gif  -geometry 40x40+5+10   -composite \
          medical.gif  -geometry      +35+30  -composite \
          present.gif  -geometry 24x24+62+50  -composite \
          shading.gif  -geometry 16x16+10+55  -composite \
          compose_geometry.gif

[IM Output]
Perhatikan bahwa efek samping 'resize' dari "-geometry" ini sebaiknya dihindari, meski praktis. Pada dasarnya efek itu lebih merupakan warisan kompatibilitas mundur dan pada situasi tertentu dapat menimbulkan efek lain. Berikut rekomendasi yang lebih panjang... |

  magick -size 100x100 xc:skyblue \
          \( balloon.gif -resize 40x40 \) -geometry +5+10   -composite \
          \( medical.gif               \) -geometry +35+30  -composite \
          \( present.gif -resize 24x24 \) -geometry +62+50  -composite \
          \( shading.gif -resize 16x16 \) -geometry +10+55  -composite \
          compose_resize.gif

[IM Output]

Menggambar banyak gambar

Masih dengan "magick", primitif draw juga dapat dipakai untuk menimpakan gambar ke kanvas kerjanya. |

  magick -size 100x100 xc:skyblue \
          -draw "image over  5,10 0,0 'balloon.gif'" \
          -draw "image over 35,30 0,0 'medical.gif'" \
          -draw "image over 62,50 0,0 'present.gif'" \
          -draw "image over 10,55 0,0 'shading.gif'" \
          drawn.gif

[IM Output]
Tentu saja Anda juga bisa menentukan pengubahan ukuran bagi gambar yang ditimpakan.. |

  magick -size 100x100 xc:skyblue \
          -draw "image over  5,10 40,40 'balloon.gif'" \
          -draw "image over 35,30  0,0  'medical.gif'" \
          -draw "image over 62,50 24,24 'present.gif'" \
          -draw "image over 10,55 16,16 'shading.gif'" \
          drawn_resize.gif

[IM Output]
Gambar yang 'digambar' juga dapat diputar, diskalakan, dan didistorsi secara affine selama proses penimpaan. Meski begitu, membuatnya bekerja seperti yang Anda inginkan bisa merepotkan. Gambar hasil draw dipengaruhi "-gravity", sama seperti teks.


Melapiskan banyak gambar

Pelapisan gambar yang sesungguhnya menuntut metode untuk menyatukan banyak gambar sekaligus, tanpa perlu mengomposisikan tiap pasang gambar satu per satu. Di sinilah berbagai metode operator -layers menunjukkan keunggulannya. Urutan gambar berlapis bisa jadi penting, jadi ada baiknya memahami operator urutan atau daftar gambar yang khusus itu. Perhatikan bahwa 'gambar berlapis' praktis sama dengan penanganan 'frame animasi'. Karena itu disarankan Anda melihat pula penanganan dasar animasi dan modifikasi animasi untuk teknik pemrosesan tiap 'layer' atau 'frame'. Sebenarnya animasi pun sering memakai operator -layers yang sama untuk memproses gambar.

Flatten - ke atas gambar latar belakang

Operator daftar gambar "-layers **flatten**" (atau jalan pintasnya "-flatten") pada dasarnya "mengomposisikan" tiap gambar yang diberikan ke atas sebuah latar belakang sehingga terbentuk satu gambar tunggal. Namun posisi tiap gambar ditentukan memakai offset kanvas virtual, atau page miliknya saat itu. Sebagai contoh, di sini saya membuat kanvas yang bagus, lalu menentukan tiap gambar yang ingin saya timpakan ke kanvas itu. |

  magick -size 100x100 xc:skyblue \
          -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 \)  \
          -layers flatten  flatten_canvas.gif

[IM Output]
| _Sejak IM v6.3.6-2 operator "-flatten" hanyalah alias bagi metode "-layers 'flatten'".

Jadi opsi "-flatten" dapat dianggap sebagai jalan pintas bagi metode "-layers" yang bernama sama._
Anda tidak harus membuat kanvas awal seperti di atas; sebagai gantinya biarkan "-flatten" yang membuatkannya. Warna kanvasnya adalah warna "-background" saat itu, sedangkan ukurannya ditentukan oleh ukuran kanvas virtual gambar pertama. |

  magick \( -page 100x100+5+10  balloon.gif \)   \( -page +35+30 medical.gif \)  \
          \( --page +62+50        present.gif \)   \( -page +10+55 shading.gif \)  \
          -background dodgerblue  -layers flatten  flatten_page.gif

[IM Output]
| _Meski pengaturan "-gravity" memengaruhi penempatan gambar yang ditentukan lewat pengaturan "-geometry", ia tidak memengaruhi penempatan gambar yang memakai offset kanvas virtual yang diatur lewat pengaturan "-page". Ini bagian dari definisi offset semacam itu. Lihat offset geometry vs page untuk keterangan lebih lanjut.

Jika penempatan dengan "-gravity" diperlukan, lihat metode komposisi multi-gambar di atas, atau metode khusus komposisi layers yang dapat menangani kedua cara penempatan sekaligus._
Jika ada gambar yang tidak muncul di dalam area kanvas virtual yang ditentukan, gambar itu akan dipotong atau diabaikan, sesuai keadaannya. Sebagai contoh, di sini kita memakai ukuran kanvas yang lebih kecil sehingga gambar-gambar berikutnya tidak muncul seutuhnya pada kanvas tersebut. |

  magick \( -page 75x75+5+10  balloon.gif \)   \( -page +35+30 medical.gif \)  \
          \( -page +62+50 present.gif \)   \( -page +10+55 shading.gif \)  \
          -background dodgerblue  -flatten  flatten_bounds.gif

[IM Output]
Pemakaian flatten yang lazim adalah menggabungkan beberapa 'layer' gambar. Artinya, Anda dapat membuat berbagai bagian dari sebuah gambar yang lebih besar, biasanya memakai tanda kurung untuk membatasi operator gambar pada satu gambar 'layer' yang sedang dibuat, lalu meratakan hasil akhirnya. Salah satu pemakaian yang khas adalah membuat layer gambar bayangan, yang di atasnya gambar asli diratakan. Misalnya... |

  magick balloon.gif \( +clone  -background navy  -shadow 80x3+5+5 \) +swap \
          -background none   -flatten   flatten_shadow.png

[IM Output]
Perhatikan bahwa karena saya ingin bayangannya berada di bawah gambar asli, saya perlu menukar kedua gambar itu agar urutannya benar. | _Memakaiflatten untuk menambahkan gambar bayangan yang dihasilkan tidak disarankan, karena gambar bayangan yang dihasilkan dapat memiliki offset gambar negatif.

Solusi yang disarankan, seperti diberikan pada bagian gambar bayangan, adalah memakai teknik penggabungan layer yang lebih maju, yang akan kita lihat nanti._
Karena kanvas virtual hanya terdiri atas sebuah ukuran, gambar hasilnya akan berukuran itu tetapi tanpa offset kanvas virtual, sehingga Anda tidak perlu mencemaskan offset apa pun pada gambar akhir. Pemakaian kanvas virtual untuk mendefinisikan kanvas tempat gambar ditimpakan berarti hal itu dapat dipakai untuk menambahkan border di sekeliling sebuah gambar. Sebagai contoh, di sini saya menetapkan ukuran dan offset virtual sebuah gambar untuk 'memberi padding' pada gambar itu hingga berukuran tertentu. |

  magick medical.gif -set page 64x64+20+20 \
          -background SkyBlue   -flatten   flatten_padding.gif

[IM Output]
Tentu saja ada cara yang lebih baik untuk menambah padding pada gambar agar IM otomatis menengahkan gambar di area yang lebih besar. Anehnya, penanganan yang persis sama dapat dipakai untuk 'memotong' atau memangkas gambar ke kanvas virtual yang lebih kecil daripada gambar aslinya. Namun dalam hal ini Anda perlu memakai offset negatif untuk menempatkan lokasi 'crop', karena yang digeser adalah gambarnya, bukan 'jendela' pemangkasannya. |

  magick logo:  -repage 100x100-190-60  -flatten  flatten_crop.gif

[IM Output]
Tentu saja pemangkasan viewport juga mengerjakan ini dengan lebih baik, tanpa pemrosesan tambahan berupa pembuatan kanvas dan penimpaan yang turut dilakukan "-flatten". Ia juga tidak akan 'melebarkan' gambarnya sendiri untuk menutupi seluruh viewport bila gambar hanya termuat sebagian di jendela tampilan itu. Salah pakai yang umum atas operator "-flatten" adalah untuk menghapus transparansi sebuah gambar, yaitu menyingkirkan transparansi yang mungkin dimiliki gambar dengan menimpakannya ke warna latar belakang. Namun cara itu tidak berhasil bila melibatkan banyak gambar, sehingga tidak lagi disarankan.

Mosaic - kanvas yang melebar

Operator "-layers **mosaic**" (atau jalan pintasnya "-mosaic") lebih mirip versi kanvas melebar dari operator flatten. Alih-alih hanya membuat kanvas awal berdasarkan ukuran kanvas gambar pertama saja, operator mosaic membuat kanvas yang cukup besar untuk memuat semua gambar (hanya ke arah positif). Sebagai contoh, di sini saya bahkan tidak menetapkan kanvas virtual yang sesuai, namun operator "-mosaic" akan menghitung sendiri seberapa besar kanvas yang dibutuhkan untuk memuat semua layer gambar. |

  magick \( -page +5+10  balloon.gif \)   \( -page +35+30 medical.gif \)  \
          \( -page +62+50 present.gif \)   \( -page +10+55 shading.gif \)  \
          -background dodgerblue  -layers mosaic  mosaic.gif

[IM Output]
| _Sejak IM v6.3.6-2 operator "-mosaic" hanyalah alias bagi "-layers 'mosaic'".

Jadi opsi "-mosaic" dapat dianggap sebagai jalan pintas bagi metode "-layers" yang bernama sama._
Perhatikan bahwa baik "-mosaic" maupun "-flatten" tetap membuat kanvas yang bermula dari 'titik asal' atau piksel 0,0. Ini bagian dari definisi 'kanvas virtual' atau 'page' sebuah gambar, dan karena itu dapat dipastikan bahwa gambar akhir dari kedua operator itu tidak akan punya offset virtual, dan seluruh kanvasnya terdefinisi penuh berupa data piksel yang sebenarnya. Perhatikan juga bahwa "-mosaic" hanya melebarkan kanvas ke arah positif (tepi bawah atau kanan), karena tepi atas dan kiri terpaku pada titik asal virtual. Tentu saja itu berarti "-mosaic" tetap akan memotong gambar yang ber-offset negatif... |

  magick \( -page -5-10  balloon.gif \)   \( -page +35+30 medical.gif \)  \
          \( -page +62+50 present.gif \)   \( -page +10+55 shading.gif \)  \
          -background dodgerblue  -mosaic  mosaic_clip.gif

[IM Output]

Merge - membuat gambar layer baru

Operator "-layers **merge**" hampir sama dengan operator-operator sebelumnya dan ditambahkan pada IM v6.3.6-2. Ia hanya membuat gambar kanvas yang persis cukup besar untuk memuat semua gambar yang diberikan pada offset masing-masing. Seperti mosaic, ia juga melebarkan kanvas, tetapi tidak hanya ke arah positif melainkan juga ke arah negatif. Pada dasarnya itu berarti Anda tidak perlu memusingkan pemotongan, offset, atau hal lain saat menggabungkan gambar layer. Semua gambar akan digabungkan relatif terhadap posisi satu sama lain. Keluarannya tidak menyertakan atau menjamin titik asal termasuk dalam kanvas yang dilebarkan. Karena itu keluaran layers merge dapat mengandung 'offset layer' yang bisa positif maupun negatif. Dengan kata lain.. layers merge menggabungkan gambar layer untuk menghasilkan gambar layer yang baru. Jadi bila offset itu tidak Anda inginkan setelah selesai, kemungkinan besar Anda perlu menyertakan operator "+repage" sebelum penyimpanan akhir. Sebagai contoh, berikut kumpulan gambar layer yang sama seperti yang kita pakai sebelumnya... |

  magick \( -page +5+10  balloon.gif \)   \( -page +35+30 medical.gif \)  \
          \( -page +62+50 present.gif \)   \( -page +10+55 shading.gif \)  \
          -background dodgerblue  -layers merge  +repage layers_merge.gif

[IM Output]
Seperti yang Anda lihat, gambarnya hanya sebesar yang diperlukan untuk memuat semua gambar yang ditempatkan relatif satu sama lain, sementara saya membuang offset gambar hasilnya terhadap titik asal kanvas virtual. Terjaganya posisi relatif tanpa pemotongan atau ruang berlebih inilah yang membuat varian ini begitu ampuh. Mari kita coba lagi dengan memberi salah satu gambar offset negatif... |

  magick \( -page -5-10  balloon.gif \)   \( -page +35+30 medical.gif \)  \
          \( -page +62+50 present.gif \)   \( -page +10+55 shading.gif \)  \
          -background dodgerblue  -layers merge  +repage layers_merge_2.gif

[IM Output]
Seperti yang Anda lihat, "balloon" tidak terpotong, hanya bergeser lebih jauh dari yang lain agar jarak relatifnya terhadap mereka tetap terjaga. Tentu saja operator "+repage" pada contoh di atas menghapus offset kanvas virtual yang mutlak pada gambar akhir, dan hanya mempertahankan penempatan relatif antargambar. Offset itu dihapus karena peramban web sering bermasalah dengan offset gambar, apalagi offset negatif, kecuali bila ia bagian dari animasi GIF. Namun bila offset itu tidak saya hapus, semua gambar akan tetap berada pada posisinya yang benar di kanvas virtual di dalam gambar layer tunggal yang dihasilkan, sehingga pemrosesannya dapat diteruskan dan lebih banyak gambar ditambahkan ke gambar gabungan itu. Biasanya dipakai warna "-background" 'None' agar area yang tidak terpakai pada gambar gabungan menjadi transparan. Bila diterapkan pada satu gambar saja, penggabungan layer akan mengganti transparansi apa pun di dalam gambar dengan latar belakang warna polos, tetapi mempertahankan ukuran asli gambar berikut offset yang ada padanya. Namun ukuran kanvas virtual gambar itu dapat disesuaikan agar 'paling pas' dengan ukuran dan offset gambar tersebut. Tujuan awal operator ini adalah memudahkan pengguna menggabungkan banyak gambar terdistorsi menjadi satu kesatuan, tanpa peduli offset masing-masing gambar. Misalnya saat menyelaraskan foto untuk membentuk 'panorama' yang lebih besar. Anda cukup memulai dari gambar dasar di tengah yang tidak terdistorsi (tanpa offset), lalu memakai operator ini untuk menimpakan gambar-gambar lain di sekitar titik awal itu (dengan offset negatif maupun positif) yang telah diselaraskan dan didistorsi agar cocok dengan gambar tengah tersebut. Untuk contoh lain pemakaian operator ini dengan mendistorsi gambar agar titik kontrol bersamanya selaras, lihat kubus foto isometrik 3D dan kotak perspektif 3D. Contoh lain pemakaian operator ini adalah membuat rangkaian sederhana foto yang saling tumpang tindih.

Operasi "-layers trim-bounds" dapat dipakai untuk memastikan semua
gambar mendapat offset positif pada ukuran kanvas minimal, dengan tetap
mempertahankan posisi relatifnya, dan tanpa benar-benar menggabungkan layer
gambar menjadi satu gambar akhir.

Dengan begitu Anda dapat memproses gambar-gambar itu lebih lanjut sebelum
benar-benar digabungkan, misalnya menempatkan gambar lain relatif terhadap
kelompok gambar tadi dengan membaca batas kanvas virtual yang dihasilkan.

Namun bila gambar memiliki transparansi, ada baiknya transparansi itu
dipangkas lebih dulu dari gambar, sehingga pemakaian idealnya menjadi...

  -alpha set -bordercolor none -border 1x1 -trim -layers trim-bounds

Cara ini meminimalkan layer gambar termasuk seluruh area transparan dari
data gambar yang sebenarnya, sekaligus memastikan semuanya termuat pada
kanvas virtual (positif) yang sah berukuran minimal.

Komposisi coalesce - pelapisan progresif

Operator gambar "-layers **coalesce**" (atau jalan pintasnya "-coalesce") sebenarnya dirancang untuk mengubah animasi GIF menjadi urutan gambar. Untuk contohnya, lihat coalesce pada animasi. Meski begitu, operator ini sangat erat kaitannya dengan "-flatten" dan dalam hal itu memberi efek yang sangat berguna bagi gambar berlapis banyak. Sebagai contoh, memakai coalesce pada satu gambar akan mengerjakan hal yang persis sama dengan memakai flatten dengan warna "-background" 'None' atau 'Transparency'. Artinya, ia akan 'mengisi' kanvas gambar itu dengan piksel transparan. |

  magick \( -page 100x100+5+10 balloon.gif \) -layers coalesce  coalesce_canvas.gif

[IM Output]
Saat menangani gambar yang terdiri atas banyak layer, coalesce dapat dipakai untuk menghasilkan 'pelapisan progresif' dari gambar itu. Tetapi untuk itu kita perlu mengambil sedikit langkah pencegahan, agar penanganan 'animasi GIF' oleh operator ini dimatikan.

   magick \( -page 100x100+5+10 balloon.gif \)   \( -page +35+30 medical.gif \)  \
           \( --page +62+50       present.gif \)   \( -page +10+55 shading.gif \)  \
           -set dispose None  -coalesce  miff:- |\
     montage - -frame 4 -tile x1 -geometry +2+2 \
             -background none -bordercolor none  coalesce_none.gif

[IM Output]

Pada contoh di atas kita "-set" semua pengaturan "-dispose" menjadi 'None'. Ini praktis memberi tahu "-coalesce" agar sekadar menimpakan tiap frame di atas hasil timpaan sebelumnya. Hasilnya, gambar pertama hanyalah 'pengisian' kanvas gambar dengan latar belakang transparan. Gambar berikutnya adalah gambar sebelumnya dengan layer itu ditimpakan. Dan seterusnya. Sebuah flatten 'progresif' atas urutan gambar. Gambar terakhir dalam urutan itu dengan demikian akan sama seperti bila Anda melakukan "-flatten" biasa dengan latar belakang transparan. Efek yang sama sekali berbeda akan muncul bila dipakai pengaturan "-dispose" 'Background'. Dalam hal ini "-coalesce" hanya akan 'mengisi' kanvas tiap gambar, seolah-olah semuanya gambar yang sepenuhnya terpisah!

  magick \( -page 100x100+5+10 balloon.gif \)   \( -page +35+30 medical.gif \)  \
          \( --page +62+50       present.gif \)   \( -page +10+55 shading.gif \)  \
          -set dispose Background  -coalesce  miff:- |\
    montage - -frame 4 -tile x1 -geometry +2+2 \
            -background none -bordercolor none  coalesce_bgnd.gif

[IM Output]

Namun perhatikan bahwa berbeda dari flatten, mosaic, atau merge, operator "-coalesce" tidak memanfaatkan pengaturan komposisi alpha "-compose" saat itu. Ia hanya memakai metode compose 'Over', karena itulah yang dibutuhkan untuk penanganan animasi GIF. Pemakaian metode "-compose" yang berbeda bersama operator pelapisan gambar yang lebih standar menjadi pokok bahasan contoh-contoh berikutnya.

Metode compose dan pelapisan

Ketiga metode pelapisan, yaitu flatten, mosaic, dan merge, memanfaatkan pengaturan "-compose" untuk menentukan metode komposisi yang dipakai saat menimpakan tiap gambar dalam urutan. Karena itu fungsi-fungsi ini dapat Anda anggap sebagai operator "-composite" multi-gambar yang mampu menyiapkan kanvas "-background" awal berwarna tertentu. Namun memakai sesuatu selain komposisi alpha bawaan 'Over' perlu dipikirkan dulu sebelum diterapkan, atau hasilnya akan di luar dugaan. Anda mungkin juga perlu memikirkan pengaruh warna "-background" yang dipakai operator-operator ini untuk membuat kanvas awal, yang di atasnya tiap gambar (termasuk yang pertama) dikomposisikan. Sebagai contoh, mari kita tempatkan tiap gambar berikutnya di bawah gambar sebelumnya memakai 'DstOver'... |

  magick \( -page 100x100+5+10 balloon.gif \)   \( -page +35+30 medical.gif \)  \
          \( --page +62+50       present.gif \)   \( -page +10+55 shading.gif \)  \
          -background none  -compose DstOver  -flatten  flatten_dstover.gif

[IM Output]
Di sini latar belakangnya diatur transparan; kalau tidak, Anda hanya akan melihat kanvas latar belakang pada hasilnya karena semua gambar lain ditempatkan 'di bawah' kanvas awal ini! Cara ini memang menyediakan jalan untuk 'mengosongkan' gambar dengan warna tertentu, seperti diperlihatkan pada kanvas seukuran gambar yang sudah ada. Berikut contoh yang lebih praktis. Alih-alih melapiskan gambar dengan kanvas latar belakang lebih dulu, yang janggal dan tidak wajar pada sebagian situasi pemrosesan gambar, gambarnya dapat langsung dibuat dari atas ke bawah, atau dari latar depan ke latar belakang. |

  magick rose: -repage +10+10 \
          \( +clone -background black -shadow 60x3+5+5 \) \
          \( granite: -crop 100x80+0+0 +repage \) \
          -background none  -compose DstOver -layers merge layer_dstover.gif

[IM Output]
Masing-masing dari tiga baris pertama menghasilkan satu gambar layer, sedangkan baris terakhir menggabungkan semua layer di bawah layer sebelumnya, yang efeknya membalik urutan.

Seperti yang Anda lihat, pemrosesan gambar di atas lebih sederhana dan lebih bersih daripada yang biasanya terlihat pada pembuatan bayangan, hanya dengan menaruh tiap gambar dalam urutan itu di bawah gambar sebelumnya (dengan kanvas awal yang transparan)

Tentu saja saya bisa saja dengan sama mudahnya membalik daftar gambarnya. |

  magick rose: -repage +10+10 \
          \( +clone -background black -shadow 60x3+5+5 \) \
          \( granite: -crop 100x80+0+0 +repage \) \
          -reverse -layers merge layer_reverse.gif

[IM Output]
Namun ingat bahwa ini hanya menyusun ulang gambar yang ada, dan tidak memengaruhi 'kanvas latar belakang awal' yang dibuat oleh metode pelapisan. Metode compose juga dapat dipakai untuk menghasilkan efek yang menarik. Sebagai contoh, jika Anda menggambar tiga lingkaran lalu menimpakannya memakai metode compose 'Xor', Anda memperoleh simbol yang tidak biasa dan tampak rumit dengan usaha yang sangat kecil. |

  magick -size 60x60 \
          \( xc:none -fill blue   -draw 'circle 21,39 24,57' \) \
          \( xc:none -fill red    -draw 'circle 39,39 36,57' \) \
          \( xc:none -fill green  -draw 'circle 30,21 30,3'  \) \
          -background none  -compose Xor   -flatten  flatten_xor.png

[IM Output]

Layers composite - menggabungkan dua daftar layer

Pada IM v6.3.3-7 ditambahkan metode '**Composite**' bagi "-layers" yang memungkinkan Anda mengomposisikan dua kumpulan gambar yang sepenuhnya terpisah. Untuk melakukannya di baris perintah diperlukan gambar penanda khusus 'null:' guna menentukan di mana daftar gambar tujuan yang pertama berakhir dan daftar gambar sumber yang ditimpakan dimulai. Hanya itulah kerumitan sesungguhnya dari metode ini. Pada dasarnya tiap gambar dari daftar pertama dikomposisikan dengan gambar yang bersesuaian pada daftar kedua, yang efeknya menggabungkan kedua daftar itu. Daftar kedua dapat ditempatkan secara global relatif terhadap daftar pertama memakai offset geometry, sama seperti pada operator composite biasa (lihat di atas). Gravity juga diterapkan dengan memakai ukuran kanvas gambar pertama untuk perhitungannya. Selain 'offset global' itu, offset virtual masing-masing gambar juga tetap terjaga saat tiap pasang gambar dikomposisikan. Satu kasus khusus turut ditangani. Bila salah satu daftar gambar hanya berisi satu gambar, gambar itu akan dikomposisikan dengan semua gambar pada daftar yang lain. Dalam kasus itu pula, metadata gambar (seperti pengaturan waktu animasi) dari daftar yang lebih besarlah yang dipertahankan, sekalipun ia bukan sisi tujuan dari komposisi tersebut.
Operator pelapisan ini lebih lazim dipakai saat mengomposisikan dua animasi, yang dapat dianggap semacam daftar gambar berlapis menurut waktu. Karena itu contohnya lebih pas ditempatkan pada bagian modifikasi animasi dari kumpulan contoh ini. Jadi lihat komposisi alpha multi-gambar untuk keterangan lebih lanjut.


Menangani layer gambar

Melapiskan banyak gambar memakai berbagai operator layer di atas adalah teknik yang sangat luwes. Teknik ini memungkinkan sejumlah besar gambar dikerjakan satu per satu, lalu setelah selesai menyatukan semuanya menjadi satu kesatuan. Sejauh ini kita sudah melihat berbagai cara menggabungkan (mengomposisikan atau melapiskan) banyak gambar. Di sini saya memberikan beberapa contoh yang lebih praktis tentang cara memanfaatkan teknik-teknik tersebut.

Melapiskan gambar thumbnail

Teknik ini juga dapat Anda pakai untuk menggabungkan banyak thumbnail dengan berbagai cara yang rumit. Di sini saya menambahkan tepi lembut pada gambar-gambar itu sembari membaca dan menempatkannya, sehingga terbentuk komposisi gambar yang cukup bagus di atas kanvas yang di-tile.

  magick -page +5+5    holocaust_tn.gif \
          -page +80+50  spiral_stairs_tn.gif \
          -page +40+105 chinese_chess_tn.gif \
          +page \
          -alpha Set -virtual-pixel transparent \
          -channel A -blur 0x10  -level 50,100% +channel \
          \( -size 200x200 tile:tile_fabric.gif -alpha Set \) -insert 0 \
          -background None -flatten  overlap_canvas.jpg

[IM Output]

Penempatan gambar yang dihitung.

Offset kanvas virtual (page) dapat diatur dengan banyak cara. Lebih khusus lagi, Anda dapat "-set" atribut per gambar ini, bahkan menghitung posisi yang berbeda bagi setiap gambar. Sebagai contoh, di sini saya membaca sekumpulan besar gambar (gambar ikon kecil yang semuanya berukuran sama) lalu menyusunnya melingkar.

  magick {balloon,castle,eye,eyeguy,ghost,hand_point,medical}.gif \
          {news,noseguy,paint_brush,pencil,present,recycle}.gif \
          {shading,skull,snowman,storm,terminal,tree}.gif \
          \
          -set page '+%[fx:80*cos((t/n)*2*pi)]+%[fx:80*sin((t/n)*2*pi)]' \
          \
          -background none -layers merge +repage image_circle.png

[IM Output]

Kunci contoh di atas adalah operasi "-set page" yang memakai indeks gambar ternormalisasi (ekspresi FX 't/n' ) untuk menghasilkan nilai dari 0.0 hingga hampir 1.0 bagi tiap gambar. Nilai ini lalu dipetakan untuk menempatkan gambar (menurut sudut) pada lingkaran berjari-jari 80 piksel, memakai ekspresi FX sebagai persen escape. Posisi yang dihitung adalah sudut kiri-atas gambar (bukan titik tengahnya, meski itu penyesuaian yang mudah), yang kemudian di-merge untuk menghasilkan gambar baru. Penempatannya dilakukan tanpa peduli offsetnya positif atau negatif, dan di situlah kekuatan operator pelapisan merge. Artinya, kita menghasilkan gambar baru berisi semua gambar pada posisi relatif satu sama lain. "+repage" di akhir menghapus offset negatif pada gambar layer hasil gabungan, karena offset itu tidak lagi diperlukan dan dapat menimbulkan masalah saat gambar hasilnya dilihat. Perhatikan bahwa gambar pertama (paling kanan pada hasil) berada di bawah semua gambar lain. Jika Anda ingin pelapisannya benar-benar siklis sehingga gambar terakhir berada di bawah gambar pertama tadi, Anda mungkin harus membelah gambar pertama itu menjadi dua dan menaruh belahan atasnya di akhir urutan, agar belahan atas gambar pertama melapisi gambar terakhir, sementara belahan bawahnya tetap berada di bawah gambar kedua. Teknik ini ampuh, tetapi hanya bisa menempatkan gambar pada offset bilangan bulat. Jika Anda memerlukan penempatan sub-piksel yang lebih tepat, gambar-gambar itu perlu didistorsi (digeser) ke lokasi sub-piksel yang tepat, bukan sekadar disesuaikan offset virtualnya.

Posisi yang dihitung secara bertahap

Anda dapat mengakses sebagian atribut gambar dari gambar lain memakai ekspresi FX, sembari menetapkan atribut gambar saat gambar itu diproses. Artinya, posisi tiap gambar dapat ditetapkan relatif terhadap posisi gambar sebelumnya yang telah dihitung. Sebagai contoh, perintah berikut menetapkan posisi tiap gambar agar berada di sebelah kanan gambar sebelumnya, yaitu posisi gambar sebelumnya ditambah lebarnya.

  magick rose: netscape: granite: \
          \
          +repage -set page '+%[fx:u[t-1]page.x+u[t-1].w]+0' \
          \
          -background none -layers merge +repage append_diy.png

[IM Output]

Tiap gambar disambungkan ke posisi gambar sebelumnya, dengan membaca posisi itu lalu menambahkan lebar gambar tersebut. Posisi sebelumnya itu sebenarnya baru saja dihitung, karena IM mengulang tiap gambar sambil menetapkan atribut 'page' (offset virtual). Hasilnya setara dengan operator append buatan sendiri, yang darinya variasi sendiri dapat dikembangkan. Perlu dicatat bahwa seluruh urutan itu sebenarnya bergeser sebesar 'u[-1].w' yang ditetapkan saat menghitung posisi gambar pertama. Nilai itu semestinya lebar gambar terakhir dalam urutan gambar saat itu. Namun pergeseran menyeluruh tersebut dibuang oleh "+repage" di akhir. Sedikit perhitungan bisa ditambahkan agar offset ini diabaikan, tetapi hal itu tidak diperlukan pada contoh di atas. | _Saat memakai indeks gambar seperti 'u[t]', semua pemilih gambar 'u', 'v', dan 's' merujuk ke gambar yang sama, sesuai '[index]' yang diberikan. Karena itu lebih baik memakai 'u' (gambar pertama atau ke-nol) sebagai pengingat perilaku pengindeksan ini (dan seandainya hal ini berubah).

Untuk keterangan lebih lanjut lihat FX, operator gambar buatan sendiri._
Berikut contoh lain. Tiap gambar diberi offset relatif terhadap gambar sebelumnya, memakai posisi sekaligus lebar gambar itu, sehingga terhitung sebuah penyambungan yang tumpang tindih.

magick font_[0-9].gif \
        -set page '+%[fx:u[t-1]page.x+u[t-1].w-8]+%[fx:u[t-1]page.y+4]' \
        -background none -layers merge +repage append_offset.gif

[IM Output]

Kemampuan mengakses atribut gambar lain ini juga mencakup data piksel gambar lain. Artinya dapat dibuat gambar khusus yang nilai warnanya mewakili 'posisi terpetakan' dari gambar-gambar lain. Tentu saja gambar 'pemetaan' itu juga ikut ditempatkan, dan perlu dihapus sebelum penimpaan dilakukan. Seberapa berguna membuat gambar 'posisi terpetakan' semacam itu adalah soal lain. Ini sekadar satu kemungkinan lagi.

Penempatan gambar dua tahap

Anda dapat menyederhanakan pemrosesan gambar dengan memisahkannya menjadi dua langkah. Satu langkah dipakai untuk membuat, mendistorsi, menempatkan, dan menambahkan hiasan pada gambar, lalu satu langkah terakhir untuk menggabungkan semuanya. Sebagai contoh, mari kita buat thumbnail polaroid dari gambar asli yang lebih besar di Photo Store, dan memproses tiap gambar satu per satu (agar sisi itu tetap terpisah dan sederhana).

  center=0   # Start position of the center of the first image.
             # This can be ANYTHING, as only relative changes are important.

  for image in ../img_photos/[a-m]*_orig.jpg
  do

    # Add 70 to the previous images relative offset to add to each image
    #
    center=`magick xc: -format "%[fx: $center +70 ]" info:`

    # read image, add fluff, and using centered padding/trim locate the
    # center of the image at the next location (relative to the last).
    #
    magick -size 500x500 "$image" -thumbnail 240x240 \
            -set caption '%t' -bordercolor Lavender -background black \
            -pointsize 12  -density 96x96  +polaroid  -resize 30% \
            -gravity center -background None -extent 100x100 -trim \
            -repage +${center}+0\!    MIFF:-

  done |
    # read pipeline of positioned images, and merge together
    magick -background skyblue   MIFF:-  -layers merge +repage \
            -bordercolor skyblue -border 3x3   overlapped_polaroids.jpg

[IM Output]

Skrip di atas tampak rumit, padahal sebenarnya tidak. Skrip itu sekadar membuat tiap gambar thumbnail dalam sebuah loop, sambil pada saat yang sama memberi padding secara terpusat (memakai extent) dan memangkas tiap gambar agar 'titik tengah' gambar berada pada posisi yang diketahui di kanvas virtual. Posisi itu sebenarnya bisa saja dihitung, tetapi hal itu mungkin menuntut file sementara, jadi lebih baik memastikan posisinya berada di tempat yang sudah pasti bagi semua gambar. Gambar itu lalu digeser (memakai operator "-repage" relatif, lihat offset kanvas) sehingga tiap gambar yang dihasilkan berada tepat 60 piksel di sebelah kanan gambar sebelumnya. Artinya, titik tengah tiap gambar berjarak tetap satu sama lain, tanpa peduli ukuran gambar yang sebenarnya, yang bisa berubah karena rasio aspek dan rotasi. Trik penting lain pada skrip ini adalah, alih-alih menyimpan tiap 'gambar layer' ke file sementara, gambar itu dapat langsung dituliskan ke sebuah pipeline memakai format file MIFF:. Cara ini dikenal sebagai streaming gambar MIFF. Hal ini bisa dilakukan karena format file "MIFF:" memungkinkan Anda merangkai banyak gambar menjadi satu aliran data, sekaligus mempertahankan seluruh metadata gambar, seperti offset kanvas virtualnya. Teknik ini menjadi titik awal yang baik bagi banyak skrip lain. Gambar dapat dibuat atau diubah, dan ukuran serta posisi akhirnya dapat dihitung sesuka Anda. Contoh lain adalah skrip "hsl_named_colors" yang mengambil daftar warna bernama di ImageMagick lalu mengurutkannya menjadi bagan warna-warna itu dalam ruang warna HSL. Keluarannya dapat dilihat di spesifikasi warna. Kemungkinan lain antara lain...

  • Pakai jenis thumbnail apa pun (atau hiasan lain), atau cukup pakai thumbnail kecil apa adanya.
  • Buat gambar sedemikian rupa sehingga gambar pertama berada di tengah dan gambar lain tersusun ke kiri dan ke kanan di bawah gambar pertama itu, seperti piramida.
  • Tempatkan gambar dalam bentuk busur, lingkaran, dan spiral, dengan menaruhnya pada koordinat X dan Y tertentu relatif satu sama lain. Sebagai contoh: PhD Circle, Sunset Flower, Fibonacci Spiral.
  • Tempatkan gambar menurut warnanya. Sebagai contoh: Book Covers.
  • Tempatkan gambar menurut waktu dalam sehari atau waktu pengirimannya. Sebagai contoh: Year of Sunsets

Pada dasarnya Anda punya kebebasan penuh dalam menempatkan gambar di kanvas virtual, lalu tinggal menyerahkan kepada IM penentuan ukuran akhir kanvas yang diperlukan agar memuat semua gambar.

Pin pada peta

Berikut contoh pelapisan yang khas: menempatkan pin berwarna pada peta di posisi tertentu. [IM Output] Di sebelah kiri ada gambar 'push pin'. Ujung pin itu berada pada posisi +18+41. Saya juga punya gambar peta Venesia, dan ingin menaruh pin di berbagai titik pada peta itu. Sebagai contoh, 'Accademia' terletak pada posisi piksel +160+283. Untuk menyelaraskan push pin dengan posisi itu, Anda perlu mengurangkan posisi ujung pin dari posisi pada peta. Hasilnya adalah offset +142+242 bagi gambar 'pin' kita. Berikut hasilnya, memakai gambar berlapis

  magick map_venice.jpg    -page +142+242 push_pin.png \
          -flatten  map_push_pin.jpg

[IM Output]

Contoh ini berasal dari diskusi Forum IM, Layering Images with Convert. Mari kita otomatiskan lebih jauh. Kita punya sebuah file yang memuat daftar posisi dan warna bagi tiap pin yang ingin kita taruh di peta. Nama lokasi di dalam file itu tidak dipakai dan hanya menjadi komentar rujukan atas posisi piksel yang tercantum.

[Data File]

Mari kita baca file teks ini untuk membuat 'pin' dalam sebuah loop.

  pin_x=18  pin_y=41

  cat map_venice_pins.txt |\
    while read x y color location; do

      [ "X$x" = "X#" ] && continue   # skip comments in data

      x=$(( x - pin_x ))    # magick x,y to pin image offsets
      y=$(( y - pin_y ))

      # magick 'color' to settings for color modulate (hue only)
      # assumes a pure 'red' color for the original push pin
      mod_args=$(
         magick xc:$color -colorspace HSL txt: |
           tr -sc '0-9\012' ' ' |\
             awk 'NR==1 { depth=$3 }
                  NR==2 { hue=$3;
                          print  "100,100,"  100+200*hue/depth
                        }'; )

      # re-color and position the push pin
      magick push_pin.png -repage +${x}+${y} -modulate $mod_args miff:-

    done |\
      # read pipeline of positioned images, and merge together
      magick map_venice.jpg  MIFF:-  -flatten  map_venice_pins.jpg

[IM Output]

Perhatikan bahwa skrip ini mengandaikan warna pin aslinya merah ( yang ronanya 0 ) dan memakai operator modulate untuk mewarnainya ulang menjadi warna lain, dengan perhitungan penskalaan yang sesuai. Perhatikan pula bahwa argumen modulate bagi perubahan rona yang tidak mengubah apa pun adalah 100, dan nilainya berputar pada 200 (semacam nilai pseudo-persentase). FUTURE: perspective distort map, adjust pin size for 'depth' on the map calculate change in pin position due to distortion, and 'pin' it to the distorted map. Contoh di atas memakai cara yang dikenal sebagai streaming gambar MIFF, dengan tiap gambar dibuat satu per satu dalam loop, lalu 'dipipa' ke perintah 'pelapisan' untuk menghasilkan gambar akhir. Cara alternatifnya (yang lazim dipakai pada skrip PHP) adalah teknik 'perintah yang dibangkitkan', yaitu skrip shell menyusun satu perintah "magick" yang panjang untuk dijalankan. Skrip pada animasi warping gambar memakai teknik ini. Kedua cara sama-sama menghindarkan kita dari keharusan membuat gambar sementara.

Layer bayangan

Menangani efek bayangan semitransparan dengan benar pada sekumpulan gambar yang saling tumpang tindih sebenarnya jauh lebih sulit daripada kelihatannya. Sekadar menimpakan foto beserta bayangannya akan membuat bayangan itu diterapkan dua kali. Artinya, dua bayangan yang tumpang tindih menjadi sangat gelap, padahal pada kenyataannya bayangan tidak bertumpuk dengan cara yang sama seperti gambar yang ditimpakan. Tiap bagian gambar semestinya cukup terkena bayangan atau tidak terkena bayangan sama sekali. Artinya, bayangan hanya boleh diterapkan satu kali pada bagian mana pun dari gambar. Seharusnya tidak muncul area yang lebih gelap, kecuali bila ada dua sumber cahaya terpisah, dan hal itu justru membuat urusannya makin sulit. Tomas Zathurecky < tom @ ksp.sk > menerima tantangan menangani efek bayangan pada gambar berlapis, dan mengembangkan teknik akumulator gambar untuk mengatasi masalah tersebut. Pada dasarnya kita perlu menambahkan tiap gambar ke dasar tumpukan satu per satu. Saat menambahkan gambar baru, bayangan dari semua gambar sebelumnya harus menggelapkan gambar baru itu sebelum ia dimasukkan ke tumpukan. Namun hanya bayangan yang jatuh pada gambar baru itulah yang perlu ditambahkan. Bayangan yang tidak jatuh pada gambar baru harus diabaikan sampai nanti, ketika ia jatuh pada gambar lain, atau pada latar belakang (jika ada). Berikut contohnya... |

  magick \
    \( holocaust_tn.gif -frame 10x10+3+3 \
          -background none  -rotate 5 -repage +0+0 \) \
    \
    \( spiral_stairs_tn.gif -frame 10x10+3+3 \
          -background none -rotate -15 -repage -90+60 \) \
    \( -clone 0   -background black -shadow 70x3+4+7 \
       -clone 1   -background black -compose DstATop -layers merge \
       -trim \) \
    \( -clone 2,0 -background none  -compose Over -layers merge \) \
    -delete 0--2 \
    \
    \( chinese_chess_tn.gif -frame 10x10+3+3 \
          -background none -rotate 20 -repage +60+90 \) \
    \( -clone 0   -background black -shadow 70x3+4+7 \
       -clone 1   -background black -compose DstATop -layers merge \
       -trim \) \
    \( -clone 2,0 -background none  -compose Over -layers merge \) \
    -delete 0--2 \
    \
    \( +clone -background black -shadow 70x3+4+7 \) +swap \
    -background none -compose Over -layers merge +repage \
    layers_of_shadows.png

[IM Output]
Program di atas tampak rumit, padahal sebenarnya cukup lugas. Gambar pertama dipakai untuk memulai tumpukan gambar yang terakumulasi (gambar indeks #0). Perhatikan bahwa kita sebenarnya bisa saja memulai dengan satu piksel transparan ("-size 1x1 xc:none") bila gambar pertama itu tidak ingin Anda pakai untuk menginisialisasi tumpukan. Nah, untuk menambahkan gambar baru ke dasar tumpukan gambar, kita menerapkan rangkaian operasi yang sama, setiap kalinya...

  • Pertama gambar thumbnail dibaca ke memori, lalu rotasi dan penempatan relatifnya (boleh negatif) diterapkan. Pada tahap ini operasi thumbnail lain juga bisa diterapkan pada gambar itu bila mau, meski untuk contoh ini semuanya sudah dikerjakan sebelumnya. Gambar baru itu menjadi gambar indeks #1.
  • Sekarang kita mengambil tumpukan gambar sebelumnya (#0), lalu membuat bayangan dengan warna, blur, offset, dan persentase cahaya ambien yang sesuai.
  • Bayangan ini ditimpakan pada gambar baru (#1) sehingga hanya bayangan yang jatuh 'ATop' gambar baru itu yang dipertahankan. Kita juga (secara opsional) menerapkan operasi trim pada hasilnya untuk menghapus ruang berlebih yang muncul dari operasi pembayangan, sehingga terbentuk gambar #2.
  • Sekarang kita tinggal menambahkan gambar baru (#2) ke tumpukan gambar yang terakumulasi (#0).
  • lalu menghapus semua gambar kerja sebelumnya, kecuali yang terakhir.

Untuk menambahkan gambar lagi, kita pada dasarnya tinggal mengulang blok operasi di atas. Setelah semua gambar masuk ke tumpukan, tinggal melakukan operasi pembayangan biasa pada tumpukan gambar yang terakumulasi itu, sambil menghapus sisa offset gambar (yang dibenci banyak peramban web). Dengan merge saya dapat menangani offset virtual secara otomatis, terutama yang negatif, sehingga gambar bisa ditaruh di mana saja relatif terhadap penempatan gambar sebelumnya. Ini juga membuat penerapan bayangan, yang dapat menghasilkan gambar lebih besar dengan offset negatif, berjalan dengan benar.
Cara di atas memang menangani bayangan gambar berlapis dengan benar, tetapi meski bayangannya diberi offset, offsetnya sama besar untuk semua gambar! Yang semestinya terjadi adalah bayangan makin bergeser dan juga makin kabur ketika jatuh pada gambar yang makin dalam di tumpukan. Artinya, gambar yang paling atas semestinya melemparkan bayangan yang sangat kabur ke latar belakang, dibandingkan gambar yang paling bawah. Ini sebenarnya lebih sulit dikerjakan karena Anda tidak hanya perlu melacak tumpukan gambar, tetapi juga melacak seberapa 'kabur' bayangannya seiring tumpukan gambar bertambah besar. Jadi Anda benar-benar memerlukan dua akumulator: tumpukan gambar (seperti di atas), dan akumulasi bayangan, seiring kita menambah gambar. Sebagai contoh, berikut kumpulan gambar yang sama tetapi dengan bayangan yang makin kabur seiring kedalaman. |

  magick xc:none xc:none \
    \
    \( holocaust_tn.gif -frame 10x10+3+3 \
          -background none  -rotate 5 -repage +0+0 \) \
    \( -clone 1   -background black -shadow 70x0+0+0 \
       -clone 2   -background black -compose DstATop -layers merge \
       -clone 0   -background none  -compose Over    -layers merge \) \
    \( -clone 2,1 -background none  -compose Over    -layers merge \
                  -background black -shadow 100x2+4+7 \) \
    -delete 0-2 \
    \
    \( spiral_stairs_tn.gif -frame 10x10+3+3 \
          -background none -rotate -15 -repage -90+60 \) \
    \( -clone 1   -background black -shadow 70x0+0+0 \
       -clone 2   -background black -compose DstATop -layers merge \
       -clone 0   -background none  -compose Over    -layers merge \) \
    \( -clone 2,1 -background none  -compose Over    -layers merge \
                  -background black -shadow 100x2+4+7 \) \
    -delete 0-2 \
    \
    \( chinese_chess_tn.gif -frame 10x10+3+3 \
          -background none -rotate 20 -repage +60+90 \) \
    \( -clone 1   -background black -shadow 70x0+0+0 \
       -clone 2   -background black -compose DstATop -layers merge \
       -clone 0   -background none  -compose Over    -layers merge \) \
    \( -clone 2,1 -background none  -compose Over    -layers merge \
                  -background black -shadow 100x2+4+7 \) \
    -delete 0-2 \
    \
    \( -clone 1 -background black -shadow 70x0+0+0 \
       -clone 0 -background none -compose Over -layers merge \) \
    -delete 0-1 -trim +repage \
    layers_of_deep_shadows.png

[IM Output]
Perhatikan hasilnya baik-baik. Offset dan kekaburan bayangannya berbeda di bagian-bagian gambar yang berbeda. Bayangan itu sangat tipis di antara gambar pada layer yang bersebelahan, tetapi sangat tebal ketika jatuh pada gambar, atau bahkan pada latar belakang yang jauh lebih dalam. Tentu saja pada contoh ini offset bayangannya mungkin terlalu besar, tetapi hasilnya tampak sangat realistis dan memberi kesan kedalaman yang lebih baik pada layer-layernya. Perhatikan bagaimana kita membagi operasi bayangan menjadi dua langkah. Saat menerapkan bayangan terakumulasi (gambar indeks #1) pada gambar baru (#2), kita hanya menambahkan persentase cahaya ambien, tanpa blur atau offset ('70x0+0+0' dalam kasus ini). Gambar baru itu lalu ditambahkan ke tumpukan gambar yang terakumulasi (#0). Tetapi setelah menambahkan bayangan gambar baru (#2) langsung ke bayangan terakumulasi (#1), lagi-lagi tanpa blur atau offset, barulah kita mengaburkan dan menggeser SEMUA bayangan itu untuk membentuk gambar bayangan terakumulasi yang baru. Dengan kata lain, gambar bayangan terakumulasi menjadi makin kabur dan makin bergeser seiring tumpukan makin tebal. Hanya bayangan gambar yang lebih dalam yang belum mengakumulasi efek itu sebanyak yang lain. Program ini pada dasarnya memisahkan penerapan bayangan dari akumulator bayangan yang bertahap. Dengan begitu hal-hal berikut dapat dikendalikan...

  • Bayangan realistis (seperti di atas): 70x0+0+0 dan 100x2+4+7
  • Bayangan konstan (seperti contoh dasar): 70x2+4+7 dan 100x0+0+0
  • blur konstan, tetapi offset kumulatif: 70x2+0+0 dan 100x0+4+7
  • offset konstan sekaligus progresif: 60x0+4+7 dan 100x0+1+1
  • efek cahaya ambien kumulatif: 80x0+0+0 dan 95x2+4+7

Kebanyakan di antaranya mungkin tidak realistis, tetapi bisa tampak bagus pada situasi lain. Selain itu, menetapkan warna "-background" sebelum komposisi "-compose ATOP" memungkinkan warna bayangannya ditentukan (sebenarnya cahaya ambien berwarna). Bahkan warna yang berbeda bisa dipakai bagi bayangan yang akhirnya jatuh pada layer latar belakang terakhir (pengaturan "-background black" yang paling akhir), atau menghilangkannya sama sekali agar gambar-gambar itu tampak tidak berada di atas latar belakang apa pun (seolah melayang di udara). Cara ini sangat luwes.
Tomas Zathurecky kemudian mengembangkan metode lain untuk menangani bayangan gambar berlapis, yaitu dengan memperlakukan daftar gambar berlapis itu sebagai satu kesatuan. Sesuatu yang tidak pernah saya kira mungkin. Keunggulan metode ini adalah seluruh daftar gambar dapat ditangani sekaligus, alih-alih harus mengakumulasi satu gambar setiap kali dan mengulang blok operasi yang sama berkali-kali. Pertama, mari kita lihat lagi masalah 'bayangan konstan' yang lebih sederhana. |

  magick \
    \( holocaust_tn.gif -frame 10x10+3+3 \
          -background none  -rotate 5 -repage +0+0 \) \
    \( spiral_stairs_tn.gif -frame 10x10+3+3 \
          -background none -rotate -15 -repage -90+60 \) \
    \( chinese_chess_tn.gif -frame 10x10+3+3 \
          -background none -rotate 20 -repage +60+90 \) \
    \
    -layers trim-bounds \
    \
    \( -clone 0--1 -dispose None -coalesce \
       -background black -shadow 70x2+4+7 \
       xc:none +insert null: +insert +insert xc:none \) \
    -layers trim-bounds -compose Atop -layers composite \
    \
    -fuzz 10% -trim \
    -reverse -background none -compose Over -layers merge +repage \
    coalesced_shadows.png

[IM Output]
Blok operator yang pertama sekadar membuat daftar gambar berlapisnya. Blok itu bisa saja berupa loop terprogram yang terpisah, seperti diperlihatkan sebelumnya. Operasinya lalu dimulai dengan "-layers trim-bounds", yaitu operasi pemangkasan batas yang melebarkan kanvas virtual semua gambar agar memuat seluruh gambar, sekaligus memastikan semua offsetnya positif. Hasilnya kemudian diklona, di-coalesce, dan diberi bayangan untuk membuat daftar bayangan progresif yang terpisah. Sekarang kita dapat memakai komposisi layer untuk menggabungkan daftar bayangan dan daftar gambar aslinya. Kerumitannya di sini, sebelum penggabungan kita tidak hanya perlu menambahkan gambar penanda khusus 'null:' untuk memisahkan kedua daftar, tetapi juga menambahkan gambar kosong khusus 'xc:none' agar daftar bayangannya bergeser. Dengan begitu tiap gambar bayangan akan ditimpakan 'ATop' gambar berikutnya dari daftar aslinya. Yang tersisa tinggal menggabungkan gambar-gambar yang kini sudah berbayang dengan benar itu dari bawah ke atas (urutan terbalik).
Untuk menangani 'bayangan dalam' diperlukan perhitungan layer. |

  magick \
    \( holocaust_tn.gif -frame 10x10+3+3 \
          -background none  -rotate 5 -repage +0+0 \) \
    \( spiral_stairs_tn.gif -frame 10x10+3+3 \
          -background none -rotate -15 -repage -90+60 \) \
    \( chinese_chess_tn.gif -frame 10x10+3+3 \
          -background none -rotate 20 -repage +60+90 \) \
    \
    \( -clone 0--1 \
       -set page '+%[fx:page.x-4*t]+%[fx:page.y-7*t]' -layers merge \) \
    -layers trim-bounds +delete \
    \
    \( -clone 0--1 \
       -set page '+%[fx:page.x-4*t]+%[fx:page.y-7*t]' \
            -dispose None -coalesce \
       -set page '+%[fx:page.x+4*t]+%[fx:page.y+7*t]' \
            -background black -shadow 70x2+4+7 \
       xc:none +insert null: +insert +insert xc:none \) \
    -layers trim-bounds -compose Atop -layers composite \
    \
    -fuzz 10% -trim \
    -reverse -background none -compose Over -layers merge +repage \
    coalesced_deep_shadows.png

[IM Output]
Anda dapat melihat rangkaian blok yang sama seperti sebelumnya, tetapi dengan perhitungan yang jauh lebih rumit untuk menetapkan pemangkasan batas awal, dan kemudian menghitung offset yang diperlukan bagi 'daftar bayangan progresif'. Namun untuk saat ini bayangannya belum menjadi lebih kabur seiring kedalaman. | Contoh di atas akan jauh lebih sederhana dengan perintah "magick" IMv7, yang memungkinkan Anda memakai 'perhitungan fx' langsung sebagai argumen "-shadow". Dengan begitu Anda tidak hanya bisa menghitung offset bayangan yang lebih besar seiring kedalaman, tetapi juga membuat bayangan makin kabur seiring kedalaman.

Menempatkan gambar perspektif yang terdistorsi

Menyelaraskan gambar yang terdistorsi bisa merepotkan, dan di sini saya akan membahas cara menyelaraskan gambar semacam itu agar bertemu pada satu posisi yang sangat spesifik. Saya punya dua gambar yang masing-masing menyorot satu titik tertentu.

[IM Output] [IM Output]

Gambar kedua bersifat semitransparan 65%, sehingga tembus pandang saat dikomposisikan ke gambar biru, dan Anda bisa melihat apakah titik yang ditandai sudah selaras. Titik kontrol yang ditandai itu sendiri berada pada koordinat 59,26 (biru) dan 35,14 (merah). Bila Anda sekadar menimpakan kedua gambar, Anda tinggal mengurangkan offsetnya lalu 'mengomposisikan' kedua gambar itu satu di atas yang lain, sehingga menghasilkan offset +24+12. |

  magick align_blue.png align_red.png -geometry +24+12 \
          -composite align_composite.png

[IM Output]
Perhatikan bahwa offset ini bisa saja negatif! Dan hal itu akan kita tangani sebentar lagi. Cara ini hanya berhasil karena koordinatnya berupa koordinat piksel bilangan bulat. Bila koordinat yang dicocokkan berada pada posisi sub-piksel (seperti yang lazim terjadi pada montase foto), komposisi sederhana tidak akan berhasil. Cara itu juga tidak bekerja dengan baik bila ada distorsi apa pun yang terlibat (yang juga umum pada gambar dunia nyata). Dan inilah masalah yang akan kita telusuri.
Saat mendistorsi gambar, Anda tentu ingin memastikan kedua piksel itu tetap selaras. Cara terbaiknya adalah memakai titik-titik yang ingin diselaraskan sebagai titik kontrol distort. Dengan begitu posisinya terjamin tepat. |

  magick align_blue.png \
          \( align_red.png -alpha set -virtual-pixel transparent \
             +distort SRT '35.5,14.5  1 75  59.5,26.5' \
          \) -flatten  align_rotate.png

[IM Output]
Karena distort menghasilkan 'gambar layer' beserta 'offset kanvas', Anda tidak bisa begitu saja memakai composite untuk menimpakan gambarnya (terlalu tingkat rendah); sebagai gantinya kita perlu operator flatten agar penempatannya memakai offset yang dihasilkan distort. Perhatikan pula bahwa saya menambahkan nilai 0.5 pada koordinat 'piksel'. Ini karena piksel memiliki luas, sedangkan titik matematis tidak; jadi bila Anda ingin menyelaraskan titik tengah sebuah piksel, Anda perlu menambahkan 0.5 pada posisi 'titik' tengah di dalam piksel itu. Lihat koordinat gambar vs koordinat piksel untuk keterangan lebih lanjut. Masalah lain pada contoh di atas adalah gambar yang ditimpakan 'terpotong' oleh gambar kanvas latar belakang berwarna biru, persis seperti yang dilakukan operator composite. Artinya, gambar 'biru' itu menyediakan 'viewport pemotong' bagi hasilnya selama komposisi berlangsung. Untuk mencegahnya kita memakai layer merge yang otomatis menghitung kanvas 'viewport' yang cukup besar untuk memuat semua gambar yang dikomposisikan. |

  magick align_blue.png \
          \( align_red.png -alpha set -virtual-pixel transparent \
             +distort SRT '35.5,14.5  1 75  59.5,26.5' \
          \) -background none -layers merge +repage  align_rotate_merge.png

[IM Output]
Sebagai hasil 'merge', gambar itu akan memiliki offset 'negatif' (agar posisi layer tiap gambar terjaga). Untuk menampilkan hasilnya saya perlu membuang offset tersebut karena banyak peramban tidak menangani offset negatif pada gambar. Saya melakukannya memakai "+repage" sebelum menyimpan gambar akhir. Seandainya saya hendak memproses lebih lanjut (tanpa menampilkan hasilnya di web), saya akan mempertahankan offset itu (menghapus "+repage") supaya posisi gambar tetap berada di tempatnya yang benar dan diketahui untuk pemrosesan berikutnya.
Nah, teknik yang sama seperti di atas juga berlaku bila Anda melakukan distorsi yang lebih rumit seperti perspektif. |

  magick align_blue.png \
          \( align_red.png -alpha set -virtual-pixel transparent \
             +distort Perspective '35.5,14.5  59.5,26.5
                       0,0 32,4    0,%h 14,36    %w,%h 72,53  ' \
          \) -background none -layers merge +repage  align_perspective.png

[IM Output]
Masalah teknik ini adalah Anda menempatkan distorsi perspektifnya memakai sebuah titik kontrol di bagian dalam, yaitu satu titik di dalam gambar dan 3 titik di sekeliling tepinya. Hal itu membuat bentuk perspektif yang sesungguhnya sulit dikendalikan, karena pergeseran kecil pada titik kontrol mana pun dapat membuat 'sudut bebas' bergerak liar. Keadaannya bisa lebih buruk lagi bila Anda memakai daftar panjang 'titik teregistrasi' untuk memperoleh 'least squares fit' yang lebih tepat dalam menempatkan gambar. Dalam hal itu titik yang Anda minati bisa jadi sama sekali tidak dekat dengan salah satu titik kontrol 'teregistrasi' yang dipakai untuk mendistorsi gambar. Alternatifnya adalah mendistorsi gambar sesuai kebutuhan kita, lalu mencari tahu seberapa jauh gambar hasilnya perlu digeser agar titik yang kita minati menjadi selaras. Agar cara itu berhasil, kita perlu tahu ke mana 'titik yang diminati' berpindah akibat distorsi tersebut. Inilah masalah nyata dalam mendistorsi dan menempatkan gambar, terutama gambar dunia nyata. Sebagai contoh, di sini saya mendistorsi gambar memakai keempat sudutnya untuk menghasilkan bentuk distorsi tertentu (yang katakanlah diinginkan), tetapi pada tahap ini saya tidak akan berusaha menyelaraskan titik kontrolnya, hanya menerapkan distorsinya saja... |

  magick align_blue.png \
          \( align_red.png -alpha set -virtual-pixel transparent \
             +distort Perspective '0,0  10,12  0,%h 14,40
                               %w,0 68,6  %w,%h 63,48 ' \
          \) -background none -layers merge +repage  align_persp_shape.png

[IM Output]
Seperti yang Anda lihat, meski gambar merahnya sudah terdistorsi, posisi titik kontrol merah sama sekali tidak dekat dengan titik kontrol biru yang ingin kita selaraskan. Anda tidak bisa sekadar mengukur kedua titik itu, karena titik merahnya kemungkinan besar tidak berada tepat pada posisi piksel, melainkan mengandung offset sub-piksel. Kita perlu lebih dulu menghitung dengan tepat di mana titik merah itu berada. Untuk itu kita dapat menjalankan ulang distorsi di atas dengan verbose aktif guna memperoleh koefisien pemetaan maju perspektifnya. Koefisien itu lalu dapat dipakai untuk perhitungan seperti diuraikan pada distorsi proyeksi perspektif.

  magick align_red.png  -define distort:viewport=1x1  -verbose \
          +distort Perspective '0,0  10,12  0,%h 14,40
                                %w,0 68,6  %w,%h 63,48 ' null:

[IM Text]

Yang kita inginkan hanyalah koefisien terhitung yang dipakai oleh distorsi itu. Karena itu gambar tujuannya tidak kita perlukan, jadi keluarannya kita buang memakai format file gambar "null:". Kita juga memberi tahu distort bahwa gambar baru yang dibuatnya hanya berukuran satu piksel, memakai viewport distort. Dengan begitu ia tetap melakukan persiapan distorsi dan pelaporan verbose, tetapi hanya mendistorsi satu piksel 'tujuan' yang kemudian dibuang. Cara ini dapat menghemat banyak waktu pemrosesan. Sebenarnya, seandainya distorsi itu tidak memakai metadata gambar sumber (yang diperlukan oleh persen escape '%w' dan '%h') dalam perhitungannya, gambar sumber "align_red.png" pun tidak kita perlukan. Dalam hal itu kita bisa memakai gambar "null:" satu piksel sebagai gambar masukan juga. Kita juga tidak benar-benar peduli pada piksel virtual, latar belakang, atau hal lain pada langkah pengumpulan informasi ini, jadi tidak perlu memusingkan pengaturan fitur-fitur tersebut.
Setelah informasi distorsi itu bisa kita peroleh, kita perlu mengambil 8 koefisien perspektif dari baris ke-3 dan ke-4 keluarannya. Koefisien itu lalu dapat dipakai untuk memetakan titik kontrol merah ke posisi barunya setelah terdistorsi, dan dari situ menguranginya dari titik kontrol biru, sehingga diperoleh besar pergeseran yang sesungguhnya diperlukan agar koordinat merah yang ditandai selaras dengan koordinat biru.

  bluex=59; bluey=26
  redx=35; redy=14

  magick align_red.png  -verbose \
             +distort Perspective '0,0  10,12  0,%h 14,40
                               %w,0 68,6  %w,%h 63,48 ' null: 2>&1 |\
    tr -d "',"  |\
      awk 'BEGIN   { redx='"$redx"'+0.5;   redy='"$redy"+0.5';
                     bluex='"$bluex"'+0.5; bluey='"$bluey"'+0.5; }
           NR == 3 { sx=$1; ry=$2;  tx=$3; rx=$4; }
           NR == 4 { sy=$1; ty=$2;  px=$3; py=$4; }
           END { div =  redx*px + redy*py + 1.0;
                 dx = ( redx*sx + redy*ry + tx ) / div;
                 dy = ( redx*rx + redy*sy + ty ) / div;
                 printf "red point now at %f,%f\n", dx, dy;
                 printf "translate shape by %+f %+f\n", bluex-dx, bluey-dy; }'

[IM Text]

Contoh di atas memakai filter teks "tr" untuk membuang tanda kutip dan koma berlebih dari keluarannya. Lalu program "awk" dipakai untuk mengambil koefisiennya dan mengerjakan matematika bilangan pecahan yang diperlukan guna 'memetakan maju' penanda merah agar cocok dengan penanda biru. Perhatikan bahwa saya kembali menambahkan 0.5 pada 'koordinat piksel' titik kontrolnya untuk memastikan titik tengah piksel itulah yang dipakai dalam perhitungan. Lihat koordinat gambar vs koordinat piksel. Setelah besar pergeseran yang dibutuhkan gambar terdistorsi itu diketahui, ada dua cara menambahkan pergeseran tersebut ke distorsinya. Bisa dengan mengubah koefisien proyeksi perspektifnya secara tepat (tidak mudah). Atau kita cukup menambahkan besar pergeseran itu ke tiap koordinat tujuan pada perintah aslinya (sangat mudah). Berikut hasil cara yang kedua (menambahkan pergeseran ke koordinat tujuan)... |

  magick align_blue.png \
          \( align_red.png -alpha set -virtual-pixel transparent \
             +distort Perspective '0,0   31.408223,15.334305
                                   0,%h  35.408223,43.334305
                                   %w,0  89.408223, 9.334305
                                   %w,%h 84.408223,51.334305 ' \
          \) -background none -layers merge +repage  align_persp_move.png

[IM Output]
Di sebelah kanan saya memangkas dan menskalakan hasilnya di sekitar titik kontrol untuk memperlihatkan bahwa keduanya selaras sempurna! |

  magick align_persp_shape.png -crop 19x19+50+17 +repage \
          -scale 500%   align_persp_shape_mag.png

[IM Output]
Seperti yang Anda lihat, kedua piksel itu selaras sempurna, tanpa luberan sub-piksel ke salah satu sisi. Ketidakselarasan sekecil apa pun akan tampak sebagai pewarnaan yang asimetris di kedua sisi piksel tengahnya. Penskalaan ini bahkan memperlihatkan sedikit perbedaan asimetris antara sisi kiri dan sisi kanan salib merah akibat distorsi perspektifnya. Sebegitu akuratnya uji pandang tingkat piksel ini.
Masalah serupa yang lebih sederhana dibahas pada penempatan teks memakai distort.


Evaluate-sequence - metode penggabungan multi-gambar secara langsung

Metode "-evaluate-sequence " dirancang untuk menggabungkan banyak gambar berukuran sama dengan cara yang sangat spesifik. Dalam beberapa hal ia merupakan perpaduan antara operator evaluate dan function dengan teknik komposisi multi-gambar yang sudah kita lihat di atas. Banyak metode yang disediakan bahkan dapat dikerjakan memakai teknik komposisi pelapisan multi-gambar biasa, tetapi tidak semuanya. Operator ini memakai metode yang sama dengan "-evaluate" sehingga daftarnya bisa diperoleh dengan "-list Evaluate". Meski begitu, sebagian di antaranya (seperti 'Mean' dan 'Medium') sebenarnya hanya berguna bila dipakai bersama operator ini.

Mean (rata-rata) dari banyak gambar

Pada dasarnya baik "-evaluate-sequence mean" yang lama maupun "-evaluate-sequence **mean**" yang lebih baru sama-sama menghasilkan rata-rata dari semua gambar yang diberikan. Sebagai contoh, berikut rata-rata gambar rose memakai semua versi flip dan flop-nya. |

  magick rose: -flip rose: \( -clone 0--1 -flop \) \
          -evaluate-sequence mean  average.png

[IM Output]
Merata-ratakan ratusan gambar dari adegan tetap yang sama dapat dipakai untuk menghilangkan sebagian besar efek sesaat, seperti orang yang berlalu-lalang, sehingga menjadi kurang menonjol. Namun area yang banyak terkena efek sesaat bisa menyisakan 'blur seperti hantu' yang mungkin sangat sulit dihilangkan. Karena urutan video terkenal ber-noise bila dilihat per frame, sejumlah frame berurutan yang tidak berubah dapat dirata-ratakan untuk memperoleh hasil yang jauh lebih bersih dan tajam. Matt Leigh, dari University of Arizona, melaporkan bahwa ia memakai teknik ini untuk meningkatkan resolusi gambar mikroskop. Ia mengambil beberapa gambar dari 'target' yang sama lalu merata-ratakan semuanya untuk menaikkan rasio sinyal/noise hasilnya. Ia menduga orang lain mungkin juga merasakan manfaatnya untuk keperluan ini. Alternatif untuk merata-ratakan dua gambar adalah operasi gambar "composite -blend 50%", yang bekerja pada dua gambar berukuran berbeda. Lihat contoh memadukan dua gambar untuk keterangan lebih lanjut. Forum diskusi IM pernah membahas Averaging a sequence 10 frames at a time, agar ribuan gambar dapat dirata-ratakan tanpa memenuhi memori komputer (yang membuatnya sangat lambat). Terkait dengan itu, dan memuat matematika yang relevan, ada diskusi jangan memuat semua gambar sekaligus. Alternatif lain selain 'mean' adalah memakai operator poly yang lebih baru, yang dapat memberi bobot pada tiap gambar secara terpisah.

Nilai maks/min dari banyak gambar

Metode 'Max ' dan 'Min ' mengambil nilai maksimum (lebih terang) dan nilai minimum (lebih gelap) dari sebuah urutan gambar. Lagi-lagi keduanya pada dasarnya setara dengan memakai metode komposisi lighten dan darken, tetapi dengan banyak gambar. Dengan pilihan warna kanvas latar belakang yang tepat, operator flatten dapat dipakai dengan metode compose yang setara. |

  magick rose: -flip rose: \( -clone 0--1 -flop \) \
          -evaluate-sequence max  max.png

[IM Output]
|

  magick rose: -flip rose: \( -clone 0--1 -flop \) \
          -evaluate-sequence min  min.png

[IM Output]
PERINGATAN: Ini bukan pemilihan piksel (menurut intensitas), melainkan pemilihan nilai. Artinya gambar keluarannya bisa saja berisi nilai merah, hijau, dan biru yang masing-masing berasal dari gambar yang berbeda, sehingga muncul warna baru yang tidak ada pada gambar masukan mana pun. Jika Anda memerlukan piksel yang dipilih menurut maks/min intensitasnya, lihat metode compose lighten menurut intensitas.

Piksel median menurut intensitas

Metode "-evaluate-sequence **Median**" mencari piksel yang intensitasnya berada di tengah dari semua gambar yang diberikan. Artinya, untuk tiap posisi ia mengumpulkan dan mengurutkan intensitas piksel dari masing-masing gambar, lalu memilih piksel yang jatuh di tengah urutan itu. Metode ini juga dapat dipakai sebagai alternatif dari sekadar merata-ratakan piksel sekumpulan gambar. Misalnya dengan menggabungkan sebuah gambar bersama dua gambar 'pembatas' atas dan bawah. Karena pikselnya adalah yang berintensitas tengah, yang diperoleh adalah piksel dari gambar aslinya, atau piksel dari gambar 'pembatas' tadi. Dengan kata lain, cara ini dapat dipakai untuk 'memotong' intensitas gambar aslinya. Aneh tetapi nyata. Untuk jumlah gambar yang genap, piksel di sisi yang lebih terang dari tengahlah yang dipilih. Karena itu, dengan hanya dua gambar, operator ini setara dengan "lighten by intensity" per piksel. Poin pentingnya, tiap piksel sepenuhnya berasal dari satu gambar, dan diurutkan menurut intensitas. Warna persis tiap piksel sepenuhnya berasal dari salah satu gambar yang diberikan, sehingga tidak ada warna baru yang dihasilkan. Sebagai contoh, berikut piksel berintensitas median dari gambar rose memakai semua versi flip dan flop-nya. Perhatikan bahwa hasilnya tidak semulus tadi, tetapi bisa memiliki batas yang tajam, karena ia berdasar pada intensitas pikselnya. |

  magick rose: -flip rose: \( -clone 0--1 -flop \) \
          -evaluate-sequence median  median.png

[IM Output]

Menjumlahkan banyak gambar

Metode 'Add ' tentu saja sekadar menjumlahkan semua gambar.

  magick ... -evaluate-sequence add ...

Yang merupakan versi lebih cepat (lebih langsung) daripada memakai flatten untuk meng-compose Plus semua gambarnya...

  magick ... -background black -compose plus -layers flatten ...

Perlu diingat bahwa menjumlahkan gambar dengan cara ini sangat mudah membuat Quantum Range gambar meluap, sehingga hasilnya bisa 'terpotong', kecuali bila Anda memakai versi HDRI IM. Karena itulah rata-rata, atau mean umumnya dipakai sebagai gantinya, sebab cara itu membagi semua gambar secara merata sehingga gambar hasilnya tidak terpotong. Alternatif lain adalah memakai operator poly yang lebih baru, yang dapat memberi bobot pada tiap gambar secara terpisah.

Mengurangkan banyak gambar

Metode 'Subtract ' mengurangkan tiap gambar dari gambar pertama. Setidaknya itulah yang seharusnya ia lakukan. Di dalamnya argumennya tertukar sehingga yang terjadi adalah mengurangkan hasil sebelumnya dari gambar berikutnya. Arrggggg! Namun dengan memanfaatkan keanehan metode compose Linear Burn, gambar kedua dan seterusnya dapat dikurangkan dari gambar pertama. Pada dasarnya dengan menegasikan semua gambar kecuali yang pertama, dan menetapkan 'white' (nol yang dinegasikan) sebagai warna latar belakang awal, Flatten lalu dapat dipakai untuk mengurangkan semua gambar dari gambar pertama.

  magick ...  \
         -negate \( -clone 0 -negate \) -swap 0 +delete \
         -compose LinearBurn -background white -flatten \
         ...

Mengalikan/membagi banyak gambar

'Multiply ' dan 'Divide ' diterima sebagai metode oleh "-evaluate-sequence" tetapi keduanya menghasilkan keluaran yang aneh dan di luar dugaan, karena keduanya memakai nilai warna gambar yang sebenarnya alih-alih nilai warna yang ternormalisasi, persis seperti "-evaluate". Akibatnya skala perkalian dan pembagiannya terlalu besar. Hal ini bisa digolongkan sebagai bug. Sementara itu, Anda lebih baik memakai metode 'flatten' yang setara untuk Multiply, yang memang bekerja sebagaimana mestinya.

  magick ... -background white -compose multiply -layers flatten ...

Poly - menggabungkan banyak gambar memakai polinomial

Yang erat kaitannya dengan "-evaluate-sequence", khususnya metode 'mean' (perata-rataan gambar), adalah operator "-poly" (ditambahkan pada IM v6.8.0-5). Operator ini diberi daftar berisi dua angka untuk tiap gambar di memori: satu memberi bobot pengali bagi tiap gambar, satu lagi memberi eksponen pangkat bagi tiap gambar. Dengan begitu sederet gambar dapat digabungkan seolah-olah tiap gambar adalah variabel masukan bagi sebuah persamaan polinomial. Nilai warna dari tiap gambar diperlakukan seakan-akan bernilai ternormalisasi 0 sampai 1. Pada tiap pasang nilai, warna gambar (yang ternormalisasi) mula-mula dipangkatkan dengan eksponen kedua, lalu diberi bobot (dikalikan) dengan angka pertama. Bila eksponennya '1', nilainya cukup dikalikan dengan bobot yang diberikan. Namun bila eksponennya '0', bobot itulah yang menjadi nilai akhirnya, sehingga menghasilkan penambahan konstanta warna ternormalisasi (bernilai 0.0 sampai 1.0). Sebuah gambar satu piksel dapat disertakan dalam urutan gambar saat itu, dan dapat dipakai untuk menambahkan warna tertentu, dengan nilai warna ternormalisasi yang berbeda bagi tiap kanal (memakai bobot dan eksponen = 1.0). Atau gambar "NULL:' (atau gambar sampah apa pun) dapat disertakan dengan eksponen 0.0. Cara ini hanya akan menambahkan faktor bobot yang diberikan sebagai konstanta. Gambar akhirnya dibangun dari gambar pertama (berikut ukuran dan metadata lainnya), persis seperti pada operator DIY FX. Sebagai contoh... |

  magick rose: granite: null: -poly '1,1 2,1 -1.0,0' poly_rose.png

[IM Output]
Perintah ini mengambil 'rose:' (tanpa perubahan, memakai bobot 1 dan pangkat 1), menambahkan padanya dua kali nilai warna dari gambar 'granite:' (bobot=2), dan akhirnya mengurangi nilai 1 memakai gambar 'null:' dengan eksponen 0 (mengabaikan gambar masukan) dan nilai bobot -1.0. Gambar hasilnya setara dengan...

rose + 2.0*granite - 1.0

atau

rose + 2.0*(granite-0.5)

Dengan kata lain, gambar rose diberi overlay tekstur granite yang ber-noise (dengan bias abu-abu 50%). Ini sebenarnya persis seperti efek pencahayaan komposisi 'Hard_Light' yang sangat kuat, tetapi dengan pembobotan overlay granite yang sangat gamblang. Perbedaan utamanya dari operasi multi-gambar lain adalah kemampuan memberi bobot pada tiap gambar secara terpisah, sekaligus mengerjakan semua perhitungan dalam satu operasi pemrosesan gambar tanpa perlu gambar antara tambahan. Cara ini menghindarkan pembulatan kuantum, pemotongan, atau efek lain pada hasil akhirnya, pada versi ImageMagick yang bukan HDRI. (Lihat efek kuantum). Cara ini misalnya dapat dipakai untuk menghitung rata-rata berbobot atas sejumlah besar gambar, seperti merata-ratakan kelompok gambar yang lebih kecil, lalu merata-ratakan kelompok-kelompok itu bersama-sama.