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"                 【通常用於創建兩個圖像之間的動畫變暗模糊效果】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM