Android實(shí)現(xiàn)動(dòng)態(tài)高斯模糊效果
高斯模糊是什么?
高斯模糊(英語:Gaussian Blur),也叫高斯平滑,是在Adobe Photoshop、GIMP以及Paint.NET等圖像處理軟件中廣泛使用的處理效果,通常用它來減少圖像噪聲以及降低細(xì)節(jié)層次。這種模糊技術(shù)生成的圖像,其視覺效果就像是經(jīng)過一個(gè)半透明屏幕在觀察圖像,這與鏡頭焦外成像效果散景以及普通照明陰影中的效果都明顯不同。
什么?看不明白?沒關(guān)系,我也看不明白,維基百科復(fù)制回來的嘛。我們直接放一些圖片來了解以下這個(gè)高斯模糊是怎么樣的。因?yàn)楦咚鼓:趇OS中最常見,這里抓了幾張iOS網(wǎng)易云的圖片:
可以看到這個(gè)界面中的背景,其實(shí)就是通過圖1中間那個(gè)小圖片模糊得到的,這樣做的好處就是整體性很好,并且不會(huì)因?yàn)閳D片過渡突兀而影響界面內(nèi)容的閱讀。
那么,究竟在Android上怎么去實(shí)現(xiàn)這個(gè)效果呢?這里推薦使用官方提供在Support Library中的一個(gè)工具來做,就是RenderScript。這個(gè)RenderScript的功能其實(shí)不止有這一個(gè),而其他的一些功能,可以在官方文檔中閱讀學(xué)習(xí),這里不給出。
使用這個(gè)工具的原因其實(shí)很簡(jiǎn)單,就是性能。因?yàn)樯婕暗嚼L圖,所以如果性能不行,那么無論對(duì)于高質(zhì)量圖片或者是變化較多的需求都是很吃力的,而這個(gè)工具則會(huì)充分發(fā)揮設(shè)備的計(jì)算能力(CPU和GPU)來進(jìn)行計(jì)算,并且是使用C99衍生語言進(jìn)行腳本編寫的,相較于Java性能是大大的提升。
說到這里,有些同學(xué)就開始方了,C99衍生?What?這個(gè)不需要擔(dān)心,對(duì)于高斯模糊這個(gè)實(shí)現(xiàn),Google官方已經(jīng)給出了對(duì)應(yīng)的解決方案,我們并不需要編寫對(duì)應(yīng)的腳本就可以使用了,所以無需擔(dān)心。
我們把整個(gè)問題分為兩個(gè)部分:
①高斯模糊實(shí)現(xiàn);
②動(dòng)態(tài)高斯模糊實(shí)現(xiàn)
① 高斯模糊實(shí)現(xiàn)
首先要說明,我們要使用Support Library,所以版本是有要求的:
Android SDK Tools 版本必須大于等于22.2
Android SDK Build-tools 版本必須大于等于18.1.0
如果沒有達(dá)到,請(qǐng)使用SDK Manager升級(jí)一下。
接著創(chuàng)建我們的工程,并且在對(duì)應(yīng)Module(默認(rèn)創(chuàng)建的是app)的build.gradle文件中加入如下代碼:
defaultConfig { ... renderscriptTargetApi 18 renderscriptSupportModeEnabled true }
renderscriptTargetApi:這個(gè)一般和App支持的最低版本相同即可。
package com.fndroid.renderscriptdemo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.renderscript.Allocation; import android.renderscript.Element; import android.renderscript.RenderScript; import android.renderscript.ScriptIntrinsicBlur; import android.support.v7.app.AppCompatActivity; import android.widget.ImageView; public class MainActivity extends AppCompatActivity { private ImageView mImageView; private Bitmap sampleImg; private Bitmap gaussianBlurImg; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageView = (ImageView) findViewById(R.id.iv); sampleImg = BitmapFactory.decodeResource(getResources(), R.drawable.icon); // 獲取原圖 gaussianBlurImg = blur(sampleImg, 25f); mImageView.setImageBitmap(gaussianBlurImg); } private Bitmap blur(Bitmap bitmap,float radius) { Bitmap output = Bitmap.createBitmap(bitmap); // 創(chuàng)建輸出圖片 RenderScript rs = RenderScript.create(this); // 構(gòu)建一個(gè)RenderScript對(duì)象 ScriptIntrinsicBlur gaussianBlue = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); // 創(chuàng)建高斯模糊腳本 Allocation allIn = Allocation.createFromBitmap(rs, bitmap); // 創(chuàng)建用于輸入的腳本類型 Allocation allOut = Allocation.createFromBitmap(rs, output); // 創(chuàng)建用于輸出的腳本類型 gaussianBlue.setRadius(radius); // 設(shè)置模糊半徑,范圍0f<radius<=25f gaussianBlue.setInput(allIn); // 設(shè)置輸入腳本類型 gaussianBlue.forEach(allOut); // 執(zhí)行高斯模糊算法,并將結(jié)果填入輸出腳本類型中 allOut.copyTo(output); // 將輸出內(nèi)存編碼為Bitmap,圖片大小必須注意 rs.destroy(); // 關(guān)閉RenderScript對(duì)象,API>=23則使用rs.releaseAllContexts() return output; } }
這里說明都注釋在代碼中了。需要了解的是RenderScript有兩個(gè)版本,分別是:
android.renderscript
android.support.v8.renderscript
上面代碼使用了第一個(gè),第二個(gè)的用法類似,可以自行嘗試。
我們來理一下思路,因?yàn)?strong>RenderScript是依賴于Script的,而上文也說到了,Script是由C99衍生語言編寫,而代碼中的ScriptIntrinsicBlur就是對(duì)應(yīng)于高斯模糊算法的腳本。而Allocation對(duì)象則是將Java中的對(duì)象轉(zhuǎn)換為Script腳本所需類型的幫手,代碼中創(chuàng)建了兩個(gè)Allocation對(duì)象分別用來充當(dāng)輸入和輸出。接著設(shè)置了高斯模糊的半徑(radius)。當(dāng)調(diào)用forEach時(shí),腳本會(huì)被執(zhí)行,并且將執(zhí)行結(jié)果填入輸出對(duì)應(yīng)的Allocation中,最后調(diào)用copyTo來轉(zhuǎn)換為Bitmap對(duì)象返回。
效果圖:
② 動(dòng)態(tài)高斯模糊
很多時(shí)候,我們可能會(huì)需要一個(gè)圖片以不同的模糊程度展現(xiàn)出來。你可能已經(jīng)注意到上面方法中的模糊半徑了,我們可以做一個(gè)實(shí)驗(yàn),就是通過一個(gè)SeekBar來動(dòng)態(tài)改變這個(gè)值看看效果:
由動(dòng)圖可以看到,我們拖動(dòng)SeekBar的時(shí)候,SeekBar已經(jīng)跟不上我們的拖動(dòng)了。這是為什么?原因就是這個(gè)渲染工具雖然性能比較優(yōu)異,但是如果圖片的質(zhì)量和尺寸都較高的時(shí)候,我們直接進(jìn)行修改模糊半徑重新渲染的做法往往時(shí)不可取的。
做法是,先創(chuàng)建一張模糊的圖片加載在ImageView中,接著在這個(gè)ImageView的上面再放置一個(gè)加載原圖ImageView,使用FrameLayout可以讓這兩個(gè)ImageView重疊再一起,接著當(dāng)我們需要?jiǎng)討B(tài)改變模糊程度的時(shí)候,改變上層的ImageView的BitmapAlpha就可以了。我們先看看效果圖:
使用了這個(gè)方法,滑動(dòng)起來就會(huì)比較流暢了。(GIF加載完才是會(huì)是正常速度哦)
這里給一下代碼參考吧:
public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener { private ImageView mImageView; private ImageView mImageViewCover; private Bitmap sampleImg; private Bitmap gaussianBlurImg; private SeekBar mSeekBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageView = (ImageView) findViewById(R.id.iv); mSeekBar = (SeekBar) findViewById(R.id.sb); mImageViewCover = (ImageView) findViewById(R.id.iv_cover); sampleImg = BitmapFactory.decodeResource(getResources(), R.drawable.icon); // 獲取原圖 gaussianBlurImg = blur(sampleImg, 25f); mImageView.setImageBitmap(gaussianBlurImg); mSeekBar.setOnSeekBarChangeListener(this); } private Bitmap blur(Bitmap bitmap, float radius) { Bitmap output = Bitmap.createBitmap(bitmap); // 創(chuàng)建輸出圖片 RenderScript rs = RenderScript.create(this); // 構(gòu)建一個(gè)RenderScript對(duì)象 ScriptIntrinsicBlur gaussianBlue = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); // // 創(chuàng)建高斯模糊腳本 Allocation allIn = Allocation.createFromBitmap(rs, bitmap); // 開辟輸入內(nèi)存 Allocation allOut = Allocation.createFromBitmap(rs, output); // 開辟輸出內(nèi)存 gaussianBlue.setRadius(radius); // 設(shè)置模糊半徑,范圍0f<radius<=25f gaussianBlue.setInput(allIn); // 設(shè)置輸入內(nèi)存 gaussianBlue.forEach(allOut); // 模糊編碼,并將內(nèi)存填入輸出內(nèi)存 allOut.copyTo(output); // 將輸出內(nèi)存編碼為Bitmap,圖片大小必須注意 rs.destroy(); // 關(guān)閉RenderScript對(duì)象,API>=23則使用rs.releaseAllContexts() return output; } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { int alpha = 255 - progress; mImageViewCover.setImageAlpha(alpha); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }
布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.fndroid.renderscriptdemo.MainActivity"> <FrameLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <ImageView android:id="@+id/iv" android:layout_width="match_parent" android:layout_height="match_parent"/> <ImageView android:id="@+id/iv_cover" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/icon"/> </FrameLayout> <SeekBar android:id="@+id/sb" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="255"/> </LinearLayout>
總結(jié)
以上就是在Android中實(shí)現(xiàn)動(dòng)態(tài)高斯模糊的全部?jī)?nèi)容,本文先是介紹了如何實(shí)現(xiàn)高斯模糊,而后才介紹實(shí)現(xiàn)動(dòng)態(tài)效果,這樣讓大家更容易理解學(xué)習(xí),希望本文對(duì)大家開發(fā)Android有所幫助。
- Android關(guān)于Glide的使用(高斯模糊、加載監(jiān)聽、圓角圖片)
- Android實(shí)現(xiàn)圖片的高斯模糊(兩種方式)
- Android圖片特效:黑白特效、圓角效果、高斯模糊
- Android 實(shí)現(xiàn)圖片模糊、高斯模糊、毛玻璃效果的三種方法
- Android 動(dòng)態(tài)高斯模糊效果教程
- Android 高仿微信語音聊天頁面高斯模糊(毛玻璃效果)
- Android項(xiàng)目實(shí)戰(zhàn)之Glide 高斯模糊效果的實(shí)例代碼
- Android RenderScript實(shí)現(xiàn)高斯模糊
- Android實(shí)現(xiàn)動(dòng)態(tài)高斯模糊效果示例代碼
- Android實(shí)現(xiàn)圖片高斯模糊
相關(guān)文章
Android 用RxBinding與RxJava2實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí)功能
這篇文章主要介紹了Android 用RxBinding與RxJava2實(shí)現(xiàn)短信倒計(jì)時(shí)功能示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Android中使用Kotlin實(shí)現(xiàn)一個(gè)簡(jiǎn)單的登錄界面
Kotlin 是一種在 Java 虛擬機(jī)上運(yùn)行的靜態(tài)類型編程語言,被稱之為 Android 世界的Swift,由 JetBrains 設(shè)計(jì)開發(fā)并開源。接下來本文通過實(shí)例代碼給大家講解Android中使用Kotlin實(shí)現(xiàn)一個(gè)簡(jiǎn)單的登錄界面,一起看看吧2017-09-09Android在Sqlite3中的應(yīng)用及多線程使用數(shù)據(jù)庫的建議(實(shí)例代碼)
這篇文章主要介紹了Android在Sqlite3中的應(yīng)用及多線程使用數(shù)據(jù)庫的建議,包括編寫數(shù)據(jù)庫具體操作類、增刪改查,通過實(shí)例代碼介紹了在實(shí)際中的應(yīng)用,需要的朋友可以參考下2022-04-04Android自定義ScrollView實(shí)現(xiàn)阻尼回彈
這篇文章主要為大家詳細(xì)介紹了Android自定義ScrollView實(shí)現(xiàn)阻尼回彈,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04詳解Android中Activity的啟動(dòng)模式及應(yīng)用場(chǎng)景
今天給大家介紹下安卓開發(fā)中不得不涉及的Activity啟動(dòng)模式及應(yīng)用場(chǎng)景,Activity一共有四種啟動(dòng)模式,分別是Standard模式、SingleTop模式、SingleTask模式以及SingleInstance模式,,需要的朋友可以參考下2023-09-09android 字體顏色選擇器(ColorPicker)介紹
本文將詳細(xì)介紹android 字體顏色選擇器(ColorPicker)需要了解更多的朋友可以參考下2012-11-11Android控件之RatingBar自定義星級(jí)評(píng)分樣式
RatingBar為評(píng)分條控件,默認(rèn)效果為若干個(gè)綠色的星星,如果想將其換成其他自定義圖片就要自定義它的style。接下來通過本文給大家介紹Android控件之RatingBar自定義星級(jí)評(píng)分樣式,感興趣的朋友一起學(xué)習(xí)吧2016-02-02Android中制作進(jìn)度框和環(huán)形進(jìn)度條的簡(jiǎn)單實(shí)例分享
這篇文章主要介紹了Android中制作進(jìn)度框和環(huán)形進(jìn)度條的簡(jiǎn)單實(shí)例分享,環(huán)形進(jìn)度條帶有基本的百分比顯示,需要的朋友可以參考下2016-03-03android實(shí)現(xiàn)桌面移動(dòng)懸浮窗口
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)桌面移動(dòng)懸浮窗口,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07