`
yaolinnan
  • 浏览: 56785 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
文章分类
社区版块
存档分类
最新评论

【转载】一种快速毛玻璃虚化效果实现

 
阅读更多

原文:http://www.androidchina.net/4626.html

 

在iOS设备上我们随处可见毛玻璃效果,而且最近越来越多的场合应用到了这种美观的虚化效果,包括本人的一个开源项目BlureImageView也是受此启发。所以,恰到好处的虚化效果能很好的改善用户体验,而且也能让你的app显得更加优雅。

不过,我们目前在android上很少见到毛玻璃效果,我认为很重要的原因是性能问题,虚化一张图片所需要的时间会因设备而异,如果为了虚化使得用户需要刻意等待,那么就是弊大于利。另外,Google官方提供的renderScript一般只是做一些小幅度的虚化,很难达到毛玻璃这类深度虚化效果。

所以本文的角度是能够在android设备上快速实现毛玻璃效果。

blob.png

blob.png

StackBlur

首先,为了实现毛玻璃效果,本文采用的是StackBlur模糊算法,这种算法应用非常广泛,能得到非常良好的毛玻璃效果。在这里,我们使用的是它的Java实现代码FastBlur.java

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

 

可以看出,使用方法非常简单,传入待虚化的bitmap、虚化程序(一般为8)、和是否重用flag。

然后,如果要对上面这张图片进行虚化,我们可以通过把它转化成bitmap传入虚化,看起来很简单就解决了,但事实并非如此。

OOM

如果直接把一张大图传入,很容易就会发生OOM内存溢出

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

 

这是我直接对原图进行虚化得到的log信息。可以看出当虚化开始时,虚拟机开始不断进行内存回收,包括把所有软引用的内存回收。然而,仍然导致了内存溢出。

那就意味着我只能虚化小图,这样才能防止内存溢出。但是我并不想换其他图,那么,我们就应该把这张图缩放。

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

从该模拟图可以看出时间随着缩放比的增大而不断减小,当缩放比达到30以上时所消耗的时间不到1ms,因此,我认为应该是完全不会产生时延破坏用户体验的。

Memory Consuming

既然时间没问题,那么,主要问题:内存占用就来了,所以我们需要考察生成一张虚化图片所占用的内存。

为了测试对一张图片进行虚化所占用内存的变化,我们改变虚化次数,即修改上面的loopCount并观察对内存的变化。其中scaleRatio = 10,以获得相对较大的内存消耗。

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

从上面的内存消耗图,可以看出虚化的确会占用一定内存,如果大量的虚化同时发生,则会由于UI线程突然加载很多bitmap而导致内存抖动。

Conclusion

希望大家如果有其他测试方法或者意见多多留言,从而继续改进性能。

附上本文所采用的

测试图

谢谢!

分享到:
评论

相关推荐

    MFC下实现毛玻璃效果

    想在Win7下重画MFC应用程序界面及实现界面的毛玻璃效果,在网上溜达一下发现“用C++品尝Vista美味:界面地毛玻璃效果”,各大网站都是相互转载的同一篇文章。这篇文章是基于WTL实现的,其中有个默认主题句柄。而MFC...

    Qt qml 实现毛玻璃效果

    Qt qml 实现毛玻璃效果

    Wpf 毛玻璃效果实现

    Wpf毛玻璃效果实现.亲测可用. 本资源来自http://download.csdn.net/download/fengchun_doff/8006205 直接编译无法通过.移除了相关引用. 可以直接使用.因为是转的,最少积分共享给大家.

    Android模糊处理简单实现毛玻璃效果

    自从iOS系统引入了Blur效果,也就是所谓的毛玻璃、模糊化效果、磨砂效果,各大系统就开始竞相模仿,这是怎样的一个效果呢,我们先来看一下,如下面的图片: 实现效果大家都知道了,如何在Android中实现呢,说白了...

    Qt Windows下的毛玻璃效果

    在windows平台上做一个半透明的毛玻璃窗体。首先实现半透明效果,再用高斯模糊处理,实现毛玻璃。

    Unity毛玻璃模糊效果Shader

    Unity毛玻璃模糊效果Shader,直接赋值到材质球上进行使用即可。

    MFC实现的窗体毛玻璃效果

    MFC实现的窗体毛玻璃效果。 实现的方法主要是使用以下函数: DwmExtendFrameIntoClientArea(...) 该函数实现将边框区域扩大到客户区,而此时边框区域的绘制,在windows vista和windows 7系统下在开启了毛玻璃效果...

    Android 局部毛玻璃透明效果

    Eclipse 工程Demo,用一个BlurringView自定义控件作为毛玻璃蒙板,对后面的背景进行局部模糊。

    unity CommandBuffer 实现毛玻璃效果

    unity command buffer 实现毛玻璃特效,可用于3D物体或UI。

    Android 毛玻璃效果完美实现

    Android 毛玻璃效果完美实现,不仅只有ios7里面才有,Android也能轻松实现

    BlurTest(毛玻璃效果的实现)

    BlurTest(毛玻璃效果的实现)

    wpf 实时毛玻璃 live blur 效果

    wpf 实现实时毛玻璃(live blur)效果

    HTML毛玻璃效果代码

    毛玻璃效果火狐不支持其他浏览器都没问题。RAR包含1个说明TXT跟4个文件夹。每个文件夹分别包含html文件、css文件跟js文件各一个。1个模板代码跟3个演示代码。

    Android 实现毛玻璃效果.rar

    Android 实现图片的毛玻璃效果,看到效果 了吗?滑块还可改变毛玻璃效果的深浅,这个效果是根据网上已有的工程修改的,使用的是Github上的工程,先对原来工程中的相关操作执行添加依赖,然后跟Glide的一样,只是多了...

    MFC实现毛玻璃效果

    使用DwmExtendFrameIntoClientArea函数实现windows7中的毛玻璃效果

    SVG排版-毛玻璃、磨砂玻璃模板效果

    SVG排版-毛玻璃、磨砂玻璃模板效果

    android毛玻璃效果

    实现android的毛玻璃效果。Sample to show how to implement blur graphical tricks

    模仿ios 动态实现毛玻璃

    模仿ios7的毛玻璃效果 实现动态处理毛玻璃 本文简单的实现了 毛玻璃的效果 新人报道 谢谢支持!!!

    WPF自定义毛玻璃窗口(自适应系统)

    自适应操作系统,可在Win7系统下使用系统毛玻璃,在Win10下使用毛玻璃滤镜...即使系统设定为高对比度原始主题,程序仍旧能显示毛玻璃效果,程序只是借用了系统的高斯滤镜而已,Win8系统下未测试,不知有无Win10的特效。

Global site tag (gtag.js) - Google Analytics