个人博客:haichenyi.com。感谢关注
GPUImage图片滤镜处理的第三方开源库,对照IOS版的GPUImage写的,部分功能尚未完善,目前也有很多种滤镜,常用的滤镜基本上都有,请先浏览一遍github上面的用法。
Android版目前没有IOS那么多类,那么多用法,我们用的最多的就是GPUImageView这个自定义view,继承的FrameLayout,并不是继承的ImageView,所以,它这里显示图片的时候,会有图片变形的问题。我的***处理方法:***
先用Glide获取图片的宽高然后获取GPUImageView的LayoutParams,动态设置控件的宽高只要构造方法,方法带参数的,都可以微调,这里微调的取值范围,Filter源码的类注释上面都有。如果,我们把seekBar的取值范围设置成类注释上面的范围,你滑动很小距离的seekBar,图片变化就会很大,所以,我们一般都是缩小范围再使用。
//第一个参数seekBar是最大值,第二个参数是最小值,第三个参数是默认值,第四个参数是seekbar分几段 //mapSeekBarBean.put(TYPE_SATURATION, new SeekBarBean(2, 0, 0.5f, 10)); mapSeekBarBean.put(TYPE_SATURATION, new SeekBarBean(100, 0, 50f, 2)); //mapSeekBarBean.put(TYPE_BRIGHTNESS, new SeekBarBean(1, -1, 0.5f, 10)); mapSeekBarBean.put(TYPE_BRIGHTNESS, new SeekBarBean(100, 0, 50f, 2)); //mapSeekBarBean.put(TYPE_EXPOSURE, new SeekBarBean(10, -10, 0.5f, 0)); mapSeekBarBean.put(TYPE_EXPOSURE, new SeekBarBean(100, 0, 50f, 2)); //mapSeekBarBean.put(TYPE_CONTRAST, new SeekBarBean(4, 0, 0.25f, 0)); mapSeekBarBean.put(TYPE_CONTRAST, new SeekBarBean(100, 0, 25f, 2)); mapSeekBarBean.put(TYPE_POSTERIZE, new SeekBarBean(256, 0, 100f, 3)); //mapSeekBarBean.put(TYPE_HIGH_LIGHT_SHADOW, new SeekBarBean(1, 0, 0f, 0)); mapSeekBarBean.put(TYPE_HIGH_LIGHT_SHADOW, new SeekBarBean(100, 0, 0f, 2)); mapSeekBarBean.put(TYPE_SHARPEN, new SeekBarBean(100, 0, 50f, 3)); //mapSeekBarBean.put(TYPE_GAMMA, new SeekBarBean(3, 0, 0.33f, 0)); mapSeekBarBean.put(TYPE_GAMMA, new SeekBarBean(100, 0, 33f, 3)); //mapSeekBarBean.put(TYPE_OPACITY, new SeekBarBean(1, 0, 1f, 0)); mapSeekBarBean.put(TYPE_OPACITY, new SeekBarBean(100, 0, 100f, 2)); //mapSeekBarBean.put(TYPE_VIBRANCE, new SeekBarBean(1, 0, 0f, 0)); mapSeekBarBean.put(TYPE_VIBRANCE, new SeekBarBean(100, 0, 0f, 2)); //这里是最终设置的值 switch (entrySet.getKey()) { case TYPE_SATURATION: //最后面*2是范围(0,2) float f1 = (entrySet.getValue().getProgress() / entrySet.getValue().getMax()) * 2; filters.add(new GPUImageSaturationFilter(f1)); break; case TYPE_BRIGHTNESS: float f2 = entrySet.getValue().getProgress(); if (f2 == 50) { f2 = 0f; } else { //后面的*0.7是范围(-1,1),以中间0为准,分成两部分(-1,0),(0,1) //负数为变暗,正数为变亮,本应该*1 f2 = (float) (((f2 - 50) / 50) * 0.4); } filters.add(new GPUImageBrightnessFilter(f2)); break; case TYPE_EXPOSURE: float f3 = entrySet.getValue().getProgress(); if (f3 == 50) { f3 = 0f; } else { //后面的*1是范围(-10,10),以中间0为准,分成两部分(-10,0),(0,10) //负数为变暗,正数为变亮,本应该*10 f3 = ((f3 - 50) / 50) * 1; } filters.add(new GPUImageExposureFilter(f3)); break; case TYPE_CONTRAST: //最后面*4是范围(0,4) float f4 = (entrySet.getValue().getProgress() / entrySet.getValue().getMax()) * 4; filters.add(new GPUImageContrastFilter(f4)); break; case TYPE_POSTERIZE: filters.add(new GPUImagePosterizeFilter((int) entrySet.getValue().getProgress())); break; case TYPE_HIGH_LIGHT_SHADOW: GPUImageHighlightShadowFilter highlightShadowFilter = new GPUImageHighlightShadowFilter(); float f9 = (entrySet.getValue().getProgress() / entrySet.getValue().getMax()) * 1; highlightShadowFilter.setHighlights(1 - f9); highlightShadowFilter.setShadows(f9); filters.add(highlightShadowFilter); break; case TYPE_SHARPEN: float f5 = entrySet.getValue().getProgress(); if (f5 == 50) { f5 = 0f; } else { //后面的*4是范围(-4,4),以中间0为准,分成两部分(-4,0),(0,4) //负数为变暗,正数为变亮,本应该*4 f5 = ((f5 - 50) / 50) * 4; } filters.add(new GPUImageSharpenFilter(f5)); break; case TYPE_GAMMA: //最后面*3是范围(0,3) float f6 = (entrySet.getValue().getProgress() / entrySet.getValue().getMax()) * 3; filters.add(new GPUImageGammaFilter(f6)); break; case TYPE_OPACITY: float f7 = (entrySet.getValue().getProgress() / entrySet.getValue().getMax()) * 1; filters.add(new GPUImageOpacityFilter(f7)); break; case TYPE_VIBRANCE: float f8 = (entrySet.getValue().getProgress() / entrySet.getValue().getMax()) * 1; filters.add(new GPUImageVibranceFilter(f8)); break; default: }上面的注意事项里面已经说了简单的用法了,怎么获取滤镜后的图片呢?
//这个方法是获取bitmap对象,至于怎么保存,那就是你自己做了 gpuImageView.getGPUImage().getBitmapWithFilterApplied(); //当然,库也提供了保存图片的方法:保存的文件夹名称,文件名字,回调方法 gpuImageView.saveToPictures(folderName,fileName,OnPictureSavedListener) //其中回调方法里面返回的uri,不能直接传给File,会找不到路径,需要转换一下 /** * 根据Uri获取文件的路径 * * @param context context * @param contentURI uri * @return 文件路径 */ public static String getRealPathFromURI(Context context, Uri contentURI) { String result; Cursor cursor = context.getContentResolver().query(contentURI, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null); if (cursor == null) { result = contentURI.getPath(); } else { cursor.moveToFirst(); int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); result = cursor.getString(index); cursor.close(); } return result; }项目就不贴出来了。