欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實現(xiàn)動態(tài)高斯模糊效果

 更新時間:2016年08月05日 09:17:09   投稿:daisy  
在Android開發(fā)中常常會用到高斯模糊,但有的時候我們可能會需要一個圖片以不同的模糊程度展現(xiàn)出來,那如何實現(xiàn)呢,一起通過本文來學習學習吧。

高斯模糊是什么?

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

什么?看不明白?沒關系,我也看不明白,維基百科復制回來的嘛。我們直接放一些圖片來了解以下這個高斯模糊是怎么樣的。因為高斯模糊在iOS中最常見,這里抓了幾張iOS網(wǎng)易云的圖片:

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

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

使用這個工具的原因其實很簡單,就是性能。因為涉及到繪圖,所以如果性能不行,那么無論對于高質(zhì)量圖片或者是變化較多的需求都是很吃力的,而這個工具則會充分發(fā)揮設備的計算能力(CPU和GPU)來進行計算,并且是使用C99衍生語言進行腳本編寫的,相較于Java性能是大大的提升。

說到這里,有些同學就開始方了,C99衍生?What?這個不需要擔心,對于高斯模糊這個實現(xiàn),Google官方已經(jīng)給出了對應的解決方案,我們并不需要編寫對應的腳本就可以使用了,所以無需擔心。

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

    ①高斯模糊實現(xiàn);

    ②動態(tài)高斯模糊實現(xiàn) 

① 高斯模糊實現(xiàn)

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

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

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

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

接著創(chuàng)建我們的工程,并且在對應Module(默認創(chuàng)建的是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); // 創(chuàng)建輸出圖片
    RenderScript rs = RenderScript.create(this); // 構(gòu)建一個RenderScript對象
    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); // 設置模糊半徑,范圍0f<radius<=25f
    gaussianBlue.setInput(allIn); // 設置輸入腳本類型
    gaussianBlue.forEach(allOut); // 執(zhí)行高斯模糊算法,并將結(jié)果填入輸出腳本類型中
    allOut.copyTo(output); // 將輸出內(nèi)存編碼為Bitmap,圖片大小必須注意
    rs.destroy(); // 關閉RenderScript對象,API>=23則使用rs.releaseAllContexts()
    return output;
  }
}

這里說明都注釋在代碼中了。需要了解的是RenderScript有兩個版本,分別是:

     android.renderscript

     android.support.v8.renderscript

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

我們來理一下思路,因為RenderScript是依賴于Script的,而上文也說到了,Script是由C99衍生語言編寫,而代碼中的ScriptIntrinsicBlur就是對應于高斯模糊算法的腳本。而Allocation對象則是將Java中的對象轉(zhuǎn)換為Script腳本所需類型的幫手,代碼中創(chuàng)建了兩個Allocation對象分別用來充當輸入和輸出。接著設置了高斯模糊的半徑(radius)。當調(diào)用forEach時,腳本會被執(zhí)行,并且將執(zhí)行結(jié)果填入輸出對應的Allocation中,最后調(diào)用copyTo來轉(zhuǎn)換為Bitmap對象返回。

效果圖:

 

② 動態(tài)高斯模糊

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

 

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

做法是,先創(chuàng)建一張模糊的圖片加載在ImageView中,接著在這個ImageView的上面再放置一個加載原圖ImageView,使用FrameLayout可以讓這兩個ImageView重疊再一起,接著當我們需要動態(tài)改變模糊程度的時候,改變上層的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); // 創(chuàng)建輸出圖片
    RenderScript rs = RenderScript.create(this); // 構(gòu)建一個RenderScript對象
    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); // 設置模糊半徑,范圍0f<radius<=25f
    gaussianBlue.setInput(allIn); // 設置輸入內(nèi)存
    gaussianBlue.forEach(allOut); // 模糊編碼,并將內(nèi)存填入輸出內(nèi)存
    allOut.copyTo(output); // 將輸出內(nèi)存編碼為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>

總結(jié)

以上就是在Android中實現(xiàn)動態(tài)高斯模糊的全部內(nèi)容,本文先是介紹了如何實現(xiàn)高斯模糊,而后才介紹實現(xiàn)動態(tài)效果,這樣讓大家更容易理解學習,希望本文對大家開發(fā)Android有所幫助。

相關文章

最新評論