官网:https://github.com/cats-oss/android-gpuimage
以下以灰色滤镜、鱼眼效果(变形,看腰和海面)、饱和度 为例,进行讲解,效果图如下:
图一:原图,刚进去的界面,没有任何操作,可以优化黑色,一开始隐藏,进行图片处理时再显示;
图二:灰色滤镜 ; 图三:鱼眼效果 ; 图四:灰色+鱼眼
第二排:饱和度,注意看进度条,图片可以随进度条变化(不会传GIF)
步骤:
注:我的项目是AndroidX的,视图绑定使用了dataBinding,不需要的话,直接忽略,布局时按照自己的来;需要的话,在使用视图绑定的build.gradle里面添加如下代码:
android {dataBinding {enabled = true}
***************
}
一.添加依赖(在用到的模块)
implementation 'jp.co.cyberagent.android:gpuimage:2.0.4'
二.封装图片处理库gpuimage方法,工具类GPUImageUtil,包含单一效果处理方法、多效果集处理方法(同一张照片需要多个效果)
package com.example.module_utils.utils;import android.graphics.Bitmap;import jp.co.cyberagent.android.gpuimage.GPUImage;
import jp.co.cyberagent.android.gpuimage.filter.GPUImageBulgeDistortionFilter;
import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter;
import jp.co.cyberagent.android.gpuimage.filter.GPUImageGrayscaleFilter;
import jp.co.cyberagent.android.gpuimage.filter.GPUImageSaturationFilter;/*** 图片处理** @author mcl 2020.6.2*/
public class GPUImageUtil {private static GPUImageFilter mGPUImageFilter;private static int progress;/*** 获取过滤器(还有其它很多的方法:高斯模糊、锐化等到,以下之列出三个,其它的自行补充)** @param GPUFlag 选择滤镜类型* @return 滤镜*/public static GPUImageFilter getGPUImageFilter(int GPUFlag) {switch (GPUFlag) {//灰色滤镜case 1:mGPUImageFilter = new GPUImageGrayscaleFilter();break;//鱼眼效果case 2:mGPUImageFilter = new GPUImageBulgeDistortionFilter();break;//饱和度case 3:mGPUImageFilter = new GPUImageSaturationFilter(progress);break;default:break;}return mGPUImageFilter;}/*** 处理图片** @param mGPUImage* @param mBitmap 原图* @param filterType 选择滤镜类型* @return 返回处理好后的图片*/public static Bitmap getGPUImage(GPUImage mGPUImage, Bitmap mBitmap, int filterType) {mGPUImage.setImage(mBitmap);mGPUImage.setFilter(getGPUImageFilter(filterType));mBitmap = mGPUImage.getBitmapWithFilterApplied();return mBitmap;}/*** 多种效果集处理照片(eg:灰度+鱼眼)(目前想到比较笨的方法,有改进时再发出来)* @param mGPUImage* @param mBitmap 原图* @param filterTypes 选择滤镜类型集* @return*/public static Bitmap getGPUImages(GPUImage mGPUImage, Bitmap mBitmap, int[] filterTypes){Bitmap bitmap=mBitmap;if (filterTypes!=null && filterTypes.length>0){//循环处理照片,是基于上一次的处理结果照片上再次处理。eg:先灰度滤镜,再鱼眼效果for (int i=0;i<filterTypes.length;i++){mGPUImage.setImage(bitmap);mGPUImage.setFilter(getGPUImageFilter(filterTypes[i]));bitmap = mGPUImage.getBitmapWithFilterApplied();}}return bitmap;}/*** 在一些图像处理方法中用得的值,eg:饱和度、亮度** @param progress 赋值*/public static void progressValue(int progress) {GPUImageUtil.progress = progress;}}
三.GpuImageActivity
public class GpuImageActivity extends AppCompatActivity {private ActivityGpuImageBinding mBinding;private GPUImage mGpuImage;private Bitmap mBitmap;private int[] filterTypes=new int[]{1,2};//图片处理效果集,先固定是灰色+鱼眼,可修改得更人性化一些,手动选择效果集@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mBinding = DataBindingUtil.setContentView(this, R.layout.activity_gpu_image);mBinding.setActivity(this);initView();}private void initView() {mGpuImage = new GPUImage(this);mBitmap = BitmapFactory.decodeResource(this.getResources(), R.mipmap.ye);mBinding.ivGpuImageOriginal.setImageBitmap(mBitmap);mBinding.sbGpuImage.setMax(10);//进度条最大值mBinding.sbGpuImage.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {GPUImageUtil.progressValue(progress);mBinding.ivGpuImageTransform.setImage(GPUImageUtil.getGPUImage(mGpuImage, mBitmap, 3));}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}});}/*** 灰色滤镜(点击事件)** @param view*/public void clickGrayScale(View view) {mBinding.ivGpuImageTransform.setImage(GPUImageUtil.getGPUImage(mGpuImage, mBitmap, 1));}/*** 鱼眼效果(点击事件)** @param view*/public void clickBulgeDistortion(View view) {mBinding.ivGpuImageTransform.setImage(GPUImageUtil.getGPUImage(mGpuImage, mBitmap, 2));}/*** 灰色滤镜+鱼眼效果(点击事件)* @param view*/public void clickGrayBulge(View view){mBinding.ivGpuImageTransform.setImage(GPUImageUtil.getGPUImages(mGpuImage, mBitmap, filterTypes));}}
四. 布局activity_gpu_image.xml,布局用到了dataBinding,如果不熟悉dataBinding的,按照自己的来布局即可,jp.co.cyberagent.android.gpuimage.GPUImageView控件用来显示处理后的图片,其它的随意。
注:android:scaleType="fitXY"是为了让图片充满控件
<?xml version="1.0" encoding="utf-8"?><layout 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"><data><variablename="activity"type="com.example.module_login.ui.activity.GpuImageActivity" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".ui.activity.GpuImageActivity"><ImageViewandroid:id="@+id/iv_gpuImage_original"android:layout_width="@dimen/dp_200"android:layout_height="@dimen/dp_200"android:layout_marginTop="@dimen/dp_20"android:scaleType="fitXY"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><SeekBarandroid:id="@+id/sb_gpuImage"android:layout_width="@dimen/dp_0"android:layout_height="wrap_content"android:layout_marginTop="@dimen/dp_20"app:layout_constraintLeft_toLeftOf="@id/iv_gpuImage_original"app:layout_constraintRight_toRightOf="@id/iv_gpuImage_original"app:layout_constraintTop_toBottomOf="@id/iv_gpuImage_original" /><Buttonandroid:id="@+id/bt_gpuImage_grayScale"android:layout_width="@dimen/dp_0"android:layout_height="wrap_content"android:layout_marginTop="@dimen/dp_40"android:onClick="@{activity.clickGrayScale}"android:text="@string/login_Grayscale"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toLeftOf="@+id/bt_gpuImage_bulgeDistortion"app:layout_constraintTop_toBottomOf="@id/sb_gpuImage" /><Buttonandroid:id="@+id/bt_gpuImage_bulgeDistortion"android:layout_width="@dimen/dp_0"android:layout_height="wrap_content"android:onClick="@{activity.clickBulgeDistortion}"android:text="@string/login_BulgeDistortion"app:layout_constraintRight_toLeftOf="@+id/bt_gpuImage_grayBulge"app:layout_constraintBottom_toBottomOf="@id/bt_gpuImage_grayScale"app:layout_constraintLeft_toRightOf="@id/bt_gpuImage_grayScale"app:layout_constraintTop_toTopOf="@id/bt_gpuImage_grayScale" /><Buttonandroid:id="@+id/bt_gpuImage_grayBulge"android:layout_width="@dimen/dp_0"android:layout_height="wrap_content"android:text="@string/login_grayBulge"android:onClick="@{activity.clickGrayBulge}"app:layout_constraintRight_toRightOf="parent"app:layout_constraintBottom_toBottomOf="@id/bt_gpuImage_bulgeDistortion"app:layout_constraintLeft_toRightOf="@+id/bt_gpuImage_bulgeDistortion"app:layout_constraintTop_toTopOf="@id/bt_gpuImage_bulgeDistortion" /><jp.co.cyberagent.android.gpuimage.GPUImageViewandroid:id="@+id/iv_gpuImage_transform"android:layout_width="@dimen/dp_200"android:layout_height="@dimen/dp_200"android:layout_marginBottom="@dimen/dp_20"app:gpuimage_show_loading="false"app:gpuimage_surface_type="surface_view"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
</layout>
到此就完成了,有不对的地方,多包含。在这篇文章中,学到最有用的是"多效果集处理方法"(名字好拗口,自己瞎取的)。一开始写的时候,我没有想到这个功能的,第一遍写完了,在检查全文有没有错误时,突发奇想,能不能把"多个效果"集合在同一张照片上面呢?然后就折腾起来,怎么封装更加合理。完成之后重新编辑文章。如果有更好的"多效果集处理方法",麻烦评论区告诉我一下,小女子感激不尽!
6.12补充:
经好心人(在评论区)的提点(感恩),gpuimage自带"GPUImageFilterGroup组合滤镜",经实践之后,前面笨笨的方法效果跟它是一样的,现在贴一下方法:
/*** 组合滤镜(eg:灰度+鱼眼)(GPUImageFilterGroup)** @param mGPUImage* @param mBitmap 原图* @param filterTypes 组合滤镜集* @return*/public static Bitmap getFPUImagesGroup(GPUImage mGPUImage, Bitmap mBitmap, int[] filterTypes) {mGPUImage.setImage(mBitmap);GPUImageFilterGroup gpuImageFilterGroup = new GPUImageFilterGroup();if (filterTypes != null && filterTypes.length > 0) {for (int i = 0; i < filterTypes.length; i++) {gpuImageFilterGroup.addFilter(getGPUImageFilter(filterTypes[i]));}}mGPUImage.setFilter(gpuImageFilterGroup);mBitmap = mGPUImage.getBitmapWithFilterApplied();return mBitmap;}