过去三天我一直在寻找一种内置的,硬件加速的方法来使用android来模拟位图。我偶然发现了某些解决方法,比如缩小位图并再次缩放,但这种方法产生的质量低,不适合我的图像识别要求。我还读到使用着色器或JNI实现卷积是一个很好的方法,但我不能相信Android框架中没有内置的解决方案用于这个非常常见的目的。目前我最终在Java中使用自编写的卷积实现,但它的速度非常慢。我的问题是:
答案 0 :(得分:70)
我终于找到了合适的解决方案:
但是,ScriptIntrinsicBlur
类的文档非常少见,我花了一些时间来确定正确的调用参数。对于模拟名为ARGB_8888
的普通photo
类型位图,这里它们是:
final RenderScript rs = RenderScript.create( myAndroidContext );
final Allocation input = Allocation.createFromBitmap( rs, photo, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT );
final Allocation output = Allocation.createTyped( rs, input.getType() );
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create( rs, Element.U8_4( rs ) );
script.setRadius( myBlurRadius /* e.g. 3.f */ );
script.setInput( input );
script.forEach( output );
output.copyTo( photo );
答案 1 :(得分:12)
最苛刻的要求可能是实时模糊,这意味着当视图发生变化时,您会模糊不清。在这种情况下,模糊不应超过10秒左右(使一些游戏室达到16ms / 60fps)看起来平滑。即使在不那么高端的设备(galaxy s3甚至更慢)上,也可以通过正确的设置实现这种效果。
以下是如何以不断下降的重要性提高绩效:
使用缩小尺寸的图片: 这会使像素大幅度模糊。当你想要一个真实的模糊图像时它也适合你。此外,图像加载和内存消耗也大幅降低。
使用Renderscript ScriptIntrinsicBlur - 自2014年起,Android中可能没有更好/更快的解决方案。我经常看到的一个错误是Renderscript上下文不会被重用,而是每次使用模糊算法时都会创建。请注意,RenderScript.create(this);
在Nexus 5上需要大约20毫秒,因此您要避免这种情况。
重用位图:不要创建不必要的实例并始终使用相同的实例。当你需要非常快速的模糊时,垃圾收集起着重要的作用(收集一些位图需要10-20毫秒)。还可以裁剪和模糊你所需要的东西。
对于实时模糊,可能是因为上下文切换,它不可能在另一个线程中模糊(即使使用线程池),只有主线程足够快以保持视图及时更新,线程我看到了100-300ms的滞后
有关更多提示,请参阅此处的其他帖子https://stackoverflow.com/a/23119957/774398