5.21. Skala, balik, dan pangkas

Subbagian sebelumnya semuanya bekerja pada piksel di posisi yang sama tempat mereka dimulai. Keluarga transform mengubah hal itu. Penskalaan mengirim setiap piksel input ke posisi output yang berbeda, mungkin ke beberapa posisi output sekaligus (saat upscaling) atau ke posisi yang dibagi dengan beberapa piksel input lain (saat downscaling). Pembalikan dan rotasi melakukan hal yang sama melalui pemetaan yang berbeda. Pemotongan mempertahankan subset piksel input berbentuk persegi panjang dan membuang sisanya.

Modul image mengekspos keluarga tersebut melalui tiga metode yang berbagi sebagian besar argumen dan perilakunya:

  • copy() -- menghasilkan salinan citra, kemungkinan diskalakan, dipangkas, atau diubah orientasinya.

  • crop() -- operasi yang sama dengan copy, tetapi dengan ekspektasi bahwa aplikasi akan memilih sub-persegi panjang dari sumber.

  • scale() -- operasi yang sama lagi, dengan ekspektasi bahwa aplikasi akan mengubah ukuran hasil.

Ketiganya berbagi argumen yang sama dan mesin transformasi yang sama; perbedaannya adalah di mana hasil mendarat secara default. copy() menghasilkan citra baru, sementara crop() dan scale() memodifikasi sumber di tempat.

5.21.1. Argumen yang dibagikan

Satu pemanggilan menggabungkan kombinasi apa pun dari penskalaan, pemotongan, orientasi, dan ekstraksi kanal yang diminta aplikasi:

x_scale dan y_scale menskalakan input sepanjang sumbu horizontal dan vertikal secara independen. Keduanya default ke 1.0 (tanpa penskalaan). Nilai berbeda untuk masing-masing menghasilkan penskalaan non-seragam -- bingkai yang diregangkan dua kali lebih lebar dari tingginya, misalnya.

roi membatasi input ke persegi panjang dari citra sumber, hanya mengambil piksel-piksel tersebut melalui sisa transformasi. Ini adalah bagian "crop" dari operasi: berikan roi untuk mengekstrak sub-wilayah.

hint adalah bitfield dari flag yang memilih metode interpolasi dan pembalikan orientasi apa pun. Beberapa flag dikombinasikan melalui bitwise OR (hint=image.BILINEAR | image.HMIRROR). Flag terbagi menjadi dua kelompok -- keluarga interpolasi dan keluarga orientasi -- yang tidak ada hubungannya satu sama lain tetapi berbagi bitfield yang sama.

rgb_channel memilih satu kanal dari sumber RGB565. 0 berarti merah, 1 berarti hijau, 2 berarti biru; hasilnya keluar sebagai citra skala abu-abu yang hanya berisi kanal tersebut. Berguna untuk pengambangan pada kanal merah saja, misalnya.

color_palette dan alpha_palette memetakan ulang nilai piksel melalui tabel pencarian saat keluar, sama seperti yang dilakukan metode konversi to_rainbow() dan to_ironbow().

copy=True dan copy_to_fb=True mengikuti konvensi yang sama yang digunakan setiap metode penghasil-hasil lainnya -- di tempat secara default, copy=True mengalokasikan hasil terpisah, copy_to_fb=True menempatkan hasil di buffer bingkai untuk pratinjau IDE.

5.21.2. Interpolasi: AREA, BILINEAR, BICUBIC

Ketika penskalaan mengirim setiap piksel output ke posisi yang tidak sejajar dengan satu piksel input mana pun, metode harus memilih nilai yang akan ditulis. Tiga flag mengontrol caranya:

image.BILINEAR menginterpolasi antara empat piksel input terdekat yang dibobotkan berdasarkan jaraknya dari posisi output. Hasilnya lebih halus dari tetangga-terdekat, tanpa jaggies yang terlihat pada garis diagonal, tetapi aritmetika tambahan membutuhkan biaya sekitar empat kali lebih banyak dari proses tetangga-terdekat. Pilihan yang tepat untuk sebagian besar pekerjaan upscaling dan untuk faktor skala non-integer.

image.BICUBIC menginterpolasi antara enam belas piksel input terdekat menggunakan kurva kubik, yang menghasilkan hasil yang lebih halus lagi dengan biaya aritmetika yang lebih besar. Kualitas terbaik untuk aplikasi yang sensitif biaya yang membutuhkannya; jarang sepadan dengan komputasi ekstra untuk bingkai langsung yang hanya akan ditampilkan IDE.

image.AREA merata-ratakan setiap piksel input yang jatuh di dalam jejak piksel output -- algoritma yang tepat untuk downscaling. Bilinear dan bicubic adalah interpolator: mereka memperkirakan nilai di antara piksel sumber, yang diperlukan untuk upscaling, tetapi ketika downscaling setiap piksel output mencakup banyak piksel sumber dan interpolator hanya membaca beberapa yang terdekat -- detail yang dilewati muncul kembali sebagai aliasing. image.AREA melipat setiap piksel yang dicakup ke dalam rata-rata.

Algoritma penskalaan default tanpa hint apa pun adalah tetangga-terdekat, yang paling murah dan jawaban yang tepat ketika sumber sudah pada resolusi piksel tujuan.

5.21.3. Orientasi: pembalikan dan rotasi

Flag orientasi adalah sekumpulan kecil transformasi boolean yang bebas dikombinasikan satu sama lain dan dengan flag interpolasi:

  • image.VFLIP membalik citra secara vertikal (atas menjadi bawah).

  • image.HMIRROR mencerminkannya secara horizontal (kiri menjadi kanan).

  • image.TRANSPOSE menukar sumbu x dan y (baris menjadi kolom).

Sebagian besar rotasi berasal dari menggabungkan ketiganya. Modul juga mengekspos pintasan bernama:

  • image.ROTATE_90 (= VFLIP | TRANSPOSE)

  • image.ROTATE_180 (= HMIRROR | VFLIP)

  • image.ROTATE_270 (= HMIRROR | TRANSPOSE)

Dalam kode:

img.copy(hint=image.ROTATE_90, copy_to_fb=True)

5.21.4. Penanganan aspek

Ketika rasio aspek sumber tidak cocok dengan persegi panjang yang sedang digambar, tiga flag memutuskan apa yang harus dilakukan dengan ketidakcocokan tersebut:

image.SCALE_ASPECT_KEEP mempertahankan rasio aspek sumber dan memberi letterbox pada hasil -- sumber diskalakan hingga muat di dalam tujuan, dengan piksel kosong (nol) mengisi sisa tujuan. Pilihan yang tepat ketika menjaga sumber tidak terdistorsi lebih penting daripada mengisi seluruh output.

image.SCALE_ASPECT_EXPAND mempertahankan rasio aspek sumber dan memangkasnya -- sumber diskalakan hingga mengisi tujuan, dengan bagian yang meluas melampaui tujuan dipotong. Pilihan yang tepat ketika mengisi seluruh output lebih penting daripada melihat setiap bagian sumber.

image.SCALE_ASPECT_IGNORE mengabaikan rasio aspek dan meregangkan sumber untuk mengisi tujuan, menerima distorsi apa pun yang diperkenalkan. Pilihan yang tepat ketika aplikasi sudah memperhitungkan distorsi -- ketika dimensi tujuan sebenarnya bukan persegi panjang dari adegan yang sama, misalnya.

Default (tidak ada flag aspek yang ditetapkan) sama dengan SCALE_ASPECT_IGNORE: regangkan untuk mengisi. Aplikasi yang peduli dengan rasio aspek menentukan salah satu dari ketiganya secara eksplisit.

5.21.5. Kapan menggunakan yang mana

Sebagian besar pengubahan ukuran menggunakan scale() dengan pasangan x_scale / y_scale dan hint interpolasi:

img.scale(x_scale=0.5, y_scale=0.5, hint=image.AREA)

Sebagian besar rotasi menggunakan panggilan yang sama dengan hint=image.ROTATE_90 atau sejenisnya.

Pemotongan menggunakan crop() dengan roi non-default:

img.crop(roi=(40, 30, 200, 150))

Ketika sumber harus bertahan dari operasi -- mengambil bingkai referensi, mengambil thumbnail dari bingkai yang akan diproses secara destruktif -- copy() menghasilkan hasil sebagai citra baru dan membiarkan sumber tidak tersentuh:

thumbnail = img.copy(x_scale=0.25, y_scale=0.25, hint=image.AREA)

Default tersebut adalah perbedaan nyata di balik ketiga nama: scale dan crop mentransformasi di tempat, copy mengalokasikan. Kata kunci penempatan-hasil menjembatani kesenjangan: copy=True pada scale atau crop mengalokasikan hasil sebagai buffer heap terpisah alih-alih menimpa sumber, dan copy_to_fb=True pada salah satu dari ketiganya menempatkannya di buffer bingkai untuk pratinjau IDE.