IOS的專利?Android也能流暢實現毛玻璃效果效果
背景介紹
上圖就是我們在IOS裝置上經常能夠見到的毛玻璃(高斯模糊)效果。不得不說,這種效果在適合的場景下使用,能夠獲得絕佳的美感。但是鑑於Android裝置效能和相容性問題,我們通常很難在Android裝置上見到這種效果。
但這並不是IOS的專利效果,Android也能輕鬆流暢的實現。本篇文章將會詳細的講解如何實現。
Android中的高斯模糊
我為什麼選擇RenderScript實現高斯模糊
目前Android裝置上實現高斯模糊效果的方式通常有:
1. 雲端處理,移動客戶端直接從網路獲取處理好的圖片。這種方式侷限性很大。
2. FastBlur等開源庫。這種方式相容性不錯,但是效率極低。
3. c實現。不懂c的理解困難。
4. OpenGL實現。效果很好,但電量和記憶體消耗比較高。
5. RenderScript實現。效果略弱於第4種,但是使用方便,速度很快,效能消耗在可接受範圍內,加上Google的相容性解決方案,可以說是能夠作為優先考慮的方式。
RenderScript
RenderScript主要在android中的對圖形進行處理,RenderScript採用C99語法進行編寫,主要優勢在於效能較高。在Api11的時候被加入到Android中。同時,Google提供了
android.support.v8.renderscript
相容包,能夠實現更低版本的相容。
RenderScript提供了一個用於實現高斯模糊的封裝類ScriptIntrinsicBlur ,這貨在Api17才被收編Android所以在不使用相容包的情況下只能相容到4.2的裝置。但是,我們有相容包啊向下相容不是夢。
準備階段
引入相容包
方法很簡單,只需在build.gradle中加入:
defaultConfig {
。
。
。
//就是這麼簡單
renderscriptTargetApi 19
renderscriptSupportModeEnabled true
}
你以為這樣就好了?nonono。
由於一些坑人的廠商會深度定製Android系統,所以一些必要的依賴檔案會被它們直接去掉!!這導致一些型號的裝置上呼叫RenderScriptd的部分方法時會報錯。所以我們得加上這些可能丟失的檔案。
其實也簡單,開啟android_sdk/build-tools/選擇19以上版本/renderscript/lib/packaged
直接複製這三個檔案加到專案工程的jniLibs 包下。什麼?找不見jniLibs包?自己建一個嘍。
注意,這時候,我們很可能遇到一個奔潰,找不到.os檔案。莫慌莫慌…
在build.gradle的android{}中加入:
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
沒完沒了!最後一步只針對使用的混淆的同學,需要在混淆中加入:
-keep class android.support.v8.renderscript.** { *; }
實現高斯模糊
終於可以開始寫程式碼了。先來看看效果。下圖高斯模糊半徑逐漸增大的效果,請忽略渣渣錄屏效果
- 將ScriptIntrinsicBlur封裝成工具類。咱們程式碼裡接著款
import android.support.v8.renderscript.*; //這句很重要啊,v8包的,不然不能向下相容啊。
public class RenderScriptGaussianBlur {
private RenderScript rs;
public RenderScriptGaussianBlur(Context context) {
// 建立RenderScript核心物件
this.rs = RenderScript.create(context);
}
/**
* 將圖片高斯模糊化
* @param radius 模糊半徑,由於效能限制,這個值的取值區間為(0,25f]
* @param bitmapOriginal 源Bitmap
*/
public Bitmap blur(float radius, Bitmap bitmapOriginal) {
Bitmap bmp = Bitmap.createBitmap(bitmapOriginal);
// 由於RenderScript並沒有使用VM來分配記憶體,所以需要使用Allocation類來建立和分配記憶體空間。
final Allocation input = Allocation.createFromBitmap(rs, bmp);
//Type: “一個Type描述了一個Allocation或者並行操作的Element和dimensions ”
Type type = input.getType();
final Allocation output = Allocation.createTyped(rs, type);
//建立一個模糊效果的RenderScript的工具物件
//第二個引數Element相當於一種畫素處理的演算法,高斯模糊的話用這個就好
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
//設定渲染的模糊程度, 25f是最大模糊度
script.setRadius(radius);
// 設定blurScript物件的輸入記憶體
script.setInput(input);
// 將輸出資料儲存到輸出剛剛建立的輸出記憶體中
script.forEach(output);
// 將資料填充到bitmap中
output.copyTo(bmp);
//銷燬它們釋放記憶體
input.destroy();
output.destroy();
script.destroy();
type.destroy();
return bmp;
}
public void destory(){
this.rs.destroy();
}
}
挺簡單的幾句,現在我們看看如何使用。
- 降低需要進行高斯模糊的圖片質量
雖然說使用RenderScript能夠高效的進行圖片的高斯模糊,但是對於較大的圖片還是顯的力不從心。畢竟是要對每一個畫素點都要進行處理。況且一般來說,高斯模糊後圖片都比較模糊,我為何要用高清圖?��
降低圖片質量的程式碼相信大家都倒背如流了,這裡就不再重複放碼了。
- 圖片的高斯模糊化一定要非同步進行
//處理化一個RenderScriptGaussianBlur,記得在Activity的onDestory()中呼叫destroy()釋放記憶體
blurRender = new RenderScriptGaussianBlur(this);
//這段程式碼的效果就是每點選一次按鈕,高斯模糊半徑blurRadius就+1,
//然後在RxJava的Schedulers.computation()執行緒中進行Bitmap的高斯模糊化,
//接著在onNext()中將處理後獲得的圖片設定顯示。
//也就是上圖的效果
btn2.setOnClickListener(v -> {
if (mBitmap != null && blurRadius <= 25) {
Disposable d = Observable.create(new ObservableOnSubscribe<Bitmap>() {
@Override
public void subscribe(ObservableEmitter<Bitmap> e) throws Exception {
LogUtils.e("當前blurRadius = " + blurRadius);
//對圖片進行高斯模糊處理
Bitmap bitmap = blurRender.blur(blurRadius, mBitmap);
blurRadius++;
if (blurRadius == 25){
blurRadius = 1;
}
e.onNext(bitmap);
e.onComplete();
}
})
.subscribeOn(Schedulers.computation()) //指定運算執行緒
.observeOn(AndroidSchedulers.mainThread()) //切換回主執行緒
.subscribeWith(new DisposableObserver<Bitmap>() {
@Override
public void onNext(Bitmap bitmap) {
iv.setImageBitmap(bitmap); //展示圖片
}
@Override
public void onError(Throwable e) {}
@Override
public void onComplete() {}
});
disposable.add(d);
}
});
效能問題
測試機:Meizu M2 Note
系統:Android 5.1
上圖高斯模糊時的CPU及記憶體變化:
從上圖可以看到,即使我原本在播放一個動畫時的CPU使用率大概在6% 左右。在開始高斯模糊運算後,隨著高斯模糊半徑的逐漸增大,CPU峰值最大也就在21.3%。可見這種解決方案的效率是極高的。
總結
通過本篇的介紹,相信大家已經對這種在Android裝置上實現高斯模糊效果的解決方案有所瞭解了。是不是手癢想親自動手試一試呢?
當然啦,如果產品說要個高斯模糊的效果,還是那句話:IOS專利!Android做不了!��
參考文獻
- Google Api文件
- Google Blog-RenderScript in the Android Support Library
- Android : Simple and fast image processing with RenderScript
- Android RenderScript 簡單高效實現圖片的高斯模糊效果;
如果覺得這篇文章不錯,點贊走一走,關注走一走啊。