1. 程式人生 > >Android開發 高斯模糊的實現

Android開發 高斯模糊的實現

同類參考文章:戳我 戳我

高斯模糊是什麼?

高斯模糊(英語:Gaussian Blur),也叫高斯平滑,是在Adobe Photoshop、GIMP以及Paint.NET等影象處理軟體中廣泛使用的處理效果,通常用它來減少影象噪聲以及降低細節層次。這種模糊技術生成的影象,其視覺效果就像是經過一個半透明螢幕在觀察影象,這與鏡頭焦外成像效果散景以及普通照明陰影中的效果都明顯不同。

什麼?看不明白?沒關係,我也看不明白,維基百科複製回來的嘛。我們直接放一些圖片來了解以下這個高斯模糊是怎麼樣的。因為高斯模糊在iOS中最常見,這裡抓了幾張iOS網易雲的圖片:

可以看到這個介面中的背景,其實就是通過圖1中間那個小圖片模糊得到的,這樣做的好處就是整體性很好,並且不會因為圖片過渡突兀而影響介面內容的閱讀。

那麼,究竟在Android上怎麼去實現這個效果呢?這裡推薦使用官方提供在Support Library中的一個工具來做,就是RenderScript。這個RenderScript的功能其實不止有這一個,而其他的一些功能,可以在官方文件中閱讀學習,這裡不給出。

使用這個工具的原因其實很簡單,就是效能。因為涉及到繪圖,所以如果效能不行,那麼無論對於高質量圖片或者是變化較多的需求都是很吃力的,而這個工具則會充分發揮裝置的計算能力(CPU和GPU)來進行計算,並且是使用C99衍生語言進行指令碼編寫的,相較於Java效能是大大的提升。

說到這裡,有些同學就開始方了,C99衍生?What?這個不需要擔心,對於高斯模糊這個實現,Google官方已經給出了對應的解決方案,我們並不需要編寫對應的指令碼就可以使用了,所以無需擔心。

 我們把整個問題分為兩個部分:

    ①高斯模糊實現;

    ②動態高斯模糊實現 

① 高斯模糊實現

首先要說明,我們要使用Support Library,所以版本是有要求的:

     Android SDK Tools 版本必須大於等於22.2

     Android SDK Build-tools 版本必須大於等於18.1.0

如果沒有達到,請使用SDK Manager升級一下。

接著建立我們的工程,並且在對應Module(預設建立的是app)的build.gradle檔案中加入如下程式碼:

defaultConfig {
    ...
    renderscriptTargetApi 18
    renderscriptSupportModeEnabled true
  }

renderscriptTargetApi:這個一般和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); // 建立輸出圖片
    RenderScript rs = RenderScript.create(this); // 構建一個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); // 設定模糊半徑,範圍0f<radius<=25f
    gaussianBlue.setInput(allIn); // 設定輸入指令碼型別
    gaussianBlue.forEach(allOut); // 執行高斯模糊演算法,並將結果填入輸出指令碼型別中
    allOut.copyTo(output); // 將輸出記憶體編碼為Bitmap,圖片大小必須注意
    rs.destroy(); // 關閉RenderScript物件,API>=23則使用rs.releaseAllContexts()
    return output;
  }
}

這裡說明都註釋在程式碼中了。需要了解的是RenderScript有兩個版本,分別是:

     android.renderscript

     android.support.v8.renderscript

上面程式碼使用了第一個,第二個的用法類似,可以自行嘗試。

我們來理一下思路,因為RenderScript是依賴於Script的,而上文也說到了,Script是由C99衍生語言編寫,而程式碼中的ScriptIntrinsicBlur就是對應於高斯模糊演算法的指令碼。而Allocation物件則是將Java中的物件轉換為Script指令碼所需型別的幫手,程式碼中建立了兩個Allocation物件分別用來充當輸入和輸出。接著設定了高斯模糊的半徑(radius)。當呼叫forEach時,指令碼會被執行,並且將執行結果填入輸出對應的Allocation中,最後呼叫copyTo來轉換為Bitmap物件返回。

效果圖:

 

② 動態高斯模糊

很多時候,我們可能會需要一個圖片以不同的模糊程度展現出來。你可能已經注意到上面方法中的模糊半徑了,我們可以做一個實驗,就是通過一個SeekBar來動態改變這個值看看效果:

 

由動圖可以看到,我們拖動SeekBar的時候,SeekBar已經跟不上我們的拖動了。這是為什麼?原因就是這個渲染工具雖然效能比較優異,但是如果圖片的質量和尺寸都較高的時候,我們直接進行修改模糊半徑重新渲染的做法往往時不可取的。

做法是,先建立一張模糊的圖片載入在ImageView中,接著在這個ImageView的上面再放置一個載入原圖ImageView,使用FrameLayout可以讓這兩個ImageView重疊再一起,接著當我們需要動態改變模糊程度的時候,改變上層的ImageViewBitmapAlpha就可以了。我們先看看效果圖:

 

使用了這個方法,滑動起來就會比較流暢了。(GIF載入完才是會是正常速度哦

這裡給一下程式碼參考吧:

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); // 建立輸出圖片
    RenderScript rs = RenderScript.create(this); // 構建一個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); // 設定模糊半徑,範圍0f<radius<=25f
    gaussianBlue.setInput(allIn); // 設定輸入記憶體
    gaussianBlue.forEach(allOut); // 模糊編碼,並將記憶體填入輸出記憶體
    allOut.copyTo(output); // 將輸出記憶體編碼為Bitmap,圖片大小必須注意
    rs.destroy(); // 關閉RenderScript物件,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>

總結

以上就是在Android中實現動態高斯模糊的全部內容,本文先是介紹瞭如何實現高斯模糊,而後才介紹實現動態效果,這樣讓大家更容易理解學習,希望本文對大家開發Android有所幫助。

相關推薦

Android開發 模糊實現

同類參考文章:戳我 戳我 高斯模糊是什麼? 高斯模糊(英語:Gaussian Blur),也叫高斯平滑,是在Adobe Photoshop、GIMP以及Paint.NET等影象處理軟體中廣泛使用的處理效果,通常用它來減少影象噪聲以及降低細節層次。這種模糊技術生成的影象,其

Android 圖片模糊解決方案

Android 圖片高斯模糊解決方案 近年來,圖片高斯模糊備受設計師的青睞,在各大知名APP中,如微信、手機QQ、網易雲音樂等等都有對背景高斯圖模糊的設計,在Adnroid 中,現在常用的圖片高斯模糊技術有三種:RenderScript 、fastBlur、對RenderScript和

Android Glide模糊載入圖片

Glide.with(this) .load(R.mipmap.bg_default_cover) .crossFade(1000) .bitmapTransform(new B

封裝個 Android模糊元件

最近基於 Android StackBlur 開源庫,根據自己碰到的需求場景,封裝了個高斯模糊元件,順便記錄一下。 為什麼要自己重複造輪子? 其實也談不上重頭自己造輪子,畢竟是基於大神的開源庫,做了二次封裝。封裝的目的在於,方便外部使用。畢竟有著自己的程式設計習慣,大神的開源庫也只是提供了基礎的功能,現實程式

DrawerLayout側滑模糊實現

國際慣例,先上效果圖: 背景圖是一張1080p的,手機一加3,大概會佔用7兆多記憶體。滑動過程記憶體一點都不會抖。 最近自己在寫一個音樂app,想實現這樣一個效果,在網上只找到了一篇2014年的文章,但是他是每次滑動都去截圖,生成模糊bitmap,記憶體會劇烈抖動。我參考網

Android高效能模糊方案

簡述: 做直播類app的時候點選進入直播間接通的過程中首先顯示一張模糊的毛玻璃效果的圖片,那麼此時就要考慮使用高斯模糊的時候了。Android中提供了RenderScript來操作圖片,但是這個的使用版本要求是在API17以上,所以我們還可以考慮使用第三方可FastBlur

Android快速模糊對話方塊

// MainActivity.java package com.example.blurdemo;import android.annotation.SuppressLint;import android.app.Activity;import android.conte

Android模糊的記錄

最近在開發專案的時候遇到一個UI提出的效果就是PS裡面的高斯模糊效果,上圖                                                            下面其實是一段文字內容,但是當用戶沒有獲取到某種許可權的時候,是不能檢視具體的文

Android 圖片模糊處理

/** 水平方向模糊度 */ private static float hRadius = 10; /** 豎直方向模糊度 */ private static float vRadius = 10; /** 模糊迭代度 */ private static int iterations = 7;

模糊實現毛玻璃效果

首先需要匯入依賴: compile 'com.github.bumptech.glide:glide:3.7.0' compile 'jp.wasabeef:glide-transformations

Android使用RenderScript實現圖片的模糊效果

Android使用RenderScript實現圖片的高斯模糊效果 首先來看一下什麼是高斯模糊效果呢? 高斯模糊(英語:Gaussian Blur),也叫高斯平滑,是在Adobe Photoshop、GIMP以及Paint.NET等影象處理軟體中廣泛使用的處理效果,通常用它

Android 模糊效果從319ms到3ms的優化實現

之前做過高斯模糊的的效果,不過依賴一個三方庫,今天看到了一篇文章,一個類檔案就能解決,感覺竊喜,分享給大家。 使用: Glide.with(getActivity()).load(mUser.avatarUrl).asBitmap().into(ne

Android實現模糊(也叫毛玻璃效果)

/*** 高斯模糊* @param bkg* @param view*/private void blur(Bitmap bkg, View view) {float radius = 25;Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasure

Android 圖片模糊模糊、毛玻璃的三種實現方法

轉載自:http://blog.csdn.net/fan7983377/article/details/51568059 效果圖: 原文連結:點選訪問 這使用也很簡單,匯入依賴,使用模糊方法就行,就這兩步搞定 依賴: <code class="hljs

Android也能流暢實現毛玻璃效果(模糊)效果

前言 上圖就是我們在IOS裝置上經常能夠見到的毛玻璃(高斯模糊)效果。不得不說,這種效果在適合的場景下使用,能夠獲得絕佳的美感。但是鑑於Android裝置效能和相容性問題,我們通常很難在Android裝置上見到這種效果。 但這並不是IOS的專利效果,Android

Android實現圖片 模糊,以及圖片映象 翻轉。

好久沒寫部落格,發現不止手癢,,原來不學習還是會頹廢的….. 哎….. 速速找了網上比較感興趣的功能,,看著前人大神門的方法實現,方便自己也方便別人: 上圖: 程式碼: MainActivity.class package com.hero.

android 實現模糊

方法一 (1)RenderScript RenderScript是Google在Android 3.0(API 11)中引入的一個高效能圖片處理框架。 使用RenderScriprt實現高斯模糊: 首先在在build.gradle的defaultConf

Android實現圖片的模糊(兩種方式)

原文地址:http://www.jb51.net/article/107482.htm 在市面上很多的APP都使用了對圖片作模糊化處理後作為背景的效果,來使得整個頁面更具有整體感。如下就是網易雲音樂的音樂播放頁面: 很明顯這個頁面的背景是由中間的小圖片模糊化後而來的。

android實現模糊功能

最近專案要求android客戶端模仿IOS的一種模糊背景的效果,高斯模糊在PS裡邊常用。大體思路是兩步: 第一步獲取Activity的螢幕截圖。 第二步對截圖進行高斯模糊演算法。 總之感覺體驗不是很好,主要原因是對Bitmap進行操作,這種東西本來就是安卓的噩夢,搞不好還會

Android 實現圖片模糊演算法,真正有效的工具類

import android.graphics.Bitmap; import android.graphics.Color; public class FastBlur {     /***      * 高斯模糊演算法      * @param bmp 要處理的影象