Saat ini dalam aplikasi Android yang saya kembangkan, saya mengulang-ulang piksel gambar untuk mengaburkannya. Ini membutuhkan waktu sekitar 30 detik pada gambar 640x480.
Saat menelusuri aplikasi di Android Market, saya menemukan satu yang menyertakan fitur blur dan blur mereka sangat cepat (seperti 5 detik) sehingga mereka harus menggunakan metode blur yang berbeda.
Adakah yang tahu cara yang lebih cepat selain mengulang melalui piksel?
Jawaban:
Ini adalah bidikan dalam gelap, tetapi Anda dapat mencoba mengecilkan gambar dan kemudian memperbesarnya lagi. Ini bisa dilakukan dengan
Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
. Pastikan dan atur parameter filter ke true. Ini akan berjalan dalam kode asli sehingga mungkin lebih cepat.sumber
Untuk Googlers masa depan, berikut adalah algoritma yang saya porting dari Quasimondo. Ini semacam campuran antara blur kotak dan blaus gaussian, sangat cantik dan cukup cepat juga.
Pembaruan untuk orang-orang yang mengalami masalah ArrayIndexOutOfBoundsException: @anthonycr di komentar memberikan informasi ini:
sumber
for
lingkaran segera sebelum dereference buruk, baik perhitunganrbs
variabel atau perhitungangsum
,rsum
ataubsum
variabel tidak menjadi dilakukan tepat. Saya menemukan bahwa dengan menggantiMath.abs
denganStrictMath.abs
atau beberapaabs
implementasi lainnya , crash tidak terjadi. SejakStrictMath.abs
didelegasikan kepada dirinya sendiriMath.abs
, sepertinya itu pasti optimasi yang buruk.Android Blur Guide 2016
dengan Aplikasi Showcase / Benchmark dan Sumber di Github . Lihat juga kerangka Blur yang sedang saya kerjakan: Dali .
Setelah banyak bereksperimen, saya sekarang dapat dengan aman memberi Anda beberapa rekomendasi kuat yang akan membuat hidup Anda lebih mudah di Android saat menggunakan Kerangka Android.
Muat dan Gunakan Bitmap yang diturunkan (untuk gambar yang sangat buram)
Jangan pernah gunakan ukuran penuh Bitmap. Semakin besar gambar semakin banyak yang perlu dikaburkan dan juga semakin tinggi radius blur yang perlu dan biasanya, semakin tinggi radius blur semakin lama algoritma dibutuhkan.
Ini akan memuat bitmap dengan
inSampleSize
8, jadi hanya 1/64 dari gambar asli. Uji apa yanginSampleSize
sesuai dengan kebutuhan Anda, tetapi simpanlah 2 ^ n (2,4,8, ...) untuk menghindari penurunan kualitas karena penskalaan. Lihat Google doc untuk lebih lanjutKeuntungan lain yang sangat besar adalah bahwa pemuatan bitmap akan sangat cepat. Dalam pengujian blur awal saya, saya menemukan bahwa waktu paling lama selama seluruh proses blur adalah pemuatan gambar. Jadi untuk memuat gambar 1920x1080 dari disk, Nexus 5 saya membutuhkan 500ms sedangkan pengaburan hanya membutuhkan sekitar 250 ms.
Gunakan Renderscript
Renderscript menyediakan
ScriptIntrinsicBlur
yang merupakan filter blur Gaussian. Ini memiliki kualitas visual yang baik dan hanya tercepat yang Anda dapatkan secara realistis di Android. Google mengklaim "biasanya 2-3x lebih cepat dari implementasi C multithreaded dan sering 10x + lebih cepat daripada implementasi Java" . Renderscript sangat canggih (menggunakan perangkat pemrosesan tercepat (GPU, ISP, dll.), Dll.) Dan ada juga perpustakaan dukungan v8 yang membuatnya kompatibel hingga 2.2.. Yah setidaknya dalam teori, melalui tes dan laporan saya sendiri dari pengembang lain tampaknya tidak mungkin untuk menggunakan Renderscript secara membabi buta, karena fragmentasi perangkat keras / driver tampaknya menyebabkan masalah dengan beberapa perangkat, bahkan dengan lvl sdk yang lebih tinggi (misalnya saya punya masalah dengan 4.1 Nexus S) jadi hati-hati dan uji pada banyak perangkat. Berikut ini contoh sederhana yang akan membantu Anda memulai:Saat menggunakan dukungan v8 dengan Gradle, yang secara khusus direkomendasikan oleh Google "karena mereka menyertakan peningkatan terbaru" , Anda hanya perlu menambahkan 2 baris ke skrip build Anda dan gunakan
android.support.v8.renderscript
dengan tools build saat ini ( sintaks yang diperbarui untuk plugin android Gradle v14 + )Tolok ukur sederhana pada Nexus 5 - membandingkan RenderScript dengan implementasi java dan Renderscript lainnya:
Rata-rata runtime per blur pada berbagai ukuran gambar
Megapiksel per detik yang dapat dikaburkan
Setiap nilai adalah rata-rata 250 putaran.
RS_GAUSS_FAST
adalahScriptIntrinsicBlur
(dan hampir selalu yang tercepat), yang lain yang memulai denganRS_
sebagian besar melibatkan implementasi dengan kernel sederhana. Detail algoritma dapat ditemukan di sini . Ini tidak sepenuhnya kabur, karena sebagian yang baik adalah pengumpulan sampah yang diukur. Ini dapat dilihat di sini (ScriptIntrinsicBlur
pada gambar 100x100 dengan sekitar 500 putaran)Paku itu gc.
Anda dapat memeriksa sendiri, aplikasi benchmark ada di playstore: BlurBenchmark
Gunakan kembali Bitmap sedapat mungkin (jika prio: kinerja> jejak memori)
Jika Anda memerlukan banyak pengaburan untuk pengaburan langsung atau sejenisnya dan memori Anda memungkinkannya tidak memuat bitmap dari drawable beberapa kali, tetapi simpanlah "di-cache" dalam variabel anggota. Dalam hal ini selalu mencoba menggunakan variabel yang sama, untuk menjaga pengumpulan sampah seminimal mungkin.
Periksa juga
inBitmap
opsi baru saat memuat dari file atau drawable yang akan menggunakan kembali memori bitmap dan menghemat waktu pengumpulan sampah.Untuk pencampuran dari tajam ke buram
Metode sederhana dan naif hanya menggunakan 2
ImageViews
, satu kabur, dan alpha memudar mereka. Tetapi jika Anda ingin tampilan yang lebih canggih yang halus memudar dari tajam ke buram, maka periksa pos Roman Nurik tentang bagaimana melakukannya seperti di aplikasi Muzei-nya .Pada dasarnya dia menjelaskan bahwa dia mengaburkan beberapa frame dengan luasan kabur yang berbeda dan menggunakannya sebagai keyframe dalam animasi yang terlihat sangat halus.
sumber
renderscriptSupportModeEnabled true
atau tidak akan dibangun! Saya mencari selamanya!EDIT (April 2014): Ini adalah halaman tanya jawab yang sepertinya masih mendapatkan banyak hit. Saya tahu saya selalu mendapatkan upvotes untuk posting ini. Tetapi jika Anda membaca ini, Anda perlu menyadari bahwa jawaban yang diposting di sini (baik milik saya maupun jawaban yang diterima) sudah usang. Jika Anda ingin menerapkan blur yang efisien hari ini , Anda harus menggunakan RenderScript, bukan NDK atau Java. RenderScript berjalan di Android 2.2+ (menggunakan Perpustakaan Dukungan Android ), jadi tidak ada alasan untuk tidak menggunakannya.
Jawaban lama berikut, tetapi waspadalah karena sudah ketinggalan zaman.
Untuk Googlers² di masa depan, berikut adalah algoritma yang saya porting dari port Yahel tentang algoritma Quasimondo, tetapi menggunakan NDK. Itu berdasarkan jawaban Yahel, tentu saja. Tapi ini menjalankan kode C asli, jadi lebih cepat. Lebih cepat. Seperti, 40 kali lebih cepat.
Saya menemukan bahwa menggunakan NDK adalah bagaimana semua manipulasi gambar harus dilakukan pada Android ... agak menjengkelkan untuk diterapkan pada awalnya (baca tutorial hebat tentang menggunakan JNI dan NDK di sini ), tetapi jauh lebih baik, dan mendekati waktu nyata untuk sebuah banyak hal.
Sebagai referensi, menggunakan fungsi Java Yahel, butuh 10 detik untuk mengaburkan gambar 480x532 piksel saya dengan radius 10 blur. Tetapi butuh 250ms menggunakan versi C asli. Dan saya cukup yakin itu masih dapat dioptimalkan lebih lanjut ... Saya baru saja melakukan konversi bodoh dari kode java, mungkin ada beberapa manipulasi yang dapat dipersingkat, tidak ingin menghabiskan terlalu banyak waktu refactoring semuanya.
Kemudian gunakan seperti ini (mempertimbangkan kelas yang disebut com.insert.your.package.ClassName dan fungsi asli yang disebut functionToBlur, seperti yang dinyatakan oleh kode di atas):
Itu mengharapkan bitmap RGB_8888!
Untuk menggunakan bitmap RGB_565, buat salinan yang dikonversi sebelum melewati parameter (yuck), atau ubah fungsi untuk menggunakan
rgb565
tipe baru alih-alihrgba
:Masalahnya adalah bahwa jika Anda melakukannya Anda tidak dapat membaca
.red
,.green
dan.blue
dari pixel lagi, Anda perlu membaca byte dengan benar, ya. Ketika saya membutuhkan itu sebelumnya, saya melakukan ini:Tapi mungkin ada cara yang kurang bodoh untuk melakukannya. Saya tidak terlalu suka kode C tingkat rendah, saya khawatir.
sumber
r[wh]
,g[wh]
danb[wh]
keuint8_t
.pastebin.com
Kode ini sangat cocok untuk saya
sumber
Anda sekarang dapat menggunakan ScriptIntrinsicBlur dari pustaka RenderScript untuk kabur dengan cepat. Berikut ini cara mengakses RenderScript API. Berikut ini adalah kelas yang saya buat untuk mengaburkan Tampilan dan Bitmap:
sumber
Ini bekerja dengan baik untuk saya: Cara Memburamkan Gambar secara Efisien dengan RenderScript Android
sumber
Gunakan Render Script seperti yang disebutkan di sini http://blog.neteril.org/blog/2013/08/12/blurring-images-on-android/
sumber
Ini untuk semua orang yang perlu meningkatkan jari-jari
ScriptIntrinsicBlur
untuk mendapatkan gaussian blur yang lebih sulit.Alih-alih menempatkan radius lebih dari 25, Anda dapat memperkecil gambar dan mendapatkan hasil yang sama. Saya menulis sebuah kelas bernama
GaussianBlur
. Di bawah ini Anda dapat melihat cara menggunakan, dan implementasi seluruh kelas.Pemakaian:
Kelas:
sumber
Terima kasih @Yahel untuk kodenya. Memposting metode yang sama dengan dukungan saluran alpha kabur karena butuh beberapa waktu untuk membuatnya berfungsi dengan benar sehingga dapat menghemat waktu seseorang:
sumber
Saya menggunakan ini sebelumnya ..
sumber
Untuk Googler masa depan yang memilih pendekatan NDK - saya menemukan algoritma stackblur yang andal. Saya menemukan implementasi C ++ yang tidak bergantung pada SSE di sini - http://www.antigrain.com/__code/include/agg_blur.h.html#stack_blur_rgba32 yang berisi beberapa optimasi menggunakan tabel statis seperti:
Saya membuat modifikasi algoritma stackblur untuk sistem multi-core - dapat ditemukan di sini http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/ Karena semakin banyak perangkat memiliki 4 core - optimasi memberikan Manfaat kecepatan 4x.
sumber
Saran Nicolas POMEPUY. Saya pikir tautan ini akan sangat membantu: Efek blur untuk desain Android
Contoh proyek di github
sumber
Kami mencoba menerapkan RenderScript blur seperti yang disebutkan di atas dalam jawaban yang berbeda. Kami terbatas untuk menggunakan versi v8 RenderScript dan itu menyebabkan kami banyak masalah.
Saya ingin berbagi versi kotor Java-only yang lambat dan harus dilakukan pada utas terpisah dan, jika mungkin, sebelum digunakan dan karenanya tetap ada.
Solusi ini jauh dari sempurna tetapi menciptakan efek blur yang masuk akal berdasarkan fakta, bahwa ia menggambar versi yang sangat transparan dari gambar yang sama di atas versi "tajam" yang nyaris tidak transparan. Alfa tergantung pada jarak ke titik asal.
Anda dapat menyesuaikan beberapa "angka ajaib" dengan kebutuhan Anda. Saya hanya ingin membagikan "solusi" itu untuk semua orang yang memiliki masalah dengan versi dukungan v8 dari RenderScript.
sumber
Bagi mereka yang masih memiliki masalah dengan pustaka dukungan Renderscript pada chipset x86, silakan lihat posting ini oleh pembuat perpustakaan. Sepertinya perbaikan yang disiapkannya tidak membuatnya entah bagaimana ke Build Tools v20.0.0, jadi dia menyediakan file untuk memperbaikinya secara manual dan penjelasan singkat tentang bagaimana melakukannya.
https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=71347
sumber
dari blog Mario Viviani kita dapat menggunakan solusi ini dari 17 Versi Android:
https://plus.google.com/+MarioViviani/posts/fhuzYkji9zz
atau
https://gist.github.com/Mariuxtheone/903c35b4927c0df18cf8
sumber
Berikut adalah overlay buram realtime menggunakan RenderScript, yang tampaknya cukup cepat.
https://github.com/mmin18/RealtimeBlurView
sumber
Saya menemukan bahwa mengurangi kontras, kecerahan dan saturasi sedikit membuat gambar buram lebih cantik, jadi saya menggabungkan berbagai metode dari stack overflow dan membuat Kelas Blur ini yang berhubungan dengan gambar buram, mengubah kecerahan, saturasi, kontras, dan ukuran gambar buram. Itu juga dapat mengkonversi gambar dari drawable ke bitmap dan sebaliknya.
sumber
Pada i / o 2019 solusi berikut disajikan:
sumber