Android RenderScript實(shí)現(xiàn)高斯模糊
昨天看了下RenderScript的官方文檔,發(fā)現(xiàn)RenderScript這廝有點(diǎn)牛逼。無(wú)意中發(fā)現(xiàn)ScriptIntrinsic這個(gè)抽象類(lèi),有些很有用的子類(lèi)。其中有個(gè)子類(lèi)叫ScriptIntrinsicBlur類(lèi),大致就是將圖片實(shí)現(xiàn)高斯模糊。
ScriptIntrinsic的申明:
ScriptIntrinsicBlur類(lèi)的申明:
加上結(jié)合著看了下SDK中的samples,自己寫(xiě)了個(gè)高斯模糊。
( sample的具體位置為:
SDK目錄/samples/android-19/renderscript/RenderScriptIntrinsic/RenderScriptIntrinsicSample/
)。
先上圖。效果如下:
【注意!! 開(kāi)始之前,我們需要導(dǎo)入需要的支持包。
支持包的具體路徑為: sdk目錄/buildtools/任意一個(gè)版本號(hào)/renderscript/lib/renderscript-v8.jar
另外:為了防止出現(xiàn)有的機(jī)型兼容問(wèn)題,最好將renderscript-v8.jar同目錄下的packaged目錄下的所有庫(kù)也一并拷貝到lib文件夾下】
例如:
好了。開(kāi)始寫(xiě)代碼。。
1、先申明常用成員變量。
private SeekBar blurSeekBar;//拖動(dòng)條 private ImageView img_blur;//顯示模糊后bitmap的ImageView //原bitmap和高斯模糊后的bitmap private Bitmap bitmap_original, bitmap_blur; //高斯模糊處理的AsyncTask private RenderScriptTask mLatestTask = null; //RenderScript 對(duì)象(Google的高性能并行計(jì)算類(lèi),他可以利用設(shè)備的GPU/CPU等計(jì)算資源) private RenderScript mRS; //下面是兩個(gè)RenderScript的傳入?yún)?shù)對(duì)象 private Allocation mInAllocation; private Allocation mOutAllocation; //高斯模糊處理實(shí)例 private ScriptIntrinsicBlur mScriptBlur;
2、加載兩份bitmap,并初始化高斯模糊相關(guān)的對(duì)象。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); blurSeekBar = (SeekBar) findViewById(R.id.aty_main_seekBar); img_blur = (ImageView) findViewById(R.id.aty_main_img_blur); bitmap_original = loadBitmap(R.drawable.meet_entry_guide_3); // 復(fù)制一份 bitmap_blur = Bitmap.createBitmap(bitmap_original.getWidth(), bitmap_original.getHeight(), bitmap_original.getConfig()); createBlureScript(); setSeekBarListening();//為SeekBar設(shè)置拖拽監(jiān)聽(tīng) } /** * Helper to load Bitmap from resource */ private Bitmap loadBitmap(int resource) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; return BitmapFactory.decodeResource(getResources(), resource, options); } /** * 創(chuàng)建Script */ private void createBlureScript() { mRS = RenderScript.create(this); mInAllocation = Allocation.createFromBitmap(mRS, bitmap_original); mOutAllocation = Allocation.createFromBitmap(mRS, bitmap_blur); /* * Create intrinsics. RenderScript has built-in features such as blur, * convolve filter etc. These intrinsics are handy for specific * operations without writing RenderScript kernel. In the sample, it's * creating blur, convolve and matrix intrinsics. */ mScriptBlur = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS)); }
3、完成高斯模糊處理代碼。
private void performFilter(Allocation inAllocation, Allocation outAllocation, Bitmap bitmapOut, float value) { /* * 設(shè)置模糊程度。范圍在0~25之間。否則會(huì)出錯(cuò) */ mScriptBlur.setRadius(value); /* * Invoke filter kernel */ mScriptBlur.setInput(inAllocation); mScriptBlur.forEach(outAllocation); outAllocation.copyTo(bitmapOut); }
4、將處理后的bitmap設(shè)置到ImageView中。
// Request UI update img_blur.setImageBitmap(bitmap_blur); img_blur.invalidate();
基本工作也就完成了。剩下就是代碼的相互調(diào)用了。
【 總 結(jié) 】
其實(shí)總起來(lái),使用RenderScript進(jìn)行高斯模糊主要是分為三步:
1、創(chuàng)建并初始化需要的對(duì)象(初始化一次就OK)。
mRS = RenderScript.create(this); mScriptBlur = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS)); //RenderScript的輸入和輸出參數(shù)對(duì)象 mInAllocation = Allocation.createFromBitmap(mRS, bitmap_original); mOutAllocation = Allocation.createFromBitmap(mRS, bitmap_blur);
2、執(zhí)行高斯模糊,并將結(jié)果拷貝出來(lái)。
/* * 設(shè)置模糊程度。范圍在0~25之間。否則會(huì)出錯(cuò)(這個(gè)也可以只設(shè)置一次) */ mScriptBlur.setRadius(value); /* * Invoke filter kernel */ mScriptBlur.setInput(inAllocation); mScriptBlur.forEach(outAllocation); //將結(jié)果拷貝出來(lái),拷貝到bitmapOut對(duì)象中 outAllocation.copyTo(bitmapOut);
3、回收RenderScript對(duì)象
mRS.destory(); mRs = null;
文章到此結(jié)束。
按照慣例:下面是我的完整的代碼實(shí)現(xiàn)。
public class MainActivity extends Activity { private SeekBar blurSeekBar; private ImageView img_blur; private Bitmap bitmap_original, bitmap_blur; private RenderScriptTask mLatestTask = null; private RenderScript mRS; private Allocation mInAllocation; private Allocation mOutAllocation; private ScriptIntrinsicBlur mScriptBlur; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); blurSeekBar = (SeekBar) findViewById(R.id.aty_main_seekBar); img_blur = (ImageView) findViewById(R.id.aty_main_img_blur); bitmap_original = loadBitmap(R.drawable.meet_entry_guide_3); // 復(fù)制一份 bitmap_blur = Bitmap.createBitmap(bitmap_original.getWidth(), bitmap_original.getHeight(), bitmap_original.getConfig()); createBlureScript(); setSeekBarListening(); } /** * 設(shè)置SeekBar的監(jiān)聽(tīng) */ private void setSeekBarListening() { blurSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { updateImage(progress); } }); } /** * 創(chuàng)建Script */ private void createBlureScript() { mRS = RenderScript.create(this); mInAllocation = Allocation.createFromBitmap(mRS, bitmap_original); mOutAllocation = Allocation.createFromBitmap(mRS, bitmap_blur); /* * Create intrinsics. RenderScript has built-in features such as blur, * convolve filter etc. These intrinsics are handy for specific * operations without writing RenderScript kernel. In the sample, it's * creating blur, convolve and matrix intrinsics. */ mScriptBlur = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS)); } private void performFilter(Allocation inAllocation, Allocation outAllocation, Bitmap bitmapOut, float value) { /* * Set blur kernel size */ mScriptBlur.setRadius(value); /* * Invoke filter kernel */ mScriptBlur.setInput(inAllocation); mScriptBlur.forEach(outAllocation); outAllocation.copyTo(bitmapOut); } /* * In the AsyncTask, it invokes RenderScript intrinsics to do a filtering. * After the filtering is done, an operation blocks at Allication.copyTo() * in AsyncTask thread. Once all operation is finished at onPostExecute() in * UI thread, it can invalidate and update ImageView UI. */ private class RenderScriptTask extends AsyncTask<Float, Integer, Integer> { Boolean issued = false; protected Integer doInBackground(Float... values) { if (isCancelled() == false) { issued = true; performFilter(mInAllocation, mOutAllocation, bitmap_blur, values[0]); } return 0; } void updateView(Integer result) { // Request UI update img_blur.setImageBitmap(bitmap_blur); img_blur.invalidate(); } protected void onPostExecute(Integer result) { updateView(result); } protected void onCancelled(Integer result) { if (issued) { updateView(result); } } } /* * Invoke AsynchTask and cancel previous task. When AsyncTasks are piled up * (typically in slow device with heavy kernel), Only the latest (and * already started) task invokes RenderScript operation. */ private void updateImage(int progress) { float f = getBlureParam(progress); if (mLatestTask != null) mLatestTask.cancel(false); mLatestTask = new RenderScriptTask(); mLatestTask.execute(f); } /** * 模糊的值在1 ~ 25之間 * * @param progress * SeekBar的進(jìn)度值(0 ~ 100) * @return 模糊值 */ private float getBlureParam(int progress) { final float max = 25.0f; final float min = 1.f; return (float) ((max - min) * (progress / 100.0) + min); } /** * Helper to load Bitmap from resource */ private Bitmap loadBitmap(int resource) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; return BitmapFactory.decodeResource(getResources(), resource, options); } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android關(guān)于Glide的使用(高斯模糊、加載監(jiān)聽(tīng)、圓角圖片)
- Android實(shí)現(xiàn)圖片的高斯模糊(兩種方式)
- Android圖片特效:黑白特效、圓角效果、高斯模糊
- Android實(shí)現(xiàn)動(dòng)態(tài)高斯模糊效果
- Android 實(shí)現(xiàn)圖片模糊、高斯模糊、毛玻璃效果的三種方法
- Android 動(dòng)態(tài)高斯模糊效果教程
- Android 高仿微信語(yǔ)音聊天頁(yè)面高斯模糊(毛玻璃效果)
- Android項(xiàng)目實(shí)戰(zhàn)之Glide 高斯模糊效果的實(shí)例代碼
- Android實(shí)現(xiàn)動(dòng)態(tài)高斯模糊效果示例代碼
- Android實(shí)現(xiàn)圖片高斯模糊
相關(guān)文章
Android程序開(kāi)發(fā)之WebView使用總結(jié)
這篇文章主要介紹了Android程序開(kāi)發(fā)之WebView使用總結(jié)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07Android 中啟動(dòng)自己另一個(gè)程序的activity如何實(shí)現(xiàn)
這篇文章主要介紹了Android 中啟動(dòng)自己另一個(gè)程序的activity如何實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2017-04-04詳解Android數(shù)據(jù)存儲(chǔ)之Android 6.0運(yùn)行時(shí)權(quán)限下文件存儲(chǔ)的思考
本篇文章主要介紹了Android數(shù)據(jù)存儲(chǔ)之Android 6.0運(yùn)行時(shí)權(quán)限下文件存儲(chǔ)的思考,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。2016-12-12Android自定義控件通用驗(yàn)證碼輸入框的實(shí)現(xiàn)
這篇文章主要介紹了Android自定義控件通用驗(yàn)證碼輸入框的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03替換so文件來(lái)動(dòng)態(tài)替換Flutter代碼實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了替換so文件來(lái)動(dòng)態(tài)替換Flutter代碼實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Android利用listview控件操作SQLite數(shù)據(jù)庫(kù)實(shí)例
我們利用SQLiteOpenHelper類(lèi)建立一個(gè)數(shù)據(jù)庫(kù),并寫(xiě)好增、刪、查等方法,通過(guò)SimpleCursorAdapter連接listview實(shí)現(xiàn)數(shù)據(jù)庫(kù)的增加、查詢以及長(zhǎng)按刪除的功能。2017-04-04android實(shí)現(xiàn)session保持簡(jiǎn)要概述及實(shí)現(xiàn)
其實(shí)sesion在瀏覽器和web服務(wù)器直接是通過(guò)一個(gè)叫做name為sessionid的cookie來(lái)傳遞的,所以只要在每次數(shù)據(jù)請(qǐng)求時(shí)保持sessionid是同一個(gè)不變就可以用到web的session了,感興趣的你可以參考下本文或許對(duì)你有所幫助2013-03-03