像我们看到的一样,结果很好并且花了57ms。由于Android的框架需致使不超过16ms(60fps),在UI线程虚化的时间段中,使我们的帧频率下降到17fps。显然这是不允许的,因此我们需要卸载这个,利用asyncTask或者其他类似的技术。
同时值得注意的是ScriptIntrinsicBlur只有在API 17时才可用。但是你可以利用renderscript依赖包兼容低版本的API。
但是,大量的人仍然不得不支持那些没有这样功能的老版本的API。在这让我们寻找我们可以找到的。
FastBlur
由于虚化的过程只不过是操作像素,显著的解决方案是试着尽量手动虚化。很幸运,有大量的java例子可以实现虚化效果。需要做的唯一事情是找到相对快速的实现方案。
感谢在SO上得博客,我找到了快速虚化的实现方式。让我们看看吧。
private void blur(Bitmap bkg, View view) { long startMs = System.currentTimeMillis(); float radius = 20; Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth()), (int) (view.getMeasuredHeight()), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(overlay); canvas.translate(-view.getLeft(), -view.getTop()); canvas.drawBitmap(bkg, 0, 0, null); overlay = FastBlur.doBlur(overlay, (int)radius, true); view.setBackground(new BitmapDrawable(getResources(), overlay)); statusText.setText(System.currentTimeMillis() - startMs + "ms"); }像我们看到的,虚化的效果也差不多。
因此,利用FastBlur的优点是消除renderscript的依赖。
糟糕!它竟然消耗了大量的时间。进行虚化花费了147ms。这远远不是最慢得SW模糊算法。我甚至不想尝试高斯模糊了。。。
Going beyond
现在让我们想想有什么更好的办法。虚化的过程它本身是一个不稳定的像素。妮知道的还有什么是关于不稳定像素的?对!Downscaling!
假设我们试着先缩减bitmap,进行模糊,然后重新扩大它 会怎么样?我尝试实现这个技术。
我只用了faseblur方法进行描述,对于renderscript是一样的。全部的代码可以查看我的github。
private void blur(Bitmap bkg, View view) { long startMs = System.currentTimeMillis(); float scaleFactor = 1; float radius = 20; if (downScale.isChecked()) { scaleFactor = 8; radius = 2; } Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth()/scaleFactor), (int) (view.getMeasuredHeight()/scaleFactor), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(overlay); canvas.translate(-view.getLeft()/scaleFactor, -view.getTop()/scaleFactor); canvas.scale(1 / scaleFactor, 1 / scaleFactor); Paint paint = new Paint(); paint.setFlags(Paint.FILTER_BITMAP_FLAG); canvas.drawBitmap(bkg, 0, 0, paint); overlay = FastBlur.doBlur(overlay, (int)radius, true); view.setBackground(new BitmapDrawable(getResources(), overlay)); statusText.setText(System.currentTimeMillis() - startMs + "ms"); }让我们仔细检查一下代码:
1.scaleFactor表示我们想要缩减模式的层级。在我的例子中,我将缩减bitmap到原来大小的1/8 。当然因为我的bitmap将会通过缩减/扩大模式进行模糊,我并不需要比较大的半径来进行模糊算法。我决定半径减为2.
2.现在我需要创建bitmap。这个bitmap比我最终需要的背景小8倍。
3.同时请注意我提供了paint的FILTER_BITMAP_FLAG。这个方法中,在缩放时将得到双线过滤应用到我的bitmap上。它可以更加平滑的模糊。
4.就像之前,使用虚化。在这个例子中,image较小,模糊半径较低,所以模糊的速度就会很快。
5.设置模糊的image作为背景色。它将重新自动扩大。
fastblur模糊的速度要远远超过renderscript。那是因为我们没有浪费时间在复制bitmap到Allocation。
利用这个简单的处理,我设法比较了fast blur机制和renderscript的依赖。
警告!请注意 FastBlur需要用大量的额外内存。(它复制了整个图片到临时缓冲区),即使它对于较小的bitmap完美运行,我不推荐利用它来进行虚化整个屏幕,因为这样在低版本设备上很容易发生内存溢出异常(OutOfMemoryException)。选择最好的决定。
源代码地址:https://github.com/paveldudka/blurring
猜你在找