【Reprint】A fast frosted glass blur effect realization

Original text: http://www.androidchina.net/4626.html

 

We can see the frosted glass effect everywhere on iOS devices, and this beautiful blur effect has been applied to more and more occasions recently, including one of my open source projects, BlueImageView , which is also inspired by this. Therefore, the right blur effect can improve the user experience very well, and it can also make your app look more elegant.

However, we rarely see the frosted glass effect on android at present. I think the important reason is performance issues. The time required to blur a picture will vary from device to device. If the user needs to wait deliberately for blurring, then It's more harm than good. In addition, the renderScript officially provided by Google generally only does some small blurring, and it is difficult to achieve a deep blurring effect such as frosted glass.

So the point of this article is to be able to quickly achieve the frosted glass effect on android devices.

blob.png

blob.png

StackBlur

First of all, in order to achieve the frosted glass effect, this paper uses the StackBlur blur algorithm , which is widely used and can get a very good frosted glass effect. Here, we are using its Java implementation code FastBlur.java .

public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap)

 

It can be seen that the usage method is very simple, pass in the bitmap to be virtualized, the virtualized program (usually 8), and whether to reuse the flag.

Then, if we want to blur the above picture, we can convert it into a bitmap and pass it into the blur, which seems to be very easy to solve, but it is not the case.

UNCLE

If you directly pass in a large image, OOM memory overflow will easily occur

03-11 21:02:02.014 16727-16742/com.wingjay.jayandroid I/art: Clamp target GC heap from 109MB to 96MB
03-11 21:02:02.026 16727-16727/com.wingjay.jayandroid I/art: Clamp target GC heap from 109MB to 96MB
03-11 21:02:02.030 16727-16727/com.wingjay.jayandroid I/art: Clamp target GC heap from 109MB to 96MB
03-11 21:02:02.031 16727-16727/com.wingjay.jayandroid I/art: Forcing collection of SoftReferences for 30MB allocation
03-11 21:02:02.035 16727-16727/com.wingjay.jayandroid I/art: Clamp target GC heap from 109MB to 96MB
03-11 21:02:02.036 16727-16727/com.wingjay.jayandroid E/art: Throwing OutOfMemoryError "Failed to allocate a 32175012 byte allocation with 2648672 free bytes and 2MB until OOM"
03-11 21:02:02.036 16727-16727/com.wingjay.jayandroid D/AndroidRuntime: Shutting down VM

 

This is the log information I got by blurring the original image directly. It can be seen that when virtualization starts, the virtual machine starts to reclaim memory continuously, including reclaiming all soft referenced memory. However, it still caused a memory overflow.

That means I can only blur the small image, so as to prevent memory overflow. But I don't want to change other pictures, then, we should scale this picture.

ReScale

 
public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) {}

我们可以利用这个function来进行bitmap的缩放。其中前三个参数很明显,其中宽高我们可以选择为原图尺寸的1/10;第四个filter是指缩放的效果,filter为true则会得到一个边缘平滑的bitmap,反之,则会得到边缘锯齿、pixelrelated的bitmap。这里我们要对缩放的图片进行虚化,所以无所谓边缘效果,filter=false。

所以,我们要使用

int scaleRatio = 10;
int blurRadius = 8;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(originBitmap,
     originBitmap.getWidth() / scaleRatio,
     originBitmap.getHeight() / scaleRatio,
     false);
Bitmap blurBitmap = FastBlur.doBlur(scaledBitmap, blurRadius, true);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageBitmap(blurBitmap);

 

可以得到如下效果:

blob.png

blob.png

从图中可以看出,首先可以确定思路是对的;然后,可以看出毛玻璃效果还不是特别的明显。为了得到如iOS那样的虚化效果,我们有两种方法:

  • 增大scaleRatio缩放比,使用一样更小的bitmap去虚化可以得到更好的模糊效果,而且有利于占用内存的减小;
  • 增大blurRadius,可以得到更高程度的虚化,不过会导致CPU更加intensive

这里本人通过增大缩放比来实验。

  • scaleRatio = 20
  • scaleRatio = 35
  • scaleRatio = 50
  • scaleRatio = 100
    scaleRatio_100

通过上面对比图我们可以找出最适合自己的虚化效果。

Performance analysis

那么,要实现这样的效果,是否具有损害用户体验的风险呢?下面,我们从消耗时间和占据内存的角度来进行分析。

Time Consuming

为了分析虚化一张图片所消耗的时间,本文通过同时虚化100来获取平均消耗时间。以期对虚化耗时和不同缩放比对耗时的影响得到一定的认识。

long start = System.currentTimeMillis();
Bitmap scaledBitmap, blurBitmap;
int scaleRatio = 10;
int loopCount = 100
for (int i=0; i<loopCount; i++) {
    scaledBitmap = Bitmap.createScaledBitmap(originBitmap,
    originBitmap.getWidth() / scaleRatio,
    originBitmap.getHeight() / scaleRatio,
    false);
    blurBitmap = FastBlur.doBlur(scaledBitmap, 8, true);
}
Log.i("blurtime", String.valueOf(System.currentTimeMillis() - start));

 
  • scaleRatio = 10: 耗时887ms,平均耗时8.87ms;
  • scaleRatio = 20: 耗时224ms,平均耗时2.24ms;
  • scaleRatio = 35: 耗时99ms,平均耗时0.99ms;
  • scaleRatio = 50: 耗时55ms,平均耗时0.55ms;
  • scaleRatio = 100: 耗时29ms,平均耗时0.29ms;

为了方便读者了解效果,我通过多组数据拟合了下面的曲线:

blob.png

It can be seen from the simulation graph that the time decreases with the increase of the zoom ratio. When the zoom ratio reaches 30 or more, the time consumed is less than 1ms. Therefore, I think there should be no delay and damage to the user experience. of.

Memory Consuming

Since the time is no problem, then the main problem: the memory usage is coming, so we need to examine the memory occupied by generating a blurred image.

In order to test the changes in the memory occupied by blurring a picture, we change the number of times of blurring, that is, modify the loopCount above and observe the changes to the memory. where scaleRatio = 10 for relatively large memory consumption.

  • loopCount = 1
  • loopCount = 10
  • loopCount = 20
  • loopCount = 50
  • loopCount = 100
  • loopCount = 300

From the memory consumption graph above, it can be seen that blurring does occupy a certain amount of memory. If a large amount of blurring occurs at the same time, it will cause memory jitter due to the sudden loading of many bitmaps by the UI thread.

Conclusion

I hope that if you have other test methods or comments, please leave a comment so that you can continue to improve the performance.

Attached is the

test chart

Thanks!

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326779144&siteId=291194637
Recommended