Contoh penggunaan ImageMagick -- mendistorsi gambar
Setelah melihat rangkaian sederhana operator pembungkusan dan distorsi gambar bawaan yang telah disediakan IM sejak masa awalnya, di sini kita masuk lebih dalam untuk melihat mekanisme internal serta distorsi matematis gambar yang lebih kompleks. Dari pemahaman yang lebih dalam ini, kita lalu melihat operator distorsi gambar yang lebih umum. Ini mencakup berbagai distorsi, mulai dari rotasi, penskalaan, dan shear yang kompleks, distorsi perspektif atau 3D, pelengkungan ke dan dari busur lingkaran, distorsi lensa kamera, hingga akhirnya distorsi umum yang menyerupai morph.
Teknik distorsi umum
Setelah berkenalan dengan operator distorsi sederhana yang disediakan IM, mari kita mundur sejenak untuk menengok seluk-beluknya: bagaimana distorsi gambar sebenarnya bekerja, dan bagaimana cara pemakaiannya dapat ditingkatkan. Nanti kita akan maju ke cara-cara mendistorsi gambar yang jauh lebih kompleks, termasuk metode yang tidak terpasang langsung di dalam ImageMagick. Hanya ada beberapa cara dasar bagi sebuah pemroses gambar untuk mendistorsi gambar. Operator distorsi sederhana misalnya diwujudkan dengan pertukaran piksel. Artinya, piksel individual, atau bahkan seluruh baris dan kolom piksel, sekadar dipertukarkan untuk melakukan flip, roll, transpose, bahkan rotasi persegi panjang pada gambar. Tidak ada perubahan warna, dan jumlah piksel tetap sama. Metode berikutnya untuk mendistorsi gambar adalah dengan menggeser atau men-shear kolom dan baris piksel secara horizontal maupun vertikal, seperti yang dilakukan IM pada shear gambar dan distorsi gelombang di atas. Shear pada gilirannya menyediakan satu metode untuk memutar gambar pada sudut berapa pun, dengan cara yang semestinya cukup cepat. Namun metode penggeseran piksel terbatas pada distorsi dasar semacam itu. Ia tidak dapat, misalnya, menskalakan gambar ke ukuran lain. Kendali atas penanganan area pada gambar hasil yang tidak tertutupi gambar sumber aslinya pun sangat sedikit. Pada fungsi-fungsi yang disebutkan di atas, IM sekadar mengisi area yang hilang dengan warna latar belakang saat ini. Agar dapat mendistorsi gambar dengan cara yang jauh lebih umum, Anda perlu memakai teknik distorsi yang lebih umum, yang dikenal sebagai pemetaan piksel terbalik. Metode ini misalnya dipakai oleh distorsi melingkar yang lebih kompleks seperti implosi dan pusaran gambar.
Pemetaan piksel maju atau langsung
Hal pertama yang terpikir ketika orang mencoba mendistorsi gambar adalah mengambil setiap piksel pada gambar sumber lalu memindahkannya langsung ke lokasi barunya di gambar tujuan. Nyatanya, kurang lebih memang begitulah yang terjadi pada distorsi sederhana, pemangkasan gambar, bahkan pada pendistorsian gambar vektor. Setiap piksel (atau koordinat) sekadar dipindahkan ke posisi barunya di gambar akhir. Sayangnya, cara ini bermasalah begitu Anda mencobanya untuk apa pun selain distorsi yang sederhana. Sebagai contoh, di sini saya mengambil daftar piksel terenumerasi dari sebuah gambar kecil, lalu sekadar mengubah lokasi setiap piksel untuk memutarnya ke lokasi barunya. |
# Rotate by 17 degrees -- get the Sine and Cosine of this angle
sin=`magick xc: -format "%[fx:sin( 17 *pi/180)]" info:`
cos=`magick xc: -format "%[fx:cos( 17 *pi/180)]" info:`
# For each Pixel, rotate that pixels coordinates
magick koala.gif txt:- | sed '2,$ s/,/:/' |\
gawk -F: 'NR == 1 { print }
NR > 1 { x = $1-32; y = $2-32;
nx = int( c*x - s*y + 32 );
ny = int( s*x + c*y + 32 );
printf( "%d,%d: %s\n", nx, ny, $3 );
}' s=$sin c=$cos - |\
magick -background black txt:- koala_rotated_direct.gif
![[IM Output]](../static/img/distorts/koala_rotated_direct.gif)
Distorsinya hanyalah rotasi sederhana sebesar 17 derajat, tetapi hasilnya sama sekali tidak bagus. Pertama-tama, setiap lokasi piksel yang baru berupa nilai floating point, padahal piksel hanya bisa berada pada kisi bilangan bulat, sehingga contoh di atas sekadar membuang pecahan non-bulat dari hasilnya. Masalah kedua, hasilnya penuh lubang di tempat tak ada piksel yang mendarat. Ini memunculkan masalah ketiga. Mungkin tidak terlihat, tetapi untuk setiap lubang pada gambar hasil, ada pula lokasi lain yang ditempati dua piksel. Artinya, ada beberapa piksel pada lokasi yang sama. Nilai piksel mana yang seharusnya dipakai? Pada contoh di atas IM sekadar memakai piksel terakhir yang didefinisikan untuk suatu lokasi. Dengan kata lain gambar hasilnya tidak lengkap: setiap piksel di tujuan tidak persis berada di tempat seharusnya, dan satu lokasi bisa berisi beberapa piksel, atau tidak ada piksel sama sekali. Ini masalah serius, dan tidak mudah dipecahkan ketika piksel dipetakan maju dari gambar sumber langsung ke gambar tujuan. Bukan berarti cara ini mustahil bekerja; banyak makalah riset membahas pemakaian teknik yang dikenal sebagai 'splatting'. Pada dasarnya mereka mengambil setiap piksel masukan, mentransformasikan lokasinya, lalu menggambarnya dengan penyebaran dan pencampuran warna piksel yang sesuai di lokasi baru. Teknik ini terutama berguna saat menangani digitalisasi 3D objek dunia nyata. Di sana Anda punya 'awan' titik-titik permukaan yang warnanya diketahui. Setiap titik yang terlihat oleh pengguna tinggal di-'splat' ke layar untuk membentuk gambar akhir. Dengan titik yang cukup banyak, gambar akan tampak lengkap. Dengan kontrol 3D interaktif, teknik ini bekerja sangat baik dan sangat cepat. Namun splatting titik-titik 3 dimensi berada di luar lingkup IM yang menangani gambar raster 2D.
Pemetaan piksel terbalik
Alih-alih mencoba memetakan piksel ke gambar akhir, Anda dapat memetakan koordinat setiap piksel di gambar tujuan ke lokasi padanannya di gambar sumber, lalu dari gambar sumber mencari warna yang seharusnya dikandung piksel itu. Ini dikenal sebagai pemetaan piksel terbalik (reverse pixel mapping), dan begitulah cara kerja hampir semua program distorsi gambar. Karena setiap piksel gambar tujuan diproses satu per satu, kita bisa yakin setiap piksel di tujuan mendapat satu dan hanya satu warna. Maka selama lokasi 'sumber' untuk setiap piksel tujuan dapat ditentukan, kita dapat mendistorsi gambar sumber ke gambar tujuan memakai rumus matematika apa pun yang bisa dibayangkan.
![[Diagram]](../static/img/img_diagrams/mapping.gif)
Singkatnya, pemetaan distorsi (pemetaan terbalik) melakukan hal berikut.
Untuk setiap piksel (I,J) pada gambar tujuan atau keluaran
Petakan posisi piksel I,J ke posisi piksel X,Y pada gambar asli
Cari warna gambar asli pada posisi X,Y
Dengan interpolasi warna, tentukan warna yang sesuai.
Atau pakai pengaturan virtual-pixel bila meleset dari gambar sumber sebenarnya.
Tetapkan warna gambar tujuan untuk piksel I,J
Perhatikan bahwa saya memakai nama variabel 'I,J' dan 'X,Y' di atas karena variabel-variabel ini terpetakan ke nama variabel yang lazim dipakai pada operator DIY FX. Sebagai contoh, di sini saya menyimulasikan rotasi 17 derajat yang sama seperti yang saya coba sebelumnya, tetapi kali ini memakai operator "-fx" untuk mencari piksel terdekat ke lokasi tersebut pada gambar sumber. |
# Rotate by 17 degrees -- get the Sine and Cosine of this angle
sin=`magick xc: -format "%[fx:sin( 17 *pi/180)]" info:`
cos=`magick xc: -format "%[fx:cos( 17 *pi/180)]" info:`
cx=37; cy=37; # center of rotation
magick -size 75x75 xc: koala.gif \
-virtual-pixel Black -interpolate NearestNeighbor \
-fx "ii = i - $cx; jj = j - $cy;
xx = $cos*ii +$sin*jj + $cx;
yy = -$sin*ii +$cos*jj + $cy;
v.p{xx,yy}" \
koala_rotated_fx.gif
![[IM Output]](../static/img/distorts/koala_rotated_fx.gif)
Rincian lebih lanjut tentang contoh DIY di atas ada di subbagian pemetaan distorsi afin DIY. Seperti terlihat, tidak ada lagi 'lubang' pada gambar kita karena warna dicari untuk setiap piksel di tujuan. Hasilnya masih belum bagus benar, tetapi itu tinggal soal menyetel warna apa persisnya yang mesti ditempatkan pada tiap piksel. Artinya, pemetaan piksel terbalik tidak menghasilkan lubang maupun piksel yang bertumpuk. Setiap piksel punya warna yang terdefinisi dengan baik sehingga gambarnya lengkap.
Perbedaan antara pemetaan maju dan terbalik ini penting, karena kebanyakan transformasi matematis didefinisikan sebagai pemetaan maju: memetakan satu posisi sumber (X,Y) ke posisi tujuan (I,J). Dan memang 'pemetaan maju' bekerja baik untuk grafika vektor dan penggambaran garis, ketika Anda cukup memetakan ujung-ujung garis lalu menggambarnya. Ini terutama berlaku untuk transformasi linear apa pun, seperti rotasi, yang membuat garis tetap lurus. Itulah yang sebenarnya dilakukan semua bahasa berbasis vektor seperti postscript dan SVG. Tetapi untuk gambar raster pada umumnya, Anda harus memakai 'pemetaan terbalik' untuk mendistorsi gambar, supaya bisa dipastikan semua piksel gambar tujuan 'terisi'. Misalnya, bila Anda amati matematika yang dipakai untuk memetakan koordinat pada dua kasus di atas, keduanya tampak hampir persis sama. Pemetaan terbalik dari sebuah 'rotasi' adalah 'rotasi' lain, hanya berlawanan arah. Bila diamati lebih saksama, konstanta 'sin'-nya dinegasikan terhadap versi pemetaan maju, dan itu cukup untuk membalik arah rotasi. Detail ini penting dan krusial. Masalahnya, tidak semua transformasi pemetaan maju bekerja baik sebagai transformasi yang dibalik. Sebagian pemetaan maju bahkan tidak punya pemetaan terbalik langsung yang sederhana. Bukan berarti tidak bisa, hanya tidak sederhana. Sebaliknya, sebagian transformasi gambar bekerja sangat baik sebagai pemetaan terbalik, tetapi tidak punya pemetaan maju yang sederhana. Jadi memakai metode pemetaan terbalik ada baik-buruknya secara matematis.
Sekadar informasi, berikut padanan yang lebih cepat dari contoh di atas memakai metode distorsi umum, SRT, yang melakukan rotasi gambar persis sama seperti di atas dan memberikan hasil yang persis sama, hanya lebih cepat. Sekali lagi pencarian warnanya dibatasi hanya pada warna piksel terdekat ke posisi terpetakan dengan memakai interpolasi 'point'. Artinya tidak ada warna baru yang ditambahkan ke gambar (kecuali saat kita 'meleset' dari gambar sumber), tetapi Anda juga mendapat efek aliasing yang parah. |
magick koala.gif -virtual-pixel Black -interpolate NearestNeighbor \
-filter point -distort SRT 17 koala_rotated_srt.gif
![[IM Output]](../static/img/distorts/koala_rotated_srt.gif)
| Untuk pembahasan alternatif tentang transformasi distorsi, lihat Leptonica, Affine Implementation, khususnya pembahasan metode 'point-wise'-nya. Metode satunya, 'sequential', pada dasarnya adalah cara IM dahulu mengimplementasikan operator distorsi Rotate dan Shear miliknya.
Apalah arti sebuah nama? Selama menelaah, saya mendapati tidak ada penamaan yang benar-benar jelas untuk metode pemrosesan gambar ini. Proses algoritmiknya sendiri dikenal sebagai 'Reverse Pixel Mapping', sedangkan pemakaian persamaan matematisnya dikenal sebagai 'Geometric Transformation'. Bila distorsinya dikendalikan oleh pergerakan berbagai titik kontrol, ia sering disebut 'Image Warping' atau 'Rubber Sheeting'. Proses mendefinisikan titik-titik tertentu, biasanya untuk menemukan titik yang berpadanan di antara dua gambar atau lebih, dikenal sebagai 'Image Registration'. Gambar juga dapat dibagi-bagi menjadi unit yang lebih kecil dan sederhana yang masing-masing didistorsi sendiri-sendiri memakai teknik bernama 'Gridding' (segi empat) dan 'Triangular Meshing' (segitiga). Dengan distorsi kecil bertahap disertai pembauran warna dari dua gambar, Anda dapat membuat 'Image Morphs' beranimasi seperti yang terlihat di film dan video musik. Bila yang dipakai adalah gambar pemetaan yang disiapkan sebelumnya, bukan pencarian matematis seketika, Anda mendapat 'Absolute Distortion Mapping'; bila pencariannya berupa pergeseran relatif (abu-abu 50% berarti tanpa pergeseran atau perubahan koordinat pencarian), Anda mendapat 'Displacement Mapping'. Bila pemetaannya hanya sedikit mengubah warna (shading) alih-alih mendistorsi pencarian, Anda mendapat teknik yang berkerabat tetapi berbeda: 'Bump Surface Mapping'. Pada pemodelan 3D, dan pada game komputer 3D, teknik-teknik yang sama juga dipakai untuk memberi semacam pola berwarna pada permukaan datar dan lengkung dalam metode yang dikenal sebagai 'Texture Mapping'. Ini bisa melibatkan pembagian gambar menjadi kisi dan mesh yang mendekati satu piksel. Lalu ada penampilan objek yang didefinisikan dari jutaan titik tunggal memakai teknik bernama 'Point Splatting', meskipun itu biasanya diterapkan dengan distorsi pemetaan maju. Semua di atas berkerabat sangat dekat, dan pada dasarnya melibatkan pencarian warna piksel berdasarkan pemetaan koordinat tujuan akhir ke gambar (atau objek) sumber. Dengan kata lain memetakan tujuan ke sumber. Istilah mana yang mesti dipakai... Silakan pilih sendiri.
Pencarian warna piksel
Masih ada beberapa masalah pada teknik pemetaan piksel terbalik di atas. Pertama, ketika memetakan piksel dari posisi bulat yang tetap di tujuan, Anda bisa berakhir pada posisi tak bulat di gambar sumber. Yakni, lokasi yang jatuh di antara piksel-piksel pada gambar sumber. Untuk menentukan warna apa yang mesti dikembalikan, proses bernama interpolasi dipakai guna menentukan warna akhir untuk posisi riil itu dengan mencampur warna piksel-piksel di sekitarnya. Pengaturan interpolasi juga menangani kasus ketika sebagian gambar terdistorsi menjadi 'teregang' sehingga satu piksel sumber terserak di area luas gambar tujuan. Namun kebalikannya tidak tertangani dengan baik oleh metode interpolasi sederhana. Itu memerlukan teknik lain yang akan kita lihat di bawah. Sebagai contoh, di sini kita kembali memutar koala kita, tetapi kali ini memakai pengaturan "-interpolate Mesh" untuk mencampur empat piksel terdekat sehingga pencarian menghasilkan warna yang lebih baik dan lebih tepat. |
magick koala.gif -virtual-pixel Black -interpolate Mesh \
-filter point -distort SRT 17 koala_rotated_mesh.gif
![[IM Output]](../static/img/distorts/koala_rotated_mesh.gif)
Seperti terlihat, dengan sekadar menggabungkan warna tetangga terdekat di sekeliling titik pencarian tak bulat, tampilan gambar terdistorsi dapat sangat diperbaiki. Tetapi ada masalah-masalah lain yang terlibat... Misalnya, apa yang Anda lakukan bila posisi terpetakan 'meleset' sama sekali dari gambar sumber. Dalam kasus ini, warna yang mesti dikembalikan ditentukan oleh pengaturan piksel virtual. Pengaturan ini akan memilih warna, misalnya tepi terdekat gambar sumber, berpura-pura gambar sumber di-tile tanpa batas (atau di-tile secara cermin) di seluruh bidang, atau memakai warna tertentu seperti 'white', 'black', 'transparent', atau warna latar belakang yang ditentukan pengguna. Ada pula kemungkinan tidak ada koordinat yang sah secara matematis untuk suatu posisi tujuan yang dipetakan. Misalnya piksel itu memandang ke 'langit' dari sebuah 'bidang' perspektif (lihat memandang cakrawala jauh), sehingga bahkan tidak melihat 'bidang' tempat gambar sumber berada. Dalam kasus ini piksel virtual tak berguna karena ia tidak 'mengenai' bidang gambar sumber di ruang berdimensi N, dan dengan demikian piksel tujuannya sama sekali tidak valid! Dalam kasus ini IM memakai pengaturan "-alpha set" saat itu untuk warna pikselnya. Bila melesetnya tipis, IM akan meng-anti-alias warna tak valid ini dengan warna-warna tetangga dari bidang gambar, bila IM tahu caranya. Untuk distorsi perspektif, IM tahu.
Super sampling
Interpolasi bekerja baik untuk distorsi gambar sederhana. Tetapi bila sebagian gambar sumber terkompresi ke area yang jauh lebih kecil, setiap piksel tujuan sebenarnya bisa memerlukan penggabungan area gambar sumber yang jauh lebih besar. Ingat, piksel sebenarnya bukan titik, melainkan mewakili area persegi panjang dari gambar riil. Artinya dalam sebagian kasus kita semestinya berusaha mengompres area besar gambar sumber ke dalam satu piksel tujuan. Ketika ini terjadi, pencarian piksel sederhana akan gagal, karena ia hanya mencari warna pada satu 'titik' di gambar sumber (memakai lingkungan piksel sekitarnya), dan tidak menggabungkan semua warna gambar masukan yang mungkin harus dikompres ke piksel tunggal itu. Akibatnya, piksel tujuan bisa berakhir dengan warna yang praktis acak dari gambar sumber, bukan rata-rata semua warna yang terlibat. Ini sendiri tidak buruk, tetapi ketika semua piksel di suatu area mengalaminya, Anda mendapat gambar dengan piksel-piksel terisolasi yang tampak acak, efek moire, dan efek 'anak tangga' beralias. Garis tipis juga mulai tampak seperti garis putus-putus dan titik-titik (lihat contoh pada operator Sample), atau bisa hilang sama sekali. Semua efek ini secara kolektif dikenal sebagai artefak aliasing. Salah satu solusinya adalah melakukan lebih banyak pencarian warna dari gambar sumber, untuk setiap piksel di tujuan, demi menentukan warna yang lebih tepat bagi setiap piksel gambar tujuan. Solusi paling sederhana umumnya dikenal sebagai super-sampling, atau over-sampling. Lihat entri Wikipedia tentang super-sampling. Dengan mengambil lebih banyak sampel dari gambar sumber, di seluruh area yang akan terpetakan ke tiap piksel tujuan, warna akhir piksel itu menjadi representasi yang lebih akurat dari gambar terdistorsi di titik tersebut. Makin banyak sampel warna yang diambil, makin akurat warna akhirnya, dan tampilan yang lebih halus dan realistis pun dihasilkan, meski distorsinya jadi makin lambat. Ingat, teknik ini benar-benar memperbaiki tampilan umum tujuan hanya di area tempat gambar sumber terkompresi lebih dari 50%. Di area tempat distorsi memperbesar gambar sumber, atau menjaganya pada skala kurang lebih sama, satu pencarian terinterpolasi atas gambar sumber umumnya sudah memberi hasil bagus dengan sekali pencarian saja. Pada contoh pelengkungan implosi gambar (dan banyak contoh lain di seluruh IM Examples), saya sudah menyinggung sekilas metode 'super-sampling' paling sederhana. Pada dasarnya: memperbesar ukuran gambar keluaran (atau dalam kasus ini cukup dengan memperbesar gambar masukan), lalu melakukan distorsinya. Setelah distorsi selesai, kita mengubah ukuran gambar kembali ke ukuran normalnya, yang menggabungkan semua 'sampel' ekstra yang dihasilkan. Sebagai contoh...
magick -size 94x94 xc:red -bordercolor white -border 3 \
-virtual-pixel tile -implode 4 \
implode_tiled_box.gif
magick -size 94x94 xc:red -bordercolor white -border 3 \
-virtual-pixel tile -resize 400% -implode 4 -resize 25% \
implode_tiled_ss.gif
![[IM Output]](../static/img/distorts/implode_tiled_box.gif)
Implosi normal gambar kotak | ![[IM Output]](../static/img/distorts/implode_tiled_ss.gif)
Implosi dengan super sampling
| Tentu saja, alih-alih memperbesar gambar masukan, Anda bisa mulai dari gambar sumber berkualitas lebih tinggi (lebih besar), atau membuatnya pada langkah pemrosesan sebelumnya. Kalau memang tersedia. Ini terutama berguna saat memutar teks, yang sering punya detail sangat halus yang perlu dipertahankan secara seragam demi tampilan akhir yang berkualitas tinggi. Contohnya lihat transformasi Polaroid. | Sejak IM v6.4.2-6, operator distorsi umum dapat langsung menghasilkan gambar keluaran yang diperbesar, yang bisa Anda skalakan (atau ubah ukurannya) kembali untuk menggabungkan dan men-super-sample piksel hasilnya. Lihat pengaturan skala distorsi, serta contoh berikutnya. |
|---|---|
| Ini baru satu metode super sampling (dikenal sebagai metode 'grid'); masih banyak variasi lain dari metode ini. Suatu saat metode-metode itu mungkin diimplementasikan lebih langsung di ImageMagick, tetapi untuk sekarang pembesaran dan penskalaan gambar yang sederhana bekerja cukup baik, tanpa perlu pengodean tambahan. Satu peringatan terakhir. Super-sampling dibatasi oleh jumlah sampel yang dipakai untuk tiap piksel pada gambar akhir, dan dengan demikian oleh besarnya penskalaan pada pengubahan ukuran terakhir. Inilah yang menentukan 'kualitas' akhir gambar terdistorsi. Tetapi dengan faktor skala lebih besar, gambar terdistorsi tentu jauh lebih lambat dihasilkan. Dan meski kualitasnya makin tinggi, tetap ada batasnya. Pada kasus ekstrem, super-sampling tidak akan bisa menangani distorsi gambar yang melibatkan ketakhinggaan (seperti di pusat gambar yang diimplosi). Untuk kasus semacam itu diperlukan teknik yang sama sekali berbeda, misalnya yang disediakan oleh resampling area (lihat di bawah). Singkatnya, super-sampling dapat memperbaiki tampilan gambar yang distorsinya ringan saja, seperti rotasi, shear, afin, dan perspektif sederhana. Tetapi jenis distorsi yang bisa diperbaikinya terbatas. Super-sampling adaptif Teknik super-sampling dapat dikembangkan lebih jauh. Alih-alih memakai jumlah pencarian warna yang tetap untuk tiap piksel, dilakukan pemeriksaan atas jarak antar-pencarian di gambar sumber, atau atas seberapa dekat warna-warna yang dikembalikan dari sampling tingkat rendah, untuk memutuskan perlu-tidaknya sampel tambahan bagi piksel tersebut. Artinya, banyaknya super-sampling bisa dibuat tanggap terhadap kebutuhan distorsi, tanpa tahu apa-apa tentang kekhususan distorsinya sendiri. Ini dikenal sebagai super-sampling adaptif. Teknik ini sebenarnya sangat umum pada ray tracer, yang nyaris mustahil menentukan seberapa kompleks gambar hasil di suatu titik tertentu. Dalam kasus itu ia sering dibatasi pada pemakaian 'selisih warna' di sekitar lokasi tertentu, untuk menentukan kapan sampel tambahan diperlukan. Bila sebuah piksel sangat berbeda dari tetangganya, lebih banyak sampel dipakai di area itu untuk mempertajam apa yang kemungkinan merupakan tepi suatu objek 3 dimensi. IM saat ini belum mendukung super-sampling adaptif. Meski cukup mungkin menambahkan metode sampling alternatif ke dalam operator distorsi umum (lihat di bawah). Itu memerlukan penataan ulang fungsional pada kodenya, jadi mungkin tidak akan ditambahkan dalam waktu dekat. Ringkasan super-sampling Kesulitan super-sampling terletak pada menentukan berapa banyak 'sampel titik' yang diperlukan, dan bagaimana sampel-sampel itu mesti diatur dalam batas sub-piksel. Juga 'pembobotan' macam apa yang mesti diterapkan. Lihat entri Wikipedia tentang super-sampling. |
Resampling area, untuk distorsi yang lebih baik
Salah satu alternatif terbaik bagi metode super-sampling adalah resampling area. Alih-alih mendistorsi gambar yang diperbesar lalu merata-ratakan hasilnya dengan pengubahan ukuran, yang sekadar mengambil dan merata-ratakan lebih banyak sampel dari gambar, kita justru menentukan secara persis berapa banyak piksel gambar sumber yang mesti digabungkan (berdasarkan 'skala' distorsi di titik itu) untuk menghasilkan tiap piksel keluaran. Yakni, memperkirakan 'area' kasar di dalam gambar sumber yang diwakili tiap piksel keluaran, lalu menggabungkan (memfilter) semua piksel di area itu menurut sebuah filter resampling. Nyatanya, persis inilah yang dilakukan operator Resize ImageMagick (sejatinya sejenis distorsi gambar yang sangat spesifik) sehingga hasilnya sebagus itu. Namun untuk resize, skala area yang perlu disampel untuk tiap piksel cukup dihitung sekali untuk seluruh gambar. Area yang perlu di-'sampel' adalah persegi panjang (jendela) berukuran tetap di gambar sumber, sehingga proses resampling-nya mudah dan menjadi jalan pintas dalam proses distorsi. Saat melakukan resampling area pada gambar terdistorsi, area piksel (jendela) sumber sampelnya bukan hanya berubah posisi, tetapi juga berubah ukuran. Karena itu satu piksel di tujuan mungkin hanya perlu menggabungkan sedikit warna gambar sumber, atau bahkan cukup satu pencarian warna terinterpolasi (misalnya pada pembesaran). Sementara piksel lain di tempat lain pada gambar tujuan mungkin perlu menyampel piksel dalam jumlah sangat besar untuk menghasilkan warna akhir yang benar. Di dekat ketakhinggaan, ia bahkan mungkin harus mengikutsertakan semua piksel gambar sumber dalam proses sampling. Selain itu, area yang diwakili sebuah piksel tujuan di gambar sumber bisa jadi bukan sekadar persegi, lingkaran, atau bahkan elips, melainkan bentuk yang sangat terdistorsi, sesuai distorsi yang dipakai. Menghitung dan menangani bentuk-bentuk janggal semacam itu bisa sangat memakan waktu, atau nyaris mustahil dilakukan.
Memakai area eliptis dari gambar sumber untuk menghitung warna tiap piksel tujuan adalah metode yang dikenal sebagai resampling Elliptical Weighted Average (EWA), yang digariskan dalam makalah riset PDF "Fundamentals of Texture Mapping and Image Warping" oleh Paul Heckbert (yang juga menulis program 'zoom', asal-usul praktis semua algoritme pengubahan ukuran gambar). Ini kemudian dipakai untuk mendefinisikan operator distorsi umum yang baru (lihat di bawah). Elips adalah bentuk yang sempurna untuk distorsi afin maupun distorsi perspektif. Ia terutama bagus untuk pengecilan skala ekstrem (lihat contoh di bawah). Dan meski tidak sempurna untuk distorsi lain, ia umumnya cukup cocok untuk banyak distorsi lain, seperti distorsi Arc dan Polar (tetapi bukan kebalikannya), serta distorsi radial seperti distorsi Barrel. Tetapi ia buruk untuk pemetaan distorsi non-linear seperti De-Polar dan distorsi Shepards, sehingga tidak dipakai untuk distorsi-distorsi itu. Super sampling tidak punya masalah bentuk ini karena tiap 'sampel' dipetakan balik ke tujuan. Maka ia menjadi metode sampling yang lebih baik dalam kasus semacam itu. Tetapi seperti disebutkan, ia bisa saja tidak menyampel semua piksel yang diperlukan, atau malah menyampel terlalu banyak piksel.
Sampling area vs super sampling
Berikut ketiga metode sampling yang saat ini disediakan IM, ketika diterapkan pada gambar perspektif ekstrem yang di-tile tanpa batas. Rincian distorsi ini lihat memandang cakrawala jauh di bawah.
# input image: special checkerboard with a gold outline.
magick -size 90x90 pattern:checkerboard -normalize -fill none \
-stroke gold -strokewidth 3 -draw 'rectangle 0,0 89,89' \
-fill red -draw 'color 20,20 floodfill' \
-fill lime -draw 'color 40,70 floodfill' \
-fill dodgerblue -draw 'color 70,40 floodfill' \
checks.png
# Using Interpolated Lookup
magick checks.png -filter point \
-virtual-pixel tile -mattecolor DodgerBlue \
-distort Perspective '0,0 20,60 90,0 70,63 0,90 5,83 90,90 85,88' \
horizon_tile_point.png
# Using Grid Super Sampling
magick checks.png -filter point -set option:distort:scale 10 \
-virtual-pixel tile -mattecolor DodgerBlue \
-distort Perspective '0,0 20,60 90,0 70,63 0,90 5,83 90,90 85,88' \
-scale 10% horizon_tile_super.png
# Using Area Resampling (default)
magick checks.png -virtual-pixel tile -mattecolor DodgerBlue \
-distort Perspective '0,0 20,60 90,0 70,63 0,90 5,83 90,90 85,88' \
horizon_tile.png
![[IM Output]](../static/img/distorts/checks.png)
Gambar papan catur | | ![[IM Output]](../static/img/distorts/horizon_tile_point.png)
Pencarian
terinterpolasi | ![[IM Output]](../static/img/distorts/horizon_tile_super.png)
Super sampling
x10 | ![[IM Output]](../static/img/distorts/horizon_tile.png)
Resampling area berbobot
eliptis (EWA)
Semua gambar itu adalah distorsi yang persis sama, hanya memakai teknik 'resampling' yang berbeda. Gambar terakhir di atas memakai pengaturan EWA bawaan dari operator distorsi umum, dan seperti terlihat, hasilnya berkualitas sangat tinggi. Namun pembuatan gambar ini memakan 4,6 detik. Tidak terlalu buruk meski agak lambat (karena keekstreman tak lazim yang terlibat). Gambar pertama mematikan resampling EWA bawaan lewat pengaturan "-filter point". Ini memaksanya memakai pencarian terinterpolasi langsung untuk tiap piksel. Karena itu gambar ini dihasilkan sangat cepat sebagai perbandingan (0,51 detik), tetapi seperti terlihat, hasilnya mengerikan karena 'minifikasi' (downsampling) meningkat seiring 'jarak'. Gambar tengah sama dengan gambar pertama, tetapi gambar keluaran terdistorsinya diperbesar 10 kali sebelum diskalakan kembali (resampling grid) agar sepadan dengan gambar lain. Artinya, lebih dari 100 piksel dicari dan dirata-ratakan untuk tiap piksel tujuan, guna men-super sample hasilnya. Pembuatannya cukup cepat (1,2 detik), dan meski memperbaiki kualitas gambar secara umum, perbaikannya terbatas. Faktor ×10 pada contoh di atas sangat berat, jauh melampaui penskalaan 3 atau 4 kali yang lebih lazim pada kebanyakan pemakaian super-sampling. Perbedaan terbesar di antara hasil-hasil itu adalah bahwa super-sampling hanya memperbaiki kualitas secara umum dan seragam di seluruh gambar. Begitu distorsinya makin parah, ia mulai jebol. Hasilnya adalah artefak resampling yang sangat terlihat di latar tengah, dan lebih khusus lagi segaris efek moire parah tepat sebelum cakrawala. Efek moire timbul ketika 10 sampel per lebar piksel hampir berimpit dengan pola papan catur gambar, menghasilkan efek warna yang terdistorsi. Sebaliknya, resampling area lebih berkonsentrasi pada piksel-piksel bermasalah di dekat cakrawala (tempat ia menghabiskan hampir seluruh waktunya) daripada piksel latar depan — dan di sana ia justru mengungguli super-sampling. Pada dasarnya contoh di atas adalah distorsi yang sangat ekstrem, dan waktu yang dimakan pencarian EWA sepadan dengannya. Pada umumnya ia memberi hasil jauh lebih baik daripada satu pencarian terinterpolasi, karena memeriksa setiap piksel yang terlibat secara efisien, tanpa memboroskan sampel di area yang tidak memerlukannya, seperti yang dilakukan super-sampling. Singkatnya... Memakai elips sederhana (resampling EWA) atau persegi panjang (Resize) untuk 'resampling area' memang memberi hasil bagus, karena semua piksel sumber yang terlibat dalam distorsi skala, afin, atau perspektif akan digabungkan untuk menghasilkan warna akhir tiap piksel tujuan. Pada distorsi yang sangat non-linear, seperti pada distorsi DePolar, atau distorsi yang tak tentu, seperti distorsi Shepard atau bahkan ray-tracing, menemukan 'area' yang benar untuk me-resample semua piksel sumber yang diperlukan menjadi terlalu mahal, dan super-sampling adalah metode terbaik untuk memperbaiki hasil. Tetapi untuk tiling lurus, pembesaran, dan rotasi tanpa penskalaan, satu pencarian terinterpolasi 'point' yang sangat cepat kemungkinan sudah mencukupi, bahkan bisa dianjurkan demi menjamin distorsi no-op (tanpa perubahan) yang sempurna (lihat di bawah). Namun ingat, semua teknik resampling hanyalah metode untuk menentukan warna tiap piksel. Ia sebenarnya bukan bagian dari cara gambar didistorsi, kecuali dalam hal pemetaan lokasi antara tujuan dan sumber (atau sebaliknya bila mungkin).
Operator distorsi umum
Seiring pembuatan contoh-contoh ini, diskusi lanjutannya di forum IM, dan banyaknya permintaan pengguna akan cara yang lebih mudah dan lebih cepat untuk melakukan distorsi perspektif dan lainnya, sebuah operator baru ditambahkan pada IM v6.3.5-1 agar kami dapat lebih mudah menambahkan distorsi gambar dari berbagai jenis. Operator distorsi umum ini bernama "-distort", dan Anda dapat melihat metode distorsi apa saja yang tersedia pada versi IM Anda memakai "-list Distort".
magick -list distort
Operator "-distort" menerima dua argumen: salah satu metode distorsi seperti daftar di atas, dan argumen string kedua berupa daftar nilai floating point yang dipisah koma atau spasi, yang dipakai untuk mengendalikan metode distorsi bersangkutan.
magick ... -distort {_method_} "{_list_of_floating_point_values_}" ...
Namun banyaknya nilai floating point yang diberikan sangat bergantung pada metode distorsi yang dipakai, dan maknanya bukan hanya bergantung pada metode yang dipilih, tetapi juga bisa bergantung pada jumlah persis titik kontrol atau atribut yang diperlukan metode tertentu. Ini terutama berlaku pada distorsi 'Scale-Rotate-Translate' (atau singkatnya 'SRT'), yang sejatinya menggabungkan tiga distorsi 'Affine' terpisah menjadi satu distorsi. Banyak metode distorsi menerima daftar titik kontrol (dalam koordinat gambar), dan biasanya ini diberikan sebagai pasangan koordinat yang mengendalikan bagaimana distorsi mengubah gambar. Pasangan-pasangan koordinat ini diperinci lebih lengkap nanti di distorsi menggunakan titik kontrol.
Opsi, kontrol, dan pengaturan distorsi
Flag best fit +distort
Secara bawaan, "-distort" biasanya mendistorsi gambar sumber menjadi gambar berukuran sama dengan gambar asli. Ada pengecualiannya, misalnya distorsi 'Arc' (varian pemetaan polar) yang ukuran gambar sumber masukannya memang tidak banyak berarti pada bentuk terdistorsinya (rincian lihat distorsi Arc di bawah). Bentuk lain operator ini, "+distort" (ditambahkan pada IM v6.3.5-7), akan berusaha mengubah ukuran gambar terdistorsi agar memuat seluruh gambar masukan (bila mungkin), mirip yang dilakukan operator rotasi dan shear yang lebih lama. Namun 'mode' operasi yang satu ini melangkah lebih jauh: ia juga menetapkan offset kanvas virtual (page) gambar hasil. Dengan begitu Anda nantinya dapat melakukan penggabungan layer gambar ini ke gambar lain, pada posisi yang benar sesuai titik kontrol Anda, memakai komposisi alpha yang sesuai (lihat kubus 3D dengan pelapisan afin sebagai contoh dasar. Selain itu (tergantung metode distorsinya) "+distort" akan berusaha memperhitungkan offset kanvas virtual yang mungkin sudah ada pada gambar sumber, dan memakainya sebagai bagian dari proses distorsi. Lihat catatan pada masing-masing metode distorsi. Karena itu Anda mungkin perlu memakai operator pengaturan atribut "+repage" secara bijak untuk menghapus atau menyetel offset itu sebelum memakai bentuk 'best-fit' "+distort" dari operator distorsi umum. Anda mungkin juga perlu memakainya sesudahnya bila kanvas virtual dan offset-nya tidak diperlukan. Lihat juga menghapus geometri kanvas/page. Bentuk normal "-distort" sekadar mengabaikan offset yang sudah ada pada gambar sumber sejauh menyangkut distorsinya sendiri, tetapi menyalin offset itu apa adanya ke gambar terdistorsi. Singkatnya... Pakai "-distort" agar hasil dipetakan ke gambar berukuran sama. Dan pakai "+distort" agar ukuran gambar keluaran dicoba ditetapkan otomatis, TETAPI sekaligus memakai dan menghasilkan offset kanvas virtual (atribut page). Lihat juga viewport distort (di bawah) bila Anda ingin menimpa pemilihan viewport umum ini dan mengendalikan secara persis ukuran serta bagian mana dari gambar terdistorsi yang ingin dilihat pada hasil.
Catatan... Viewport best-fit yang dihasilkan "+distort" 2 piksel lebih besar daripada yang biasanya diharapkan pengguna. Alasannya, piksel-piksel ini memuat piksel semitransparan hasil filter resampling area, dan piksel-piksel ini vital untuk 'penyambungan tepi' dan penumpangan gambar terdistorsi yang benar. Secara teknis banyaknya piksel yang ditambahkan semestinya bergantung pada penskalaan keluaran dari support filter resampling. Yakni, seberapa jauh area sebuah piksel bisa 'menyebar' akibat filter resampling. Namun karena penskalaan tiap piksel bisa berubah-ubah, menghitung jumlah piksel tambahan yang benar-benar tepat sangatlah pelik, dan biasanya tidak sepadan usahanya. Tambahan 2 piksel itu dengan demikian sebuah 'kira-kira', karena distorsi jarang memperbesar gambar, yang membuat piksel makin 'menyebar'. Lagi pula, karena kebanyakan filter resampling standar punya support 2 unit, penambahan 2 piksel cukup masuk akal. Dan karena tambahan ini 'tetap', pengguna tetap punya opsi untuk sekadar memangkas ukuran gambar (dengan berbagai cara), bila itu yang diinginkan. 'Kira-kira' 2 piksel ini memang jadi jelas terlalu kecil saat memperbesar gambar. Tetapi distorsi semacam itu cukup jarang, dan pengguna dapat mendefinisikan viewport-nya sendiri (lihat di bawah) bila ini jadi masalah. Offset virtual gambar terdistorsi pada kanvas virtual disetel untuk memperhitungkan 2 piksel ekstra ini, sehingga gambar terdistorsinya benar untuk penumpangan, meski tidak untuk komposisi sederhana. Tetapi berhati-hatilah: sementara Crop dan Trim mempertahankan lokasi gambar berlapis, Shave dan Chop akan menggeser gambar layer relatif terhadap offset ini.
Penentuan warna piksel pada distort
Seperti dibahas pada pemetaan piksel terbalik di atas, setiap titik pada gambar hasil ditentukan dengan lebih dulu memetakan lokasi piksel itu di gambar tujuan ke lokasi padanannya (terdistorsi balik) di gambar sumber, sesuai metode distorsi yang dipilih. Namun warna akhir pikselnya tidak sesederhana itu ditentukan, karena dipengaruhi banyak sekali faktor.
Piksel virtual dan tiling
Titik hasil pemetaan distorsi bisa saja tidak mengenai gambar sumber sebenarnya, melainkan jatuh di sampingnya, atau bahkan jauh sekali dari gambar itu. Solusinya adalah berpura-pura gambar sumber dikelilingi permukaan 'tak berhingga' atau 'virtual', yang didefinisikan oleh pengaturan "-virtual-pixel" saat itu. Rincian dan contoh efek pengaturan ini lihat contoh piksel virtual. Ini bisa sangat berguna untuk membuat pola tile gambar sumber, baik yang terdistorsi maupun tidak. Tekniknya ditunjukkan di bagian piksel virtual sendiri (tanpa distorsi) serta di tiling afin dan memandang cakrawala jauh di bawah.
Piksel distorsi yang tidak valid
Terkadang distorsi sebuah piksel tujuan bahkan tidak 'mengenai' gambar virtual yang di-tile itu! Ini umumnya terjadi ketika Anda mendistorsi gambar dengan sejenis metode distorsi ruang 3 dimensi dan 'vektor' pikselnya bahkan tidak mengenai bidang sumber tempat gambar berada. Pada dasarnya hasil distorsinya menjadi 'tak terdefinisi' secara matematis. Dalam kasus itu warnanya ditentukan dari pengaturan "-mattecolor". Misalnya ketika Anda melihat 'langit' pada distorsi perspektif (contohnya lihat memandang cakrawala jauh), matematika untuk menentukan lokasi gambar sumbernya menjadi 'tak terdefinisi' (sebenarnya terdefinisi, tetapi tidak valid dari sudut pandang memandang ke depan si pengguna). Karena itu "-mattecolor" dikeluarkan untuk 'langit' tersebut. Sebenarnya algoritme distorsi perspektif juga sempat menyertakan informasi 'anti-aliasing' untuk piksel-piksel dekat cakrawala, meski itu tidak lazim untuk situasi semacam ini.
Resampling EWA dan filter
Begitu tahu di mana sebuah piksel tujuan 'mengenai' gambar sumber, Anda perlu menentukan warna piksel tujuan itu memakai piksel-piksel di dekat titik 'kenaan' pada gambar sumber. Normalnya operator distort memakai metode resampling area EWA (Elliptical Weighted Average) untuk merata-ratakan area gambar sumber yang lebih luas demi memperoleh warna yang tepat bagi piksel ini. Filter yang dipakai resampling EWA dapat diganti lewat pengaturan "-filter". Lihat filter resampling, dan lebih khusus filter silindris, untuk rinciannya. Semula filter Gaussian silindris dipakai untuk resampling EWA, karena itulah yang didefinisikan makalah riset asli untuk resampling EWA. Tetapi filter ini cenderung memberi hasil sangat buram, meski juga tidak menimbulkan efek aliasing. Ini dulunya filter bawaan, disertai bug implementasi yang menyebabkan keburaman ekstrem sebelum versi tersebut (kini sudah diperbaiki) Sejak IM v6.6.5-0, setelah diskusi besar dengan Nicolas Robidoux, profesor matematika di Laurentian University, filter bawaan untuk distorsi gambar diganti dengan filter '**Robidoux**', filter kubik yang sangat 'mirip Mitchell' dan dirancang khusus untuk resampling EWA. Lihat filter silindris untuk informasi filter ini dan filter silindris lainnya. Namun perhatikan bahwa fungsi filter Windowed Sinc apa pun yang mendasarinya diganti dengan fungsi filter Windowed Jinc yang lebih melingkar. Karena itu memilih filter 'Lanczos' akan mengembalikan filter "Jinc windowed Jinc", bukan filter "Sinc windowed Sinc". Rincian lihat filter silindris Windowed Jinc. SELINGAN: fungsi 'Sinc' sebenarnya TIDAK bisa dipakai sebagai fungsi silindris, karena interaksi fungsi itu dengan jarak radial pada kisi membuat bobot filter berbentuk sedemikian sehingga cenderung saling meniadakan (jumlah bobot nol) setiap kali jumlah 'lobe' yang dipakai genap. Ini pada gilirannya membuatnya berusaha menghasilkan warna yang nyaris tak berhingga bila dipakai pada pola 'hash' papan catur setingkat piksel. Pada dasarnya EWA memakai filter resampling, mirip operator Resize, sehingga Anda juga dapat memodifikasi filternya memakai opsi filter pakar yang khusus. Keburaman filter 'Gaussian' dan filter mirip Gaussian misalnya dapat dikendalikan lewat pengaturan blur filter. Demikian pula Anda dapat memakai pengaturan support lobe untuk mengendalikan ukuran dan kekuatan filter Windowed Jinc, misalnya filter 'Lanczos'. | _Ada sejumlah metode distorsi ekstrem yang otomatis mematikan resampling EWA dan hanya memakai pencarian terinterpolasi yang lebih langsung.
Misalnya distorsi Depolar menghasilkan area resampling berbentuk busur lingkaran yang tidak begitu cocok dengan resampling 'eliptis' (EWA). Distorsi lain seperti Shepards membuat penghitungan 'faktor skala' sangat sulit, meski perbaikan operator distort di masa depan bisa saja memungkinkannya).
Teknik super sampling dianjurkan untuk metode-metode distorsi ini demi mencegah timbulnya artefak aliasing parah di area kompresi gambar (downsampling) pada hasil.
Kegagalan resampling
Pada beberapa situasi khusus, elips resampling EWA bisa gagal benar-benar 'mengenai' piksel riil mana pun untuk dijadikan rata-rata berbobot. Pada dasarnya elipsnya begitu kecil, atau begitu tipis, sampai jatuh sepenuhnya di sela-sela setiap piksel gambar. Dan tanpa warna piksel apa pun, ia tidak dapat menghasilkan warna untuk gambar keluaran di titik itu. Ini situasi ekstrem, dan umumnya mustahil terjadi kecuali Anda bermain-main dengan pengaturan filter pakar. Tetapi pada kejadian langka ketika tidak ada piksel yang kena, atau bobot filternya berjumlah nol, resampling akan gagal. Dalam kasus itu IM jatuh kembali ke pencarian terinterpolasi langsung yang sederhana, persis seperti bila Anda mematikan pemfilteran EWA (lihat berikutnya). Bila ingin memeriksa apakah ini terjadi, Anda dapat memakai interpolasi background khusus dengan warna latar belakang tak lazim (misalnya 'red') untuk menyorot kegagalan resampling semacam itu. Sebagai contoh, di sini saya sengaja menyetel support sebuah filter box terlalu kecil, sehingga elips resampling-nya sangat kecil. Saya juga sangat memperbesar gambarnya agar Anda bisa melihat bagian mana yang 'mengenai piksel' dan mana yang tidak. |
magick \( xc:red xc:white xc:black +append \) \
\( xc:blue xc:lime xc:white +append \) \
\( xc:black xc:red xc:blue +append \) -append \
-filter Box -define filter:support=0.4 \
+distort SRT 30,0 bad_box_distort.png
![[IM Output]](../static/img/distorts/bad_box_distort.png)
Pada gambar yang sangat diperbesar itu, lingkaran resampling entah hanya mengenai satu piksel (menghasilkan lingkaran beralias berwarna polos. Atau ia gagal mengenai piksel mana pun karena area sampling lingkarannya jatuh sepenuhnya di sela-sela piksel, sehingga filternya jatuh kembali ke gradien warna terinterpolasi (interpolasi bilinear secara bawaan), demi memperoleh setidaknya warna yang cukup sahih untuk gambar hasil. Berikut contoh yang sama, tetapi metode interpolasinya diganti dengan interpolasi background yang khusus (dan biasanya tak berguna) (sekadar mengembalikan warna latar belakang, yang disetel ke 'gray'). |
magick \( xc:red xc:white xc:black +append \) \
\( xc:blue xc:lime xc:white +append \) \
\( xc:black xc:red xc:blue +append \) -append \
-filter Box -define filter:support=0.4 \
-interpolate background -background Gray \
+distort SRT 30,0 bad_box_distort_gray.png
![[IM Output]](../static/img/distorts/bad_box_distort_gray.png)
Untuk cakupan penuh (agar selalu menemukan setidaknya satu piksel), filter resampling silindris memerlukan 'support' minimal sekitar 0.707 (sqrt(2)/2) (bawaan untuk filter box). Semua filter biasanya jauh lebih besar dari ukuran support minimal ini. Contohnya lihat bagian filter silindris. | _Titik-titik kecil berwarna di pojok-pojok disebabkan oleh optimasi resampling untuk piksel virtual (membatalkan resampling EWA yang mahal saat menyampel area VP berwarna polos). Titik-titik itu akan hilang atau berubah dengan pilihan pengaturan "-virtual-pixel" yang berbeda.
Normalnya ini bukan masalah, dan hanya terlihat di sini karena distort memakai 'viewport best fit' yang sedikit lebih besar dari gambar asli, sehingga menyertakan beberapa piksel ekstra di sekeliling tepi yang dalam kasus ini menyampel piksel virtual.
Pencarian warna terinterpolasi, atau langsung
Anda dapat memakai "-filter point" untuk mematikan pemfilteran, dan dengan demikian resampling EWA.Bila ini dilakukan, Imagemagick mengalihkan pencarian warna ke interpolasi piksel yang cepat dan lebih sederhana. Yakni, ia mencari warna hanya memakai rujukan 'satu titik' ke gambar sumber tanpa 'area resampling' apa pun. Warna piksel hasil memakai warna terinterpolasi yang hanya berdasarkan tetangga terdekat titik itu.
Interpolasi umumnya menimbulkan efek aliasing parah
setiap kali terjadi minifikasi atau downsampling gambar dalam bentuk apa pun.
Tetapi ia bekerja sangat baik untuk gambar dengan distorsi minim seperti rotasi, tiling, atau untuk pembesaran gambar (magnifikasi atau upsampling). Teknik super sampling dapat dikombinasikan dengan interpolasi untuk memperbaiki hasil di area yang mengalami kompresi, minifikasi, atau downsampling kuat. Lihat masalah siklus Depolar-Polar (distorsi yang tidak bisa memakai resampling EWA) untuk contoh pemakaian super-sampling guna mengatasi aliasing interpolasi.
Ringkasan distorsi verbose
Dengan menyetel "-verbose" sebelum menjalankan "-distort" (pakai "+verbose" untuk mematikannya lagi), distort akan mengeluarkan ke kanal standard error informasi tentang algoritme serta koefisien internal yang dihitungnya dan dipakainya saat mendistorsi gambar bersangkutan dengan cara yang ditentukan. Informasi ini dapat dipakai untuk mengamati dan memahami bagaimana distorsi bekerja dan diterapkan. Ia juga alat debugging yang bisa kita pakai untuk mencari tahu apa yang salah, dan bagian dari proses implementasi distorsi baru.
magick koala.gif -verbose -distort SRT 0 +verbose koala_noop.gif
| CATATAN: Gambar hasilnya hampir, tetapi tidak persis, sama dengan gambar masukan (lihat "distorsi no-op" berikutnya).
Keluaran verbose itu memerinci dua teknik distorsi alternatif untuk distorsi bersangkutan. Satu adalah distorsi 'AffineProjection', sedangkan satunya menunjukkan alternatif operator DIY FX yang memerinci persis bagaimana ia memetakan suatu piksel di gambar keluaran (i,j) ke pencarian terinterpolasi di gambar masukan (xx,yy), untuk mentransformasikan gambar. Ia memang melakukan penghitungan elips resampling yang memakai matematika rumit (nilai eigen); yang dihitung di sini hanyalah titik pencarian terinterpolasi tanpa skala di gambar sumber yang darinya warna piksel (i,j) ditentukan. Keduanya memberi informasi tentang proses distorsi dan dapat dipakai untuk mengambil informasi tambahan yang berguna pada distorsi lain berjenis sama. Contoh lebih kompleks pemakaian informasi ini lihat internal Perspective dan internal Bilinear di bawah. Contoh pemakaian perintah FX untuk distorsi gambar lihat juga pengubahan ukuran gambar dengan FX. Penambahan dan pengurangan '0.5' ekstra di atas diperlukan untuk mengubah 'koordinat piksel' menjadi 'koordinat gambar', dan wajib demi penanganan matematis distorsi gambar yang benar. Lihat koordinat gambar vs koordinat piksel di bawah.
Distorsi no-op
Contoh di atas menunjukkan hasil distort no-op. Yakni, menjalankan gambar melalui distort (untuk suatu efek sekunder) tetapi tanpa distorsi sungguhan (sekadar pemetaan piksel 1 ke 1). Filter resampling EWA tidak akan mereproduksi warna yang persis sama dengan aslinya, melainkan mem-blur tiap piksel sangat sedikit dengan tetangganya. Ini akibat filter 2 dimensi yang dipakai, dan meski blur warnanya minimal, ia tak pernah bisa dihilangkan. Karena itu, untuk melakukan 'no-op' sejati kita juga harus mematikan pemfilteran EWA dan memakai pencarian warna terinterpolasi atau langsung (lihat di atas). |
magick koala.gif -filter point -distort SRT 0 koala_noop_perfect.gif
![[IM Output]](../static/img/distorts/koala_noop_perfect.gif)
Hampir semua pengaturan interpolasi umumnya mengekstrak salinan persis dari piksel sumber bila dirujuk secara tepat. Namun sebagai pencegahan, Anda juga dapat menentukan interpolasi Nearest-Neighbor, demi kecepatan dan kepastian bahwa hanya kecocokan warna yang persis yang dikembalikan, apa pun error floating-point yang mungkin dihasilkan distort. |
magick koala.gif -filter point -interpolate nearest \
-distort SRT 0 koala_noop_perfect_2.gif
![[IM Output]](../static/img/distorts/koala_noop_perfect_2.gif)
Ini mungkin tampak kontraproduktif, tetapi bisa menjadi metode yang sangat berguna untuk memperluas area gambar, atau men-tile gambar (memakai metode piksel virtual), tanpa benar-benar mengubah ukuran data gambar aslinya. Contohnya lihat tiling memakai piksel virtual via distort. Yakni, memakai operator distort demi efek-efek sekundernya, seperti tiling piksel virtual multi-gambar, pembesaran atau pemangkasan ukuran gambar, penambahan border, atau bahkan translasi (sebanyak bilangan bulat atau bahkan sub-piksel). Tidak satu pun yang sebenarnya menuntut gambar 'didistorsi', hanya 'dimodifikasi' dengan cara 'terprogram' tertentu.
Viewport, tempat distort melihat
Seperti disebut di atas, memakai "-distort" atau "+distort" mengubah ukuran dan lokasi 'gambar tujuan' hasilnya menjadi: sama dengan gambar sumber (mengabaikan pengaturan kanvas virtual apa pun), atau, hasil hitungan best fit untuk gambar sumber terdistorsi (bila mungkin), masing-masing. Dua hal ini pada dasarnya menentukan bagian mana dari 'ruang terdistorsi' hasil yang dilihat gambar tujuan. Cara lain memikirkannya: gambar tujuan adalah 'jendela' yang memandang gambar terdistorsi hasil, atau sebuah 'viewport' ke dalam ruang terdistorsi. Pengaturan "distort:viewport" menimpa kedua bawaan ini, dan memungkinkan Anda langsung menentukan bagian mana dari ruang terdistorsi yang ingin dilihat...
[-define](https://imagemagick.org/command-line-options/#define) distort:viewport=WxH+X+Y [-set](https://imagemagick.org/command-line-options/#set) option:distort:viewport WxH+X+Y
Keduanya ditambahkan pada IM v6.3.6-1. Ia tidak memperbesar atau menskalakan gambar terdistorsi, hanya menentukan lokasi dan area yang dilihat (viewport) di ruang gambar terdistorsi. Ini bisa dipakai untuk membuat gambar tujuan berukuran tertentu, atau menggeser pandangan ke area tertentu di ruang gambar terdistorsi. Ini sangat mirip memakai 'pemangkasan viewport' atas gambar terdistorsi berukuran tak berhingga (yang didefinisikan piksel virtual). Sebagai contoh, di sini kita memangkas keluaran menjadi kepala koala saja (dengan distorsi no-op). Dengan kata lain sekadar 'pemangkasan viewport' langsung atas gambar asli yang tak terdistorsi. |
magick koala.gif -define distort:viewport=44x44+15+0 \
-filter point -distort SRT 0 +repage koala_viewport.gif
![[IM Output]](../static/img/distorts/koala_viewport.gif)
Dan di sini kita memperluas pandangan, untuk melihat ruang ekstra di sekeliling gambar terdistorsi, sekaligus menunjukkan efek pengaturan piksel virtual pada ruang tak berhingga di sekeliling gambar sumber asli. |
magick koala.gif -define distort:viewport=125x125-25-25 \
-filter point -distort SRT 0 +repage koala_viewport_2.gif
![[IM Output]](../static/img/distorts/koala_viewport_2.gif)
Dalam kasus ini lebih mirip memakai operator Extent untuk memperbesar gambar. Namun alih-alih sekadar mengisi dengan warna latar belakang, distort mengisi area tambahan dengan pengaturan piksel virtual. Dalam kasus ini memakai pengaturan piksel virtual bawaan 'Edge', yang menghasilkan garis-garis piksel horizontal dan vertikal, direplikasi dari piksel-piksel di sepanjang tepi gambar asli. Anda mungkin ingin membuat pilihan pengaturan piksel virtual yang lebih baik. Misalnya pengaturan 'Background' akan membuat distort no-op ini bekerja hampir persis seperti operator Extent. Untuk gambar ini, pengaturan piksel virtual 'White' barangkali pilihan yang lebih baik. |
magick koala.gif -define distort:viewport=125x125-25-25 \
-virtual-pixel White -distort SRT 0 +repage koala_viewport_3.gif
![[IM Output]](../static/img/distorts/koala_viewport_3.gif)
"+repage" terakhir pada contoh-contoh sebelumnya diperlukan untuk menghapus offset kanvas virtual viewport yang dibiarkan "-distort" ketika pengaturan viewport dipakai. Informasi ini memang tidak diinginkan dalam kasus ini. Pada kasus lain, misalnya saat melapis gambar-gambar terdistorsi, informasi offset itu justru Anda perlukan. Opsi viewport terutama berguna dengan pengaturan piksel virtual 'Tile' atau bahkan 'Mirror', yang memungkinkan Anda membuat gambar yang di-tile berukuran berapa pun dan dengan gaya berbeda-beda. Anda bahkan bisa memakai distort untuk mendistorsi gambar-gambar yang di-tile itu, seperti dicontohkan pada tiling afin di bawah. |
magick koala.gif -define distort:viewport=125x125-25-25 \
-virtual-pixel Mirror -distort SRT 0 +repage koala_viewport_4.gif
Pemangkasan persegi terpusat
Bila Anda memakai opsi "-set" untuk menyetel 'viewport' gambar hasil, nilai yang diberikan boleh memuat escape persen. Lebih khusus lagi, Anda dapat menyertakan escape persen FX yang bisa melakukan perhitungan matematis. Artinya 'viewport' dapat dihitung, sambil memanfaatkan atribut seperti ukuran gambar yang sedang ada di memori, untuk menentukan ukuran akhir gambar hasil. Apa maksudnya? Maksudnya, 'viewport' dapat dipakai untuk menghasilkan jenis-jenis pemangkasan khusus yang biasanya memerlukan satu kali pra-baca gambar atau lebih (atau antarmuka pemrograman API yang lebih canggih), serta perhitungan eksternal. Misalnya Anda dapat memangkas 'persegi tengah' sebuah gambar tanpa perlu tahu lebih dulu ukuran atau orientasi gambar aslinya. Ini rumit, maka saya menaruh ekspresi viewport-nya dalam variabel agar lebih mudah dibaca, dikodekan, dan di-debug, meski sebenarnya ia hanyalah ekspresi konstan (tetap).
size='%[fx: w>h ? h : w ]'
offset_x='%[fx: w>h ? (w-h)/2 : 0 ]'
offset_y='%[fx: w>h ? 0 : (h-w)/2 ]'
viewport="${size}x${size}+${offset_x}+${offset_y}"
magick worldmap_sm.jpg -set option:distort:viewport "$viewport" \
-filter point -distort SRT 0 +repage viewport_square.gif
Gambar hasilnya adalah persegi terpusat terbesar yang dapat diekstrak dari gambar sumber masukan mana pun, berapa pun ukuran gambarnya. Distort-nya sendiri sebenarnya tidak mendistorsi gambar, hanya menyalin area yang dicakup viewport. Perhatikan bahwa KEEMPAT angka perlu dihitung untuk menghasilkan "pemangkasan persegi terpusat" karena semua nilainya bergantung pada orientasi gambar. Karena itu tiap ekspresi memakai uji 'orientasi gambar' berbentuk 'w>h ? ... : ...', sehingga nilai hasilnya bergantung pada orientasi gambar. Ini bentuk alternatifnya memakai fungsi "min()" dan "max()", alih-alih uji orientasi gambar. |
magick worldmap_sm.jpg -set option:distort:viewport \
"%[fx:min(w,h)]x%[fx:min(w,h)]+%[fx:max((w-h)/2,0)]+%[fx:max((h-w)/2,0)]" \
-filter point -distort SRT 0 +repage viewport_square_2.gif
![[IM Output]](../static/img/distorts/viewport_square_2.gif)
Atas kebaikan halaman Tidbits Fred Weinhaus. Teknik yang memakai beberapa teknik pemrosesan gambar untuk hal yang sama ditunjukkan di thumbnail, pengisian dan pemangkasan persegi.
Pemangkasan rasio aspek
Teknik ini dapat dikembangkan sehingga Anda memangkas gambar secara terpusat agar pas dengan rasio aspek tertentu. Lihat juga diskusi forum Crop to Aspect Ratio.
Contoh viewport lainnya
Lihat juga metode memutar gambar di bawah untuk contoh lain pemakaian viewport guna mengendalikan bagian mana dari ruang terdistorsi yang tampak pada hasil.
Penskalaan keluaran, dan super-sampling
[-define](https://imagemagick.org/command-line-options/#define) distort:scale=N [-set](https://imagemagick.org/command-line-options/#set) option:distort:scale N
Ditambahkan pada IM v6.4.2-6, sebagai faktor penskalaan umum gambar keluaran. Ini memperbesar gambar keluaran sebesar faktor yang diberikan, sehingga "-distort" perlu menghasilkan N2 kali lebih banyak 'sampel' pencarian terdistorsi. Angkanya biasanya bilangan bulat, tetapi boleh berupa faktor pembesaran floating point. Perhatikan bahwa banyak distorsi juga memungkinkan Anda 'menskalakan' ukuran gambar terdistorsi hasilnya, tetapi ukuran gambar hasil tidak terpengaruh penskalaan itu (kecuali "+distort" 'best-fit' dipakai). Pengaturan 'scale' ini sebaliknya sama sekali tidak mengubah isi gambar hasil, hanya memperbesar atau mengecilkan gambar keluaran hasilnya. Ini bisa dipakai misalnya bersama 'viewport' yang sesuai untuk menghasilkan gambar yang mudah di-"-resize" ke ukuran tertentu, sehingga Anda bisa membuat 'zoom' terkendali ke dalam gambar terdistorsi, tanpa kehilangan kualitas. Sebagai contoh, kita 'zoom' ke kepala koala. |
magick koala.gif -set option:distort:scale 2.5 \
-set option:distort:viewport 44x44+15+0 \
-distort SRT 0 +repage koala_zoom.gif
![[IM Output]](../static/img/distorts/koala_zoom.gif)
Perhatikan bahwa meski viewport yang diminta 44x44 piksel, gambar keluaran sebenarnya telah diskalakan menjadi 110x110 piksel. Lebih lazimnya, ia dipakai sebagai cara sederhana untuk men-'super sample' (lihat di atas) operasi distorsi. Untuk itu dipakai faktor skala 'super-sampling' bilangan bulat, dan setelah didistorsi gambarnya diskalakan kembali ke ukuran semula, untuk menggabungkan sampel-sampel ekstra dan menghasilkan hasil berkualitas lebih tinggi. |
magick koala.gif -filter point -set option:distort:scale 10 \
-distort SRT 0 -scale 10% koala_super.gif
![[IM Output]](../static/img/distorts/koala_super.gif)
Selain itu, karena 'resampling area' tidak diperlukan saat memakai 'super sampling' untuk memperbaiki kualitas gambar (ia hanya memperlambatnya), biasanya ia dimatikan lewat opsi "-filter point" (lihat bagian sebelumnya).
Pengantar metode distorsi
Distorsi Scale-Rotate-Translate (SRT)
Salah satu distorsi paling sederhana, tetapi barangkali salah satu yang paling serbaguna, adalah distorsi 'SRT atau 'Scale-Rotate-Translate'. (SRT sekadar singkatan cepatnya) Anda sudah melihat contoh 'no-op' distorsi ini pada contoh-contoh di atas, tempat gambar diproses tanpa distorsi sungguhan diterapkan padanya, meski tetap difilter sehingga bisa menimbulkan keburaman sangat kecil. Berikut pengulangan hasil distort 'no-op' di atas...
magick koala.gif -distort SRT 0 koala_noop.gif
| _Perhatikan bahwa gambar akan buram sangat sedikit sebagai konsekuensi pemakaian resampling area. Namun filter resampling IM sengaja dirancang untuk meminimalkan keburaman ini pada distorsi no-op, dan itu diperlukan untuk pemakaian normal.
Bila Anda ingin distort 'no-op' yang sempurna untuk keperluan khusus, matikan resampling EWA. Yakni, tentukan filter 'no-op' "-filter Point" pada perintah di atas sebelum operator distort.
Distorsi 'SRT sebenarnya adalah tiga distorsi terpisah dalam satu metode distorsi, itulah sebabnya ia disebut distorsi 'Scale-Rotate-Translate'. Semua argumen, kecuali rotasi _angle, bersifat opsional, dan ini membuat argumennya sangat bervariasi, tergantung persisnya berapa banyak argumen terpisah koma atau spasi yang Anda berikan, hingga maksimum 7 bilangan floating point. **-distort SRT "** |
Angle
| **"** | -> rotasi terpusat
Scale Angle
| -> skala dan rotasi terpusat
X,Y Angle
| -> rotasi mengelilingi koordinat yang diberikan
X,Y Scale Angle
| -> skala dan rotasi mengelilingi koordinat
X,Y ScaleX,ScaleY Angle
| -> sama seperti di atas
X,Y Scale Angle NewX,NewY
| -> skala, rotasi, dan translasi koordinat
X,Y ScaleX,ScaleY Angle NewX,NewY
| -> sama seperti di atas
Yang dilakukannya adalah mengambil gambar yang Anda pilih, dan sebuah titik kontrol opsional. Bila tidak ada titik kontrol yang diberikan, pusat persis gambar sumber masukanlah yang dipakai. Mengelilingi titik itu, distorsi akan, secara berurutan... men-skala-kan gambar, me-rotasi-nya, lalu men-translasi-kan atau memindahkan titik kontrol terpilih ke posisi baru. Dari situlah nama distorsi ini. Urutan argumen di atas mencerminkan urutan operasi yang benar-benar diterapkan pada gambar. X,Y untuk mentranslasikan 'pusat' transformasi ke titik asal, ScaleX,ScaleY menskalakan gambar, Angle memutar gambar, lalu NewX,NewY mentranslasikan 'pusat' ke koordinat ini. Artinya, operator ini sebenarnya mewakili 4 operasi distorsi internal yang semuanya diterapkan serentak sebagai satu distorsi. Meski bagi kita manusia hanya 3 distorsi berbeda yang terlibat. Mari kita ambil contoh sederhana memakai gambar 'koala'... Satu argumen berarti sekadar rotasi sederhana mengelilingi pusat gambar, pada dasarnya memberi hasil serupa operator Rotate yang lebih lama, tetapi tanpa penambahan ukuran gambar. |
magick koala.gif -background skyblue -virtual-pixel background \
-distort ScaleRotateTranslate -110 koala_srt_rotate.png
![[IM Output]](../static/img/distorts/koala_srt_rotate.png)
Perhatikan bahwa secara bawaan ukuran gambar masukan juga dipakai untuk gambar keluaran, sehingga gambar yang diputar bisa terpotong. Ia juga terpusat sempurna, tak peduli jumlah piksel gambarnya ganjil atau genap. Dengan bentuk 'plus' "+distort", dan pembersihan offset kanvas virtual hasilnya, kita bisa membuat sesuatu yang sangat mirip operator Rotate biasa. |
magick koala.gif -background skyblue -virtual-pixel background \
+distort ScaleRotateTranslate -110 +repage koala_srt_rotate2.png
![[IM Output]](../static/img/distorts/koala_srt_rotate2.png)
| Sejak IM 6.7.3-4, operator Rotate kini memakai distorsi SRT dari distort. Sebelumnya ia memakai operasi shear, yang hasilnya tidak sebagus itu.
Mari kita kecilkan juga 30%, tetapi memakai latar belakang transparan. |
magick koala.gif -alpha set -virtual-pixel transparent \
+distort ScaleRotateTranslate '.7,-110' +repage koala_srt_scale.png
![[IM Output]](../static/img/distorts/koala_srt_scale.png)
Rangkaian argumen berikutnya menentukan 'pusat' yang mengelilinginya gambar diputar dan diskalakan. Titik ini disebut 'titik kontrol' atau 'pegangan' pada gambar, yaitu lokasi yang dipakai untuk mengendalikan distorsi. Karena kita memakai titik tertentu untuk distorsi ini, mari tidak memakai mode 'best-fit' demi menghindari kerumitan 'offset virtual'. Misalnya mari kita rotasi dan skalakan koala mengelilingi 'hidung'-nya, yang terletak di 28,24 pada gambar sumber. Sekalian saja kita buat skala X dan Y-nya berbeda. |
magick koala.gif -background skyblue -virtual-pixel background \
-distort ScaleRotateTranslate '28,24 .4,.8 -110' \
koala_srt_center.png
![[IM Output]](../static/img/distorts/koala_srt_center.png)
Dan sebagai contoh terakhir, mari kita pindahkan juga 'hidung'-nya ke dekat bagian bawah gambar, dan setel latarnya ke latar belakang putih yang serasi. |
magick koala.gif -virtual-pixel white \
-distort ScaleRotateTranslate '28,24 .4,.8 -110 37.5,60' \
koala_srt_trans.png
![[IM Output]](../static/img/distorts/koala_srt_trans.png)
Perhatikan bahwa posisi akhirnya juga nilai floating point. Bahkan semua argumennya boleh berupa nilai floating point dan distorsinya akan berlaku benar. Ingat, tiap operasi, yaitu Scale, Rotate, dan Translate, dilakukan dalam urutan itu. Seperti terlihat, distorsi ini sangat serbaguna, dan meski Anda bisa membayangkannya sebagai mendistorsi gambar dengan tiga metode berbeda secara berurutan, kenyataannya ia menerapkan ketiga distorsi itu serentak untuk menghasilkan hasil yang ditunjukkan. Ini membuatnya lebih cepat daripada menjalankan beberapa operator terpisah, dan umumnya memberi hasil akhir yang lebih baik. Contoh di atas juga memperagakan pemakaian berbagai pengaturan piksel virtual untuk menentukan warna area yang dirujuk di luar gambar sumber sebenarnya. Untuk melihat efek interpolasi pada rotasi, lihat interpolasi garis dan tepi yang diputar. Distorsi ini memang dirancang untuk mengambil sebuah gambar dan membuat animasi berdasarkan gerakan dan rotasi objek itu. Sebagai contoh, di sini saya membuat pesawat luar angkasa bergaya, yang lalu saya animasikan dengan sangat kasar. Pesawat itu duduk di alasnya pada 20,75 (untuk penskalaan 'merunduk' awal), sedangkan 'pegangan' normal untuk gerakan dan rotasi adalah pusat pesawat yang terletak di 20,60 pada gambar asli. Titik-titik ini merupakan titik kontrol yang dengannya objek kemudian dapat dianimasikan secara sederhana.
magick -size 80x80 xc:skyblue -fill yellow -stroke black \
-draw 'path "M 15,75 20,45 25,75 Z M 10,55 30,55" ' \
spaceship.gif
magick spaceship.gif \
\( -clone 0 -distort SRT '20,75 1.0,0.6 0' \) \
\( -clone 0 -distort SRT '20,60 1 0 20,49' \) \
\( -clone 0 -distort SRT '20,60 0.9 20 27,35' \) \
\( -clone 0 -distort SRT '20,60 0.8 45 40,23' \) \
\( -clone 0 -distort SRT '20,60 0.5 70 55,15' \) \
\( -clone 0 -distort SRT '20,60 0.3 75 72,11' \) \
\( -clone 0 -distort SRT '20,60 0.1 80 100,8' \) \
-set delay 50 -loop 0 spaceship_launch.gif
Tentu ini contoh yang sangat kasar tentang cara memakai distorsi 'SRT' untuk menganimasikan gambar statis, tetapi idenya semestinya tertangkap. Anda bisa menambah frame, dan mungkin api serta asap, untuk memperbaikinya lebih jauh (kiriman disambut baik, dan hasil terbaik akan ditambahkan di sini beserta nama Anda).
Metode memutar gambar
Gambar dapat diputar dengan banyak cara. Tetapi rotasi sederhana saja mungkin bukan yang Anda cari. Memutar gambar tanpa mengubah ukuran... |
magick rose: -virtual-pixel black -distort SRT '20' rotate_normal.png
![[IM Output]](../static/img/distorts/rotate_normal.png)
Atau memutar sedemikian rupa agar tak ada bagian gambar hasil rotasi yang terpotong... |
magick rose: -virtual-pixel black +distort SRT '20' rotate_noclip.png
![[IM Output]](../static/img/distorts/rotate_noclip.png)
Namun biasanya Anda tidak ingin melihat piksel virtual 'hitam' (atau warna non-gambar lain apa pun) yang mengelilingi gambar sebenarnya. Salah satu solusinya adalah memangkas gambar (memakai pengaturan viewport distort) ke persegi panjang terbesar dengan rasio aspek sama, sehingga hanya memuat piksel gambar riil hasil rotasi. Namun menghitung persegi panjang ini cukup pelik, dan sempat ramai dibahas di forum ImageMagick memakai beberapa persamaan yang ditemukan di Math Help Forum. Di sini kita memutar dan melakukan pemangkasan internal sedekat mungkin ke rasio aspek asli. |
angle=20
ratio=`magick rose: -format \
"%[fx:aa=$angle*pi/180; min(w,h)/(w*abs(sin(aa))+h*abs(cos(aa)))]" \
info:`
crop="%[fx:floor(w*$ratio)]x%[fx:floor(h*$ratio)]"
crop="$crop+%[fx:ceil((w-w*$ratio)/2)]+%[fx:ceil((h-h*$ratio)/2)]"
magick rose: -set option:distort:viewport "$crop" \
+distort SRT $angle +repage rotate_internal.png
![[IM Output]](../static/img/distorts/rotate_internal.png)
Ini tampak rumit, tetapi itu karena ia memang harus menghitung 4 nilai terpisah untuk mendefinisikan pengaturan viewport: lebar, tinggi, dan offset pada gambar asli. Alternatif lain adalah bukan hanya memutar, tetapi juga menskalakan gambar sedikit lebih besar agar 'mengisi' batas gambar asli. |
angle=20
magick rose: -distort SRT \
"%[fx:aa=$angle*pi/180;(w*abs(sin(aa))+h*abs(cos(aa)))/min(w,h)], $angle" \
rotate_correction.png
![[IM Output]](../static/img/distorts/rotate_correction.png)
Yang terakhir ini ideal untuk koreksi rotasi kecil pada foto, agar ukuran asli gambar tetap terjaga. Satu-satunya alasan metode ini lebih sederhana adalah karena hanya satu nilai 'skala' yang perlu dihitung, sehingga bisa dilakukan 'sebaris'.
Distorsi menggunakan titik kontrol
Sementara metode distorsi 'SRT' didefinisikan dengan menentukan sudut rotasi dan faktor skala, kebanyakan distorsi didefinisikan dengan memindahkan 'titik-titik' pada gambar sumber ke posisi baru di gambar hasil. Ini agak mirip perpindahan titik 'pusat' saat mendefinisikan translasi 'SRT'. Titik-titik ini disebut titik kontrol, dan lebih lazim didefinisikan dengan memberikan 4 nilai floating point (2 pasang koordinat) untuk tiap satu titik kontrol. Maka distorsi sering didefinisikan dalam bentuk beberapa rangkaian 4 nilai. Sebagai contoh....
X1,Y1 I1,J1 X2,Y2 I2,J2 X3,Y3 I3,J3 X4,Y4 I4,J4 . . . .
| Dengan titik kontrol Xi,Xi pada gambar sumber (relatif terhadap kanvas virtualnya) dipetakan ke Ii,Ji pada gambar tujuan terdistorsi. | Namun karena operator distort sebenarnya memetakan koordinat tujuan ke koordinat sumber (lihat pemetaan piksel terbalik), pemakaian internalnya adalah memetakan koordinat I,J ke koordinat X,Y. Hasilnya semestinya sama saja, hanya cara berpikirnya yang berbeda. |
|---|---|
| Sebelum IM versi 6.3.6-0, ketika operator distort pertama kali diperkenalkan, urutan koordinat titik kontrol didefinisikan sebagai semua koordinat sumber, disusul semua koordinat tujuan. Namun ini menyulitkan sekali menentukan koordinat sumber dan tujuan mana yang saling berpasangan, dan tidak memungkinkan penambahan titik kontrol secara sederhana untuk memperhalus distorsi lebih lanjut. | |
| --- | --- |
Ia didefinisikan begini supaya perpindahan tiap titik kontrol tetap berkumpul dalam daftar nilai floating point yang dipisah koma (atau spasi). Ini juga membuka pemakaian 'file titik kontrol' eksternal di masa depan. Distorsi paling sederhana yang memakai titik kontrol adalah distorsi 'Affine'; meski, seperti akan Anda lihat nanti, ia biasanya didefinisikan dengan tiga titik, Anda boleh memakai perpindahan satu atau dua titik kontrol saja. Sebenarnya 'SRT' hanyalah sub-himpunan dua atau satu titik dari distorsi 'Affine'. Sebagai contoh, di sini kita memindahkan 'hidung' gambar koala kita di '28,24' ke posisi baru '45,40' (seperti ditunjukkan panah merah), yang menghasilkan 'translasi' sederhana lokasi gambar. |
magick koala.gif -virtual-pixel white \
-distort Affine '28,24 45,40' koala_one_point.png
Dengan dua titik, distorsi 'Affine' bukan hanya bisa mentranslasikan gambar, tetapi juga menskalakan dan memutarnya (rentang penuh distorsi 'SRT'. Sebagai contoh, di sini saya memetakan 'telinga' koala (garis merah dari '30,11' dan '48,29') ke posisi horizontal yang lebih besar (garis biru dari '15,15' ke '60,15'), yang menuntut gambar diskalakan, diputar, dan ditranslasikan agar titik-titik kontrolnya berpindah ke posisi baru ini.
magick koala.gif -virtual-pixel white \
-distort Affine '30,11 15,15 48,29 60,15' koala_two_point.png
Tentu distorsi 'SRT' bisa saja mereproduksi distorsi 'Affine' dua titik di atas, hanya saja di sini kita mendefinisikan distorsinya dengan cara berbeda. Bentuk mana yang mesti dipakai terserah Anda, tergantung apa yang ingin dicapai.
Koordinat gambar vs koordinat piksel
Pemakaian titik kontrol pada kasus umum cukup lugas, tetapi menjadi lebih sulit ketika Anda perlu menjajarkan gambar terdistorsi dengan gambar lain atau konstruksi yang digambar. Sebabnya, sementara kebanyakan operator di IM menangani koordinat dalam bentuk 'posisi piksel' (misalnya saat memangkas, menggambar, dsb.), distorsi menangani koordinat dalam 'koordinat gambar' yang matematis. Yang perlu diingat: piksel pada gambar bukan 'titik' melainkan 'area' seluas 1 unit piksel. Yakni, piksel yang terletak di 10,10mendefinisikan area warna persegi, dari 10unit ke bawah/ke samping hingga 11unit ke bawah dan ke samping. Dalam koordinat gambar, pusat 'piksel' itu sebenarnya terletak di 10.5,10.5. Artinya, 0.5 perlu ditambahkan ketika Anda mendistorsi gambar untuk memindahkan pusat sebuah 'piksel' ke lokasi tertentu. Maka untuk memosisikan ulang 'piksel' pojok sebuah gambar, Anda perlu memindahkan gambar dalam bentuk piksel yang terletak di 0.5,0,5dan _Width_ -0.5,_Height_ -0.5. Sebaliknya, untuk memosisikan ulang gambar dalam bentuk 'tepi' gambar yang sebenarnya, cukup pakai koordinat 0.0,0,0dan _Width_ ,_Height_. Anda hanya perlu memikirkan apa yang sebenarnya ingin diposisikan: pusat 'piksel' gambar, atau 'tepi' gambar. Atau apakah itu bahkan berpengaruh untuk masalah Anda. Ingat, bila Anda ingin menggambarelemen lain ke gambar terdistorsi Anda, posisi gambarnya perlu diberikan dalam bentuk 'posisi piksel'. Dan ya, operator "-draw" dapat menggambar garis, lingkaran, dan bentuk lain memakai nilai floating point. Demikian pula lebar goresan dan/atau jari-jari objek boleh diberikan sebagai nilai floating point.
![[IM Output]](../static/img/distorts/koala_two_point.png)
| _Lebar goresan draw di bawah 1.0 tidak bekerja baik, (lihat menggambar garis). Selain itu, pengisian area menambahkan 0.5 ekstra (sepadan dengan tambahan lebar goresan) ke tepi-tepi area isian (lihat batas isian draw). Ini dilakukan berapa pun strokewidth yang sebenarnya dipakai.
Informasi lebih lanjut lihat batas isian draw. Sesuatu yang saya anggap bug._
Titik kontrol dengan escape persen
Anda juga dapat memakai escape persen di dalam argumen distort. Misalnya Anda bisa mengambil atribut gambar dari satu gambar, lalu memakainya untuk mengubah ukuran gambar lain agar cocok dengan gambar pertama. Di sini saya mengambil ukuran gambar bawaan "rose:", lalu memakai distorsi 'Affine' untuk mengubah ukuran gambar "logo:" yang lebih besar ke ukuran yang sama (tanpa mempertahankan rasio aspek). |
magick rose: -set option:rw %w -set option:rh %h +delete \
logo: -alpha set -virtual-pixel transparent \
+distort Affine '0,0 0,0 %w,0 %[rw],0 0,%h 0,%[rh]' \
+repage logo_sized_as_rose.png
![[IM Output]](../static/img/distorts/logo_sized_as_rose.png)
Perhatikan bahwa distort menghasilkan 'gambar berlapis' yang sedikit lebih besar pada kanvas virtual (termasuk offset negatif); itulah sebabnya saya perlu menyertakan "+repage" pada contoh di atas. Tepiannya juga akan kabur, karena distort menghasilkan distorsi gambar yang eksak atau sejati, bukan gambar hasil resize ortogonal yang disterilkan. Contoh lebih lanjut pemakaian operator distort untuk mengubah ukuran gambar, persis seperti yang dilakukan operator Resize, lihat distort vs resize, serta metode distort Resize di bawah. Anda juga dapat memakai escape persen untuk menghitung distorsi berdasarkan posisi gambar dalam daftar gambar saat itu. Contohnya diberikan di distorsi teranimasi.
Kecocokan kuadrat terkecil titik kontrol
Bila Anda memberikan lebih dari 3 titik kontrol untuk distorsi 'Affine', atau lebih dari 4 titik untuk distorsi 'Perspective' atau 'Bilinear', ImageMagick akan melakukan perataan kuadrat terkecil atas semua titik yang diberikan untuk menemukan representasi 'rata-rata' distorsi tersebut. Artinya, bila Anda mencoba mencocokkan satu gambar dengan gambar lain (teknik yang dikenal sebagai 'Image Registration'), Anda dapat mendefinisikan lebih banyak titik dari jumlah minimum yang diperlukan agar hasilnya menjadi distorsi yang lebih presisi. Tentu bila satu titik atau lebih tidak 'pas' dengan titik-titik lain, hasilnya akan melenceng gara-gara titik yang 'janggal' itu, karena IM berusaha menemukan kecocokan terbaik memakai semua titik kontrol yang diberikan, termasuk yang buruk. Untuk beberapa situasi mungkin diperlukan semacam pemeriksaan guna menemukan dan membuang 'pasangan koordinat yang buruk'.
Titik kontrol dari file
Daftar angka (argumen) untuk sebuah distorsi juga dapat dibaca dari file memakai sintaksis '@filename', persis seperti Anda memasukkan teks untuk hal-hal seperti "-annotate" dan "label:" (lihat karakter escape pada argumen teks). Misalnya Anda dapat menentukan distorsi seperti ini...
magick input.png -distort Perspective '@file_of_coords.txt' output.png
Nama file-nya boleh sekadar '@-' yang berarti membaca file dari standard input. File itu sendiri akan dibaca sebagai string dan diperlakukan sebagai daftar koordinat (argumen) yang diperlukan distorsi bersangkutan. Karena angka boleh dipisah koma maupun spasi, pasangan koordinatnya dapat ditata rapi sebagai satu pasang koordinat per baris dalam bentuk...
X1 Y1 I1 J1
X2 Y2 I2 J2
X3 Y3 I3 J3
X4 Y4 I4 J4
....
Itu, bersama kecocokan kuadrat terkecil, membuat pemakaian registrasi gambar sangat praktis. Karena file-nya sekadar daftar empat angka per baris, Anda dapat memakai perkakas skrip pemrosesan teks lain seperti "cut", "paste", "column", dan perkakas skrip pemrosesan teks yang lebih canggih seperti "sed", "awk", "perl", dsb. untuk memanipulasi koordinatnya. Pemakaian file koordinat dan argumen distorsi akan makin penting pada distorsi yang lebih maju, seperti distorsi 'Shepards', dan distorsi 'Grid' serta "Mesh' yang direncanakan ke depan, yang bisa melibatkan ratusan pasang koordinat.
Metode distorsi afin (tiga titik)
Distorsi afin
Baik distorsi 'SRT' maupun bentuk satu dan dua titik distorsi 'Affine' di atas sebenarnya adalah penyederhanaan dari bentuk 3 titik penuh distorsi 'Affine'. Bahkan bila Anda telaah keluaran "-verbose" dari distorsi 'SRT' mana pun (contohnya lihat pengaturan distort verbose), Anda akan mendapati bahwa secara internal ia sejatinya distorsi 'AffineProjection' (lihat di bawah). Satu-satunya efek distorsi yang tidak bisa ditangani penuh oleh metode-metode di atas adalah 'shear' serupa yang disediakan operator Shear. Untuk itu Anda perlu memakai distorsi afin tiga titik. Anda bisa membayangkannya sebagai distorsi tiga titik: pemetaan koordinat pertama sebagai 'titik asal' dan dua pemetaan koordinat lainnya sebagai vektor dari titik asal itu. Sebagai contoh, di sini saya menggambar teks, lalu menumpangkan 'vektor' merah dan biru untuk mendefinisikan ketiga titik kontrol relatif terhadap teks itu. Kini dengan memindahkan koordinat (sebagai koordinat gambar kedua garis itu, kita dapat mentranslasikan, memutar, menskalakan, dan men-shear gambar teks itu agar pas dengan lokasi baru garis-garis tersebut.
magick -background lightblue -fill Gray -font Candice \
-size 100x100 -gravity center label:Affine\! \
-draw 'fill blue stroke blue path "M 3,60 32,60 M 27,58 27,62 32,60 Z"' \
-draw 'fill red stroke red path "M 3,60 3,30 M 1,35 5,35 3,30 Z"' \
label_axis.png
magick label_axis.png \
-distort Affine ' 3.5,60.5 3.5,60.5
32.5,60.5 32.5,60.5
3.5,30.5 33.5,20.5' label_axis_distort_shear.png
magick label_axis.png \
-distort Affine ' 3.5,60.5 3.5,60.5
32.5,60.5 27.5,85.5
3.5,30.5 27.5,35.5' label_axis_distort_rotate.png
magick label_axis.png \
-distort Affine ' 3.5,60.5 30.5,50.5
32.5,60.5 60.5,80.5
3.5,30.5 30.5,5.5' label_axis_distort_affine.png
Pada contoh pertama hanya koordinat ketiga (untuk garis merah vertikal) yang diubah, membuat gambar ter-shear dan teregang sepanjang sumbu Y. Tentu tidak harus terbatas pada sumbu Y saja. Contoh-contoh berikutnya melakukan perubahan lebih radikal pada gambar, termasuk rotasi dan translasi. Tentu operator teks annotate juga bisa memiringkan teks sungguhan dengan cara yang sama, meski hanya lewat perubahan sudut. Operator itu tidak akan menskalakan atau memperbesar teks ke arah tertentu. Boleh dibilang ia bisa memutar sebuah 'vektor' tetapi tidak bisa meregangkannya lebih panjang atau lebih pendek. Lihat pemakaian argumen annotate untuk tabel contohnya. Distorsi afin dapat melakukan distorsi jenis ini untuk gambar apa pun, bukan hanya teks yang digambar. Affine dengan pasangan koordinat kurang atau lebih dari tiga Bila hanya 1 atau 2 pasang titik kontrol yang diberikan, IM memakai bentuk distorsi afin yang lebih terbatas agar sesuai dengan perpindahan titik-titik yang lebih sedikit itu. Misalnya dengan hanya 1 pasang koordinat, ia membatasi diri pada translasi gambar tanpa penskalaan. Dengan 2 titik ia membatasi diri pada distorsi 'Scale-Rotate-Translation' (tanpa shear). Contohnya lihat pembahasan sebelumnya tentang distorsi menggunakan titik kontrol. Bila lebih dari 3 titik kontrol diberikan pada distorsi 'Affine', IM memakai kecocokan kuadrat terkecil untuk menemukan distorsi afin '3 titik' terbaik yang cocok dengan semua pasangan koordinat yang diberikan. Artinya titik kontrol gambar sumber mungkin tidak terpetakan persis ke titik kontrol gambar tujuan, melainkan ke 'rata-rata' best-fit dari semua titik yang diberikan. Misalnya bila Anda punya hasil pindaian dokumen, Anda bisa menandai dan memetakan keempat pojok dokumen untuk distorsi afin guna mengoreksi rotasi dan skala dokumen. Dengan cara ini Anda mendapat kecocokan 'rata-rata' yang lebih baik berbasis 4 titik alih-alih 3 titik. Perhatikan bahwa meski lebih banyak koordinat bisa menghasilkan distorsi yang lebih baik dan lebih akurat, bila satu pasangan koordinat sangat buruk, kecocokan kuadrat terkecilnya bisa sama sekali tidak bagus. Mungkin diperlukan semacam pemeriksaan untuk menyingkirkan 'pasangan koordinat yang buruk'. Future: Add some code to IM to report how 'accurate' each input coordinate pair is relative to the others to help determine what 'bad points' should be eliminated by the user.
Distorsi proyeksi afin (Affine Projection)
Seperti sudah saya sebut, berbagai argumen distorsi 'SRT' dan titik-titik kontrol distorsi 'Affine' ditransformasikan secara matematis menjadi 6 angka khusus yang mewakili 'koefisien' sebuah 'Affine Projection'. Angka-angka pada Affine Projection ini adalah koefisien yang dipakai untuk pemetaan maju titik-titik dari gambar sumber ke gambar tujuan. Yakni, nilai-nilai matematis yang dipakai untuk memetakan x,y gambar sumber ke i,j gambar tujuan. Keenam argumen floating point-nya adalah (dalam urutan pemberian)...
sx, rx, ry, sy, tx, ty
Ini pada gilirannya membentuk ekspresi distorsi.. Xd = | sx*Xs + ry*Ys + tx | , | Yd = | rx*Xs + sy*Ys + ty |
Dengan "Xs,Ys" koordinat gambar sumber dan "Xd,Yd" koordinat gambar tujuan. Secara internal distort ImageMagick membalik persamaan-persamaan di atas untuk melakukan pemetaan piksel yang sesuai, yakni memetakan koordinat "Xd,Yd" guna mencari warna di "Xs,Ys" pada gambar sumber. Informasi lebih lanjut tentang bagaimana berbagai nilai matriks Affine Projection memengaruhi gambar lihat sub-halaman transformasi matriks afin. Bila koefisien-koefisien ini sudah Anda hitung sebelumnya (misalnya diambil dari keluaran verbose distort, atau Anda hitung sendiri dengan metode lain dari bentuk argumen masukan lain, Anda dapat memberikannya langsung ke IM untuk mendistorsi gambar. Sebagai contoh, di sini saya men-'shear' gambar tetapi memakai sudut untuk menghitung koefisiennya, bukan perpindahan titik kontrol. |
angle=-20
tan=`magick xc: -format "%[fx:tan( $angle *pi/180)]" info:`
magick koala.gif -alpha set -virtual-pixel Transparent \
+distort AffineProjection "1,$tan,0,1,0,0" +repage \
koala_affine_proj.png
![[IM Output]](../static/img/distorts/koala_affine_proj.png)
Cara lama melakukan distorsi ini di ImageMagick adalah memakai pasangan operasi "-affine" dan "-transform". Namun sejak IM v6.4.2-8 itu sekadar panggilan sederhana ke 'AffineProjection' memakai bentuk 'plus' atau 'bestfit' dari operator distort. Rincian lebih lanjut lihat sub-halaman transformasi matriks afin.
Contoh distorsi afin
Tiling afin
Ketiga metode distorsi mirip-afin yang sudah kita lihat di atas juga menyediakan cara-cara menarik untuk membuat berbagai pola tiling, berdasarkan gambar yang terdistorsi.
magick checks.png -alpha set -virtual-pixel tile \
-distort ScaleRotateTranslate '20,20 .5 30' \
checks_srt_tile.png
magick checks.png -alpha set -virtual-pixel tile \
-distort Affine '0,0 10,10 0,89 10,50 89,0 50,0' \
checks_affine_tile.png
magick checks.png -alpha set -virtual-pixel tile \
-distort AffineProjection '0.9,0.3,-0.2,0.7,20,15' \
checks_amatrix_tile.png
Memakai pemetaan distorsi seperti ini sebenarnya adalah cara kerja 'texture mapping' pada pustaka grafika 3D dan game. Bedanya hanya mereka memetakan koordinat 3 dimensi permukaan kembali ke gambar dua dimensi. Bahkan distorsi 'no-op' ("-distort SRT 0"), dengan viewport distort yang sesuai, menyediakan cara berguna untuk men-tile seluruh rangkaian gambar seperti tile gemerlap teranimasi.
magick glitter_blue.gif -virtual-pixel tile \
-filter point -set option:distort:viewport 100x100 -distort SRT 0 \
glitter_blue_tiled.gif
Perhatikan bahwa saya juga memakai "-filter point" untuk mematikan resampling EWA, demi mempercepat operasinya sekaligus menjamin salinan piksel gambar sumber yang sempurna (tanpa sampling). Viewport distort juga bisa menentukan offset, untuk 'menggulung' gambar-gambar yang di-tile pada gambar hasil.
Kubus 3D, dengan pelapisan afin
Distorsi 'Affine', dengan titik-titik kontrolnya, ideal untuk membuat kubus ortografis dan isometrik (definisinya lihat Wikipedia, Orthographic Projection dan Isometric Projection) dari tiga gambar. Yang perlu Anda lakukan hanyalah menentukan empat titik kontrol pada gambar tujuan. Karena kita akan memakai teknik pelapisan gambar, titik-titiknya bahkan boleh bernilai negatif, dan IM dapat menyesuaikan ukuran gambar akhir dengan gambar-gambar terlengkung yang dihasilkan. Untuk contoh ini saya memilih titik kontrol '0,0' untuk pusat kubus, dan tiga titik berjarak sama mengelilingi titik pusat itu, di '-87,-50', '87,-50', dan '0,100'. Yang kemudian perlu saya lakukan hanyalah memetakan pojok-pojok yang sesuai dari tiga gambar (sebaiknya persegi) ke titik-titik kontrol ini. |
magick \
\( lena_orig.png -alpha set -virtual-pixel transparent \
+distort Affine '0,512 0,0 0,0 -87,-50 512,512 87,-50' \) \
\( mandrill_orig.png -alpha set -virtual-pixel transparent \
+distort Affine '512,0 0,0 0,0 -87,-50 512,512 0,100' \) \
\( pagoda_sm.jpg -alpha set -virtual-pixel transparent \
+distort Affine ' 0,0 0,0 0,320 0,100 320,0 87,-50' \) \
\
-background none -compose plus -layers merge +repage \
-bordercolor black -compose over -border 5x2 isometric_cube.png
![[IM Output]](../static/img/distorts/isometric_cube.png)
Perhatikan bahwa saya memakai koordinat tepi gambar yang sebenarnya saat mendistorsi gambar Artinya secara matematis gambar-gambar itu semestinya saling bertaut persis. Perhatikan pula saya tidak sekadar 'mengomposisikan' gambar-gambar itu (memakai komposisi alpha Over bawaan). Bila itu yang Anda lakukan, akan muncul 'celah' agak transparan di antara gambar-gambar. Cara yang benar (seperti ditunjukkan) adalah memakai komposisi alpha Plus untuk menyambung potongan-potongan yang 'terhubung di tepi', yang menghasilkan sambungan sempurna tanpa celah transparan. Informasi lebih lanjut lihat menjajarkan dua gambar ter-mask. Sesudahnya saya menambahkan border ekstra, dan menghapus semua transparansi. Ini tidak wajib, dan Anda bisa saja memakai latar belakang apa pun (atau "none"), tetapi melakukannya akan menonjolkan 'celah' apa pun yang mungkin ada pada gambar Anda.
Di kanan ditunjukkan pembesaran salah satu sambungan pada gambar, memperlihatkan tiadanya celah 'terisi hitam' di sepanjang sambungan. Metode alternatif membuat kubus isometrik, tanpa memakai "-distort", diberikan di kubus isometrik dengan shear. Namun teknik itu tidak memungkinkan Anda memakai koordinat sub-piksel (bukan berarti saya memakainya di atas, tetapi bisa saja), melainkan terbatas pada penempatan gambar memakai koordinat piksel utuh (bilangan bulat).
Bayangan 3D, dengan shear afin
Metode pelapisan yang dipakai di atas juga bisa dipakai untuk membuat bayangan 3 dimensi yang keren dari bentuk-bentuk aneh. Yakni menambahkan bayangan untuk bentuk 'pipih' apa pun yang berdiri tegak. Misalnya mari kita buat bentuk dengan alas datar, supaya mungkin bisa berdiri tegak. |
magick -background None -virtual-pixel Transparent -fill DodgerBlue \
-pointsize 72 -font Ravie label:A -trim +repage \
-gravity South -chop 0x5 standing_shape.png
![[IM Output]](../static/img/distorts/standing_shape.png)
Perhatikan bahwa 'bentuk' itu punya alas datar yang juga merupakan baris terakhir gambar. Ini penting karena kita akan mendistorsi bentuknya sepanjang baris itu, sehingga bayangan tersambung ke bentuk berdiri di sepanjang baris tersebut. Berikut perintah untuk membuat bayangan 3D dari 'bentuk berdiri' ini |
magick standing_shape.png -flip +distort SRT '0,0 1,-1 0' \
\( +clone -background Black -shadow 60x5+0+0 \
-virtual-pixel Transparent \
+distort Affine '0,0 0,0 100,0 100,0 0,100 100,50' \
\) +swap -background white -layers merge \
-fuzz 2% -trim +repage standing_shadow.jpg
![[IM Output]](../static/img/distorts/standing_shadow.jpg)
Perintah di atas melakukan cukup banyak langkah untuk mencapai hasil yang ditunjukkan. Namun yang paling pelik adalah baris pertamanya. Ia membalik (flip) gambar lalu melakukan 'flip distort' kembali. Hasilnya, baris paling bawah kini terletak sedemikian rupa sehingga bernilai Y=0 pada kanvas virtual. Yakni, seluruh gambar diberi offset negatif untuk memosisikannya agar baris paling bawah melewati titik asal kanvas virtual. Dengan 'trik' ini kita bisa memakai 'shear afin' yang sangat sederhana pada 'bayangan' hasil ekstraksi untuk mendistorsinya. Dengan begitu kita tidak perlu tahu ukuran gambar bentuknya untuk mendistorsi bayangan, tetapi tetap berhasil menjaga semuanya 'sejajar', karena semuanya tetap sinkron di sepanjang baris bawah (Y=0) gambar asli. Anda dapat menyetel arah jatuh bayangan dan panjangnya cukup dengan menyetel koordinat terakhir ('100,50') dari 'shear afin' itu. Dua 'pasangan koordinat' pertama jangan diubah karena keduanya 'mengunci' bayangan ke gambar asli di sepanjang baris bawah. Namun perhatikan bahwa sampai tepat sebelum langkah terakhir semua gambar memuat offset kanvas virtual negatif, jadi berhati-hatilah bila Anda berencana melihat atau menyimpan gambar-gambar pemrosesan antara. Satu-satunya masalah efek bayangan ini adalah ia 'buram seragam'. Yakni, bayangannya tidak realistis. Pada kenyataannya bayangan semestinya tajam di tempat ia bertemu 'bentuk berdiri' dan makin buram saat bayangan makin menjauh. Ini bisa dilakukan memakai pemetaan blur variabel, seperti dipakai pada font bayangan buram berjarak.
Bayangan 3D, dengan kompresi perspektif
Ini cara lain menambahkan blur variabel pada bayangan; meski sebenarnya tidak saya anjurkan, implementasinya cukup sederhana. Contoh ini dikembangkan sebelum pemetaan blur variabel ditambahkan ke ImageMagick. Pada dasarnya Anda lebih dulu mendistorsi bentuk bayangan awal memakai distorsi perspektif (yang dibahas rinci di bawah), untuk mengompres kuat-kuat 'bagian jauh' bayangan sehingga buram, lalu memekarkan kompresi itu dengan mendistorsinya ke posisi 'shear afin' akhirnya yang kita pakai di atas. |
magick standing_shape.png -flip +distort SRT '0,0 1,-1 0' \
\( +clone -virtual-pixel Transparent -mattecolor None \
+distort Perspective \
'0,0 0,0 100,0 100,0 0,-100 45,-100 100,-100 60,-100' \
-fuzz 2% -trim -background Black -shadow 60x3+0+0 \
+distort Perspective \
'0,0 0,0 100,0 100,0 45,-100 -100,-50 60,-100 0,-50' \
\) +swap -background white -layers merge \
-fuzz 2% -trim +repage standing_shadow_var.jpg
![[IM Output]](../static/img/distorts/standing_shadow_var.jpg)
Ini hampir persis sama dengan contoh bayangan 3D asli, tetapi dengan beberapa langkah tambahan. Bentuk asli lebih dulu didistorsi menjadi trapesium, lalu ruang berlebihnya dipangkas untuk mempercepat langkah berikutnya. Kemudian kita mengekstrak bayangan buram dari bentuk terdistorsi itu. Begitu gambar bayangan tercipta dari gambar terdistorsi, titik-titik kontrol yang sama dipakai untuk membatalkan distorsi gambar bayangan, dan memindahkannya ke posisinya sebagai shear afin. Kuncinya, blur bayangan terjadi pada gambar yang terdistorsi, yang kemudian dibatalkan distorsinya (dan dalam kasus ini di-shear afin sekaligus). Akibatnya blur-nya ikut terdistorsi dan memekar sehingga lebih buram di sekitar bagian atas bayangan, dan jauh lebih sedikit di sepanjang garis alas. Berkat blur perspektif itu, kita mendapat blur variabel yang semestinya memuncak sekitar 100 piksel dari garis alas tanah. Sebagaimana didefinisikan titik-titik kontrol blur perspektif awal.
Mengubah ukuran gambar dengan distort
Distort dan Resize sebenarnya sangat mirip dalam banyak segi. Keduanya operator distorsi gambar, dan keduanya memakai pemetaan piksel terbalik untuk membuat gambar hasil. Keduanya juga memanfaatkan pengaturan "-filter" beserta kontrol pakarnya untuk penentuan warna, meski melakukannya dengan cara sangat berbeda. Resize adalah operasi distorsi gambar yang disederhanakan (dan jauh lebih umum), sehingga memungkinkan banyak optimasi. Ia sejajar ortogonal, sehingga resize bisa memakai metode pemfilteran gambar ortogonal 2 lintasan. Boleh dibilang ia menskalakan lebih dulu di satu dimensi, lalu di dimensi lainnya, memakai gambar sementara antara. Selain itu, karena faktor skalanya konstan di seluruh gambar tujuan, dengan tepi sejajar pada dimensi piksel utuh (bilangan bulat), algoritmenya dapat sangat menyederhanakan pemrosesan dan kebutuhan caching filter yang dipakainya. Semua keterbatasan ini memungkinkan berbagai optimasi yang membuatnya sangat cepat dibandingkan kerja yang harus dilakukan distort. Distort juga bisa mengubah ukuran gambar, tetapi melakukannya dalam satu lintasan yang langsung mengonversi dari gambar asli ke gambar baru hasilnya. Ia tidak perlu menyejajarkan tepi ke posisi piksel bulat, dan bisa memutar serta menskalakan tiap posisi piksel. Dengan kata lain ia operator yang jauh lebih umum, yang menuntutnya melakukan banyak pemrosesan ekstra untuk tiap piksel pada hasil akhir, dengan lebih sedikit ruang optimasi. Agar distort menghasilkan gambar yang setara dengan Resize, ia perlu mengikuti keterbatasan yang persis sama, dan memakai sejumlah muslihat pemrosesan gambar yang rumit. Ini dibahas di forum IM, di Correct Resize (using distorts), dan membuahkan teknik resize distort setara yang berbasis pemakaian metode distorsi afin. Metode distorsi 'Resize' hasilnya ditambahkan ke ImageMagick versi 6.6.9-2. Versi antarmuka baris perintah (CLI) distorsi ini menerima dan memproses argumen geometry yang persis sama dengan Resize, termasuk selisih kecil faktor skala untuk kedua dimensinya, menjadikannya alternatif resize langsung. |
magick logo: -distort Resize 150x logo_resized.png
![[IM Output]](../static/img/distorts/logo_resized.png)
| _Antarmuka API lain untuk metode distorsi 'Resize' hanya menerima dua angka sebagai argumen, yang diperlakukan sebagai ukuran bulat akhir gambar hasil. Saat ini antarmuka itu tidak menerima argumen geometry sungguhan dengan berbagai flag kontrol resize-nya yang mengubah ukuran akhir gambar. Yakni, flag seperti persentase, hanya memperbesar/memperkecil, atau bahkan mempertahankan rasio aspek, tidak tersedia.
Menambahkan dukungan semacam itu untuk metode distorsi gambar khusus ini diserahkan kepada para pemelihara API tersebut._
Perbedaan sesungguhnya antara resize distort di atas dan operator Resize biasa adalah bahwa versi distort memakai filter silindris (eliptis) satu lintasan yang jauh lebih lambat, untuk menentukan warna akhir setiap piksel. Dengan kata lain ia menyediakan perbandingan langsung antara filter ortogonal 2 lintasan (resize) versus filter silindris 2 dimensi tetapi satu lintasan (resize distort). Lihat distort vs resize untuk satu perbandingan semacam itu.
Internal resize distort
Berikut operasi setara yang dilakukan resize distort di atas secara internal.
magick logo: -alpha set -virtual-pixel transparent \
+distort Affine '0,0 0,0 %w,0 150,0 0,%h 0,113' \
-alpha off -crop 150x113+0+0 +repage distort_resize.png
Nilai '150' dan '113' (dipakai di dua tempat) adalah ukuran gambar akhir yang diinginkan, dibulatkan ke bilangan bulat terdekat. Ia dihitung untuk berusaha mempertahankan rasio aspek gambar sebaik mungkin, sambil tetap dalam batasan ukuran bulat akhir. Normalnya ia dihitung ImageMagick dari argumen geometry resize yang diberikan, memakai fungsi API terpisah. Ia lalu mengaktifkan transparansi dan piksel virtual transparan, agar 'piksel virtual' eksternal tidak ikut serta dalam penghitungan warna piksel akhir. Setelah distorsinya selesai, transparansinya dihapus lagi (dimatikan), dan piksel 'penyangga' yang ditambahkan distort dibuang memakai pemangkasan gambar. Karena pemakaian piksel transparan, perintah di atas hanya bekerja benar untuk gambar yang tidak mengandung transparansi sama sekali, seperti gambar bawaan "logo:" yang dicontohkan di atas. Berikut versi yang jauh lebih rumit, yang diperlukan untuk memisahkan efek piksel virtual dari kemungkinan transparansi yang sudah ada pada gambar.
magick logo: -alpha set -virtual-pixel transparent \
\( +clone -alpha extract -alpha opaque \) \
+distort Affine '0,0 0,0 %w,0 150,0 0,%h 0,113' \
-alpha off -crop 150x113+0+0 +repage \
-compose CopyOpacity -composite distort_resize_trans.png
Ini melakukan dua distort: pertama mendistorsi gambarnya, lalu mendistorsi kanal alpha (transparansi) secara terpisah, masing-masing memakai transparan untuk menghilangkan efek virtual-pixel. Akibatnya ia setidaknya dua kali lebih lambat daripada versi ketika gambar aslinya tidak memuat transparansi. Kedua teknik ini diimplementasikan secara internal oleh metode resize distort. Karena itu 'metode' ini sebenarnya 'makro' kemudahan bagi pengguna, bukan metode distorsi sungguhan — yang sejatinya adalah distorsi 'afin'.
Metode distorsi empat titik
Distorsi perspektif
Jenis distorsi yang barangkali paling sering diminta adalah operasi distorsi perspektif yang cepat. Ini distorsi 4 titik, jadi perlu setidaknya 4 pasang titik kontrol, atau 16 nilai floating point. Sebagai contoh, di sini saya punya sebuah gambar gedung. Dari gambar itu saya menemukan sendiri lokasi 4 titik (merah). Saya juga menetapkan lokasi akhir yang menjadi tujuan transformasi titik-titik tersebut pada gambar akhir (biru), supaya bidang muka gedungnya 'diluruskan' atau 'direktifikasi'.
magick building.jpg \
-draw 'fill none stroke red polygon 7,40 4,124, 85,122, 85,2' \
building_before.jpg
magick building.jpg \
-draw 'fill none stroke blue polygon 4,30 4,123, 100,123, 100,30' \
building_after.jpg
Untuk melakukan distorsi gambarnya sendiri, koordinat-koordinat itu cukup diumpankan ke metode 'perspective' dari "-distort".
magick building.jpg -alpha set -virtual-pixel transparent \
-distort Perspective \
'7,40 4,30 4,124 4,123 85,122 100,123 85,2 100,30' \
building_pers.png
Perhatikan area kosong di kanan atas, tempat distorsi 'meleset' dari data piksel pada gambar sumber. Apa yang IM lakukan dalam situasi ini dikendalikan oleh pengaturan "-virtual-pixel" (lihat piksel virtual). Yang kurang kentara, sedikit bagian tepi paling kiri gambar asli juga 'hilang' karena alasan yang sama. Sekadar menarik untuk dicoba, mari kita balik juga distorsinya dengan menukar koordinat pada setiap pasangan pemetaan. Dengan begitu terlihat seberapa besar gambar merosot kualitasnya akibat distorsi.
magick building_pers.png -alpha set -virtual-pixel transparent \
-distort Perspective \
'4,30 7,40 4,123 4,124 100,123 85,122 100,30 85,2' \
building_pers_rev.png
Lumayan. Banyak 'keburaman' yang muncul, tetapi itu tidak bisa dihindari. Perhatikan bahwa 'keburaman' itu lebih parah di sisi kanan gambar, tempat kompresinya paling besar. Semua distort mengalami masalah kompresi ini, jadi sebaiknya selalu mendistorsi dari gambar asli, bukan mendistorsi gambar yang sudah terdistorsi. Berikut contoh lain pemakaian transformasi ini, dengan gambar uji papan catur khusus yang kita buat di atas, yang kita distorsi lalu kita balik distorsinya.
magick checks.png -alpha set -virtual-pixel transparent \
-distort Perspective '0,0,0,0 0,90,0,90 90,0,90,25 90,90,90,65' \
checks_pers.png
magick checks_pers.png -alpha set -virtual-pixel transparent \
-distort Perspective '0,0,0,0 0,90,0,90 90,25,90,0 90,65,90,90' \
checks_pers_rev.png
Terlihat sedikit keburaman akibat kompresi gambar, tetapi gambarnya pada dasarnya pulih. Yang sebenarnya terjadi, IM memakai semua pasangan titik kontrol yang diberikan untuk menghitung koefisien yang sesuai bagi sebuah 'Perspective Projection' (lihat berikutnya). Bila pengaturan Verbose disertakan, koefisien maupun padanan DIY FX yang dipakai IM secara internal untuk melakukan distorsi ini dapat dilihat sekaligus. Bila hanya 3 pasang titik kontrol atau kurang yang diberikan, IM otomatis mundur ke distorsi 'Affine' yang lebih sederhana. Sedangkan lebih dari 4 titik (untuk 'Image Registration ') akan menjalani kecocokan kuadrat terkecil untuk menemukan distorsi yang paling pas bagi semua titik kontrol yang diberikan. FUTURE: Alternative. The four coordinates could also represent a triangle and center point. You can fix the triangle and move the center point, or fix that center and move the other three coordinates, to generate the perspective view. Bila ingin melihat lebih rinci cara kerja distorsinya, lihat internal Perspective di bawah. Anda juga bisa melihat implementasi Postscript yang disajikan dalam makalah PDF Perspective Rectification oleh Gernot Hoffmann. Lihat pula Leptonica Affine and Perspective Transforms.
Memandang cakrawala jauh
Efek yang sangat tidak biasa dapat dihasilkan dengan distorsi perspektif bila koordinatnya disetel sehingga muncul 'titik lenyap' di dalam batas gambar.
magick checks.png -mattecolor DodgerBlue \
-virtual-pixel background -background Green \
-distort Perspective '0,0 20,60 90,0 70,63 0,90 5,83 90,90 85,88' \
checks_horizon.png
![[IM Output]](../static/img/distorts/checks_horizon.png)
Nah, kita memakai 'Green' untuk piksel virtual yang 'mengelilingi' gambar asli, yang kita aktifkan lewat pengaturan latar belakang piksel virtual. Tetapi yang lebih menarik adalah munculnya warna 'biru' yang didefinisikan lewat pengaturan "-mattecolor". Warna 'biru' ini mewakili area tempat piksel yang dihasilkan distorsi tidak valid , dan di area seperti itu operator "-distort" akan sekadar mengeluarkan pengaturan "-mattecolor". Untuk distorsi perspektif, setiap piksel yang berakhir di 'langit' pada gambar hasil digolongkan tidak valid. 'Langit' di sini didefinisikan sebagai sisi 'cakrawala' tempat gambar sumber tidak akan muncul. 'Langit' hanya tampak pada gambar terdistorsi perspektif ketika gambar hasilnya sangat terpendekkan oleh distorsi. Bila Anda tidak ingin ada 'langit' pada hasil akhir, cara terbaiknya adalah menyetel "-background" dan "-mattecolor" ke warna yang sama. Distorsi perspektif jadi lebih menarik ketika salah satu pengaturan piksel virtual tiling tak hingga yang khusus itu dipakai. Sebagai contoh, di sini kita memakai pengaturan 'tile' untuk menghasilkan bidang yang di-tile tanpa batas.
magick checks.png -virtual-pixel tile -mattecolor DodgerBlue \
-distort Perspective '0,0 20,60 90,0 70,63 0,90 5,83 90,90 85,88' \
horizon_tile.png
![[IM Output]](../static/img/distorts/horizon_tile.png)
Satu peringatan soal gambar ini. Meminta gambar yang di-tile tanpa batas sangat lambat dihasilkan. Makin besar gambarnya, makin lambat. Kemajuan "-distort" (atau tugas pemrosesan gambar lambat lainnya) dapat dipantau memakai "-monitor", yaitu pengaturan kontrol operasional. Pada dasarnya, untuk satu piksel yang dekat cakrawala, ImageMagick harus merata-ratakan piksel dalam jumlah sangat besar dari gambar asli untuk mengetahui warna yang tepat. Ini bisa memakan waktu sangat lama. ImageMagick memang berusaha membatasi waktu yang dipakainya untuk menangani piksel dekat-cakrawala ini, dengan menyimpan informasi ke cache dan memakai pengetahuan bawaan tentang berbagai pengaturan piksel virtual, tetapi tetap saja bisa lama. Untuk rincian lebih lanjut tentang metode ini lihat resampling area di atas. Gambar perspektif yang di-tile tak hingga lainnya dapat dihasilkan memakai pengaturan piksel virtual Random...
magick checks.png -virtual-pixel random -mattecolor DodgerBlue \
-distort Perspective '0,0 20,60 90,0 70,63 0,90 5,83 90,90 85,88' \
horizon_random.png
![[IM Output]](../static/img/distorts/horizon_random.png)
Yang terjadi adalah semua piksel virtual di sekeliling gambar sekadar hasil pengambilan acak dari piksel mana pun di dalam gambar itu sendiri. Hasilnya berupa tanah yang tersusun dari noise acak yang makin halus dan makin ter-blur ketika pandangan bergerak ke arah cakrawala gambar. Ini memberi kesan kedalaman yang alami, tanpa pola berulang tertentu. Di sini saya mengulang contoh di atas tetapi dengan gambar sumber hitam-putih murni. Namun saya tidak tertarik pada gambar terdistorsinya, hanya pada pola 'random' piksel virtual yang dihasilkan, jadi saya mengubah bagian mana dari 'ruang gambar terdistorsi' yang saya lihat, dengan memakai pengaturan khusus '-set option:distort:viewport'. Pengaturan ini menimpa ukuran dan lokasi normal dari area ruang terdistorsi yang sedang dilihat. Dalam hal ini area yang hanya berisi piksel virtual, bukan gambar terdistorsinya.
magick -size 90x90 pattern:gray50 -alpha set \
-virtual-pixel random -mattecolor none \
-set option:distort:viewport 120x120+100-15 \
-distort Perspective '0,0 20,60 90,0 70,63 0,90 5,83 90,90 85,88' \
+repage -size 120x50 gradient:dodgerblue-tomato \
-compose DstOver -composite sunset_horizon.png
![[IM Output]](../static/img/distorts/sunset_horizon.png)
Untuk merampungkan gambarnya saya menghapus offset viewport (memakai "+repage" ), lalu menaruh gradien warna senja di bawah 'langit' transparan dengan Underlay atau DstOver (langit itu disetel memakai "alpha setmattecolor") . Gambar yang sangat menarik dan bisa dipakai sebagai latar untuk pekerjaan pemrosesan gambar lain. Parameter distorsinya dapat disetel untuk mengatur tinggi dan kemiringan cakrawala. Berikut uji yang lebih lazim untuk distorsi perspektif yang di-tile.
magick pattern:checkerboard -scale 120x120 -normalize \
-virtual-pixel tile -distort Perspective \
'0,0 10,61 119,0 60,60 0,119 5,114 119,119 125,110' \
checkered_plain.gif
![[IM Output]](../static/img/distorts/checkered_plain.gif)
Dalam penelaahan saya, uji di atas ternyata menyesatkan karena tidak memberi gambaran nyata tentang kualitas teknik resampling area pada skala gambar yang mendekati satu banding satu (area latar depan, bukan area yang jauh). Yakni pengamatan dari dekat atas masalah resampling seperti yang diuraikan di artefak resampling. Gambar terakhir ini juga memperlihatkan titik 'potong' dekat cakrawala, tempat ImageMagick memutuskan bahwa menentukan warna yang tepat untuk sebuah piksel (dengan mempertimbangkan pengaturan piksel virtual saat itu) tidak lagi sepadan, lalu memotong jalan algoritma EWA dan memakai warna rata-rata seluruh gambar. Ini hanya terlihat pada gambar ini karena adanya pola warna diagonal berskala besar di dalamnya. Warna rata-rata sebuah gambar hanya dihitung sekali per operasi distorsi, dan hanya ketika pertama kali diperlukan. Dengan memakainya ImageMagick menghemat banyak sekali waktu penghitungan warna dekat cakrawala, yang hasilnya biasanya memang warna rata-rata gambar. Ini terjadi ketika elipsnya menjadi begitu memanjang hingga melampaui batas floating point, atau ketika jumlah piksel sampling (jajaran genjang pembatas elips) menjadi 4 kali lebih besar daripada gambar sumber masukan. Saat ini nilainya tidak dapat disetel pengguna.
Kotak 3D, pelapisan perspektif
Bentuk 'plus' dari "+distort", yang memastikan seluruh gambar terdistorsi tersimpan pada layer (atau 'kanvas virtual') dengan posisi yang benar, dirancang sedemikian rupa sehingga bila 'titik kontrol' yang sama dipakai untuk mendistorsi beberapa gambar, titik-titik itu akan berjajar rapi di 'ruang virtual'. Artinya, bila gambar-gambar itu digabungkan sebagai layer, gambar-gambar tersebut juga akan berjajar sesuai titik kontrolnya. Sebagai contoh, di sini kita menghasilkan dua gambar, gambar 'depan' dan gambar 'punggung', sehingga dua titik kontrol tepinya berjajar satu sama lain membentuk punggung sebuah kotak.
# Generate a Spine Image
magick -size 200x40 xc:skyblue \
-pointsize 20 -gravity north -annotate +5+0 'IM Examples' \
-pointsize 10 -gravity south -annotate +0+0 'ImageMagick' \
-stroke blue -strokewidth 2 -draw 'line 30,0 30,40' \
-rotate -90 box_spine.jpg
# generate the front cover
magick -size 150x200 xc:skyblue \
-fill black -pointsize 20 -gravity north -annotate +0+5 'IM Examples' \
-fill blue -pointsize 15 -gravity northeast -annotate +5+28 'Box Set' \
-fill black -pointsize 15 -gravity south -annotate +0+5 'ImageMagick' \
-stroke blue -strokewidth 2 -draw 'line 0,169 150,169' \
\( logo.gif -resize 100x100 \) \
-gravity center -compose multiply -composite box_front.jpg
# Distort both images and merge using common points.
magick \
\( box_spine.jpg -alpha set -virtual-pixel transparent \
+distort Perspective \
'0,0 -30,20 0,200 -30,179 40,200 0,200 40,0 0,0' \) \
\( box_front.jpg -alpha set -virtual-pixel transparent \
+distort Perspective \
'0,0 0,0 0,200 0,200 150,200 100,156 150,0 100,30' \) \
\
-background black -compose plus -layers merge +repage \
-bordercolor black -compose over -border 15x2 box_set.jpg
Perhatikan juga pemakaian komposisi alpha Plus untuk menyambung potongan yang 'bertemu di tepi'. Ini perlu supaya tidak muncul 'celah semitransparan' di antara kedua gambar. Untuk keterangan lebih lanjut lihat contoh kubus 3D dengan pelapisan afin di atas, serta menjajarkan dua gambar ter-mask. Memakai posisi seperti ini berarti hampir seluruh gambar 'punggung' sebenarnya terdistorsi ke posisi 'x' negatif. Gambar hasilnya karena itu punya offset negatif pada kanvas virtual. IM tidak bermasalah melakukan ini bila memakai versi pelapisan "+distort" dari operator tersebut. Operator Layers Merge juga dirancang untuk menangani pelapisan gambar dengan offset negatif, 'menjahit' kedua gambar menjadi satu dengan rapi. Saya tetap perlu memakai "+repage" di akhir untuk menghapus offset negatif itu dari gambar akhir, setelah keduanya di-'merge'. Kalau tidak, program lain seperti peramban web mungkin tidak memahami offset negatif semacam itu dan menimbulkan efek yang tak terdefinisi. Contoh di atas juga sudah dituangkan ke skrip shell "box_set_example " supaya dapat diunduh dan dijajal dengan lebih nyaman. Ini bisa dikembangkan lagi dengan menambahkan bayangan cermin 'kotak' itu pada permukaan tempatnya berdiri, walau Anda mungkin juga ingin mewarnai ulang atau meredupkan gambar cermin itu agar lebih realistis. Lihat Refleksi untuk teknik pencerminan semacam itu.
Contoh lanjutan dalam PHP dikembangkan pada sebuah diskusi tentang pembungkusan 'foto' ke rangka kanvas tanpa tepi. Lihat Canvas wrap transformation untuk rincian lebih lanjut.
Sebagai penutup, berikut contoh luar biasa dari Jean-François Hren untuk www.animecoversfan.com yang banyak dibahas di Forum Diskusi IM.
![[Diagram]](../static/img/img_diagrams/video_box_example.png)
Gambar ini dibuat dengan mengambil gambar artistik sampul kotak video anime, memecah sampul itu menjadi 3 segmen ('cover', 'spine', dan 'back'), mendistorsi masing-masing secara terpisah menjadi gambar berlapis, menambahkan gambar 'cakram' keempat, lalu menggabungkan semuanya. Gambar itu kemudian dirampungkan dengan penambahan sorotan dan efek bayangan (memakai komposisi gambar HardLight), serta penambahan tepi dan efek bayangan semitransparan (memakai CopyOpacity). Yang lebih mengagumkan, seluruh prosesnya dikerjakan oleh satu perintah "magick" saja, dari gambar-gambar masukannya. Ini contoh yang sangat bagus tentang apa yang bisa dilakukan IM, dan tentang bagaimana skrip perintah yang rumit dapat disusun. Saya menyarankan membaca diskusi forumnya karena berisi banyak petunjuk, kiat, dan teknik debug umum. (Contoh sumbangan lain sangat diterima)
Distorsi proyeksi perspektif (Perspective Projection)
Sebagaimana distorsi 'Affine' dapat ditangani langsung dengan memberikan koefisien matematisnya lewat 'AffineProjection', begitu pula 'Perspective' dapat ditangani lewat 8 koefisien distorsi 'Perspective Projection'. Seperti sebelumnya, angka-angka ini mewakili koefisien yang dipakai untuk pemetaan maju titik-titik pada gambar sumber ke gambar tujuan. Yakni, nilai matematis yang dipakai untuk memetakan x,y gambar sumber ke i,j gambar tujuan. Kedelapan argumen floating point tersebut adalah (dalam urutan berikut)... sx, ry, tx,
rx, sy, ty,
px, py
Nilai-nilai koefisien ini pada gilirannya membentuk ekspresi.. Xd = | sx*Xs + ry*Ys + tx | , | Yd = | rx*Xs + sy*Ys + ty |
|
px*Xs + py*Ys + 1.0 | px*Xs + py*Ys + 1.0
Di sini "Xs,Ys" adalah koordinat gambar sumber dan "Xd,Yd" koordinat gambar tujuan. Secara internal Distort ImageMagick akan membalik persamaan di atas supaya dapat melakukan pemetaan piksel terbalik yang sesuai, yaitu memetakan koordinat "Xd,Yd" untuk mencari warna pada "Xs,Ys" di gambar sumber. Enam nilai pertama 'Perspective Projection' sebenarnya koefisien yang sama dengan 'AffineProjection', hanya urutannya sedikit diubah agar lebih logis (dalam istilah 'matematika matriks', keenam elemen pertama ditransposisi secara diagonal). Dua argumen tambahan px,py membentuk pembagi penskalaan bagi keseluruhan distorsi, yang membuat gambar tampak lebih kecil pada arah tertentu sesuai nilai yang diberikan, sehingga gambar terdistorsi mendapat efek 'jarak' perspektif. Bila kedua nilai ini disetel nol, distorsi 'Perspective Projection' menjadi setara dengan 'Affine Projection'. Sebagai contoh... |
magick rose: -alpha set -virtual-pixel transparent \
-distort Perspective-Projection \
'1.40, 0.25, 3.0 0.15, 1.30, 0.0 0.007, 0.009' \
perspective_projection_rose.png
![[IM Output]](../static/img/distorts/perspective_projection_rose.png)
Ingat, matriks yang Anda berikan adalah matriks proyektif maju, yang memetakan koordinat gambar sumber ke koordinat gambar tujuan. Secara internal ImageMagick akan membalik matriks itu supaya dapat memetakan koordinat gambar tujuan ke koordinat gambar sumber. Bila ingin tahu nilainya, pakai opsi distorsi verbose agar IM mengeluarkan koefisien internalnya sebagai ekspresi operator FX (lihat berikutnya).
Internal Perspective
Bila "-verbose" (lihat ringkasan distorsi verbose di atas) ditambahkan tepat sebelum distorsi Perspective, IM akan mengeluarkan dua operator yang mestinya nyaris setara sebagai pengganti operator "-distort". Satu berupa versi "-fx" yang SANGAT LAMBAT (lihat operator DIY FX). Satunya lagi berupa matriks Perspective_Projection pemetaan maju. Sebagai contoh... |
magick rose: -alpha set -virtual-pixel transparent -verbose \
-distort Perspective "0,0,3,0 0,46,10,46 70,0,70,7 70,46,60,40" \
+verbose perspective_rose.png
![[IM Output]](../static/img/distorts/perspective_rose.png)
| ![[IM Text]](../static/img/distorts/perspective_verbose.txt.gif)
Bagian pertama, Perspective Projection , dapat dipakai untuk memetakan koordinat sumber ke koordinat tujuan. Rumusnya seperti di atas.
i = ( 1.430099*x +0.246650*y +3 )/( 0.006757*x + 0.009448*y +1 )
j = ( 0.147296*x +1.434591*y +0 )/( 0.006757*x + 0.009448*y +1 )
Contoh pengambilan dan pemakaian nilai-nilai ini diperlihatkan pada kumpulan contoh terakhir di Memosisikan gambar layer terdistorsi. Sebaliknya, bagian padanan FX yang kedua memakai kumpulan 8 koefisien yang berbeda, yang menjalankan pemetaan piksel terbalik yang sebenarnya diperlukan sebuah distorsi gambar. Yakni...
x = ( 0.711858*i -0.108326*j -2.135575 )/(-0.004119*i -0.005877*j +1 )
y = (-0.073090*i +0.699571*j +0.219269 )/(-0.004119*i -0.005877*j +1 )
Perhatikan bahwa pada rumus FX equivelent yang dikeluarkan, koefisien pembagi dipakai lebih dahulu karena dipakai bersama oleh persamaan koordinat X maupun Y. Ingat, semua koordinat yang Anda berikan adalah koordinat gambar, bukan koordinat piksel; lihat koordinat gambar vs koordinat piksel untuk rinciannya. Karena itu setiap posisi piksel perlu ditambah 0,5 pada koordinat piksel masukannya sebelum rumus di atas diterapkan, lalu dikurangi 0,5 dari koordinat akhirnya untuk mengubahnya kembali menjadi koordinat piksel (draw). Penerapannya terlihat pada kode FX equivalent di atas. Pengujian terakhir dalam padanan FX, tepat sebelum pencarian gambar sumber, menangani piksel 'langit' yang tidak valid, yaitu ketika tujuan gagal terpetakan dengan benar ke gambar sumber. Namun ia sekadar menyubstitusikan 'blue' untuk piksel semacam itu alih-alih "-mattecolor", dan tidak menyediakan anti-alias cakrawala seperti yang disediakan algoritma internal untuk distorsi perspektif.
Contoh pemetaan maju perspektif... Pemetaan ini memungkinkan sebuah koordinat tertentu pada satu gambar diubah menjadi lokasi pada gambar satunya (ke arah mana pun). Sebagai contoh, sebuah titik gelap di tengah gambar rose sumber berada pada koordinat piksel '39,20'. Petakan itu ke koordinat gambar dengan menambahkan ½ sehingga menjadi '39.5,20.5'. Sekarang persamaan x,y ke i,j dapat dipakai untuk memetakannya ke koordinat gambar tujuan '44.2,24.1'. Dan terakhir ke koordinat piksel 'draw' dengan mengurangi ½, sehingga posisi akhirnya '43.7,23.6'. Di sini saya menandai koordinat itu dengan lingkaran pada gambar masukan maupun keluaran..
magick rose: -fill none -stroke black \
-draw 'circle 39,20 39,24' rose_marked.png
magick perspective_rose.png -fill none -stroke black \
-draw 'circle 43.7,23.6 43.7,26.6' perspective_rose_marked.png
Seperti terlihat, titik yang sama pada gambar terdistorsi perspektif berhasil ditempatkan dengan benar di kedua gambar (bahkan sampai tingkat sub-piksel)!
Distorsi Bilinear
Metode distorsi 'Bilinear' mewujudkan jenis distorsi 4 titik yang lain. Namun yang ini sama sekali tidak selugas distorsi 'Perspective' yang kita lihat di atas. Tetapi, seperti akan terlihat, ia distorsi alternatif yang sangat berguna.
Distorsi Bilinear maju
Sebagai contoh, mari kita ambil gambar uji khusus seekor mandrill yang di atasnya sudah dihamparkan kisi, lalu kita distorsi dengan perspective dan bilinear.
magick mandrill_grid.jpg -alpha set -virtual-pixel black \
-distort Perspective \
'0,0 26,0 128,0 114,23 128,128 128,100 0,128 0,123' \
mandrill_pers.jpg
magick mandrill_grid.jpg -alpha set -virtual-pixel black -interpolate Spline \
-distort BilinearForward \
'0,0 26,0 128,0 114,23 128,128 128,100 0,128 0,123' \
mandrill_blin.jpg
![[IM Output]](../static/img/img_photos/mandrill_grid.jpg)
Asli | | ![[IM Output]](../static/img/distorts/mandrill_pers.jpg)
Perspective | ![[IM Output]](../static/img/distorts/mandrill_blin.jpg)
Bilinear
Pertama-tama perhatikan bahwa kedua distorsi sama-sama memetakan gambar dengan benar dari satu kumpulan titik kontrol ke kumpulan titik yang lain. Semua garis horizontal dan vertikal pada gambar sumber pun tetap lurus pada kedua distorsi. Namun kemiripannya berhenti di situ. Perspective akan mengurangi jarak antargaris sehingga garis diagonalnya pun tetap lurus. Akibatnya luas setiap persegi mengecil, sehingga sudut kanan atas mendapat tampilan 'jauh di kejauhan' yang realistis. Bilinear sebaliknya tidak membuat satu sisi gambar tampak 'lebih jauh', dan juga tidak berusaha menjaga garis tetap lurus. Yang diusahakannya adalah menjaga semua jarak antargaris tetap sama, tetapi akibatnya garis diagonal jadi melengkung. Artinya, ia mempertahankan rasio jarak di sepanjang garis mana pun. Yakni, panjang relatif setiap ruas garis tetap sama di seluruh panjang garis itu, meskipun garisnya sendiri mungkin bengkok, melengkung, atau memendek secara keseluruhan. Itu berarti jarak kisi pada contoh di atas tetap berskala sama di seluruh gambar, dan persegi terdistorsi di kanan atas kurang lebih masih sebesar persegi terdistorsi di kiri bawah. Gambarnya tetap 'tampak datar', hanya terdistorsi menjadi bentuk lain. Perhatikan bahwa bilinear (maju) memang menjamin garis horizontal atau vertikal mana pun pada gambar asli akan tetap lurus pada gambar akhir. Yakni, ia mengambil persegi panjang yang sejajar sumbu dan mentransformasikannya menjadi segi empat yang ditentukan, sehingga tiap sisi persegi panjang aslinya tetap lurus dengan penskalaan tetap di sepanjang garis. Aspek inilah yang membuat distorsi 'BilinearForward' berguna pada distorsi 'kisi' yang jauh lebih rumit. Sebabnya, dua 'segi empat' yang bertetangga, meski terdistorsi dengan sangat berbeda, tetap akan berjajar dengan benar tepi ke tepi. Berikut perbandingan lain antara 'Perspective' dan 'BilinearForward', memakai distorsi yang sangat ekstrem pada gambar rose bawaan...
magick rose: -alpha set -virtual-pixel transparent \
-distort Perspective "0,0,3,0 0,46,10,46 70,0,70,7 70,46,60,40" \
perspective_rose.png
magick rose: -alpha set -virtual-pixel transparent -interpolate Spline \
-distort BilinearForward "0,0,3,0 0,46,10,46 70,0,70,7 70,46,60,40" \
bilinear_rose.png
![[IM Output]](../static/img/images/rose.png)
Asli | | ![[IM Output]](../static/img/distorts/perspective_rose.png)
Perspective | ![[IM Output]](../static/img/distorts/bilinear_rose.png)
Bilinear
Demi mencapai tujuannya (mempertahankan semua garis lurus), distorsi Perspective seolah 'menyedot' hampir seluruh gambar ke area yang lebih kecil di sebelah kanan, sedangkan distorsi Bilinear menjaga rose yang terletak di tengah tetap di tengah pada hasilnya. Sekali lagi ia mempertahankan rasio jarak, menjaga rose tetap berjarak sama dari tepi kiri dan kanan. Yang dilakukannya hanyalah menekan tinggi gambar secara vertikal, secara linear di sepanjang panjangnya. Aspek distorsi 'BilinearForward' inilah yang membuatnya dikenal juga sebagai distorsi 'Trapezoidal'. Yakni, sekadar menekan gambar secara linear ke satu arah, ketika hanya satu arah yang diskalakan. Arah penekanan itu bahkan bisa miring, tidak harus sejajar salah satu sumbu. | _Perhatikan bahwa karena rumitnya pemetaan piksel terbalik yang diperlukan untuk menjalankan distorsi 'BilinearForward', resampling area saat ini dimatikan.
Karena itu area dengan kompresi ekstrem (lebih dari faktor 2) kemungkinan besar akan memperlihatkan efek aliasing (lihat tepi garis pada contoh di atas). Namun super-sampling atau '-interpolate Spline' dapat dipakai untuk memperbaiki kualitas gambar akhir.
| _Sebelum IM v6.5.7-0 distorsi 'BilinearForward' masih dalam pengembangan dan bermasalah pada kasus 'degenerate' tertentu, yang dalam situasi tertentu bisa menghasilkan gambar error 'hitam'.
Distorsi Bilinear terbalik
Karena hanya garis horizontal dan vertikal yang tetap lurus, distorsi 'BilinearForward tidak bisa dipakai untuk membalik distorsinya. Karena garis kisi pada gambar hasil transformasi tidak lagi horizontal atau vertikal, garis-garis itu tidak akan tetap lurus pada gambar hasilnya! Sebagai contoh, menukar pasangan koordinat lalu menerapkan ulang distorsi 'maju' (seperti yang kita lakukan dengan distorsi 'Perspective' di atas) tidak akan berhasil memulihkan gambar aslinya.
magick mandrill_blin.jpg -alpha set -virtual-pixel black \
-distort BilinearForward \
'26,0 0,0 114,23 128,0 128,100 128,128 0,123 0,128' \
mandrill_blin_back.jpg
Perhatikan bahwa koordinat yang ditentukan memang menempatkan dirinya dengan benar, tetapi distorsi gambarnya tidak terbalik. Ringkasnya, distorsi 'BilinearForward' BUKAN kebalikan dirinya sendiri. Untuk memulihkan gambarnya Anda perlu memakai distorsi yang sedikit berbeda tetapi berkerabat dekat. Kebalikan matematis dari 'transformasi geometris' itu diwujudkan sebagai distorsi 'BilinearReverse'. Sebagai contoh...
magick mandrill_blin.jpg -alpha set -virtual-pixel black \
-distort BilinearReverse \
'26,0 0,0 114,23 128,0 128,100 128,128 0,123 0,128' \
mandrill_blin_rev.jpg
| Seperti sudah disebutkan, karena rumitnya distorsi 'BilinearForward', resampling area saat ini dimatikan, sehingga pada contoh di atas muncul efek aliasing yang parah.
'BilinearReverse' punya sifat mempertahankan rasio jarak yang sama seperti 'BilinearFoward', tetapi ia akan mengubah segi empat apa pun menjadi persegi panjang yang sejajar sumbu, memastikan sisi-sisi segi empat itu tetap lurus ketika dipetakan ke penjajaran vertikal dan horizontal. Seperti terlihat di atas. | Sebelum IM v6.5.1-2 distorsi 'BilinearReverse' diwujudkan begitu saja sebagai 'Bilinear'.
Sebagian implementasi distorsi bilinear (termasuk IM versi lama dan pustaka Leptonica) hanya mewujudkan versi distorsi Bilinear yang lebih sederhana (terbalik) di atas. Namun distorsi semacam itu kurang cocok untuk 'pemetaan maju' sebuah gambar persegi panjang. Sebagai contoh, di sini saya mencoba memakai 'BilinearReverse' untuk distorsi yang semestinya memakai 'BilinearForward'.
magick mandrill_grid.jpg -alpha set -virtual-pixel black \
-distort BilinearReverse \
'0,0 26,0 128,0 114,23 128,128 128,100 0,128 0,123' \
mandrill_blin_rev2.jpg
Seperti terlihat, karena segi empat tujuannya bukan persegi panjang yang sejajar sumbu, gambarnya terdistorsi parah dan menghasilkan banyak garis yang melengkung ke dalam.
Distorsi Bilinear yang di-tile
Nah, 'BilinearReverse' memang menghasilkan gambar 'melengkung' dari gambar persegi panjang. Efek itu menghasilkan pola tile menarik yang seolah membentuk permukaan lengkung berkesan 3 dimensi. Sebagai contoh, dengan menerapkan transformasi yang sama seperti pada memandang cakrawala jauh di atas, kita mendapat hasil menarik ini. |
magick checks.png -virtual-pixel tile -mattecolor DodgerBlue \
-distort BilinearReverse \
'0,0 20,60 90,0 70,63 0,90 5,83 90,90 85,88' \
bilinear_rev_tile.png
![[IM Output]](../static/img/distorts/bilinear_rev_tile.png)
Sebenarnya 'BilinearReverse' tidak akan pernah menghasilkan 'cakrawala' (piksel tidak valid). Sebaliknya, 'BilinearForward' cenderung cukup sering menghasilkan 'langit' atau 'piksel tidak valid' (diisi dengan "-mattecolor" saat itu). Malah pola tile-nya cenderung jadi kacau... |
magick checks.png -virtual-pixel tile -mattecolor DodgerBlue \
-interpolate Spline -distort BilinearForward \
'0,0 20,60 90,0 70,63 0,90 5,83 90,90 85,88' \
bilinear_fwd_tile.png
![[IM Output]](../static/img/distorts/bilinear_fwd_tile.png)
| Seperti sudah disebutkan, karena rumitnya distorsi 'BilinearForward', resampling area saat ini dimatikan, sehingga pada contoh di atas muncul efek aliasing yang parah.
Karena itu saya tidak menyarankan pemakaian bentuk yang di-tile dari 'BilinearForward'. Tetapi saya menyarankan Anda menetapkan "-mattecolor" yang sesuai ketika memakai distorsi maju, supaya tidak muncul bercak 'langit' abu-abu yang tak terduga.
Internal Bilinear
Rumus sebenarnya untuk memetakan sebuah koordinat pada gambar sumber ke gambar tujuan memakai 'distorsi Bilinear pemetaan maju adalah... Xd = |
C0*Xs + C1*Ys + C2*Xs*Ys + C3 |
, | Yd = |
C4*Xs + C5*Ys + C6*Xs*Ys + C7 |
|---|---|---|---|---|
| Namun karena IM mewujudkan distorsi memakai teknik pemetaan piksel terbalik, rumus di atas perlu dibalik. Prosesnya rumit dan menuntut penyelesaian persamaan kuadrat, akar kuadrat, serta aljabar sepanjang satu halaman penuh. Bila IM diminta mengeluarkan padanan FX secara verbose, kerumitan itu akan terlihat. Sebagai contoh, memakai gambar checks yang kita buat sebelumnya... |
magick checks.png -alpha set -virtual-pixel transparent -mattecolor none \
-interpolate Spline -verbose -distort BilinearForward \
'0,0,0,0 0,90,0,90 90,0,60,30 90,90,90,90' \
+verbose bilinear_checks.png
![[IM Output]](../static/img/distorts/bilinear_checks.png)
| ![[IM Text]](../static/img/distorts/bilinear_verbose.txt.gif)
Pemeriksaan '(rt > 0 ) ? red :' pada baris terakhir 'FX equivalent ' berfungsi menghindari akar kuadrat negatif yang tidak valid. Pemeriksaan inilah yang menciptakan efek 'langit' yang terlihat pada contoh-contoh sebelumnya. Sebaliknya, karena distorsi Bilinear terbalik jauh lebih sederhana, persamaan polinomial yang lebih sederhana dapat diterapkan langsung untuk membalik distorsi sebelumnya... |
magick bilinear_checks.png -virtual-pixel transparent \
-verbose -distort BilinearReverse \
'0,0,0,0 0,90,0,90 60,30,90,0 90,90,90,90' \
+verbose bilinear_checks_rev.png
| Seperti terlihat, persamaan hasilnya sangat sederhana, karena kita kini menerapkannya untuk melakukan pemetaan piksel terbalik dari koordinat tujuan ke koordinat gambar sumber. | Efek aliasing yang terlihat di atas disebabkan oleh 'BilinearForward', bukan oleh distort 'BilinearReverse'. Sebabnya, saat ini resampling area dimatikan untuk versi pemetaan 'maju' karena kerumitannya. |
|---|---|
| Untuk bacaan lebih lanjut saya arahkan Anda ke Leptonica Affine and Perspective Transforms. |
Distorsi Bilinear gabungan
Sedang dikerjakan
Kedua metode distorsi Bilinear bersama-sama memungkinkan Anda mendistorsi SEMBARANG segi empat langsung menjadi segi empat lain, sambil menjaga sisi-sisinya tetap lurus. Pada dasarnya Anda dapat lebih dulu mendistorsi satu segi empat menjadi gambar persegi panjang dengan 'Reverse', lalu mendistorsi persegi panjang itu menjadi segi empat akhir dengan 'Forward'. Jenis distorsi ini juga berarti Anda dapat mengambil sembarang kisi koordinat persegi panjang dan mendistorsinya ke kisi koordinat persegi panjang lain. Ini dikenal sebagai distorsi 'Grid'. Teknik ini adalah landasan utama Image Morphing: Anda mendefinisikan kisi garis persegi panjang di atas dua gambar lalu memakainya untuk menggabungkan kedua gambar menjadi komposit antara, atau bahkan menghasilkan animasi yang benar-benar mengubah bentuk satu gambar menjadi gambar lain. Namun ini belum diwujudkan, meski sudah direncanakan sebagai tambahan.
Distorsi Polynomial (distorsi memakai kecocokan polinomial)
Seperti kebanyakan metode distorsi sebelumnya, distorsi 'Polynomial' juga memetakan pasangan titik kontrol, tetapi memakai persamaan polinomial standar. Artinya diperlukan satu argumen tambahan sebelum titik kontrol diberikan.
Order X1,Y1 I1,J1 X2,Y2 I2,J2 X3,Y3 I3,J3 X4,Y4 I4,J4 . . . .
Argumen 'Order ' biasanya bilangan bulat mulai dari '1', meski nilai khusus '1.5' juga dapat dipakai. Argumen ini menentukan 'orde' atau kerumitan persamaan matematis 2 dimensi (memakai 'x' dan 'y' sekaligus) yang akan diterapkan. Sebagai contoh, polinomial orde '1' akan mencocokkan persamaan berbentuk... Xd = | C2x*Xs + C1x*Ys + C0x | , | Yd = | C2y*Xs + C1y*Ys + C0y |
Kalau dibandingkan dengan persamaan yang dipakai untuk AffineProjection, terlihat bahwa keduanya setara. Karena diperlukan 3 konstanta untuk masing-masing rumus X dan Y, Anda juga perlu memberikan setidaknya 3 pasang koordinat X,Y. Lebih dari itu akan membuat persamaannya dicocokkan ke koordinat yang diberikan dengan kuadrat terkecil. 'Orde' berikutnya, '1.5', setara dengan 'BilinearReverse' (ingat, persamaannya dipakai untuk memetakan koordinat tujuan ke gambar sumber). Xd = | C3x*Xs*Ys + C2x*Xs + C1x*Ys + C0x | , | Yd = | C3x*Xs*Ys + C2y*Xs + C1y*Ys + C0y |
Sama seperti distorsi 'BilinearReverse', ia memerlukan minimal 4 koordinat. Sebagai contoh... Pada dasarnya ini persis sama dengan persamaan orde '1' tetapi dengan 1 suku tambahan pada persamaan polinomialnya. Yakni, karena tiap persamaan kini punya 4 suku per sumbu dengan 4 konstanta, Anda perlu setidaknya 4 pasang koordinat supaya IM dapat menentukan konstanta-konstanta itu.
magick mandrill_grid.jpg -alpha set -virtual-pixel black \
-distort Polynomial \
'1.5 0,0 26,0 128,0 114,23 128,128 128,100 0,128 0,123' \
mandrill_poly_1.5.jpg
Dengan orde '2' persamaan polinomialnya diperluas lagi menjadi kecocokan kuadratik penuh, yang menuntut minimal 6 pasang koordinat. Xd = |
C5x*Xs2 + C4x*Xs*Ys + C3x*Ys2 + C2x*Xs + C1x*Ys + C0x |
|---|---|
Yd = |
C5y*Xs2 + C4y*Xs*Ys + C3y*Ys2 + C2y*Xs + C1y*Ys + C0y |
Pada dasarnya ini persis sama dengan persamaan orde '1' tetapi dengan 3 suku tambahan (orde 2 + 1) yang disisipkan di depan persamaan polinomialnya. Yakni, karena tiap persamaan kini punya 6 suku dengan 6 konstanta, Anda perlu setidaknya 6 koordinat supaya IM dapat menentukan konstanta-konstanta itu. Setiap orde polinomial berikutnya menambahkan lagi 'order'+1 suku ke masing-masing dari pasangan persamaan tersebut. Karena itu polinomial kecocokan kubik orde '3' memerlukan minimal 10 pasang koordinat untuk terdefinisi penuh, dan polinomial kecocokan kuintik orde '4' memerlukan 15 pasang koordinat. Anda dapat memakai ringkasan distorsi verbose untuk melihat persamaan hasil yang dicocokkan distorsi polinomial ke koordinat yang ditentukan. Sebagai contoh yang lebih besar, saya punya sebuah gambar kisi. Saya juga punya kumpulan koordinat yang besar (disimpan dalam file "grid16_control_points.txt") berisi cara saya ingin melengkungkan kisi itu. Lalu saya meminta IM menghasilkan polinomial kubik untuk 'best-fit' koordinat masukan tersebut. |
# warp image
magick grid16.png -virtual-pixel gray \
-distort polynomial "3 $(cat grid16_control_points.txt)" \
grid16_polynomial.png
# reverse image coordinate order
awk '{print $3, $4, $1, $2}' grid16_control_points.txt \
> grid16_cp_inverse.txt
# warp image back again
magick grid16_polynomial.png -virtual-pixel gray \
-distort polynomial "3 $(cat grid16_cp_inverse.txt)" \
grid16_restored.png
Skrip "awk" kecil itu mengambil kumpulan pasangan titik kontrol X,Y yang asli dan membalik urutannya, sehingga file barunya dapat kita pakai untuk mencoba 'membatalkan' distorsinya. | _Koordinat dalam file titik kontrol "grid16_control_points.txt" adalah koordinat gambar, artinya tiap angka merujuk ke pusat piksel yang dimaksud. Tanpa tambahan 0,5, nilainya akan menjadi 'koordinat piksel' bilangan bulat. Lihat koordinat gambar vs koordinat piksel di atas.
Nilai-nilai itu ditentukan murni dengan pembacaan manual memakai penampil gambar, jadi sebenarnya tidak terlalu tepat. Ini mungkin menjadi salah satu sumber artefak pada distorsi baliknya, meski 'best-fit' fungsional dari persamaan polinomial semestinya sudah mengurangi efek distorsi keseluruhan.
Ini menunjukkan bahwa meski distorsi polinomial bekerja, dan bekerja dengan baik, ia bukan distorsi yang eksak atau dapat dibalik. Pada dasarnya ke-81 koordinat itu 'dirata-ratakan' bersama untuk menghasilkan 'best-fit' matematis dari koordinat masukan. Karena titik kontrol yang diberikan (81) lebih banyak daripada jumlah minimum yang diperlukan (10), tidak ada satu pun titik kontrol yang dijamin persis cocok dengan koordinat yang diminta. Namun untuk contoh khusus ini, ketika koordinatnya sudah dekat dengan hasil distorsi yang diharapkan, hasilnya semestinya cukup mendekati. Fungsi polinomial umumnya paling banyak keliru di sepanjang tepi, terutama di sudut-sudut gambar. Ini tidak hanya memengaruhi lokasi piksel, tetapi juga area sampling (EWA) di tepi. Ini akibat wajar dari hampiran yang dipakai. Polinomial orde lebih tinggi bisa saja dipakai, tetapi dalam kasus ini tidak memberi perbaikan berarti. Untuk kasus khusus ini, polinomialnya sebenarnya sedang berusaha mencocokkan diri dengan fungsi trigonometri yang bukan polinomial. Karena sifat fungsi-fungsi itu, distorsi kedua akan lebih tidak akurat daripada yang pertama. Contoh ini sebenarnya berkerabat sangat dekat dengan metode radial distorsi Barrel yang akan kita lihat di bawah. Perhatikan pula bahwa koordinat yang dipetakan sebenarnya tidak harus tersusun dalam kisi, melainkan boleh berupa sembarang kumpulan pemetaan koordinat. Karena itu teknik ini sering dipakai para geograf untuk menjajarkan (dan menghamparkan) foto udara dengan peta geofisika, memakai lokasi kota, persimpangan jalan, puncak gunung, dan penanda lain yang sudah diketahui sebagai titik kontrol. | _Karena distorsi Polynomial umumnya tidak dapat dibalik, IM tidak mungkin menghitung 'best-fit' viewport gambar tujuan untuk gambar sumber yang diberikan. Karena itu bentuk "+distort" dari operator ini tidak bekerja, dan mundur ke operasi "-distort" biasa. Namun Anda tetap dapat memakai opsi viewport distort untuk menetapkan viewport gambar tujuan.
Metode distorsi melingkar dan radial
Ini distorsi yang melibatkan pemakaian vektor radial sebagai komponen utama proses distorsinya.
Distorsi Arc (melengkungkan gambar menjadi busur lingkaran)
Distorsi 'Arc' (sejak IM v6.3.5-5) adalah variasi sederhana dari distorsi polar yang jauh lebih rumit (lihat di bawah). Secara bawaan ia akan melengkungkan gambar yang diberikan menjadi busur lingkaran sempurna sepanjang sudut yang ditentukan, dan tanpa argumen lain ia akan berusaha sebisa mungkin mempertahankan skala garis tengah horizontal gambar sekaligus rasio aspeknya. Untuk itu ia menerima sampai empat argumen.
_arc_angle rotate_angle top_radius bottom_radius_
Namun hanya "_arc_angle_" yang wajib; argumen lainnya opsional dan dapat ditambahkan sesuai kebutuhan, dalam urutan yang diberikan. Sebagai contoh, 'Arc' sebuah gambar sepanjang sudut 60 derajat... |
magick rose: -virtual-pixel White -distort Arc 60 arc_rose.jpg
![[IM Output]](../static/img/distorts/arc_rose.jpg)
| _Perhatikan bahwa tidak seperti operator distorsi gambar lain, distort 'Arc' selalu menetapkan ukuran gambar hasil sedemikian rupa sehingga seluruh gambar sumber tercakup. Termasuk piksel tepi hasil anti-alias. Karena itu gambar hasilnya jarang sekali seukuran gambar masukan.
Hanya opsi viewport distort yang memungkinkan Anda mengubah ukuran gambar hasil untuk distorsi tertentu._
Menambahkan argumen kedua "_rotate_agle_" memungkinkan gambar diputar mengelilingi lingkaran. Misalnya memutarnya 90 derajat. |
magick rose: -virtual-pixel White -distort Arc '60 90' arc_rose_rot.jpg
![[IM Output]](../static/img/distorts/arc_rose_rot.jpg)
Karena tidak ada argumen radius yang disebutkan, metode distorsi 'Arc' berupaya keras memastikan skala gambar asli dipertahankan sebisa mungkin. Untuk itu garis tengah horizontal gambar disetel ke 'radius ideal' bagi lebar dan "_arc_angle_" gambar sumber yang diberikan. Artinya, bila gambar di-arc sepanjang "_arc_angle_" yang lebih besar, radius garis tengah yang dipakai juga mengecil dengan faktor yang sama. Radius garis tengahnya pun menjadi lebih kecil dan lebih rapat. |
magick rose: -virtual-pixel White -distort Arc 120 arc_rose_3.jpg
![[IM Output]](../static/img/distorts/arc_rose_3.jpg)
Perhatikan gambarnya kini muat dalam lingkaran yang lebih kecil, tetapi tepi bawah gambar berupa lingkaran yang lebih kecil lagi! Bila sudut untuk meng-arc gambar disetel lebih besar lagi, tepi bawahnya akan mengenai pusat distorsi bahkan melewatinya, sehingga bagian bawah gambar sumber lenyap sama sekali.
magick rose: -virtual-pixel White -distort Arc 60 arc_rose_1.jpg
magick rose: -virtual-pixel White -distort Arc 90 arc_rose_2.jpg
magick rose: -virtual-pixel White -distort Arc 120 arc_rose_3.jpg
magick rose: -virtual-pixel White -distort Arc 180 arc_rose_4.jpg
magick rose: -virtual-pixel White -distort Arc 240 arc_rose_5.jpg
magick rose: -virtual-pixel White -distort Arc 300 arc_rose_6.jpg
magick rose: -virtual-pixel White -distort Arc 360 arc_rose_7.jpg
Arc menjadi cincin lingkaran penuh
Gambar yang lebih panjang akan jauh lebih baik hasil distorsi 'Arc'-nya pada sudut yang sangat besar. Misalnya, gambar panjang (seperti pesan teks) dapat dibungkus menjadi cincin. Dan supaya benar-benar terlihat apa yang terjadi di sini, saya menyetel warna latar belakang piksel virtual yang berbeda, sehingga batas gambar aslinya kelihatan.
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel Background -background SkyBlue \
-distort Arc 60 arc_circle_1.jpg
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel Background -background SkyBlue \
-distort Arc 120 arc_circle_2.jpg
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel Background -background SkyBlue \
-distort Arc 180 arc_circle_3.jpg
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel Background -background SkyBlue \
-distort Arc 270 arc_circle_4.jpg
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel Background -background SkyBlue \
-distort Arc 360 arc_circle_5.jpg
Dan taraa, gambar label itu sudah kita 'arc' menjadi lingkaran penuh. Bila diperhatikan dari dekat, pada sambungan gambar lingkaran penuh itu mungkin terlihat segaris kecil piksel tempat sambungannya kurang rapat. Ini disebabkan oleh efek latar belakang piksel virtual 'SkyBlue' di sekelilingnya, karena pada dasarnya kita sedang menyambung dua tepi sebuah gambar. Ketika menghasilkan lingkaran penuh, perlu dipakai metode piksel virtual yang akan 'menyambung' kedua tepi itu dengan benar. Umumnya ini dilakukan dengan salah satu metode piksel virtual tiling, seperti Tile. |
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel Tile -background SkyBlue \
-distort Arc 360 arc_circle_tile.jpg
![[IM Output]](../static/img/distorts/arc_circle_tile.jpg)
Sayangnya, seperti terlihat, cara ini tidak hanya menyambung gambar dengan benar, tetapi juga menghasilkan garis-garis gambar yang berulang masuk dan keluar dari cincin utama. Kurang bagus. Sejak IM v6.4.2-6 metode piksel virtual baru, HorizontalTile, memecahkan masalah ini. Metode ini men-tile gambar ke samping saja, sehingga sambungan gambar lingkaran kita bagus, sementara area di atas dan di bawah tile diisi warna latar belakang saat itu, menghasilkan lingkaran teks yang sempurna. |
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel HorizontalTile -background SkyBlue \
-distort Arc 360 arc_circle.jpg
![[IM Output]](../static/img/distorts/arc_circle.jpg)
Bila sebelum meng-'arc' sebuah gambar Anda memutar gambar masukannya menjadi terbalik, 'atas' gambar aslinya dapat ditempatkan pada tepi dalam lingkaran. Tentu Anda mungkin ingin 'memutar' hasilnya kembali tegak setelah itu, tetapi kemampuan itu sudah tertanam dalam metode distorsi 'Arc'. |
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel Background -background SkyBlue \
-rotate 180 -distort Arc '270 180' arc_flip.jpg
![[IM Output]](../static/img/distorts/arc_flip.jpg)
Argumen ketiga "_top_radius_" akan menimpa radius garis tengah 'ideal' yang dihitung, sehingga bagian atas gambar menjadi lingkaran dengan radius yang diberikan. Ini menghasilkan cincin selebar 100 piksel, meski gambar penampungnya selebar 102 piksel untuk memberi ruang bagi efek anti-alias. |
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel HorizontalTile -background SkyBlue \
-distort Arc '360 0 50' arc_radius.jpg
![[IM Output]](../static/img/distorts/arc_radius.jpg)
Gambarnya tetap dengan rasio aspek yang sama, jadi contoh di atas pada dasarnya sama seperti sebelumnya, hanya diskalakan agar pas dengan lingkaran beradius yang diminta. Ingat, radiusnya boleh berupa bilangan floating point, tetapi pusat sebuah arc selalu dijajarkan ke 'sudut' piksel, sehingga lebar gambar hasilnya tetap berupa bilangan piksel genap. Bila Anda memberikan argumen keempat "_bottom_radius_", kendali atas lebar cincin, atau 'tinggi radial'-nya, menjadi penuh. |
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel HorizontalTile -background SkyBlue \
-distort Arc '360 0 45 30' arc_inner.jpg
![[IM Output]](../static/img/distorts/arc_inner.jpg)
Ini akan mendistorsi penskalaan radial gambar, dan pada praktiknya memisahkan penskalaan radial dari 'lebar arc' atau sudut gambar hasilnya. Dengan kata lain rasio aspek gambar asli tidak lagi dipertahankan. Anda bahkan bisa memaksanya mengisi penuh bagian dalam lingkaran, membungkus tepi bawah gambar masukan di pusat, atau 'kutub' distorsinya. |
magick -font Candice -pointsize 20 label:' Around the World ' \
-virtual-pixel HorizontalTile -background SkyBlue \
-distort Arc '360 0 45 0' arc_fill.jpg
Contoh distorsi Arc
Efek menarik dapat dihasilkan dengan distorsi Arc, misalnya meng-arc pola papan catur yang agak panjang menjadi cincin (memakai pengaturan piksel virtual 'HorizontalTile' menghasilkan... |
magick -size 210x30 pattern:checkerboard -alpha set \
-virtual-pixel HorizontalTile -background SkyBlue \
-distort Arc 360 arc_checks.png
![[IM Output]](../static/img/distorts/arc_checks.png)
Dengan memakai pengaturan piksel virtual bawaan, yaitu 'Edge', efek yang lebih menarik dapat dihasilkan. |
magick -size 210x30 pattern:checkerboard -virtual-pixel Edge \
-distort Arc 360 arc_checks_edge.png
![[IM Output]](../static/img/distorts/arc_checks_edge.png)
Tentu pengaturan 'Tile' juga menghasilkan efek 'radial' yang menarik, sehingga Anda bisa membuat pola papan catur melingkar. |
magick -size 210x30 pattern:checkerboard -virtual-pixel Tile \
-distort Arc 360 arc_checks_tile.png
![[IM Output]](../static/img/distorts/arc_checks_tile.png)
Contoh di atas dapat diperhalus lagi dengan mengendalikan radius atas dan bawah gambar hasilnya. Berikut beberapa contoh distort 'Arc' lainnya, tetapi silakan Anda utak-atik sendiri untuk mengetahui cara kerjanya. Apa yang bisa Anda hasilkan? |
magick -size 90x1 pattern:gray50 -scale 900x100 -normalize \
-virtual-pixel Tile -set option:distort:viewport 100x100-50-50 \
-distort Arc 360 +repage arc_radii.gif
magick -size 400x100 pattern:hs_diagcross \
-virtual-pixel Tile -set option:distort:viewport 100x100-50-50 \
-distort Arc '360 0 80 0' +repage arc_cross.gif
magick -size 360x80 xc: -draw "fill none stroke black line 0,5 360,80" \
-virtual-pixel White -distort Arc '360 0 50 0' arc_spiral.gif
magick tree.gif -set option:distort:viewport 120x60-60-60 \
-virtual-pixel Dither +distort Arc '180 0 25 0' \
+repage arc_rays.gif
![[IM Output]](../static/img/distorts/arc_rays.gif)
'Sinar' pada contoh terakhir ini adalah produk sampingan dari pengaturan piksel virtual semiacak 'Dither', yang menghasilkan pola piksel ganjil berwarna 'matahari' dari sudut kiri atas gambar asli. Efek dithering yang sama juga menghasilkan garis melingkar berupa 'garis putus-putus' yang mengelilingi gambar 'pohon'. Versi efek ini yang serupa dan lebih terkendali dapat dicapai dengan pengaturan 'Edge' pada gambar yang sudah dimodifikasi agar punya piksel tepi yang menarik.
Penempatan titik pusat Arc
Secara bawaan 'Arc' sama sekali mengabaikan offset kanvas virtual yang mungkin dimiliki gambar, bahkan tidak melaporkan lokasi 'pusat' tempat gambar itu di-arc. Padahal mengetahui lokasi 'titik pusat' bisa sangat berguna. Bila alih-alih "-distort" Anda memakai bentuk plus khusus "+distort", gambarnya akan diberi kanvas virtual sehingga pusat itu terletak di titik asal kanvas virtual. Dengan kata lain titik '0,0' gambar disetel menjadi 'pusat' arc. Ini terutama berguna untuk memosisikan gambar ber-arc dengan sudut yang lebih kecil daripada lingkaran penuh, ketika 'pusat' arc bukan pusat gambar. Sebagai contoh... |
magick logo: -resize x150 -gravity NorthEast -crop 100x100+10+0! \
\( -background none label:'IM Examples' \
-virtual-pixel Background +distort Arc '270 50 20' \
-repage +75+21\! \) -flatten arc_overlay.jpg
![[IM Output]](../static/img/distorts/arc_overlay.jpg)
Di sini saya membuat label teks lalu mendistorsinya dengan 'Arc' menjadi lingkaran tak penuh memakai bentuk plus "+distort" dari operator tersebut. 'Pusat' arc-nya dijaga IM dengan cermat lewat offset kanvas virtual gambar. Artinya, cukup dengan penyesuaian relatif atas offset itu memakai "-repage" berikut flag '!', lingkaran teks hasilnya dapat kita tempatkan di mana pun kita mau! Misalnya di ujung topi penyihir, yang pada contoh di atas terletak di koordinat piksel 75,21. Sayangnya, karena offset virtual dipakai untuk memposisikan gambar, penempatan persisnya terbatas pada ukuran piksel bilangan bulat. Anda tidak dapat menempatkan distorsi Arc ke lokasi sub-piksel tanpa melakukan distorsi kedua. Namun hal itu dapat dilakukan pada distorsi Polar (lihat berikutnya).
Distorsi Polar (distorsi lingkaran penuh)
Distort 'Polar' (ditambahkan pada IM v6.4.2-6) adalah versi yang lebih rendah tingkatannya dari distorsi 'Arc' di atas. Tetapi ia tidak otomatis melakukan 'bestfit', dan juga tidak berusaha mempertahankan rasio aspek gambar. Keenam argumen floating point opsionalnya adalah... Radius_Max Radius_Min Center_X,Center_Y Start_Angle,End_Angle
Semua argumen bersifat opsional pada posisinya yang dipisah spasi. Secara bawaan 'CenterX,Y ' akan mengambil titik paling tengah dari area gambar masukan. Lalu gambar polar lingkaran penuh dihasilkan sedemikian rupa sehingga seluruh tepi atas menjadi pusatnya, sementara tepi bawah dibungkus penuh mengelilingi bagian luar lingkaran. Tepi kiri dan kanan akan bertemu di atas titik pusat pada sudut '-180' sampai '+180'. Karena 'Radius_Max ' wajib diberikan, nilainya harus positif. Namun bila diberi nilai '0', nilainya akan disetel ke jarak antara pusat dan tepi terdekat, sehingga bila nilai lain tidak diberikan (bawaan), seluruh gambar masukan dipetakan ke sebuah lingkaran di tengah gambar. Sebagai contoh, mari kita ubah peta dunia menjadi pandangan polar, memakai semua nilai bawaan. Tentu Anda sebaiknya menentukan pengaturan piksel virtual 'HorizontalTile' ketika menghasilkan pemetaan polar lingkaran penuh...
magick worldmap_sm.jpg -virtual-pixel HorizontalTile \
-background Black -distort Polar 0 polar_arctic.jpg
Tentu saja ini mendistorsi belahan bumi selatan dengan parah, membungkus Antartika penuh mengelilingi keliling 'diskworld'. Dengan memutar gambar sumber lalu memangkasnya agar hanya menampilkan tudung kutub, kita dapat menghasilkan peta Benua Antartika yang bagus. Saya juga menentukan radius keluaran yang lebih besar supaya lebih terlihat, dan meminta IM menyesuaikan ('fit') gambar keluaran ke ukuran itu memakai bentuk 'plus' dari operator distort. |
magick worldmap_md.jpg -rotate 180 -crop 100%x25%+0+0 +repage \
-virtual-pixel HorizontalTile -background Black \
+distort Polar 80 +repage polar_antarctica.jpg
![[IM Output]](../static/img/distorts/polar_antarctica.jpg)
Perlu dicatat bahwa yang di atas bukan pandangan bumi yang benar-benar tepat, karena peta kartesian adalah representasi sebuah bola, bukan gambar dalam koordinat polar. Bila dipakai nilai 'Radius_Max ' khusus persis '-1', radius gambar terdistorsi disetel ke jarak dari pusat ke sudut terjauh (diagonal). Ini untuk menyediakan 'kebalikan' yang ideal bagi distorsi 'DePolar' satu gambar penuh yang akan kita lihat berikutnya. (Lihat trik (De)Polar di bawah untuk contoh pemakaiannya). | Ingat, tidak seperti distorsi 'Arc', 'Polar' (dikenal juga sebagai distorsi 'Cartesian to Polar') sama sekali tidak berusaha mempertahankan rasio aspek 'ideal' gambar sumber. Sebaiknya berhati-hati.
Argumen 'CenterX,Y ' paling berguna untuk memposisikan pusat gambar hasil pada offset sub-piksel. Yakni, apakah pusatnya berada di batas piksel (bilangan bulat) atau di tengah piksel (dengan offset 0,5). Tentu ia juga menentukan lokasi 'layer' kanvas virtual. Namun secara bawaan nilainya diisi titik tengah gambar (untuk "-distort" yang memakai gambar masukan sebagai viewport) atau 0,0 (untuk gambar layer "+distort"). Argumen berikutnya, 'Start_Angle,End_Angle , bahkan lebih jarang dipakai; keduanya membatasi sudut yang dicakup gambar masukan, dengan nilai bawaan -180 sampai 180 derajat (0 adalah lurus ke bawah). Seperti pada distorsi 'Arc', ini dapat dipakai untuk memutar gambar polar hasilnya. Tetapi dapat juga dipakai untuk menghasilkan 'busur'. Sebagai contoh...
magick worldmap_sm.jpg -virtual-pixel Black -background Black \
+distort Polar '60,20 0,0 -60,60' +repage polar_arc.jpg
Perhatikan bahwa saat ini IM tidak mengecilkan ukuran gambar layer hasilnya, yang dijajarkan sehingga titik asal gambar virtualnya berada di koordinat 0,0, sesuai permintaan. Selain gaya argumennya, inilah perbedaan terbesar antara distorsi 'Arc' dan 'Polar'. Perhatikan pula bahwa tepi kiri (sudut -60) berada di sebelah kiri. Ini benar secara matematis bila diingat bahwa sumbu 'Y' mengarah ke bawah (sama seperti pada semua rotasi gambar). Tentu, seperti Arc, Anda dapat memakai efek tiling piksel virtual untuk menghasilkan pola berulang. Sebagai contoh, ini persis sama dengan contoh terakhir, hanya dengan pengaturan 'HorizontalTileEdge'... |
magick worldmap_sm.jpg -virtual-pixel HorizontalTile -background Black \
+distort Polar '60,20 0,0 -60,60' +repage polar_arc_tiled.jpg
Distorsi DePolar (polar ke kartesian)
Ini pada dasarnya kebalikan dari distorsi 'Polar', dan punya kumpulan argumen opsional yang persis sama. Keenam argumen floating point opsionalnya adalah...
Radius_Max Radius_Min Center_X,Center_Y Start_Angle,End_Angle
Sekali lagi, bila 'Radius_Max ' disetel '0', yang dipakai adalah jarak dari 'CenterX,Y ' ke tepi terdekat, yang berarti apa pun di dalam lingkaran utuh terbesar akan dipetakan agar muat ke gambar seukuran gambar masukan. Sebagai contoh, mari kita balik 'diskworld' sebelumnya menjadi peta kartesian lagi.
magick polar_arctic.jpg -distort DePolar 0 world_restored.jpg
| Karena ukuran gambar masukan dipertahankan di sepanjang kedua distorsi itu, hasil di atas pada dasarnya persis sama dengan peta aslinya. Tentu, karena gambarnya terkompresi baik di 'kutub' atas maupun pada radiusnya, keluarannya jauh lebih buram daripada yang mungkin Anda kira. | Sebenarnya keadaan diperparah oleh kenyataan bahwa algoritma resampling area (EWA) tidak dapat men-sampling piksel dalam busur lingkaran. Karena itu resampling area dimatikan untuk distorsi "DePolar". Disarankan memakai teknik super-sampling sebagai gantinya, seperti yang ditunjukkan pada bagian berikutnya. |
|---|---|
Bila IM dibiarkan memakai 'bestfit' (lewat bentuk "+distort" dari operator ini), ia akan mengubah ukuran gambar keluaran agar 'Radius_Max ' tetap pada skala satu banding satu, dan menyetel lebarnya ke jarak keliling dari radius di tengah-tengah antara 'Radius_Max ' dan 'Radius_Min '. Pada dasarnya ini berusaha mempertahankan rasio aspek gambar polar sebaik mungkin, meski hasilnya bisa berupa gambar yang lebih panjang dan lebih tipis daripada dugaan. Sebagai contoh. |
magick polar_arctic.jpg +distort DePolar 0 world_restored_2.jpg
Trik siklus (De)Polar (blur radial/angular)
Seperti kita lihat di atas, memakai 'Radius_Max ' '0' memastikan seluruh gambar dipetakan ke dalam lingkaran ketika memakai distorsi 'Polar' (Cartesian to Polar), dan pengaturan yang sama akan memetakan lingkaran itu kembali menjadi gambar persegi panjang lewat 'DePolar' (Polar to Cartesian). Namun cara ini kurang berhasil bila yang Anda inginkan adalah men-'DePolar' sebuah gambar persegi panjang lalu membalik distorsinya lagi dengan 'Polar'. Sebagai contoh, mari kita ambil gambar bunga, de-polar, lalu pulihkan memakai nilai 'Radius_Max ' khusus '0' (radius = tepi terdekat).
magick flower_sm.jpg -virtual-pixel Black \
-distort DePolar 0 flower_depolar.jpg
magick flower_depolar.jpg \
-virtual-pixel HorizontalTile -background black \
-distort Polar 0 flower_circle.jpg
Nah, gambarnya tidak pulih dengan benar karena sudah terpotong oleh distorsi 'DePolar' yang pertama. Meski begitu, ini sendiri teknik yang berguna dan dapat dipakai untuk menghasilkan mask lingkaran sempurna bagi sebuah gambar, dengan ukuran yang sepenuhnya lepas dari gambar masukan yang diberikan. Agar teknik siklus 'DePolar'-'Polar' ini berjalan benar, kita perlu memakai radius berupa jarak dari pusat ke sudut terjauh. Nilai 'Radius_Max ' khusus '-1' meminta IM menghitung dan memakai sudut terjauh dari 'titik pusat' sebagai radiusnya.
magick flower_sm.jpg -virtual-pixel Black \
-distort DePolar -1 flower_depolar-1.jpg
magick flower_depolar-1.jpg \
-virtual-pixel HorizontalTile -background black \
-distort Polar -1 flower_restored.jpg
Gambar yang dipulihkan sedikit buram, akibat kompresi radius yang diperlukan untuk mempertahankan seluruh gambar selama operasi 'DePolar'. Namun itu dapat diperbaiki dengan teknik super-sampling yang sesuai (lihat kumpulan contoh berikutnya). Tetapi mengapa Anda ingin mengubah gambar ke bentuk ini lalu kembali lagi? Begini: dengan menerapkan distorsi lain pada versi 'DePolar' antara dari gambar itu, efek radial atau angular yang sangat memikat dapat dihasilkan dengan sangat mudah. Misalnya, dengan me-roll gambar antaranya, gambar keluarannya akan berputar, meski sudut-sudutnya mungkin sedikit terpotong... |
magick flower_sm.jpg -virtual-pixel Black -distort DePolar -1 \
-roll +15+0 \
-virtual-pixel HorizontalTile -background Black \
-distort Polar -1 flower_polar_rotate.jpg
![[IM Output]](../static/img/distorts/flower_polar_rotate.jpg)
Perhatikan bahwa arah putarannya berlawanan dengan arah pada operator Rotate atau distorsi SRT.
Masalah siklus Depolar-Polar
Pada rotasi gambar di atas Anda mungkin memperhatikan adanya distorsi seperti 'anak tangga' di sepanjang tepi gambar yang diputar. Ini masalah yang sudah dikenal dan disebabkan oleh penekanan keliling lingkaran gambar yang besar ke dalam 'lebar' gambar masukan yang lebih kecil. Sebagai contoh, di sini saya mengambil gambar uji papan catur dan sekadar menjalankannya melalui siklus Depolar-Polar biasa tanpa perubahan apa pun.
magick checks.png -virtual-pixel Transparent \
-distort DePolar -1 checks_depolar.png
magick checks_depolar.png -virtual-pixel HorizontalTile -background None \
-distort Polar -1 checks_cycled.png
Efek aliasing akibat kompresi gambar jelas terlihat pada ujung-ujung gambar antaranya. Keadaan diperparah oleh kenyataan bahwa resampling area biasa tidak dipakai selama konversi 'Depolar' awal atas gambar masukan. Cara terbaik memecahkan masalah ini adalah memakai penskalaan keluaran distort untuk memperbesar gambar antaranya sekaligus mengecilkan gambar akhirnya. Ini menghasilkan keluaran ber-super-sampling yang menghilangkan artefak kompresi yang terlihat di atas. Sebagai contoh, inilah siklus depolar-polar 'no-op' yang lebih baik, semuanya dalam satu perintah... |
magick checks.png -virtual-pixel Background -background None \
-set option:distort:scale 4 -distort DePolar -1 \
-noop \
-virtual-pixel HorizontalTile -background None \
-set option:distort:scale .25 -distort Polar -1 \
checks_cycled_ss.png
![[IM Output]](../static/img/distorts/checks_cycled_ss.png)
Seperti terlihat, efek aliasing yang mengerikan itu praktis lenyap. Namun perlu diingat, gambar yang sangat tinggi dan tipis bisa memunculkan masalahnya kembali. Sebaiknya batasi cara ini pada gambar 'lanskap' atau gambar lebar, dengan super-sampling seperti di atas. Yang perlu dilakukan sekarang hanyalah mengganti operator "-noop" dengan perintah yang sesuai untuk menghasilkan efek radial dan rotasional yang Anda cari.
Contoh efek Depolar-Polar
Jadi mari kita tunjukkan lagi rotasi polar gambar yang lebih baik, kali ini memakai super sampling. Perhatikan bahwa karena gambar antaranya 4 kali lebih besar, besaran roll gambar juga perlu 4 kali lebih besar. |
magick flower_sm.jpg -virtual-pixel Black \
-set option:distort:scale 4 -distort DePolar -1 \
-roll +60+0 \
-virtual-pixel HorizontalTile -background Black \
-set option:distort:scale .25 -distort Polar -1 \
flower_polar_rotate_ss.jpg
![[IM Output]](../static/img/distorts/flower_polar_rotate_ss.jpg)
Seperti terlihat, efek 'anak tangga' di sepanjang tepi sudah hilang, dan kualitas gambar hasilnya jauh lebih tinggi.
Atau Anda dapat menerapkan blur linear sederhana pada gambar antaranya (misalnya dengan memampatkan lalu memperbesar gambarnya lagi). |
magick flower_sm.jpg -virtual-pixel Black \
-set option:distort:scale 4 -distort DePolar -1 \
-scale 10%x100%\! -filter Gaussian -resize 1000%x100%\! +filter \
-virtual-pixel HorizontalTile -background Black \
-set option:distort:scale .25 -distort Polar -1 \
flower_angular_blur.jpg
![[IM Output]](../static/img/distorts/flower_angular_blur.jpg)
Hasilnya sangat mirip dengan 'blur rotasional ' pada gambar. Ini mirip, tetapi tidak sepenuhnya sama, dengan operator Radial Blur yang namanya keliru itu. Sebenarnya hasilnya berkualitas lebih tinggi daripada metode blur khusus tersebut. Perhatikan bahwa pemakaian warna 'black' pada berbagai bentuk pengaturan piksel virtual yang diterapkan akan sedikit menggelapkan tepi, tetapi pada kasus di atas tidak terlalu parah. Salah satu cara menghilangkan efek tepi 'hitam' adalah memakai warna 'transparency' sebagai gantinya, lalu mematikan kanal alpha sepenuhnya setelah selesai sehingga tersisa warna yang benar-benar dihitung IM. Cara lain adalah memakai dua metode piksel virtual 'edge' ('Edge' dan 'HorizontalTileEdge'), yang memperpanjang tepi gambar ke ruang kanvas virtual yang tak terdefinisi. |
magick flower_sm.jpg -virtual-pixel Edge \
-set option:distort:scale 4 -distort DePolar -1 \
-scale 10%x100%\! -filter Gaussian -resize 1000%x100%\! +filter \
-virtual-pixel HorizontalTileEdge -background Black \
-set option:distort:scale .25 -distort Polar -1 \
flower_angular_blur_edge.jpg
![[IM Output]](../static/img/distorts/flower_angular_blur_edge.jpg)
Hasilnya jauh lebih baik di dekat tepi.
Dengan mem-blur versi polar gambar secara vertikal, kali ini memakai operator Motion Blur alih-alih kompresi lewat resize, Anda dapat menghasilkan guratan radial yang bergerak keluar dari pusat gambar... |
magick flower_sm.jpg -virtual-pixel Black \
-set option:distort:scale 4 -distort DePolar -1 \
-virtual-pixel Edge -motion-blur 0x28-90 \
-virtual-pixel HorizontalTile -background Black \
-set option:distort:scale .25 -distort Polar -1 \
flower_radial_blur.jpg
![[IM Output]](../static/img/distorts/flower_radial_blur.jpg)
Supaya hasilnya hanya mem-blur bagian terang (kelopaknya) dari gambar, komposisikan hasil ini dengan gambar asli memakai Lighten, sehingga hanya warna terang yang sudah di-blur yang tetap terlihat, sementara warna gelap tidak ikut mem-blur ke area terang dan merusak bintik kuning di tengah bunga. |
magick flower_sm.jpg flower_radial_blur.jpg \
-compose Lighten -composite flower_radial_blur_lighten.jpg
![[IM Output]](../static/img/distorts/flower_radial_blur_lighten.jpg)
Lihat pula Bintang dan komet untuk contoh lain hal ini, tetapi dengan langsung menghasilkan gambar 'DePolar' antaranya sebelum menerapkan distorsi 'Polar'. Terima kasih khusus kepada Fred Weinhaus atas pemakaian khusus siklus DePolar-Polar ini, dan karena bersikeras agar saya memastikan distorsi-distorsi ini benar-benar dapat dibalik untuk gambar persegi panjang. Ia memanfaatkan teknik ini dengan baik pada sejumlah skrip ImageMagick miliknya, termasuk "bump", "ripples", dan "striations".
Distorsi Barrel (mengoreksi distorsi lensa)
Distorsi Barrel (ditambahkan pada IM v6.4.2-4) dirancang khusus untuk mengoreksi distorsi bulat yang disebabkan lensa kamera pada foto. Yakni distorsi seperti efek barrel dan pincushion, yang pada dasarnya saling berkebalikan. Untuk penerapan nyata operator ini pada koreksi distorsi lensa, lihat bagian Koreksi lensa. Distort ini diwujudkan berdasarkan sekumpulan 4 nilai koefisien, yang dikenal sebagai A, B, C, dan D, sebagaimana didefinisikan oleh Profesor Helmut Dersch pada situs web yang kini sudah lenyap. Arsip Wayback Machine dari situs itu dapat dilihat di Correcting Barrel Distortion. Nilai-nilai itu pada dasarnya membentuk persamaan distorsi seperti ini...
_R src_ = r * ( A*_r 3_ + B*_r 2_ + C*_r_ + D )
Di sini "_r_" adalah radius tujuan dan "_R src_" piksel sumber tempat warna piksel diambil. Radiusnya dinormalisasi sehingga radius = '1.0' untuk setengah dari lebar atau tinggi minimum gambar masukan. Ini mungkin terkesan terbalik, tetapi itu karena teknik pemetaan piksel terbalik dipakai untuk memastikan gambar hasilnya tercakup seluruhnya. Keempat koefisien (A, B, C, dan D) tetap untuk kombinasi kamera, lensa, dan zoom tertentu. Ketiganya biasanya tersimpan bersama gambar dalam profil EXIF. Ini penting, karena artinya setelah nilai-nilai itu Anda dapatkan untuk kamera Anda, nilai yang sama dapat dipakai untuk menghilangkan distorsi lensa bulat yang ada pada semua foto yang diambil dengan kombinasi kamera dan lensa tersebut. Argumen yang diperlukan metode distort '**Barrel**'. Umumnya Anda cukup memberikan 3 atau 4 nilai...
_A B C_ [ _D_ [ _X_ , _Y_ ] ]
Argumen opsional X ,Y menyediakan 'pusat' opsional bagi distorsi radialnya; bila tidak diberikan, nilainya jatuh ke pusat persis gambar yang diberikan (tanpa memperhitungkan offset virtualnya). Koefisiennya dirancang sedemikian rupa sehingga bila keempat nilai A sampai D berjumlah '1.0', lebar/tinggi minimum gambar tidak berubah. Karena itu bila D (yang mengendalikan penskalaan keseluruhan gambar) tidak diberikan, nilainya akan disetel supaya keempat nilai itu berjumlah '1.0'. Memakai parameter '0.0 0.0 0.0' (setara dengan _A_ =_B_ =_C_ =0.0 dan _D_ =1.0') tidak mengubah gambar masukan sama sekali, dan itulah argumen 'no-op' bagi distorsi ini. Berikut contoh dari situs web aslinya, memakai koefisien yang disediakan untuk kamera yang dipakai memotret foto tersebut.
magick barrel_distorted.jpg -virtual-pixel black \
-distort Barrel "0.0 0.0 -0.075 1.1" \
barrel_distorted_fixed.jpg
Perhatikan bagaimana distorsi pada gambar dikoreksi sehingga pilar-pilar gedungnya menjadi lurus. Namun karena keempat koefisiennya berjumlah lebih dari 1.0, gambarnya menyusut sedikit, sehingga muncul area hitam kecil di tengah tepi atas dan bawah (sesuai pengaturan piksel virtual yang diberikan). Berikut efek penambahan 0,2 pada masing-masing koefisien masukan; sekali lagi jumlah nilainya lebih dari 1.0 sehingga gambar terdistorsinya akan lebih kecil.
magick checks.png -virtual-pixel gray \
-distort Barrel "0.2 0.0 0.0 1.0" barrel_checks_A.png
magick checks.png -virtual-pixel gray \
-distort Barrel "0.0 0.2 0.0 1.0" barrel_checks_B.png
magick checks.png -virtual-pixel gray \
-distort Barrel "0.0 0.0 0.2 1.0" barrel_checks_C.png
magick checks.png -virtual-pixel gray \
-distort Barrel "0.0 0.0 0.0 1.2" barrel_checks_D.png
Mengurangi 0.2 menghasilkan efek sebaliknya, meski saya mengimbanginya dengan nilai 'D ' yang lebih besar (untuk mengecilkan gambar) supaya hasilnya lebih jelas terlihat.
magick checks.png -virtual-pixel gray \
-distort Barrel "-0.2 0.0 0.0 1.3" barrel_checks-A.png
magick checks.png -virtual-pixel gray \
-distort Barrel "0.0 -0.2 0.0 1.3" barrel_checks-B.png
magick checks.png -virtual-pixel gray \
-distort Barrel "0.0 0.0 -0.2 1.3" barrel_checks-C.png
magick checks.png -virtual-pixel gray \
-distort Barrel "0.0 0.0 0.0 1.3" barrel_checks-D.png
Perhatikan bahwa nilai A menghasilkan efek yang lebih besar daripada B , dan B lebih besar daripada C , sementara D memberikan penskalaan keseluruhan atas hasilnya. Dengan begitu tiap koefisien dapat dipakai untuk menyetel gambar sehingga satu distorsi di sekitar tepi luar dan distorsi lain ke arah tengah dapat dikoreksi sekaligus, yang satu pincushion dan yang lain barrel. Sangat luwes. Koefisien di atas (A , B , C , dan D) dirancang untuk bekerja dengan radius 'ternormalisasi' berupa setengah dari lebar atau tinggi minimum gambar (seperti pengaturan radius '0' pada distort Polar. Artinya, koefisien itu tidak bergantung pada ukuran gambar. Karena itu kumpulan nilai yang sama dapat dipakai untuk gambar apa pun yang dihasilkan sebuah kamera tertentu, berapa pun ukuran kualitasnya (pengaturan kamera), atau bila gambarnya sudah Anda perkecil. Nilai koefisien dapat pula disetel agar memakai nilai radius 'ternormalisasi' yang lain dengan pengali/pembagi yang sesuai pada tiap koefisien. Misalnya memakai setengah dari lebar/tinggi maksimum, atau memakai radius diagonal. | _Helmut Dersch juga mencatat bahwa sebaiknya Anda mempertimbangkan pemakaian ruang warna LAB untuk koreksi distorsi pada foto, karena interpolasi warnanya lebih baik. Ini mungkin berlaku untuk semua distorsi (termasuk Resize.
Pengujian menunjukkan ruang LAB sama tidak linearnya dengan sRGB, tetapi memang menghindarkan kemungkinan distorsi warna ketika nilai ekstrem terpotong. Lihat Persepsi warna manusia, dan contoh praktisnya di Mengubah ukuran dengan koreksi ruang warna._
Anda juga dapat menyatakan kumpulan koefisien yang berbeda untuk sumbu x dan y, sehingga dapat dihasilkan distorsi yang tidak biasa.
_A x Bx Cx Dx Ay By Cy Dy_ [ _X_ , _Y_ ]
Pemakaian argumen X dan Y terpisah dirintis dalam skrip pinbarrel milik Fred Weinhaus, meski urutan argumennya terbalik dengan D di depan dan A di belakang. Dengan memakai nilai C positif, disertai nilai D yang sesuai hanya pada kumpulan koefisien 'y', gambar dapat didistorsi sehingga menggembung vertikal di tengah. |
magick rose: -alpha set -virtual-pixel transparent \
-distort Barrel "0.0 0.0 0.0 1.0 0.0 0.0 0.5 0.5" \
barrel_bulge.png
![[IM Output]](../static/img/distorts/barrel_bulge.png)
Serupa dengan itu, memakai nilai C negatif membuat gambar 'terjepit' di tengah. |
magick rose: -alpha set -virtual-pixel transparent \
-distort Barrel "0.0 0.0 0.0 1.0 0.0 0.0 -0.5 1.9" \
barrel_pinch.png
![[IM Output]](../static/img/distorts/barrel_pinch.png)
Atau dengan menambahkan efek sebaliknya pada koefisien X, gambarnya jadi tampak seperti diperas di antara jari-jari Anda sehingga menggembung ke samping. |
magick rose: -alpha set -virtual-pixel transparent \
-distort Barrel "0.0 0.0 0.5 0.5 0.0 0.0 -0.5 1.9" \
barrel_pinch_2.png
Distorsi BarrelInverse (distorsi barrel alternatif)
Metode distorsi 'BarrelInverse' sangat mirip dengan metode distorsi Barrel sebelumnya, dan memang menerima kumpulan argumen yang sama. Namun rumus yang diterapkan sedikit berbeda: bagian utama persamaannya membagi radius. Artinya persamaannya dibalik.
_R src_ = r / ( A*_r 3_ + B*_r 2_ + C*_r_ + D )
| Persamaan ini TIDAK menghasilkan 'kebalikan' distorsi 'Barrel'. Ia TIDAK dapat dipakai untuk 'membatalkan' distorsi sebelumnya.
Akibatnya Anda perlu memakai bentuk 'negatif' dari A , B , C , dengan penyesuaian yang setara pada D , untuk mencapai hasil yang mirip tetapi sedikit berbeda. Beberapa sumber, seperti makalah riset Method for Correcting Lens Distortion (PDF), menyatakan bahwa hasil yang lebih baik dapat dicapai dengan distorsi koreksi lensa berbentuk seperti ini. Sebagai contoh, berikut padanan contoh 'Pinch' terakhir memakai bentuk distorsi ini. |
magick rose: -alpha set -virtual-pixel transparent \
-distort BarrelInverse "0.0 0.0 -0.5 1.5 0.0 0.0 0.3 0.5" \
barrel_inv_pinch.png
Distorsi proyektif
Ini distorsi yang dipakai untuk memproyeksikan atau memetakan gambar yang berada pada satu permukaan ke permukaan lain. Garis proyeksinya bisa sejajar, bisa pula memancar dari suatu lokasi tertentu. Secara teknis distorsi afin dan perspektif juga 'proyektif' karena keduanya 'memproyeksikan' gambar pada satu permukaan datar ke permukaan datar lain (masing-masing memakai proyeksi sejajar dan radial), tetapi keduanya begitu lazim sehingga dibahas lebih rinci di bagian contohnya sendiri di atas. Berikut 'distorsi proyektif' yang lebih tidak biasa dan sudah diwujudkan, umumnya dengan bantuan Forum Diskusi IM.
Cylinder 2 Plane
Distort 'Cylinder2Plane' adalah distorsi proyektif radial dari sebuah titik di pusat sebuah silinder ke bidang datar yang menyinggung silinder itu.
![[diagram]](../static/img/distorts/cylinder2plane.png)
Susunan seperti ini khas pada kamera lubang jarum khusus yang dikenal sebagai kamera P.90, yaitu ketika foto berbusur 90 derajat ditangkap pada film yang membentuk silinder di dalam kamera. Berikut contoh foto dari kamera semacam itu...
![[photo]](../static/img/img_photos/p90_orig.jpg)
Masalahnya, gambar hasilnya terdistorsi sehingga garis lurus menjadi busur melengkung, akibat susunan fisik filmnya. Pada dasarnya permukaan lengkung yang membungkus dirinya mengelilingi sumber proyeksi 'titik' (sebuah lubang jarum). Perhatikan bahwa kamera lubang jarum biasa tidak bermasalah begini karena proyeksinya jatuh ke permukaan datar dari sumber titik. Distort 'Cylinder2Plane' membereskannya dengan memproyeksikan gambar dari susunan silindernya ke bidang datar. Parameternya...
_fov_angle center_x,y fov_output dest_center_x,y_
Hanya parameter pertama, sudut medan pandang kamera, yang wajib. Kamera P.90 memakai panjang fokus (radial) 90mm dan film standar selebar 57mm, yang menghasilkan 'medan pandang' sebesar 90 / 57 * 180/pi atau 90,467 derajat. Di sini misalnya saya memproyeksikan foto P90 ke sebuah bidang supaya gambarnya tampak lebih 'normal' dan garis lurusnya kembali lurus.
magick p90_orig.jpg -virtual-pixel Gray \
+distort Cylinder2Plane 90.467 p90_plane.png
Perhatikan bahwa lebar maupun tinggi gambarnya berubah, karena kita memakai versi 'plus' dari distort agar semua piksel terdistorsi pada gambar asli tetap tampil. Gambarnya jadi lebih lebar karena proyeksinya, sedangkan tinggi gambar itu sendiri di sepanjang garis tengah vertikal tidak berubah. Foto dan algoritmenya berasal dari diskusi IM Correcting for a curved film plane. Diskusi itu mengalir pula ke diskusi lain tentang Algorithmic vignetting correction for pinhole cameras.
'fov_output ' khusus itu, bila diberikan, akan menskalakan gambar keluaran hasilnya sehingga lebar gambar keluaran (biasanya ukuran viewport) persis sesuai dengan sudut ini. Bila tidak ada viewport yang diberikan, pencocokan terbaik diaktifkan untuk mendekati penskalaan 1:1 gambar sebaik mungkin, sambil tetap menjajarkan tepi gambar ke bilangan bulat. Parameter titik pusat distorsinya (titik singgung dan titik cakrawala dari masukan). Parameter 'center' terakhir mengendalikan penempatan floating point yang presisi atas hasilnya di dalam 'layer' gambar viewport (yakni pergeseran sub-piksel). Bersama parameter 'center_x,y ', ini memungkinkan Anda mengambil bagian dari gambar yang lebih besar. Misalnya mengambil pandangan 90 derajat yang kecil dari gambar panorama 360 derajat yang lebih besar. FUTURE: extracting smaller flat 'viewing' images from a 360 panorama, as well as an animation that slowly pans around those 360 degrees.
Plane 2 Cylinder
Distort 'Plane2Cylinder' adalah kebalikan dari proyeksi di atas, dan menerima parameter...
_fov_angle center_x,y_
Sebagai contoh, ini membatalkan contoh kamera P.90 sebelumnya.
magick p90_plane.png -virtual-pixel Black \
+distort Plane2Cylinder 90.467 p90_restored.png
Hasilnya masih mengandung piksel tambahan yang ditambahkan sebelumnya, bahkan bertambah lagi. Piksel-piksel itu sebaiknya dipangkas dari hasil di atas. Di sini saya memakai distorsi ini untuk menghasilkan animasi 'gulungan film' lengkap dengan lubang gerigi di tepinya.
magick -size 12x12 xc: -draw 'circle 6,6 6,2' -negate \
-duplicate 5 +append +duplicate \
rose: +swap -background black -append \
-duplicate 3 +append \
-virtual-pixel HorizontalTile -background SkyBlue \
-duplicate 19 -distort SRT '%[fx:72*t/n],0 1 0 0,0' \
-distort Plane2cylinder 115 \
-bordercolor Skyblue -border 0x3 -set delay 5 \
film_strip_anim.gif
Penjelasan:
- Mula-mula sebuah gambar lubang digambar, lalu diduplikasi dan disambung untuk membuat deretan 6 lubang. Kemudian diduplikasi lagi.
- Gambar rose bawaan lalu ditambahkan dan diapit di antara dua salinan deretan lubang gerigi itu, lalu semuanya disambung (dengan isian hitam) untuk membentuk satu frame gulungan film akhir.
- Ini diduplikasi untuk membuat gulungan film sepanjang 4 frame, yang menentukan panjang gambar akhirnya.
- Animasi 20 frame dibuat memakai distorsi 'translation' SRT. Lihat animasi distort.
- Kemudian tiap frame dari 20 frame itu didistorsi ke sebuah silinder sepanjang busur 115 derajat, memakai pengaturan piksel virtual untuk menghasilkan tile horizontal tak hingga dari gulungan film tersebut
- Sudut dalam hal ini hanya untuk lebar gambar masukan; lebar gambar akhirnya lebih dari 180 derajat, karena saya tidak memakai versi 'plus' dari distort. Jadi meski lebar hasil distorsinya menyusut, gambar keluarannya tidak.
- Terakhir sebuah tepi ditambahkan, dan pengaturan animasi diterapkan.
Distorsi multi-titik dan bentuk bebas
Distorsi Shepard (distort mirip taffy)
Metode Shepard (ditambahkan pada IM v6.4.2-4) memakai pergerakan titik kontrol yang diberikan untuk mendistorsi gambar dalam bentuk efek 'lokal'. Bayangkan ini setara dengan bongkahan tebal 'taffy' yang mewakili gambar sumber, lalu ditancapi jarum dan jarum-jarum itu digeser-geser. Secara lebih teknis, ia memindahkan titik memakai interpolasi jarak kuadrat terbalik. Bila hanya satu titik kontrol yang dipakai, wajar saja seluruh gambar ikut berpindah (bergeser), sama seperti hasil distorsi 'Affine' satu titik. Tidak terlalu menarik. Jadi mari kita coba memindahkan dua titik kontrol. Misalnya, mari kita siksa si 'koala' dengan menarik kupingnya (di '30,11' dan '48,29')...
magick koala.gif -virtual-pixel Black \
-distort Shepards '30,11 20,11 48,29 58,29' \
koala_ear_pull.png
Seperti terlihat, bagian gambar di antara kedua titik kontrol itu terentang karena pergerakan titik kontrolnya. Namun semua bagian gambar lainnya nyaris utuh, termasuk bagian gambar yang dekat dengan titik kontrol itu sendiri, bagian bawah gambar, dan seterusnya. Area yang terletak di tengah-tengah antara kedua titik kontrol ditarik dan terentang supaya titik kontrolnya berada persis di tempat yang Anda minta. Yang mungkin kurang kentara, bagian di sisi jauh dari titik kontrol juga tertekan, sehingga makin jauh dari titik kontrol makin kecil pengaruhnya terhadap hasil. Artinya, distorsi ini menghasilkan distorsi yang 'terlokalisasi'. Mari kita perlebar pandangan (memakai viewport distort) supaya ini lebih jelas terlihat... |
magick koala.gif -virtual-pixel Black \
-set option:distort:viewport 115x115-20-20 \
-distort Shepards '30,11 15,11 48,29 58,29' \
+repage koala_ear_pull_2.png
![[IM Output]](../static/img/distorts/koala_ear_pull_2.png)
Seperti terlihat, bentuk gambarnya ikut terdistorsi untuk mengakomodasi 'kepala' koala yang terentang. Untuk menghindari efek ini, lebih lazim juga 'menancapkan' jarum di sudut-sudut dan mungkin sebagian tepi gambar, supaya bagian itu tidak bergerak. |
magick koala.gif -virtual-pixel Black \
-set option:distort:viewport 115x115-20-20 \
-distort Shepards '30,11 15,11 48,29 58,29
0,0 0,0 0,74 0,74 74,0 74,0 74,74 74,74' \
+repage koala_ear_pull_3.png
![[IM Output]](../static/img/distorts/koala_ear_pull_3.png)
Bahkan memindahkan satu titik saja, sambil menancapkan titik lain (dalam hal ini hanya sudut-sudutnya), bisa berguna. Misalnya, mari kita pindahkan saja hidung koala (di '28,24') ke tengah gambar. |
magick koala.gif -virtual-pixel Black \
-distort Shepards '28,24 37,37
0,0 0,0 0,74 0,74 74,0 74,0 74,74 74,74' \
+repage koala_move_nose.png
![[IM Output]](../static/img/distorts/koala_move_nose.png)
Contoh yang satu ini istimewa karena inilah distorsi yang dipakai Fred Weinhaus untuk skrip 'animated morphing' satu titik miliknya, "shapemorph". Namun skrip aslinya memakai operator DIY FX yang lambat, karena distorsi Shepard waktu itu belum ditambahkan ke IM. Skrip inilah yang sebenarnya menjadi asal gagasan distorsi Shepard.
Memindahkan area gambar
Anda bahkan dapat memindahkan seluruh bagian gambar dengan memindahkan sekumpulan titik di sekeliling bagian itu sekaligus. Misalnya, mari kita geser kepala koala ke samping memakai titik-titik di sekeliling kepala (garis merah), sekaligus menancapkan bagian gambar yang tidak ingin kita pindahkan (garis hijau).
magick koala.gif -virtual-pixel Black -distort Shepards \
'19,8, 29,8 19,27 29,27 26,34 36,34
33,37 43,37 36,37 46,37 53,37 63,37 58,25 68,25
13,20 13,20 17,28 17,28 25,36 25,36
35,39 35,39 46,40 46,40 50,43 50,43 ' \
+repage koala_head_move.png
Perhatikan bahwa meski kepalanya berpindah, tepi kepalanya terdistorsi cukup parah. Sebabnya, distort ini tidak memindahkan area, melainkan titik. Bila titik penanda tepi itu terlalu berjauhan, gambarnya akan seolah meleleh, merembes, atau membengkok di antara titik-titik tersebut, persis seperti taffy atau agar-agar. (SELINGAN: istilah sebenarnya adalah merentangkan 'lembar karet' atau 'balon'.) Selain itu, bila dua titik kontrol berdekatan tetapi bergerak ke arah atau sejauh yang berbeda, gambarnya bisa berpusar dan membengkok secara lokal di sekitar keduanya. Titik kontrolnya tetap berakhir di lokasi yang benar, tetapi segala hal di sekelilingnya terpelintir parah demi mencapai tujuan itu. Dan itulah yang terjadi di sepanjang tepi kepala. Jadi seberapa rapat titik penanda tepi seharusnya? Pada dasarnya paling tidak setengah dari jarak ke titik mana pun yang bergerak secara berbeda. Jadi tambahkan lebih banyak titik tepi, atau beri jarak tambahan antara titik yang tetap dan titik yang bergerak. Dengan begitu ruang tempat gambar boleh terentang dan tertekan menjadi lebih jelas terdefinisi. Perhatikan pula bahwa gambar secara keseluruhan juga bergeser ke kiri bersama kepalanya. Hanya titik kontrol yang ditetapkan tetap atau dipindahkan ke tujuan tertentu yang dijamin ditempatkan dengan benar. Bagian gambar yang lebih jauh dari titik kontrol mana pun juga akan bergerak berdasarkan rata-rata kasar dari semua pergerakan titik kontrol. Karena itu lebih baik memakai jauh lebih banyak titik 'tetap' yang tersebar di seluruh gambar, atau bahkan beberapa titik yang digerakkan ke arah berlawanan agak jauh di luar gambar, untuk mengimbangi pergerakan rata-rata secara umum. Anda juga dapat menduplikasi atau menggandakan titik kontrol (mencantumkannya dua kali) untuk memberi titik tertentu pengaruh atau 'daya' yang lebih besar atas distorsi di area itu. Berikut versi lain dari 'menggeser kepala ke samping', tetapi kali ini saya memberi jarak tambahan antara titik yang bergerak (merah) dan yang tetap (hijau). Saya juga menambahkan jauh lebih banyak titik tetap untuk mengurangi pergerakan umum rata-rata dari gambar terdistorsinya.
magick koala.gif -virtual-pixel Black -distort Shepards \
'15,15, 25,15 19,27 29,27 26,34 36,34
33,37 43,37 36,37 46,37 53,37 63,37
10,2 10,2 2,10 2,10 4,55 4,55 14,47 14,47
25,47 25,47 45,51 45,51 55,45 55,45
5,70 5,70 15,60 15,60 55,60 55,60 70,70 70,70' \
+repage koala_head_move_2.png
Yang terakhir perlu dilakukan pada contoh di atas hanyalah menyetel pengaturan "-virtual-pixel" yang lebih baik untuk menentukan warna apa yang seharusnya mengisi area hitam tak terdefinisi di atas.
Shepards dan rotasi gambar
Satu segi distorsi ini: ia tidak menyukai rotasi dalam bentuk apa pun! Sebagai contoh, berikut pengulangan Perspective dan BilinearForward, bersanding dengan distorsi Shepard.
magick mandrill_grid.jpg -alpha set -virtual-pixel black \
-distort Perspective \
'0,0 26,0 128,0 114,23 128,128 128,100 0,128 0,123' \
mandrill_pers.jpg
magick mandrill_grid.jpg -alpha set -virtual-pixel black -interpolate Spline \
-distort BilinearForward \
'0,0 26,0 128,0 114,23 128,128 128,100 0,128 0,123' \
mandrill_blin.jpg
magick mandrill_grid.jpg -alpha set -virtual-pixel black -interpolate Spline \
-distort Shepards \
'0,0 26,0 128,0 114,23 128,128 128,100 0,128 0,123' \
mandrill_shep.jpg
![[IM Output]](../static/img/img_photos/mandrill_grid.jpg)
Asli | | ![[IM Output]](../static/img/distorts/mandrill_pers.jpg)
Perspective | ![[IM Output]](../static/img/distorts/mandrill_blin.jpg)
Bilinear | ![[IM Output]](../static/img/distorts/mandrill_shep.jpg)
Shepards
Perhatikan bagaimana distorsi Shepard menghasilkan gambar yang sangat melengkung dibandingkan dua metode distorsi lainnya. Sebabnya, ia berusaha mempertahankan gambar persis apa adanya di area yang dekat dengan titik kontrol yang diberikan. Termasuk rotasi gambarnya. Akibat 'pelestarian' ini kisinya melengkung supaya tetap 'ortogonal' di titik kontrol yang sebenarnya. Ini agak mirip bila 'jarum' di titik kontrol itu bukan jarum bulat, melainkan 'silang', yang memaksa 'agar-agar' atau 'lembar karet' penopang gambar untuk ikut mempertahankan rotasi gambarnya. Ini juga sumber dari banyak efek 'pusaran' yang dapat dihasilkan distorsi ini. Misalnya, bila kita mengambil dua titik pada gambar lalu mendorong keduanya saling melewati. Gambarnya akan berpusar, bukan berputar. Sebagai contoh, mari kita coba mendorong kuping koala saling mendekat alih-alih menjauh.
magick koala.gif -virtual-pixel Black \
-distort Shepards '30,11 40,11 48,29 38,29' \
koala_ear_push.png
Faktor power Shepard
Biasanya bobot jarak pada IWD (Inverse Weighted Distance) Shepard mengikuti hukum kuadrat terbalik (1/r2), tetapi sejak IM v6.8.0-10 Anda kini dapat memakai define tingkat pakar 'shepards:power' untuk mengendalikan 'tingkat power' bobot globalnya. Bila tidak didefinisikan, nilainya 2.0; dengan mendefinisikannya lebih kecil, distorsi yang dihasilkan lebih terlokalisasi di sekitar titik kontrol yang dipindahkan, lepas dari pergeseran rata-rata keseluruhan gambar terdistorsinya. Memakai nilai lebih besar akan memperluas area pengaruh di sekitar titik kontrol. Sebagai contoh, berikut pengulangan contoh 'menarik kuping koala' dengan tingkat power berbeda-beda yang diterapkan pada bobot distorsi.
magick koala.gif -virtual-pixel Black -define shepards:power=0.5 \
-distort Shepards '30,11 20,11 48,29 58,29' \
koala_ear_pull_pow0.5.png
magick koala.gif -virtual-pixel Black -define shepards:power=1.0 \
-distort Shepards '30,11 20,11 48,29 58,29' \
koala_ear_pull_pow1.png
magick koala.gif -virtual-pixel Black \
-distort Shepards '30,11 20,11 48,29 58,29' \
koala_ear_pull.png
magick koala.gif -virtual-pixel Black -define shepards:power=3.0 \
-distort Shepards '30,11 20,11 48,29 58,29' \
koala_ear_pull_pow3.png
magick koala.gif -virtual-pixel Black -define shepards:power=8.0 \
-distort Shepards '30,11 20,11 48,29 58,29' \
koala_ear_pull_pow8.png
![[IM Output]](../static/img/distorts/koala_ears.png)
Asli
& aksi | | ![[IM Output]](../static/img/distorts/koala_ear_pull_pow0.5.png)
power 0.5 | ![[IM Output]](../static/img/distorts/koala_ear_pull_pow1.png)
power 1.0 | ![[IM Output]](../static/img/distorts/koala_ear_pull.png)
power 2.0
(bawaan) | ![[IM Output]](../static/img/distorts/koala_ear_pull_pow3.png)
power 3.0 | ![[IM Output]](../static/img/distorts/koala_ear_pull_pow8.png)
power 8.0
Semua hasil gambar di atas memakai kumpulan pergerakan titik kontrol yang persis sama. Yang berbeda hanyalah luas area pengaruh di sekitar titik kontrol itu. Power yang kecil akan 'melokalisasi' pergerakannya hanya ke area dekat titik kontrol, sedangkan power yang lebih besar akan menyeret lebih banyak bagian gambar di sekitar titik kontrol tersebut. Pada power yang sangat besar, tarikan ini cenderung 'merobek' gambar menjadi area-area terpisah di sepanjang garis tengah antartitik kontrol. Anda bahkan dapat memakai power yang jauh lebih besar, yang sekadar menggeser region di sekitar titik kontrol sumber ke area di sekitar titik kontrol tujuan. Area-area itu akan membentuk pola 'region voronoi' dan dapat berisi salinan ganda gambar sumber. Sebagai contoh, di sini saya memetakan area di sekitar hidung koala (di koordinat 28,24) ke 7 area berbeda dalam pola heksagonal, sehingga menghasilkan efek mirip 'mata serangga' dengan cara yang sangat efisien. |
magick koala.gif -virtual-pixel Black -define shepards:power=25 \
-distort Shepards '28,24 35,35 \
28,24 20,10 28,24 50,10 \
28,24 20,60 28,24 50,60 \
28,24 10,35 28,24 60,35' koala_hexagonal.png
![[IM Output]](../static/img/distorts/koala_hexagonal.png)
Ingat, distorsi Shepard sebenarnya setara dengan sebuah displacement map (memetakan piksel tujuan ke gambar sumber) yang dihasilkan dengan teknik yang sama seperti operator Sparse Color Shepards, yang juga terpengaruh oleh define faktor power yang sama.
Distorsi Shepard, ringkasnya
| Distorsi Shepard adalah metode yang sangat luwes dan berbentuk bebas, yang membatasi distorsinya pada area yang ditandai oleh bergerak atau tidak bergeraknya titik-titik yang diberikan. Distorsinya terlokalisasi dan terbatasi menurut jarak antartitik kontrol yang bertetangga, meski semua titik tetap punya efek global yang dirata-ratakan. Ingat saja bahwa distorsi ini digerakkan oleh titik, bukan oleh garis atau area, sehingga bagian di antara titik-titik itu bisa menggembung atau berpusar tak terduga ketika titik kontrol yang bergerak berbeda ditempatkan terlalu berdekatan. Ia akan memusar, merentang, dan menekan gambar di antara titik kontrol, tetapi berusaha keras tidak memutar atau menskalakan gambar di dekat titik kontrol. Dan terakhir, ia dapat menghasilkan pergeseran rata-rata menyeluruh pada bagian gambar yang jauh dari titik kontrol mana pun. Namun bila blok titik kontrol dapat dipindahkan dengan menjaga posisi relatifnya secara umum, metode ini memang menyediakan cara untuk mewujudkan teknik 'Image Morphing' yang umum dan sangat sederhana, digerakkan oleh titik. Skrip 'shapemorph2' milik Fred Weinhaus memakai distorsi Shepard untuk menyediakan program 'Animated Image Morphing' serbaguna yang bagus. | Secara internal distort ini setara dengan memakai pembangkit gradien Shepards Sparse Color untuk membuat dua peta pergeseran relatif yang mendistorsi gambar. Inilah yang dilakukan skrip "shapemorph" asli milik Fred Weinhaus, dan dari situlah teknik distorsi ini berasal. |
|---|---|
Karena rumitnya perhitungan yang diperlukan distorsi Shepard, IM tidak menyediakan bentuk 'best-fit' viewport tujuan apa pun lewat bentuk plus "+distort" dari operator ini. Namun Anda tetap dapat memakai opsi viewport distort untuk menetapkan gambar keluaran yang lebih besar. |
|
| --- | --- |
| Karena alasan yang sama, resampling area dimatikan. Karena itu area dengan kompresi ekstrem (lebih dari faktor 2) kemungkinan besar memperlihatkan efek aliasing. Contohnya, lihat tepi pola heksagon pada contoh terakhir. Namun super-sampling dapat dipakai untuk memperbaiki kualitas gambar akhir dan mengurangi efek aliasing semacam itu. | |
| --- | --- |
![[IM Output]](../static/img/images/koala.gif)
![[IM Text]](../static/img/distorts/distort_verbose.txt.gif)
![[IM Output]](../static/img/distorts/koala_noop.gif)
![[IM Output]](../static/img/distorts/koala_viewport_4.gif)
![[IM Output]](../static/img/img_photos/worldmap_sm.jpg)
![[IM Output]](../static/img/distorts/viewport_square.gif)
![[IM Output]](../static/img/distorts/spaceship.gif)
![[IM Output]](../static/img/distorts/spaceship_launch.gif)
![[IM Output]](../static/img/distorts/koala_arrow.png)
![[IM Output]](../static/img/distorts/koala_one_point.png)
![[IM Output]](../static/img/distorts/label_axis.png)
![[IM Output]](../static/img/distorts/label_axis_distort_shear.png)
![[IM Output]](../static/img/distorts/label_axis_distort_rotate.png)
![[IM Output]](../static/img/distorts/label_axis_distort_affine.png)
![[IM Output]](../static/img/distorts/checks_srt_tile.png)
![[IM Output]](../static/img/distorts/checks_affine_tile.png)
![[IM Output]](../static/img/distorts/checks_amatrix_tile.png)
![[IM Output]](../static/img/images/glitter_blue.gif)
![[IM Output]](../static/img/distorts/glitter_blue_tiled.gif)
![[IM Output]](../static/img/img_photos/building.jpg)
![[IM Output]](../static/img/distorts/building_before.jpg)
![[IM Output]](../static/img/distorts/building_after.jpg)
![[IM Output]](../static/img/distorts/building_pers.png)
![[IM Output]](../static/img/distorts/building_pers_rev.png)
![[IM Output]](../static/img/distorts/checks_pers.png)
![[IM Output]](../static/img/distorts/checks_pers_rev.png)
![[IM Output]](../static/img/distorts/box_spine.jpg)
![[IM Output]](../static/img/distorts/box_front.jpg)
![[IM Output]](../static/img/distorts/box_set.jpg)
![[IM Output]](../static/img/distorts/rose_marked.png)
![[IM Output]](../static/img/distorts/perspective_rose_marked.png)
![[IM Output]](../static/img/distorts/mandrill_blin_back.jpg)
![[IM Output]](../static/img/distorts/mandrill_blin_rev.jpg)
![[IM Output]](../static/img/distorts/mandrill_blin_rev2.jpg)
![[IM Output]](../static/img/distorts/bilinear_checks_rev.png)
![[IM Text]](../static/img/distorts/bilinear_rev_verbose.txt.gif)
![[IM Output]](../static/img/distorts/mandrill_poly_1.5.jpg)
![[IM Output]](../static/img/images/grid16.png)
![[IM Output]](../static/img/distorts/grid16_polynomial.png)
![[IM Output]](../static/img/distorts/grid16_restored.png)
![[IM Output]](../static/img/distorts/arc_rose_1.jpg)
![[IM Output]](../static/img/distorts/arc_rose_2.jpg)
![[IM Output]](../static/img/distorts/arc_rose_4.jpg)
![[IM Output]](../static/img/distorts/arc_rose_5.jpg)
![[IM Output]](../static/img/distorts/arc_rose_6.jpg)
![[IM Output]](../static/img/distorts/arc_rose_7.jpg)
![[IM Output]](../static/img/distorts/arc_circle_1.jpg)
![[IM Output]](../static/img/distorts/arc_circle_2.jpg)
![[IM Output]](../static/img/distorts/arc_circle_3.jpg)
![[IM Output]](../static/img/distorts/arc_circle_4.jpg)
![[IM Output]](../static/img/distorts/arc_circle_5.jpg)
![[IM Output]](../static/img/distorts/arc_fill.jpg)
![[IM Output]](../static/img/distorts/arc_radii.gif)
![[IM Output]](../static/img/distorts/arc_cross.gif)
![[IM Output]](../static/img/distorts/arc_spiral.gif)
![[IM Output]](../static/img/distorts/polar_arctic.jpg)
![[IM Output]](../static/img/distorts/polar_arc.jpg)
![[IM Output]](../static/img/distorts/polar_arc_tiled.jpg)
![[IM Output]](../static/img/distorts/world_restored.jpg)
![[IM Output]](../static/img/distorts/world_restored_2.jpg)
![[IM Output]](../static/img/distorts/flower_sm.jpg)
![[IM Output]](../static/img/distorts/flower_depolar.jpg)
![[IM Output]](../static/img/distorts/flower_circle.jpg)
![[IM Output]](../static/img/distorts/flower_depolar-1.jpg)
![[IM Output]](../static/img/distorts/flower_restored.jpg)
![[IM Output]](../static/img/distorts/checks_depolar.png)
![[IM Output]](../static/img/distorts/checks_cycled.png)
![[IM Output]](../static/img/img_photos/barrel_distorted.jpg)
![[IM Output]](../static/img/distorts/barrel_distorted_fixed.jpg)
![[IM Output]](../static/img/distorts/barrel_checks_A.png)
![[IM Output]](../static/img/distorts/barrel_checks_B.png)
![[IM Output]](../static/img/distorts/barrel_checks_C.png)
![[IM Output]](../static/img/distorts/barrel_checks_D.png)
![[IM Output]](../static/img/distorts/barrel_checks-A.png)
![[IM Output]](../static/img/distorts/barrel_checks-B.png)
![[IM Output]](../static/img/distorts/barrel_checks-C.png)
![[IM Output]](../static/img/distorts/barrel_checks-D.png)
![[IM Output]](../static/img/distorts/barrel_pinch_2.png)
![[IM Output]](../static/img/distorts/barrel_inv_pinch.png)
![[IM Output]](../static/img/distorts/p90_plane.png)
![[IM Output]](../static/img/distorts/p90_restored.png)
![[IM Output]](../static/img/distorts/film_strip_anim.gif)
![[IM Output]](../static/img/distorts/koala_head.png)
![[IM Output]](../static/img/distorts/koala_head_move.png)
![[IM Output]](../static/img/distorts/koala_head_2.png)
![[IM Output]](../static/img/distorts/koala_head_move_2.png)
![[IM Output]](../static/img/distorts/koala_push.png)
![[IM Output]](../static/img/distorts/koala_ear_push.png)