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