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

來源:互聯網
上載者:User

標籤:

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


Hello,好久不見,好久沒寫部落格了,總結了下原因有三,第一,變懶了;第二,變懶了;第三,還是變懶了;因為任何不更新部落格的理由都是借口!


一、效果示範

項目中用到了高斯模糊效果,查閱過一些資料,考慮到效能問題最終還是選擇使用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 RS jni 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的包路徑更換過來:import android.renderscript更換為import android.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,就到這裡了。


四、附:

另外分享兩個處理高斯模糊的GitHub:

https://github.com/wl9739/BlurredView

https://github.com/robinxdroid/Blur


【轉載註明gao_chun的Blog:http://blog.csdn.net/gao_chun/article/details/52193511】


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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.