一. 簡介
對圖片做高斯模糊,有非常多的方法
高斯模糊的計算量很大,為減少計算時間,有兩種優(yōu)化途徑:
1.使用render script,并對高斯算法做優(yōu)化
2.使用jni,在c層對圖片做處理
后者的優(yōu)點是兼容android 1.x,前者只能在android 2.2以上版本才能運(yùn)行
對我們來說,使用render script就好了
注意:模糊半徑,根據(jù)原圖尺寸設(shè)置,一般設(shè)置為原圖尺寸的15%-30%效果比較好,例如
原圖大小 540*960px ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? radius = 50px ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? radius = 100px
原圖大小 200*200px ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? radius = 20px ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? radius = 40px ? ? ? ? ? ? ? ? ? ? ? ? ? ?radius = 60px
二. 類介紹
即使是使用render script,做高斯模糊的方法也有很多種,
在此,推薦兩種方法:
1.使用google原生代碼中的高斯模糊類ScriptIntrinsicBlur,radius 范圍為 1-25px
2.使用?kikoso 整理的stack 高斯算法,radius 范圍為 1-254px
我對這兩種方法都做了封裝,方便大家調(diào)用,一共提供了三個類,
RSGaussianBlur(使用google原生代碼中的高斯模糊類ScriptIntrinsicBlur)
RSStackBlur_kikoso(使用?kikoso 整理的stack 高斯算法)
這兩個類都implement了IBlur 接口,
publicinterfaceIBlur {
/**
* 給定一個bitmap,以及模糊半徑,對圖片做模糊后返回一張模糊后的bitmap
* 一般來說,返回的bitmap與給定的bitmap不是同一個,你必須自己回收這個新的bitmap
* 因為render script限制,返回的bitmap寬度會是4的倍數(shù),
*?例如,如果原圖寬度為202px,返回的bitmap寬度為200px
*/
publicBitmap blur(intradius, Bitmapin);
/**
* 給定一個bitmap,以及模糊半徑,對圖片做模糊后返回一張模糊后的bitmap
* 一般來說,返回的bitmap與給定的bitmap不是同一個,你必須自己回收這個新的bitmap
*@paraminSampleSize 如果大于1,先壓縮原圖,然后做模糊,返回的新bitmap大小比原圖小,
*?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 如果小于等于1,則忽略該參數(shù)
* ? ? ? ? ? ?例如,inSampleSize 為 4,新建一個bitmap,寬高各為原圖1/4,并將寬度調(diào)整為4的倍數(shù),
* ? ? ? ? ? ? ? ? ? ? ? 同時使用新的模糊半徑 radius/4, 對新bitmap 做模糊后返回這個新bitmap
* ?使用這個類有兩個好處:
* ?1. 反正是模糊圖,先壓縮再模糊,效果基本一樣,但是時間消耗大量減少,建議 inSampleSize為4
* ? ? ?例如,原圖寬度小于1080px,inSampleSize為4,原圖寬度到達(dá)1440px,取6或8
* ?2. 對RSGaussianBlur類,可使用blur(100,in, ?4);,從而突破了半徑不能超過25px的限制
*/
publicBitmap blur(intradius, Bitmapin,intinSampleSize);
/**
* 使用完類后,必須調(diào)用該方法釋放render script資源,
*?否則每次new一個新對象,有增加1個新的render script線程和占用一堆資源
* 至于返回的bitmap,由你自己管理,在此并沒有去釋放那個bitmap
*/
publicvoidrecycle();
/**
* 獲取你上次調(diào)用?blur() 所花的時間
*/
publiclonggetTimeMs();
}
在模糊半徑比較小的時候,你隨便用哪個類都可以,
但是,如果模糊半徑太大,你又不希望原圖壓縮太多的話,使用RSStackBlur_kikoso 更合適
例如,原圖大小為1920*1080,模糊半徑為100,使用這兩個沒什么區(qū)別
但是,1)如果原圖為100*100,模糊半徑為100,如果使用RSGaussianBlur,則必須設(shè)置inSampleSize參數(shù)為4,
即先將原圖壓縮為 24*25 的小圖,然后做模糊,這將導(dǎo)致模糊出來的效果很差,因為壓縮圖太小,細(xì)節(jié)全沒了
這種情況下必須用RSStackBlur_kikoso,設(shè)置inSampleSize參數(shù)為1,即不要壓縮原圖,反正它很小
三 類文件和用法
1.將下面壓縮包中的幾個文件copy到你的目錄下
并修改各個類的import為你的包名,
最后將stackblur_kikoso.rs文件中的
#pragmarsjava_package_name(com.monster.blur.algorithm)
修改為:
#pragmarsjava_package_name(你自己的包名)
2.在代碼中調(diào)用即可
IBluriBlur=newRSGaussianBlur(this); 或IBluriBlur=newRSStackBlur_kikoso(this);
intradius= 60;
Bitmapin= ...;
intinSampleSize= 4;
iBlur.blur(radius,in,inSampleSize);// 在調(diào)用 iBlur.recycle()之前,可反復(fù)使用blur()函數(shù)
iBlur.recycle();