Jawaban ini diringkas dari Memuat bitmap besar secara Efisien
yang menjelaskan cara menggunakan inSampleSize untuk memuat versi bitmap yang diperkecil.
Secara khusus, bitmap Pra-penskalaan menjelaskan detail berbagai metode, cara menggabungkannya, dan mana yang paling hemat memori.
Ada tiga cara dominan untuk mengubah ukuran bitmap di Android yang memiliki properti memori berbeda:
createScaledBitmap API
API ini akan menggunakan bitmap yang ada, dan membuat bitmap BARU dengan dimensi yang tepat yang Anda pilih.
Di sisi positifnya, Anda bisa mendapatkan ukuran gambar yang Anda cari (terlepas dari tampilannya). Namun sisi negatifnya, API ini membutuhkan bitmap yang sudah ada agar dapat berfungsi . Artinya gambar harus dimuat, didekodekan, dan dibuat bitmap, sebelum dapat membuat versi baru yang lebih kecil. Ini sangat ideal dalam hal mendapatkan dimensi yang tepat, tetapi mengerikan dalam hal overhead memori tambahan. Dengan demikian, ini adalah semacam pemecah kesepakatan bagi sebagian besar pengembang aplikasi yang cenderung sadar memori
tanda inSampleSize
BitmapFactory.Options
memiliki properti inSampleSize
yang akan mengubah ukuran gambar Anda saat mendekodekannya, untuk menghindari kebutuhan untuk mendekode ke bitmap sementara. Nilai integer yang digunakan di sini akan memuat gambar dengan ukuran yang diperkecil 1 / x. Misalnya, menyetel inSampleSize
ke 2 mengembalikan gambar berukuran setengah, dan Menyetelnya ke 4 mengembalikan gambar berukuran 1/4. Pada dasarnya ukuran gambar akan selalu lebih kecil dari ukuran sumber Anda.
Dari perspektif memori, penggunaan inSampleSize
adalah operasi yang sangat cepat. Secara efektif, ini hanya akan mendekode setiap piksel X dari gambar Anda ke bitmap yang dihasilkan. Ada dua masalah utama dengan inSampleSize
:
Itu tidak memberi Anda resolusi yang tepat . Ini hanya mengurangi ukuran bitmap Anda dengan beberapa pangkat 2.
Itu tidak menghasilkan pengubahan ukuran kualitas terbaik . Sebagian besar filter pengubah ukuran menghasilkan gambar yang terlihat bagus dengan membaca blok piksel, dan kemudian menimbangnya untuk menghasilkan piksel yang diubah ukurannya. inSampleSize
menghindari semua ini dengan hanya membaca setiap beberapa piksel. Hasilnya cukup baik, dan memori rendah, tetapi kualitas buruk.
Jika Anda hanya berurusan dengan mengecilkan gambar Anda dengan beberapa ukuran pow2, dan pemfilteran tidak menjadi masalah, maka Anda tidak dapat menemukan metode yang lebih efisien memori (atau kinerja efisien) daripada inSampleSize
.
tanda inScaled, inDensity, inTargetDensity
Jika Anda perlu menskalakan gambar ke dimensi yang tidak sama dengan pangkat dua, Anda memerlukan inScaled
, inDensity
dan inTargetDensity
bendera BitmapOptions
. Ketika inScaled
bendera telah disetel, sistem akan mendapatkan nilai skala untuk diterapkan ke bitmap Anda dengan membaginya inTargetDensity
dengan inDensity
nilai.
mBitmapOptions.inScaled = true;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeResources(getResources(),
mImageIDs, mBitmapOptions);
Menggunakan metode ini akan mengubah ukuran gambar Anda, dan juga menerapkan 'filter pengubah ukuran', hasil akhirnya akan terlihat lebih baik karena beberapa perhitungan tambahan telah diperhitungkan selama langkah pengubahan ukuran. Namun berhati-hatilah: langkah filter ekstra itu, membutuhkan waktu pemrosesan ekstra , dan dapat dengan cepat bertambah untuk gambar besar, mengakibatkan pengubahan ukuran yang lambat, dan alokasi memori ekstra untuk filter itu sendiri.
Biasanya bukan ide yang baik untuk menerapkan teknik ini pada gambar yang secara signifikan lebih besar dari ukuran yang Anda inginkan, karena overhead pemfilteran ekstra.
Kombinasi Ajaib
Dari perspektif memori dan kinerja, Anda dapat menggabungkan opsi ini untuk hasil terbaik. (pengaturan inSampleSize
, inScaled
, inDensity
dan inTargetDensity
bendera)
inSampleSize
pertama-tama akan diterapkan pada gambar, membuatnya menjadi kekuatan dua LEBIH BESAR berikutnya dari ukuran target Anda. Kemudian, inDensity
& inTargetDensity
digunakan untuk menskalakan hasil ke dimensi yang tepat yang Anda inginkan, menerapkan operasi filter untuk membersihkan gambar.
Menggabungkan keduanya adalah operasi yang jauh lebih cepat, karena inSampleSize
langkah tersebut akan mengurangi jumlah piksel yang diperlukan untuk menerapkan langkah berbasis Densitas untuk menerapkan filter pengubahan ukurannya.
mBitmapOptions.inScaled = true;
mBitmapOptions.inSampleSize = 4;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth * mBitmapOptions.inSampleSize;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeFile(fileName, mBitmapOptions);
Jika Anda perlu menyesuaikan gambar dengan dimensi tertentu, dan beberapa pemfilteran yang lebih baik, maka teknik ini adalah jembatan terbaik untuk mendapatkan ukuran yang tepat, tetapi dilakukan dalam operasi footprint yang cepat dan memiliki memori rendah.
Mendapatkan dimensi gambar
Mendapatkan ukuran gambar tanpa mendekode seluruh gambar Untuk mengubah ukuran bitmap Anda, Anda harus mengetahui dimensi yang masuk. Anda dapat menggunakan inJustDecodeBounds
bendera untuk membantu Anda mendapatkan dimensi gambar, tanpa perlu benar-benar mendekode data piksel.
// Decode just the boundaries
mBitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fileName, mBitmapOptions);
srcWidth = mBitmapOptions.outWidth;
srcHeight = mBitmapOptions.outHeight;
//now go resize the image to the size you want
Anda dapat menggunakan tanda ini untuk mendekode ukuran terlebih dahulu, lalu menghitung nilai yang tepat untuk penskalaan ke resolusi target Anda.