美文网首页Android多媒体技术OpenGL渲染gpuimage
Android图像滤镜框架GPUImage从配置到应用

Android图像滤镜框架GPUImage从配置到应用

作者: mocen_王琪 | 来源:发表于2017-09-13 11:45 被阅读153次

    源作者博客地址:http://blog.csdn.net/it_zjyang/article/details/52268918

    GPUImage简介
    GPUImage 是iOS下一个开源的基于GPU的图像处理库,提供各种各样的图像处理滤镜,并且支持照相机和摄像机的实时滤镜。GPUImage for Android是它在Android下的实现,同样也是开源的。其中提供了几十多种常见的图片滤镜API,且其机制是基于GPU渲染,处理速度相应也比较快,是一个不错的图片实时处理框架。

    GitHub地址:https://github.com/CyberAgent/android-gpuimageGPUImage使用
    环境搭建
    首先,要使用这个库自然是要先导入依赖,在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" 【通常用于创建两个图像之间的动画变暗模糊效果】

    相关文章

      网友评论

      • Tomkk:这个库点进去没了,404

      本文标题:Android图像滤镜框架GPUImage从配置到应用

      本文链接:https://www.haomeiwen.com/subject/hrpksxtx.html