摘要:今天就來研究一下如何在上實(shí)現(xiàn)高斯模糊效果。平時我們對圖片縮小,必然會帶來很明顯的清晰度的損失,但高斯模糊本身的目的就是要實(shí)現(xiàn)模糊的效果,因此實(shí)際上的效果差別不大,幾乎可以忽略。
前言
從 iOS 7 開始 Apple 從 擬物化 過渡到了 扁平化 的設(shè)計(jì)風(fēng)格,同時也搭配使用了 毛玻璃風(fēng)格 當(dāng)做背景效果,不得不說十分驚艷,頗有當(dāng)時pc上 Widows Vista 和 OS X Yosemite 的味道,在那之后,Google 也從 Android L(5.0)開始使用了 原質(zhì)化設(shè)計(jì)(Material Design) 設(shè)計(jì)語言,與 Microsoft 的 Metro 那種純扁平化風(fēng)格看似很相像,但實(shí)則因?yàn)橐昧?Z軸 的概念,使其有了陰影和立體感,傳達(dá)了 響應(yīng)式交互 的設(shè)計(jì)理念。說到這里有一些跑題,因?yàn)楣P者對設(shè)計(jì)美學(xué)很感興趣,所以對這些平臺都稍微了解一些皮毛。今天就來研究一下如何在 Android 上實(shí)現(xiàn)高斯模糊效果。
目前 Android 上實(shí)現(xiàn)高斯模糊效果的方式有:Java : FastBlur.java ,應(yīng)用非常廣泛的 StackBlur 模糊算法實(shí)現(xiàn)代碼,效率最低
C++ :兩種實(shí)現(xiàn),1:標(biāo)準(zhǔn)高斯模糊算法 2:均值模糊,效率中等
Android : RenderScript ,用來在 Android 上編寫高性能代碼的一種語言(使用C99標(biāo)準(zhǔn),運(yùn)行時機(jī)器再次優(yōu)化編譯, 可以均衡的運(yùn)行在多個CPU 和 GPU上,有一個半徑限制小于25的限制),效率最高
簡單聊聊 FastBlur因?yàn)樾Ч膶?shí)現(xiàn)是基于 Java 的,所以有必要先來了解一下方法如何使用。
public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap)
可以看出,使用方法非常簡單,傳入待虛化的bitmap、虛化程度(一般為8)、是否重用flag,最后返回模糊后的bitmap。
但如果直接把一張大圖傳入進(jìn)行虛化,很容易就會產(chǎn)生OOM內(nèi)存溢出,那就意味著我只能虛化小圖,這樣才能防止內(nèi)存溢出。但是我并不想換其他圖,那么,我們就應(yīng)該把這張圖縮小。
平時我們對圖片縮小,必然會帶來很明顯的清晰度的損失,但高斯模糊本身的目的就是要實(shí)現(xiàn)模糊的效果,因此實(shí)際上的效果差別不大,幾乎可以忽略。
同時由于圖片縮小后再進(jìn)行模糊處理,需要處理的像素點(diǎn)和半徑都變小,從而使得模糊處理速度加快。
ReScalepublic static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) {}
我們可以利用Bitmap的 createScaledBitmap() 方法來進(jìn)行bitmap的縮放。其中前三個參數(shù)很明顯,其中寬高我們可以選擇為原圖尺寸的1/5;第四個filter是指縮放的效果,filter為true則會得到一個邊緣平滑的bitmap,反之,則會得到邊緣鋸齒、pixelrelated的bitmap。這里我們要對縮放的圖片進(jìn)行虛化,所以無所謂邊緣效果,filter=false。
所以,我們要使用
int scaleRatio = 5;// 縮放比例 此處代表1/5 int blurRadius = 8;// 虛化程度 Bitmap scaledBitmap = Bitmap.createScaledBitmap(originBitmap, originBitmap.getWidth() / scaleRatio, originBitmap.getHeight() / scaleRatio, false); Bitmap blurBitmap = FastBlur.doBlur(scaledBitmap, blurRadius, true); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setImageBitmap(blurBitmap);
可以得到如下效果:
從圖中可以看出,首先可以確定思路是對的;然后,可以看出毛玻璃效果還不是特別的明顯。為了得到如iOS那樣的虛化效果,我們有兩種方法:
增大scaleRatio縮放比,使用更小的bitmap去虛化可以得到更好的模糊效果,而且有利于占用內(nèi)存的減小;
增大blurRadius,可以得到更高程度的虛化,不過會導(dǎo)致CPU更加intensive
這里筆者通過增大縮放比來實(shí)驗(yàn)。
scaleRatio = 10
scaleRatio = 20
通過上面對比圖我們可以找出最適合自己的虛化效果。
再來聊聊 RenderScriptRenderScript 主要 在Android中的對圖形進(jìn)行處理,RenderScript 采用C99語法進(jìn)行編寫,主要優(yōu)勢在于性能較高。在 API 11 的時候被加入到 Android 中。同時,Google提供了android.support.v8.renderscript兼容包,能夠?qū)崿F(xiàn)更低版本的兼容。
RenderScript 提供了一個用于實(shí)現(xiàn)高斯模糊的封裝類 ScriptIntrinsicBlur ,因?yàn)樵?API 17 后才正式適配到 Android ,所以在不使用兼容包的情況下只能兼容到4.2的設(shè)備。但是,我們有兼容包啊向下兼容不是夢。
準(zhǔn)備階段 引入兼容包方法很簡單,只需在build.gradle中加入:
defaultConfig { .... // 就是這么簡單 renderscriptTargetApi 19 renderscriptSupportModeEnabled true }
另外由于一些廠商會深度定制Android系統(tǒng),所以一些必要的依賴文件會被他們直接去掉,這導(dǎo)致一些型號的設(shè)備上調(diào)用RenderScriptd的部分方法時會報錯。遇到這種兼容問題的話,需要加上這些可能丟失的文件。
其實(shí)也簡單,打開android_sdk/build-tools/選擇19以上版本/renderscript/lib/packaged我們可以看見3個包含.so文件的文件夾。
直接復(fù)制這三個文件加到項(xiàng)目工程的 jniLibs 包下,沒有的話去建一個。
如果首次創(chuàng)建 jniLibs 文件夾,還需要在 build.gradle 的 android{} 中加入:
sourceSets { main { jniLibs.srcDirs = ["jniLibs"] } }
針對使用的混淆的同學(xué),需要在混淆中加入:
-keep class android.support.v8.renderscript.** { *; }實(shí)現(xiàn)高斯模糊
將核心實(shí)現(xiàn)方法 ScriptIntrinsicBlur 封裝成工具類。
import android.support.v8.renderscript.*; // 需要導(dǎo)入v8包,否則無法向下兼容 public class BlurBitmapUtil { /*** * 圖片縮放比例 (例如 1/10) */ private static int scaleRatio = 10; /** * 對圖片進(jìn)行高斯模糊 * * @param context 上下文對象 * @param image 需要模糊的圖片 * @param blurRadius 模糊半徑,由于性能限制,這個值的取值區(qū)間為(0至25f) * @return 模糊處理后的圖片 */ public static Bitmap blurBitmap(Context context, Bitmap image, @FloatRange(from = 1, to = 25) float blurRadius) { // 計(jì)算圖片縮小后的長寬 int width = Math.round(image.getWidth() / scaleRatio); int height = Math.round(image.getHeight() / scaleRatio); // 創(chuàng)建一張縮小后的圖片做為渲染的圖片 Bitmap bitmap = Bitmap.createScaledBitmap(image, width, height, false); // 創(chuàng)建RenderScript內(nèi)核對象 RenderScript rs = RenderScript.create(context); // 創(chuàng)建一個模糊效果的RenderScript的工具對象,第二個參數(shù)Element相當(dāng)于一種像素處理的算法,高斯模糊的話用這個就好 ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); // 由于RenderScript并沒有使用VM來分配內(nèi)存,所以需要使用Allocation類來創(chuàng)建和分配內(nèi)存空間 // 創(chuàng)建Allocation對象的時候其實(shí)內(nèi)存是空的,需要使用copyTo()將數(shù)據(jù)填充進(jìn)去 Allocation input = Allocation.createFromBitmap(rs, bitmap); // 創(chuàng)建相同類型的Allocation對象用來輸出 Type type = input.getType(); Allocation output = Allocation.createTyped(rs, type); // 設(shè)置渲染的模糊程度, 25f是最大模糊度 blurScript.setRadius(blurRadius); // 設(shè)置blurScript對象的輸入內(nèi)存 blurScript.setInput(input); // 將輸出數(shù)據(jù)保存到輸出內(nèi)存中 blurScript.forEach(output); // 將數(shù)據(jù)填充到bitmap中 output.copyTo(bitmap); // 銷毀它們釋放內(nèi)存 input.destroy(); output.destroy(); blurScript.destroy(); rs.destroy(); type.destroy(); return bitmap; }
使用 RenderScript 增加虛化程度的方法和 FastBlur 一樣,有兩種方法:
增大scaleRatio縮放比,使用更小的bitmap去虛化可以得到更好的模糊效果,而且有利于占用內(nèi)存的減小;
增大blurRadius,可以得到更高程度的虛化,不過會導(dǎo)致虛化時間變長
但因?yàn)?RenderScript 的天然優(yōu)勢(低級語言, 運(yùn)行時機(jī)器再次優(yōu)化編譯, 可以均衡的運(yùn)行在多個CPU 和 GPU上),所以這里筆者通過增大虛化程度來實(shí)驗(yàn),縮放比例為 1/10,實(shí)際運(yùn)用時可以根據(jù)需求在對虛化程度和縮放比例上采取一個合適的數(shù)值。
blurRadius = 5
blurRadius = 15
blurRadius = 25
通過上面對比圖我們可以找出最適合自己的虛化效果。
目前來看,為何 Google 設(shè)置這個25的限制, 原因應(yīng)該有兩個 :
半徑大于25的話耗時就成為了一個瓶頸;
如果想實(shí)現(xiàn)大于25的模糊效果,可以通過縮小原圖,模糊,再放大來達(dá)到同樣的效果
總結(jié)以上就是如何用 FastBlur 和 RenderScript 在 Android 上實(shí)現(xiàn)和 iOS 一樣的高斯模糊效果的簡單介紹,雖然在性能上毋庸置疑是 RenderScript 上最好,但是在一些使用場景上 FastBlur 耗時會更短,所以我們各取所需,根據(jù)實(shí)際需求去選擇使用。
另一種可能性上面說的2種解決方案都是從性能和效率出發(fā)的產(chǎn)物,但如果我的需求就是從網(wǎng)絡(luò)上加載一張圖片(比如頭像),然后再高斯模糊化當(dāng)背景,走一遍轉(zhuǎn)換成bitma再將其轉(zhuǎn)換成高斯模糊的流程或許會有一點(diǎn)點(diǎn)麻煩,這里我再提供一種簡單快捷的解決方案 —— 基于Glid加載框架去實(shí)現(xiàn)一鍵 加載網(wǎng)絡(luò)圖片→高斯模糊化→展示。
引入兼容包首先在build.gradle中加入圖片框架需要的庫和圖片工具庫:
defaultConfig { .... compile "com.yutianran.maven:super-adapter:1.0.0" compile "jp.wasabeef:glide-transformations:2.0.2" }然后就開寫,一行代碼即可
Glide.with(this).load(url).bitmapTransform(new BlurTransformation(this,25)).into(imageView);
需要的參數(shù)很分別是
上下文對象
圖片url
上下文對象,虛化數(shù)值
imageView控件
效果如上,可以看出 glide-transformations 庫的虛化效果也是十分不錯的,但對圖片本身做的縮放應(yīng)該不是很多,所以在加載速度上會弱于 FastBlur 和 RenderScript ,但作為輕量級圖片而言足夠了。
Code相關(guān)代碼已上傳至Github:BlurView,歡迎Star,F(xiàn)ork。
參考文獻(xiàn)[[譯] RenderScript:簡單而快速的圖像處理](https://toutiao.io/posts/44zw...
圖片高斯模糊效果簡單優(yōu)化
高斯模糊效果實(shí)現(xiàn)方案及性能對比
Android:簡單靠譜的動態(tài)高斯模糊效果
教你一分鐘實(shí)現(xiàn)動態(tài)模糊效果
什么?IOS的專利?Android也能流暢實(shí)現(xiàn)毛玻璃效果(高斯模糊)效果
Android 高斯模糊總結(jié)
Android RenderScript 簡單高效實(shí)現(xiàn)圖片的高斯模糊效果
干貨 一種快速毛玻璃虛化效果實(shí)現(xiàn)--Android
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/66982.html
摘要:毛玻璃效果相信很多朋友都眼紅很久了,隔壁系統(tǒng)對高斯模糊早就大范圍使用了,咱們卻絲毫不為所動,于是就只能靠廣大開發(fā)者咯。 毛玻璃效果相信很多朋友都眼紅很久了,隔壁ios系統(tǒng)對高斯模糊早就大范圍使用了,咱們Android卻絲毫不為所動,于是就只能靠廣大開發(fā)者咯。 這是目前市面上性能最高的方案,也不知道最初是哪位大神寫的,我也只是拿來封裝一下,變得更簡單、更好用,加上了陰影遮罩的效果。 先來...
閱讀 922·2019-08-30 15:54
閱讀 1484·2019-08-30 15:54
閱讀 2409·2019-08-29 16:25
閱讀 1304·2019-08-29 15:24
閱讀 758·2019-08-29 12:11
閱讀 2516·2019-08-26 10:43
閱讀 1239·2019-08-26 10:40
閱讀 480·2019-08-23 16:24