天天看點

Android實作動态高斯模糊

網上有一把分享,不過我還是打算搞一下,嘻嘻嘻。。。先上核心代碼,後說明

private Bitmap blur(Bitmap bitmap, float radius) {
        Bitmap output = Bitmap.createBitmap(bitmap); // 建立輸出圖檔
        RenderScript rs = RenderScript.create(getActivity()); // 建構一個RenderScript渲染對象
        ScriptIntrinsicBlur gaussianBlue = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); //
        // 建立高斯模糊腳本
        Allocation allIn = Allocation.createFromBitmap(rs, bitmap); // 開辟輸入記憶體
        Allocation allOut = Allocation.createFromBitmap(rs, output); // 開辟輸出記憶體
        gaussianBlue.setRadius(radius); // 設定模糊半徑,(0.0f,25.0f]
        gaussianBlue.setInput(allIn); // 設定輸入記憶體
        gaussianBlue.forEach(allOut); // 模糊編碼,并将記憶體填入輸出記憶體
        allOut.copyTo(output); // 将輸出記憶體編碼為Bitmap,圖檔大小必須注意,可以預先将圖檔壓縮
        rs.destroy(); // 關閉RenderScript對象,API>=23則使用rs.releaseAllContexts()
        return output;
    }
           

RenderScript渲染腳本是安卓平台進行高性能計算的架構,該類使用了大量的native方法,我現在着實看不懂,隻會調用其方法。在此mark一下。這個blur類隻要輸入目标圖檔和想要模糊的程度參數就可以了。

動态實作高斯模糊如果是通過blur類動态修改模糊度的話,會設計大量的計算,結果就是效果很卡頓。

這裡有一個巧妙的實作,就是将兩張圖檔疊加在一起,底下的那張圖檔事先就已經實作了模糊度,然後動态修改上面的那張圖檔的透明度。

<LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="300dp">

                <ImageView
                    android:scaleType="fitCenter"
                    android:id="@+id/fragment3_iv1"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />

                <ImageView
                    android:id="@+id/fragment_vi2"
                    android:src="@drawable/beatui"
                    android:scaleType="fitCenter"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />

            </FrameLayout>

            <SeekBar
                android:id="@+id/fragment_seekBar"
                android:layout_width="match_parent"
                android:layout_height="50dp" />

</LinearLayout>
           
iv=findViewById(R.id.fragment3_iv1);
        iv2=findViewById(R.id.fragment_vi2);
        seekBar=findViewById(R.id.fragment_seekBar);
        seekBar.setMax(255);
   
        final Bitmap res=BitmapFactory.decodeResource(getResources(),R.drawable.beatui);
        iv.setImageBitmap(blur(res,25f));
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                iv2.setImageAlpha(255-progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
           

然後通過seekbar動态就該圖檔的透明度就實作動态高斯模糊了。學習是一個過程,堅持!