Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 實現高斯模糊效果及低版本兼容

Android 實現高斯模糊效果及低版本兼容

編輯:關於Android編程

一、效果演示

項目中用到了高斯模糊效果,查閱過一些資料,考慮到性能問題最終還是選擇使用Android自帶的RenderScript庫來實現,關於使用RenderScript來實現高斯模糊網上也有很多類似的方法,大部分都總結的比較亂,此處算是做一個整理吧,供有類似需求的同學參考及學習。

\

 

\ \

(項目效果圖)

簡單描述項目效果圖的實現思路:

① 加載定義的xml的Layout

② 使用截屏方法獲取當前窗口的Bitmap對象

③ 將Bitmap對象進行壓縮及高斯模糊處理

④ 將處理過的模糊圖對象作為①中所加載出來的Layout的Background

⑤ 將已經加入了模糊圖對象的Layout添加到PopuWindow中並處理子條目的彈出方式

 

二、適用RenderScript實現高斯模糊

實現高斯模糊效果的方法有很多,可以用java來實現,可以使用NDK來實現,也可以使用本文推薦的方式來實現(也是使用了JNI的方式),至於為什麼選擇使用RenderScript方式來實現,必然有一定優點。

優點:RenderScript方式,速度極快,約為java方式100倍的速度,NDK方式20倍速度(不同圖片質量測試所得結果不同,供參考)

缺點:API17以上有效。(但Google已提供向下兼容的方法,文章後面會有介紹)

下面是使用RenderScript方式的核心代碼:

 

/************************
* 高斯模糊處理
* @param bitmap
* @param context
* @return
***********************/

public static Bitmap blurBitmap(Bitmap bitmap, Context context) {

        // 用需要創建高斯模糊bitmap創建一個空的bitmap
        Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), 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);

        //設定模糊度(注:Radius最大只能設置25.f)
        blurScript.setRadius(15.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;
    }

 

該方法中注釋描述的很清楚,但需要注意的是blurScript.setRadius();方法,該方法設定模糊度時Radius最大只能設置25.f,可能是對圖片直接進行處理會導致模糊效果不好,故此值最大有效設定為25,但若想實現更深度的模糊效果,可以先壓縮圖片,降低圖片的質量來實現更模糊的效果。

下方是圖片的壓縮處理方法:

 

/**
     * Compress image by pixel, this will modify image width/height.
     *
     * @param imgPath image path
     * @param pixelW target pixel of width
     * @param pixelH target pixel of height
     * @return
     */
    public static Bitmap ratio(String imgPath, float pixelW, float pixelH) {
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        // 開始讀入圖片,此時把options.inJustDecodeBounds 設回true,即只讀邊不讀內容
        newOpts.inJustDecodeBounds = true;
        newOpts.inPreferredConfig = Config.RGB_565;
        // Get bitmap info, but notice that bitmap is null now
        Bitmap bitmap = BitmapFactory.decodeFile(imgPath,newOpts);

        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;

        float ww = pixelW;    //設置寬度為120f,可以明顯看到圖片縮小了
        float hh = pixelH;    //設置高度為240f時,可以明顯看到圖片縮小了

        //縮放比,由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可
        int be = 1;//表示不縮放
        if (w > h && w > ww) {          //如果寬度大的話根據寬度固定大小縮放
            be = (int) (newOpts.outWidth / ww);
        } else if (w < h && h > hh) {   //如果高度高的話根據寬度固定大小縮放
            be = (int) (newOpts.outHeight / hh);
        }
        if (be <= 0) be = 1;
        newOpts.inSampleSize = be;//設置縮放比例
        // 開始壓縮圖片,注意此時已經把options.inJustDecodeBounds 設回false了
        bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
        // 壓縮好比例大小後再進行質量壓縮
        //return compress(bitmap, maxSize); //這裡再進行質量壓縮的意義不大,反而耗資源,刪除
        return bitmap;
    }
以上方法是使用RenderScript來實現高斯模糊的核心代碼塊及需注意的地方。但是,還是需要注意兼容問題,上述有提到該方法僅適用於API17以上才有效,那麼問題來了,需要處理API向下兼容問題。

三、處理API向下兼容問題及注意點

在按照上述方法實現高斯模糊後,運行一看效果,滿滿的成就感,此時,Boss正好帶著客戶過來,小伙子,來,幫客戶安裝一個最新的版本(客戶手機系統版本為Android4.0),裝完後一點。。。。。。。。。。。這特麼就尴尬了…………!

追蹤bug時有同學可能會出現如下錯誤信息:

異常信息一:

09-21 15:07:34.417: E/AndroidRuntime(4476): android.support.v8.renderscript.RSRuntimeException: Error loading RSjni library: java.lang.UnsatisfiedLinkError: Couldn't load RSSupport: findLibrary returned null………………

異常信息二:

java.lang.NoClassDefFoundError: android.renderscript.ScriptIntrinsicBlur………………

 

解決方案:

報錯信息為android.support.v8.renderscript.RSRuntimeException: Error loading以及java.lang.UnsatisfiedLinkError: Couldn't load RSSupport from loader dalvik.system.PathClassLoader是由於在4.2以上的手機自帶librsjni.so和libRSSupport.so庫,而4.2以下某些手機沒有這兩個jni庫。所以得把這兩個jni 導入到我們的工程下便可。那麼文件在何處呢?

以下是本人的文件路徑:C:\Tools\android-sdk\build-tools\23.0.3\renderscript\lib\packaged,renderscript-v8.jar包位於renderscript\lib目錄下。

即:android sdk 路徑下 build-tools\各個版本\renderscript\lib\packaged 下的四個目錄,這裡需要注意jar包和.so版本的選擇最好選最新的,例如24.0.0中增加了x86-64的適配。

\

好了,到這裡就可以完美的兼容4.2以下的版本了。另外,還有一個最最最重要的注意點,我被這個細節困擾了至少2小時,現在想起來還覺得蛋疼,在你做完上面的一切事情之後,請注意一定能要將import的包路徑更換過來:importandroid.renderscript更換為importandroid.support.v8.renderscript。具體如下:

 

import android.support.v8.renderscript.Allocation;
import android.support.v8.renderscript.Element;
import android.support.v8.renderscript.RenderScript;
import android.support.v8.renderscript.ScriptIntrinsicBlur;
最最最最後需要注意的一點,若項目中對代碼加了混淆,別忘了這個。OK,就到這裡了。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved