1. 程式人生 > >使用RenderScript來實現高斯模糊,相容低版本

使用RenderScript來實現高斯模糊,相容低版本

這兩天看到公司工程裡有用到高斯模糊,是通過java實現的,很慢,所以找了一些資料,看到RenderScript,效能很好,而且RenderScript是可以相容低版本的,實現方式也是jni。相容低版本的教程網上有很多,就是在sdk目錄裡把RenderScript v8包新增到自己的工程裡,並且把jni的檔案新增到自己的專案裡。這裡把只把程式碼和方法發出來。

/**
     * 初始化控制元件
     */
private void initView(){
        iv_gaussian = (ImageView)findViewById(R.id.iv_gaussian);
        tv_time 
= (TextView)findViewById(R.id.tv_time); long timeStart = SystemClock.currentThreadTimeMillis(); Bitmap bitmap = blurBitmap(getBitmapFromDrawable(),this); time = SystemClock.currentThreadTimeMillis()-timeStart; iv_gaussian.setImageBitmap(bitmap); tv_time.setText("耗時:"
+time); } /** * 獲取資原始檔的bitmap * @return */ private Bitmap getBitmapFromDrawable(){ Resources res = getResources(); return BitmapFactory.decodeResource(res, R.mipmap.bg_1,getScaleOptions(res,R.mipmap.bg_1,200,200)); } /** * 執行高斯模糊 * * @param bitmap
* @param context * @return */ public Bitmap blurBitmap(Bitmap bitmap, Context context) { // 用需要建立高斯模糊bitmap建立一個空的bitmap Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); // 初始化Renderscript,這個類提供了RenderScript context, // 在建立其他RS類之前必須要先建立這個類,他控制RenderScript的初始化,資源管理,釋放 RenderScript rs = RenderScript.create(context); // 建立高斯模糊物件 ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); // 建立Allocations,此類是將資料傳遞給RenderScript核心的主要方法, // 並制定一個後備型別儲存給定型別 Allocation allIn = Allocation.createFromBitmap(rs, bitmap); Allocation allOut = Allocation.createFromBitmap(rs, outBitmap); // 設定模糊度 blurScript.setRadius(25.f); // Perform the Renderscript blurScript.setInput(allIn); blurScript.forEach(allOut); // Copy the final bitmap created by the out Allocation to the outBitmap allOut.copyTo(outBitmap); // recycle the original bitmap bitmap.recycle(); // After finishing everything, we destroy the Renderscript. rs.destroy(); return outBitmap; } /** * 獲取壓縮比例的options * @param width 圖片的最大寬度 * @param height 圖片的最大高度 * @return */ private BitmapFactory.Options getScaleOptions(Resources res,int resId,int width,int height){ BitmapFactory.Options newOpts = new BitmapFactory.Options(); // 開始讀入圖片,此時把options.inJustDecodeBounds 設回true了 newOpts.inJustDecodeBounds = true; // newOpts.inJustDecodeBounds = false; //空的bitmap,不佔記憶體,只是為了拿到寬和高 不需要回收 Bitmap bitmap = BitmapFactory.decodeResource(res,resId,newOpts); int w = newOpts.outWidth; int h = newOpts.outHeight; // 縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可 int be = 1;// be=1表示不縮放 if (w > h && w > width) {// 如果寬度大的話根據寬度固定大小縮放 be = (int) (newOpts.outWidth / width); } else if (w < h && h > height) {// 如果高度高的話根據寬度固定大小縮放 be = (int) (newOpts.outHeight / height); } if (be <= 0) be = 1; newOpts.inSampleSize = be;// 設定縮放比例 LogUtils.showDebugLog("GaussianActivity","縮放比例:"+be); //因為外部的進行解碼操作,所以這時候需要重新設為false newOpts.inJustDecodeBounds = false; return newOpts; }

執行高斯的程式碼是網上拷過來的,模糊半徑最大隻能設到25,可能對圖片直接處理的時候會導致模糊的效果不太好,太清晰,但是可以通過降低圖片的質量來實現更模糊的效果,不知道這個思路對不對,或者說效能上是不是會有什麼不好影響,歡迎大家指正。

2016.4.14更新

昨天聽同事說,圖片的縮放會耗時,又看了一下程式碼,發現程式碼裡有錯誤,現在訂正過了,然後現在把時間的起始放到了縮放之前,耗時是70毫秒左右,圖片大小是720*1080,縮放倍數是6

2016.6.24更新

jar包和.so版本的選擇一定要選最新的,我現在用的是24.0.0,增加了x86-64的適配,體積也小了很多,老版本的在有些64位的機器上會閃退