一步步帶你實現Android圖片處理庫gpuimage的配置、使用、封裝、多效果集於一身(eg:灰度濾鏡+魚眼效果)

官網: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};//圖片處理效果集,先固定是灰色+魚眼,可修改得更人性化一些,手動選擇效果集

    @Override
    protected 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() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                GPUImageUtil.progressValue(progress);
                mBinding.ivGpuImageTransform.setImage(GPUImageUtil.getGPUImage(mGpuImage, mBitmap, 3));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public 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>

        <variable
            name="activity"
            type="com.example.module_login.ui.activity.GpuImageActivity" />

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.activity.GpuImageActivity">

        <ImageView
            android: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" />

        <SeekBar
            android: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" />


        <Button
            android: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" />

        <Button
            android: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" />

        <Button
            android: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.GPUImageView
            android: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>

 

到此就完成了,有不對的地方,多包含。在這篇文章中,學到最有用的是"多效果集處理方法"(名字好拗口,自己瞎取的)。一開始寫的時候,我沒有想到這個功能的,第一遍寫完了,在檢查全文有沒有錯誤時,突發奇想,能不能把"多個效果"集合在同一張照片上面呢?然後就折騰起來,怎麼封裝更加合理。完成之後重新編輯文章。如果有更好的"多效果集處理方法",麻煩評論區告訴我一下,小女子感激不盡!

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章