欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 实现高斯模糊效果且兼容低版本

程序员文章站 2024-03-05 08:21:24
 一、效果演示 项目中用到了高斯模糊效果,查阅过一些资料,考虑到性能问题最终还是选择使用android自带的renderscript库来实现,关于使用rende...

 一、效果演示

项目中用到了高斯模糊效果,查阅过一些资料,考虑到性能问题最终还是选择使用android自带的renderscript库来实现,关于使用renderscript来实现高斯模糊网上也有很多类似的方法,大部分都总结的比较乱,此处算是做一个整理吧,供有类似需求的同学参考及学习。

Android 实现高斯模糊效果且兼容低版本


Android 实现高斯模糊效果且兼容低版本Android 实现高斯模糊效果且兼容低版本

(项目效果图)

简单描述项目效果图的实现思路:

① 加载定义的xml的layout

② 使用截屏方法获取当前窗口的bitmap对象

③ 将bitmap对象进行压缩及高斯模糊处理

④ 将处理过的模糊图对象作为①中所加载出来的layout的background

⑤ 将已经加入了模糊图对象的layout添加到popuwindow中并处理子条目的弹出方式

二、适用renderscript实现高斯模糊

实现高斯模糊效果的方法有很多,可以用java来实现,可以使用ndk来实现,也可以使用本文推荐的方式来实现(也是使用了jni的方式),至于为什么选择使用renderscript方式来实现,必然有一定优点。

优点:renderscript方式,速度极快,约为java方式100倍的速度,ndk方式20倍速度(不同图片质量测试所得结果不同,供参考)

缺点:api17以上有效。(但google已提供向下兼容的方法,文章后面会有介绍)

下面是使用renderscript方式的核心代码:

/************************ 
* 高斯模糊处理 
* @param bitmap 
* @param context 
* @return 
***********************/ 
public static bitmap blurbitmap(bitmap bitmap, context context) { 
// 用需要创建高斯模糊bitmap创建一个空的bitmap 
bitmap outbitmap = bitmap.createbitmap(bitmap.getwidth(), bitmap.getheight(), config.argb_8888); 
// 初始化renderscript,该类提供了renderscript context,创建其他rs类之前必须先创建这个类,其控制renderscript的初始化,资源管理及释放 
renderscript rs = renderscript.create(context); 
// 创建高斯模糊对象 
scriptintrinsicblur blurscript = scriptintrinsicblur.create(rs, element.u8_4(rs)); 
// 创建allocations,此类是将数据传递给renderscript内核的主要方法,并制定一个后备类型存储给定类型 
allocation allin = allocation.createfrombitmap(rs, bitmap); 
allocation allout = allocation.createfrombitmap(rs, outbitmap); 
//设定模糊度(注:radius最大只能设置25.f) 
blurscript.setradius(15.f); 
// perform the renderscript 
blurscript.setinput(allin); 
blurscript.foreach(allout); 
// copy the final bitmap created by the out allocation to the outbitmap 
allout.copyto(outbitmap); 
// recycle the original bitmap 
bitmap.recycle(); 
// after finishing everything, we destroy the renderscript. 
rs.destroy(); 
return outbitmap; 
}

该方法中注释描述的很清楚,但需要注意的是blurscript.setradius();方法,该方法设定模糊度时radius最大只能设置25.f,可能是对图片直接进行处理会导致模糊效果不好,故此值最大有效设定为25,但若想实现更深度的模糊效果,可以先压缩图片,降低图片的质量来实现更模糊的效果。

下方是图片的压缩处理方法:

/** 
* compress image by pixel, this will modify image width/height. 
* 
* @param imgpath image path 
* @param pixelw target pixel of width 
* @param pixelh target pixel of height 
* @return 
*/ 
public static bitmap ratio(string imgpath, float pixelw, float pixelh) { 
bitmapfactory.options newopts = new bitmapfactory.options(); 
// 开始读入图片,此时把options.injustdecodebounds 设回true,即只读边不读内容 
newopts.injustdecodebounds = true; 
newopts.inpreferredconfig = config.rgb_565; 
// get bitmap info, but notice that bitmap is null now 
bitmap bitmap = bitmapfactory.decodefile(imgpath,newopts); 
newopts.injustdecodebounds = false; 
int w = newopts.outwidth; 
int h = newopts.outheight; 
float ww = pixelw; //设置宽度为120f,可以明显看到图片缩小了 
float hh = pixelh; //设置高度为240f时,可以明显看到图片缩小了 
//缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 
int be = 1;//表示不缩放 
if (w > h && w > ww) { //如果宽度大的话根据宽度固定大小缩放 
be = (int) (newopts.outwidth / ww); 
} else if (w < h && h > hh) { //如果高度高的话根据宽度固定大小缩放 
be = (int) (newopts.outheight / hh); 
} 
if (be <= 0) be = 1; 
newopts.insamplesize = be;//设置缩放比例 
// 开始压缩图片,注意此时已经把options.injustdecodebounds 设回false了 
bitmap = bitmapfactory.decodefile(imgpath, newopts); 
// 压缩好比例大小后再进行质量压缩 
//return compress(bitmap, maxsize); //这里再进行质量压缩的意义不大,反而耗资源,删除 
return bitmap; 
} 

以上方法是使用renderscript来实现高斯模糊的核心代码块及需注意的地方。但是,还是需要注意兼容问题,上述有提到该方法仅适用于api17以上才有效,那么问题来了,需要处理api向下兼容问题。

三、处理api向下兼容问题及注意点

在按照上述方法实现高斯模糊后,运行一看效果,满满的成就感,此时,boss正好带着客户过来,小伙子,来,帮客户安装一个最新的版本(客户手机系统版本为android4.0),装完后一点。。。。。。。。。。。这特么就尴尬了…………!

追踪bug时有同学可能会出现如下错误信息:

异常信息一:

09-21 15:07:34.417: e/androidruntime(4476): android.support.v8.renderscript.rsruntimeexception: error loading rs jni library: java.lang.unsatisfiedlinkerror: couldn't load rssupport: findlibrary returned null………………

异常信息二:

java.lang.noclassdeffounderror: android.renderscript.scriptintrinsicblur………………

解决方案:

报错信息为android.support.v8.renderscript.rsruntimeexception: error loading 以及 java.lang.unsatisfiedlinkerror: couldn't load rssupport from loader dalvik.system.pathclassloader 是由于在4.2以上的手机自带 librsjni.so和librssupport.so库,而4.2以下某些手机没有这两个jni库。所以得把这两个jni 导入到我们的工程下便可。那么文件在何处呢?

以下是本人的文件路径:c:\tools\android-sdk\build-tools\23.0.3\renderscript\lib\packaged,renderscript-v8.jar包位于renderscript\lib目录下。

即:android sdk 路径下 build-tools\各个版本\renderscript\lib\packaged 下的四个目录,这里需要注意jar包和.so版本的选择最好选最新的,例如24.0.0中增加了x86-64的适配。

Android 实现高斯模糊效果且兼容低版本

好了,到这里就可以完美的兼容4.2以下的版本了。另外,还有一个最最最重要的注意点,我被这个细节困扰了至少2小时,现在想起来还觉得蛋疼,在你做完上面的一切事情之后,请注意一定能要将import的包路径更换过来:import android.renderscript更换为import android.support.v8.renderscript。具体如下:

import android.support.v8.renderscript.allocation; 
import android.support.v8.renderscript.element; 
import android.support.v8.renderscript.renderscript; 
import android.support.v8.renderscript.scriptintrinsicblur; 

最最最最后需要注意的一点,若项目中对代码加了混淆,别忘了这个。ok,就到这里了。

四、附:

另外分享两个处理高斯模糊的github:

https://github.com/wl9739/blurredview
https://github.com/robinxdroid/blur

以上所述是小编给大家介绍的android 实现高斯模糊效果且兼容低版本的全部叙述,希望对大家有所帮助