1. 程式人生 > >【Android】影象濾鏡框架GPUImage從配置到應用

【Android】影象濾鏡框架GPUImage從配置到應用

GPUImage簡介

GPUImage 是iOS下一個開源的基於GPU的影象處理庫,提供各種各樣的影象處理濾鏡,並且支援照相機和攝像機的實時濾鏡。GPUImage for Android是它在Android下的實現,同樣也是開源的。其中提供了幾十多種常見的圖片濾鏡API,且其機制是基於GPU渲染,處理速度相應也比較快,是一個不錯的圖片實時處理框架。


GitHub地址:https://github.com/CyberAgent/android-gpuimage

 

GPUImage使用

環境搭建

首先,要使用這個庫自然是要先匯入依賴,在app的gradle檔案中新增:

compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1'

將要處理的圖片素材放進Assets資料夾,如果目錄中沒有這個資料夾,可以自己新建一個:

我這裡以名為link.jpg的圖片作為素材複製進去:

素材原圖link.jpg:

API呼叫:

GPUImage主要通過一個GPUImageFilter類來提供各種濾鏡效果實現類,比如我們來實現一個將圖片變成黑白的濾鏡:

public class GPUActivity extends Activity{
 
	private GPUImage gpuImage;
	//顯示處理結果
	private ImageView resultIv;
 
	protected void onCreate(Bundle savedInstanceState) {
        	super.onCreate(savedInstanceState);
        	setContentView(R.layout.activity_gpu);
		resultIv = (ImageView) findViewById(R.id.resultIv);
 
		//獲得Assets資原始檔
		AssetManager as = getAssets();
		InputStream is = null;
		Bitmap bitmap = null;
		try {
			//注意名字要與圖片名字一致
    			is = as.open("link.jpg");
    			bitmap = BitmapFactory.decodeStream(is);
    			is.close();
		} catch (IOException e) {
    			Log.e("GPUImage", "Error");
		}
 
		// 使用GPUImage處理影象
		gpuImage = new GPUImage(this);
		gpuImage.setImage(bitmap);
		gpuImage.setFilter(new GPUImageGrayscaleFilter());
		bitmap = gpuImage.getBitmapWithFilterApplied();
		//顯示處理後的圖片
		resultIv.setImageBitmap(bitmap);
	}
}

佈局檔案:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
	<ImageView
       	    android:id="@+id/resultIv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            />
</LinearLayout>

效果:

可以看到,只是將Assets中的資源轉換為bitmap,再通過GPUImage物件來設定圖片(setImage)和過濾(setImage),在setFilter中傳進了一個GPUImageGrayscaleFilter例項,表示設定為灰度濾鏡,最終再通過呼叫getBitmapWithFilterApplied()來應用以上設定,並返回一個處理後的bitmap物件,再將其顯示出來。

因此,如果你要使用其他濾鏡,只需替換setFilter的引數便可以,GPUImage提供了50多種濾鏡類。

調整飽和度|亮度

在GPUImage的一些濾鏡類中,有一些是帶有數值引數的構造方法,傳進不同的值會有不同程度的效果。

調整飽和度主要通過這個方法:GPUImageSaturationFilter(float saturation)

程式碼:

public class GPUActivity extends Activity{
 
	private GPUImage gpuImage;
	//顯示處理結果
	private ImageView resultIv;
	//進度條
	private SeekBar seekbar;
 
	protected void onCreate(Bundle savedInstanceState) {
        	super.onCreate(savedInstanceState);
        	setContentView(R.layout.activity_gpu);
		resultIv = (ImageView) findViewById(R.id.resultIv);
 
		seekbar = (SeekBar)this.findViewById(R.id.seekbar);
        	seekbar.setMax(10);
        	seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            		@Override
            		public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
				//通過進度條的值更改飽和度
                		resultIv.setImageBitmap(getGPUImageFromAssets(progress));
            		}
 
            		@Override
            		public void onStartTrackingTouch(SeekBar seekBar) {
 
            		}
 
            		@Override
            		public void onStopTrackingTouch(SeekBar seekBar) {
 
            		}
        	});
 
		
		
		//初始化圖片
		resultIv.setImageBitmap(getGPUImageFromAssets(0));
	}
 
	//根據傳進來的數值設定素材飽和度
	public Bitmap getGPUImageFromAssets(int progress){
		
		//獲得Assets資原始檔
		AssetManager as = getAssets();
		InputStream is = null;
		Bitmap bitmap = null;
		try {
			//注意名字要與圖片名字一致
    			is = as.open("link.jpg");
    			bitmap = BitmapFactory.decodeStream(is);
    			is.close();
		} catch (IOException e) {
    			Log.e("GPUImage", "Error");
		}
 
		// 使用GPUImage處理影象
		gpuImage = new GPUImage(this);
		gpuImage.setImage(bitmap);
		gpuImage.setFilter(new GPUImageSaturationFilter(progress));
		bitmap = gpuImage.getBitmapWithFilterApplied();
		return bitmap;
	}
}

佈局檔案:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical">
	<ImageView
       	    android:id="@+id/resultIv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            />
	<SeekBar
            android:id="@+id/seekbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:visibility="visible"/>
</LinearLayout>

效果:

分析:我們這裡通過一個seekbar進度條來調整其飽和度大小,一拖動進度條,便呼叫seekBar的onProgressChanged()方法,並將progress傳遞給getGPUImageFromAssets()方法,注意到在getGPUImageFromAssets()方法中gpuImage.setFilter(new GPUImageSaturationFilter(progress));將progress設定給了飽和度濾鏡,從而調整圖片的飽和度。

上面演示瞭如何通過GPUImage調整飽和度,要實現亮度的調整僅需將Filter改為GPUImageBrightnessFilter,並且在設定progress的時候在區間0-1之間設定便可,如下:

gpuImage.setFilter(new GPUImageBrightnessFilter(progress*0.1f));

網路圖片濾鏡處理

上面的demo中的Bitmap都是從Assets資料夾中獲取而來,但實際開發中可能還有很多情況是通過URL獲取網路資源圖片,可以通過如下方式:

public class GPUActivity extends Activity{
 
    private GPUImage gpuImage;
    //顯示處理結果
    private ImageView resultIv;
 
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gpu);
        resultIv = (ImageView) findViewById(R.id.resultIv);
 
	//開啟非同步執行緒載入圖片並處理
        MyAsynTask asynTask = new MyAsynTask();
        asynTask.execute();
 
    }
 
    class MyAsynTask extends AsyncTask<Integer,Integer,Bitmap>{
 
        @Override
        protected Bitmap doInBackground(Integer... params) {
            Bitmap bitmap = getGPUImageFromURL("http://pic36.nipic.com/20131225/15361977_174053547194_2.jpg");
            return bitmap;
        }
 
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            // 使用GPUImage處理影象
            gpuImage = new GPUImage(getApplicationContext());
            gpuImage.setImage(bitmap);
            gpuImage.setFilter(new GPUImageGrayscaleFilter());
            bitmap = gpuImage.getBitmapWithFilterApplied();
            //顯示處理後的圖片
            resultIv.setImageBitmap(bitmap);
        }
    }
 
    public static Bitmap getGPUImageFromURL(String url) {
        Bitmap bitmap = null;
        try {
            URL iconUrl = new URL(url);
            URLConnection conn = iconUrl.openConnection();
            HttpURLConnection http = (HttpURLConnection) conn;
            int length = http.getContentLength();
            conn.connect();
            // 獲得影象的字元流
            InputStream is = conn.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is, length);
            bitmap = BitmapFactory.decodeStream(bis);
            bis.close();
            is.close();// 關閉流
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }
}

當然,還要記得在Application.xml中新增網路訪問許可權:

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

程式碼分析:由於訪問網路圖片,所以需要放在子執行緒中進行,所以這裡通過AsynTask(Android非同步執行緒,不清楚的可以度娘),現在子執行緒請求完網路圖片並轉換為Bitmap傳遞給主執行緒中對圖片進行濾鏡處理並顯示出來。

最佳實踐

在實際開發中可以將這些API封裝成一個工具類,只需傳入我們的圖片資源以及濾鏡型別,便可以對圖片做出處理:

public class GPUImageUtil {
 
    private static GPUImageFilter filter;
    
    //飽和度、亮度等引數指數
    private static int count;
 
    /**
     * 獲取過濾器
     * @param GPUFlag
     * @return 濾鏡型別
     */
    public static GPUImageFilter getFilter(int GPUFlag){
        switch (GPUFlag){
            case 1:
                filter = new GPUImageGrayscaleFilter();
                break;
            case 2:
                filter = new GPUImageAddBlendFilter();
                break;
            case 3:
                filter = new GPUImageAlphaBlendFilter();
                break;
            case 4:
                filter = new GPUImageBilateralFilter();
                break;
            case 5:
                filter = new GPUImageBoxBlurFilter();
                break;
            case 6:
                filter = new GPUImageBrightnessFilter();
                break;
            case 7:
                filter = new GPUImageBulgeDistortionFilter();
                break;
            case 8:
                filter = new GPUImageCGAColorspaceFilter();
                break;
            case 9:
                filter = new GPUImageChromaKeyBlendFilter();
                break;
            case 10:
                filter = new GPUImageColorBalanceFilter();
                break;
	    case 11:
                filter = new GPUImageSaturationFilter(count);
                break;                
        }
        return filter;
    }
 
    public static Bitmap getGPUImageFromAssets(Context context,GPUImage gpuImage,int FilterFlag){
        AssetManager as = context.getAssets();
        InputStream is = null;
        Bitmap bitmap = null;
        try {
            is = as.open("link.jpg");
            bitmap = BitmapFactory.decodeStream(is);
            is.close();
        } catch (IOException e) {
            Log.e("GPUImage", "Error");
        }
 
        // 使用GPUImage處理影象
        gpuImage = new GPUImage(context);
        gpuImage.setImage(bitmap);
        gpuImage.setFilter(getFilter(FilterFlag));
        bitmap = gpuImage.getBitmapWithFilterApplied();
        return bitmap;
    }
 
    public static Bitmap getGPUImageFromURL(String url) {
        Bitmap bitmap = null;
        try {
            URL iconUrl = new URL(url);
            URLConnection conn = iconUrl.openConnection();
            HttpURLConnection http = (HttpURLConnection) conn;
            int length = http.getContentLength();
            conn.connect();
            // 獲得影象的字元流
            InputStream is = conn.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is, length);
            bitmap = BitmapFactory.decodeStream(bis);
            bis.close();
            is.close();// 關閉流
            } catch (Exception e) {
                e.printStackTrace();
            }
        return bitmap;
    }
 
    //調整飽和度、亮度等
    public static void changeSaturation(int curCount){
        GPUImageUtil.count = curCount;
    }
}

這裡只列舉了部分作為舉例,可以根據自己實際開發想要的濾鏡進行新增。

作了一個小Demo,可以進行濾鏡切換和飽和度調整,效果如下:

感興趣的朋友可以下載原始碼:點此下載

附錄

附上部分濾鏡型別的API中文參照,便於查閱:

"GPUImageFastBlurFilter"                               【模糊】
"GPUImageGaussianBlurFilter"                       【高斯模糊】
"GPUImageGaussianSelectiveBlurFilter"        【高斯模糊,選擇部分清晰】
"GPUImageBoxBlurFilter"                                【盒狀模糊】
"GPUImageTiltShiftFilter"                                【條紋模糊,中間清晰,上下兩端模糊】
"GPUImageMedianFilter.h"                             【中間值,有種稍微模糊邊緣的效果】
"GPUImageBilateralFilter"                               【雙邊模糊】
"GPUImageErosionFilter"                                【侵蝕邊緣模糊,變黑白】
"GPUImageRGBErosionFilter"                         【RGB侵蝕邊緣模糊,有色彩】
"GPUImageDilationFilter"                               【擴充套件邊緣模糊,變黑白】
"GPUImageRGBDilationFilter"                        【RGB擴充套件邊緣模糊,有色彩】
"GPUImageOpeningFilter"                             【黑白色調模糊】
"GPUImageRGBOpeningFilter"                      【彩色模糊】
"GPUImageClosingFilter"                               【黑白色調模糊,暗色會被提亮】
"GPUImageRGBClosingFilter"                        【彩色模糊,暗色會被提亮】
"GPUImageLanczosResamplingFilter"          【Lanczos重取樣,模糊效果】
"GPUImageNonMaximumSuppressionFilter"     【非最大抑制,只顯示亮度最高的畫素,其他為黑】
"GPUImageThresholdedNonMaximumSuppressionFilter" 【與上相比,畫素丟失更多】


"GPUImageCrosshairGenerator"              【十字】
"GPUImageLineGenerator"                       【線條】
"GPUImageTransformFilter"                     【形狀變化】
"GPUImageCropFilter"                              【剪裁】
"GPUImageSharpenFilter"                        【銳化】
"GPUImageUnsharpMaskFilter"               【反遮罩銳化】


"GPUImageSobelEdgeDetectionFilter"           【Sobel邊緣檢測演算法(白邊,黑內容,有點漫畫的反色效果)】
"GPUImageCannyEdgeDetectionFilter"          【Canny邊緣檢測演算法(比上更強烈的黑白對比度)】
"GPUImageThresholdEdgeDetectionFilter"    【閾值邊緣檢測(效果與上差別不大)】
"GPUImagePrewittEdgeDetectionFilter"         【普瑞維特(Prewitt)邊緣檢測(效果與Sobel差不多,貌似更平滑)】
"GPUImageXYDerivativeFilter"                        【XYDerivative邊緣檢測,畫面以藍色為主,綠色為邊緣,帶彩色】
"GPUImageHarrisCornerDetectionFilter"       【Harris角點檢測,會有綠色小十字顯示在圖片角點處】
"GPUImageNobleCornerDetectionFilter"      【Noble角點檢測,檢測點更多】
"GPUImageShiTomasiFeatureDetectionFilter" 【ShiTomasi角點檢測,與上差別不大】
"GPUImageMotionDetector"                             【動作檢測】
"GPUImageHoughTransformLineDetector"      【線條檢測】
"GPUImageParallelCoordinateLineTransformFilter" 【平行線檢測】


"GPUImageLocalBinaryPatternFilter"        【影象黑白化,並有大量噪點】
"GPUImageLowPassFilter"                          【用於影象加亮】
"GPUImageHighPassFilter"                        【影象低於某值時顯示為黑】




"GPUImageSketchFilter"                          【素描】
"GPUImageThresholdSketchFilter"         【閥值素描,形成有噪點的素描】
"GPUImageToonFilter"                             【卡通效果(黑色粗線描邊)】
"GPUImageSmoothToonFilter"                【相比上面的效果更細膩,上面是粗曠的畫風】
"GPUImageKuwaharaFilter"                     【桑原(Kuwahara)濾波,水粉畫的模糊效果;處理時間比較長,慎用】


"GPUImageMosaicFilter"                         【黑白馬賽克】
"GPUImagePixellateFilter"                       【畫素化】
"GPUImagePolarPixellateFilter"              【同心圓畫素化】
"GPUImageCrosshatchFilter"                  【交叉線陰影,形成黑白網狀畫面】
"GPUImageColorPackingFilter"              【色彩丟失,模糊(類似監控攝像效果)】


"GPUImageVignetteFilter"                        【暈影,形成黑色圓形邊緣,突出中間影象的效果】
"GPUImageSwirlFilter"                               【漩渦,中間形成捲曲的畫面】
"GPUImageBulgeDistortionFilter"            【凸起失真,魚眼效果】
"GPUImagePinchDistortionFilter"            【收縮失真,凹面鏡】
"GPUImageStretchDistortionFilter"         【伸展失真,哈哈鏡】
"GPUImageGlassSphereFilter"                  【水晶球效果】
"GPUImageSphereRefractionFilter"         【球形折射,圖形倒立】
    
"GPUImagePosterizeFilter"                 【色調分離,形成噪點效果】
"GPUImageCGAColorspaceFilter"      【CGA色彩濾鏡,形成黑、淺藍、紫色塊的畫面】
"GPUImagePerlinNoiseFilter"              【柏林噪點,花邊噪點】
"GPUImage3x3ConvolutionFilter"      【3x3卷積,高亮大色塊變黑,加亮邊緣、線條等】
"GPUImageEmbossFilter"                   【浮雕效果,帶有點3d的感覺】
"GPUImagePolkaDotFilter"                 【畫素圓點花樣】
"GPUImageHalftoneFilter"                  【點染,影象黑白化,由黑點構成原圖的大致圖形】


混合模式 Blend

"GPUImageMultiplyBlendFilter"            【通常用於建立陰影和深度效果】
"GPUImageNormalBlendFilter"               【正常】
"GPUImageAlphaBlendFilter"                 【透明混合,通常用於在背景上應用前景的透明度】
"GPUImageDissolveBlendFilter"             【溶解】
"GPUImageOverlayBlendFilter"              【疊加,通常用於建立陰影效果】
"GPUImageDarkenBlendFilter"               【加深混合,通常用於重疊型別】
"GPUImageLightenBlendFilter"              【減淡混合,通常用於重疊型別】
"GPUImageSourceOverBlendFilter"       【源混合】
"GPUImageColorBurnBlendFilter"          【色彩加深混合】
"GPUImageColorDodgeBlendFilter"      【色彩減淡混合】
"GPUImageScreenBlendFilter"                【螢幕包裹,通常用於建立亮點和鏡頭眩光】
"GPUImageExclusionBlendFilter"            【排除混合】
"GPUImageDifferenceBlendFilter"          【差異混合,通常用於建立更多變動的顏色】
"GPUImageSubtractBlendFilter"            【差值混合,通常用於建立兩個影象之間的動畫變暗模糊效果】
"GPUImageHardLightBlendFilter"         【強光混合,通常用於建立陰影效果】
"GPUImageSoftLightBlendFilter"           【柔光混合】
"GPUImageChromaKeyBlendFilter"       【色度鍵混合】
"GPUImageMaskFilter"                           【遮罩混合】
"GPUImageHazeFilter"                            【朦朧加暗】
"GPUImageLuminanceThresholdFilter" 【亮度閾】
"GPUImageAdaptiveThresholdFilter"     【自適應閾值】
"GPUImageAddBlendFilter"                    【通常用於建立兩個影象之間的動畫變亮模糊效果】
"GPUImageDivideBlendFilter"                 【通常用於建立兩個影象之間的動畫變暗模糊效果】

--------------------- 本文來自 IT_ZJYANG 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/it_zjyang/article/details/52268918?utm_source=copy