Android毛玻璃处理代码(Blur)
以下为将bitmap图像处理为毛玻璃效果的图像的工具类:
- public class FastBlurUtil {
- public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {
- // Stack Blur v1.0 from
- // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
- //
- // Java Author: Mario Klingemann <mario at quasimondo.com>
- // http://incubator.quasimondo.com
- // created Feburary 29, 2004
- // Android port : Yahel Bouaziz <yahel at kayenko.com>
- // http://www.kayenko.com
- // ported april 5th, 2012
- // This is a compromise between Gaussian Blur and Box blur
- // It creates much better looking blurs than Box Blur, but is
- // 7x faster than my Gaussian Blur implementation.
- //
- // I called it Stack Blur because this describes best how this
- // filter works internally: it creates a kind of moving stack
- // of colors whilst scanning through the image. Thereby it
- // just has to add one new block of color to the right side
- // of the stack and remove the leftmost color. The remaining
- // colors on the topmost layer of the stack are either added on
- // or reduced by one, depending on if they are on the right or
- // on the left side of the stack.
- //
- // If you are using this algorithm in your code please add
- // the following line:
- //
- // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
- Bitmap bitmap;
- if (canReuseInBitmap) {
- bitmap = sentBitmap;
- } else {
- bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
- }
- if (radius < 1) {
- return (null);
- }
- int w = bitmap.getWidth();
- int h = bitmap.getHeight();
- int[] pix = new int[w * h];
- bitmap.getPixels(pix, 0, w, 0, 0, w, h);
- int wm = w - 1;
- int hm = h - 1;
- int wh = w * h;
- int div = radius + radius + 1;
- int r[] = new int[wh];
- int g[] = new int[wh];
- int b[] = new int[wh];
- int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
- int vmin[] = new int[Math.max(w, h)];
- int divsum = (div + 1) >> 1;
- divsum *= divsum;
- int dv[] = new int[256 * divsum];
- for (i = 0; i < 256 * divsum; i++) {
- dv[i] = (i / divsum);
- }
- yw = yi = 0;
- int[][] stack = new int[div][3];
- int stackpointer;
- int stackstart;
- int[] sir;
- int rbs;
- int r1 = radius + 1;
- int routsum, goutsum, boutsum;
- int rinsum, ginsum, binsum;
- for (y = 0; y < h; y++) {
- rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
- for (i = -radius; i <= radius; i++) {
- p = pix[yi + Math.min(wm, Math.max(i, 0))];
- sir = stack[i + radius];
- sir[0] = (p & 0xff0000) >> 16;
- sir[1] = (p & 0x00ff00) >> 8;
- sir[2] = (p & 0x0000ff);
- rbs = r1 - Math.abs(i);
- rsum += sir[0] * rbs;
- gsum += sir[1] * rbs;
- bsum += sir[2] * rbs;
- if (i > 0) {
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
- } else {
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
- }
- }
- stackpointer = radius;
- for (x = 0; x < w; x++) {
- r[yi] = dv[rsum];
- g[yi] = dv[gsum];
- b[yi] = dv[bsum];
- rsum -= routsum;
- gsum -= goutsum;
- bsum -= boutsum;
- stackstart = stackpointer - radius + div;
- sir = stack[stackstart % div];
- routsum -= sir[0];
- goutsum -= sir[1];
- boutsum -= sir[2];
- if (y == 0) {
- vmin[x] = Math.min(x + radius + 1, wm);
- }
- p = pix[yw + vmin[x]];
- sir[0] = (p & 0xff0000) >> 16;
- sir[1] = (p & 0x00ff00) >> 8;
- sir[2] = (p & 0x0000ff);
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
- rsum += rinsum;
- gsum += ginsum;
- bsum += binsum;
- stackpointer = (stackpointer + 1) % div;
- sir = stack[(stackpointer) % div];
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
- rinsum -= sir[0];
- ginsum -= sir[1];
- binsum -= sir[2];
- yi++;
- }
- yw += w;
- }
- for (x = 0; x < w; x++) {
- rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
- yp = -radius * w;
- for (i = -radius; i <= radius; i++) {
- yi = Math.max(0, yp) + x;
- sir = stack[i + radius];
- sir[0] = r[yi];
- sir[1] = g[yi];
- sir[2] = b[yi];
- rbs = r1 - Math.abs(i);
- rsum += r[yi] * rbs;
- gsum += g[yi] * rbs;
- bsum += b[yi] * rbs;
- if (i > 0) {
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
- } else {
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
- }
- if (i < hm) {
- yp += w;
- }
- }
- yi = x;
- stackpointer = radius;
- for (y = 0; y < h; y++) {
- // Preserve alpha channel: ( 0xff000000 & pix[yi] )
- pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
- rsum -= routsum;
- gsum -= goutsum;
- bsum -= boutsum;
- stackstart = stackpointer - radius + div;
- sir = stack[stackstart % div];
- routsum -= sir[0];
- goutsum -= sir[1];
- boutsum -= sir[2];
- if (x == 0) {
- vmin[y] = Math.min(y + r1, hm) * w;
- }
- p = x + vmin[y];
- sir[0] = r[p];
- sir[1] = g[p];
- sir[2] = b[p];
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
- rsum += rinsum;
- gsum += ginsum;
- bsum += binsum;
- stackpointer = (stackpointer + 1) % div;
- sir = stack[stackpointer];
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
- rinsum -= sir[0];
- ginsum -= sir[1];
- binsum -= sir[2];
- yi += w;
- }
- }
- bitmap.setPixels(pix, 0, w, 0, 0, w, h);
- return (bitmap);
- }
- }
可以看出,使用方法非常简单,传入待续话的bitmap、虚化程序(一般为8),和是否重用flag。
然后,对于大图,往往会出现OOM异常的报错,那是因为当虚化开始时,虚拟机开始不断进行内存回收,包括所有软引用的回收。然后,仍然出现了内存溢出。那就意味着我们只能对小图进行虚化,这样才能防止内存溢出。但我并不想换其他图,那么,我们应该把这张图先进性缩放。
缩放方法:
- public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
第四个输入输入的参数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);
如果图片的虚化效果较弱或者并不是很明显,提供增强虚化效果的方法:
1、增大scaleRatio的数值(增大缩放比),使用更小的bitmap去虚化,这样可以得到更好的虚化效果,而且有利于减小内存消耗。
2、增大blurRadius的数值,这样可以提高续话层度,不过会导致cpu更加intensive。
参考资料:实现虚化、bitmap代码地址
Android毛玻璃处理代码(Blur)的更多相关文章
- wpf 实现实时毛玻璃(live blur)效果
原文:wpf 实现实时毛玻璃(live blur)效果 I2OS7发布后,就被它的时实模糊吸引了,就想着能不能将这个效果引入到我们的产品上.拿来当mask肯定会很爽,其实在之前也做过类似的,但是不是实 ...
- 转--Android实用的代码片段 常用代码总结
这篇文章主要介绍了Android实用的代码片段 常用代码总结,需要的朋友可以参考下 1:查看是否有存储卡插入 复制代码 代码如下: String status=Environment.getE ...
- Android 上的代码阅读器 CoderBrowserHD 修改支持 go 语言代码
我在Android上的代码阅读器用的是 https://github.com/zerob13/CoderBrowserHD 改造的版本,改造后的版本我放在 https://github.com/ghj ...
- 利用android proguard混淆代码
利用android proguard混淆代码 2014-02-05 17:50 1207人阅读 评论(1) 收藏 举报 网上虽然有很多相关博客,不过貌似都不是最新版的..于是百度+谷歌+github上 ...
- 转:Android 2.3 代码混淆proguard技术介绍
ProGuard简介 ProGuard是一个SourceForge上非常知名的开源项目.官网网址是:http://proguard.sourceforge.net/. Java的字节码一般是非常容易反 ...
- 关于下拉刷新你是否真的非常理解还是只会搬砖?附 Android 实例子源代码文件下载地址380个合集
1,推荐几篇非常有用的博文 原创写的真的非常好 主要讲解原理,整体布局三部分组成以及设置padding等等作用, 下拉的具体实现 滑动到底部具体加载以及判断手势事件,再次推荐作者的 详细讲解 建议先看 ...
- Android 简单的代码混淆
Android的代码混淆是开发者需要了解的相关知识,它能够防止android应用程序的反编译.因为android程序多数是java语言开发的,而java代码很容易被反编译,所以为了使android应用 ...
- android studio 实现代码混淆
=======本文章属于转载==========原文章地址:http://my.oschina.net/aibenben/blog/370985 这篇文章等是跟大家分享一在Android studio ...
- 《Android第一行代码》笔记
学习Android开发差点儿相同有两年时间了.期间也做了大大小小的一些项目.近来抽出闲暇想把Android基础强化一下,之前在网上看到了郭霖郭大神的几篇博客.从中受益不少.于是花了近一周时间看完了郭神 ...
随机推荐
- 用gradle管理android项目出现的问题以及解决方法
1.项目结构 最好是全部在root 项目配置 一个settings.gradle 一个build.gradle 2.多项目依赖 http://www.gradle.org/docs/current/u ...
- HBase总结(二十)HBase经常使用shell命令具体说明
进入hbase shell console $HBASE_HOME/bin/hbase shell 假设有kerberos认证,须要事先使用对应的keytab进行一下认证(使用kinit命令),认证成 ...
- XSS分析及预防(转)
阅读目录 XSS的种类和特点 XSS预防 总结 XSS(Cross Site Scripting),又称跨站脚本,XSS的重点不在于跨站点,而是在于脚本的执行.在WEB前端应用日益发展的今天,XSS漏 ...
- csdn肿么了,这两天写的博文都是待审核
昨天早上8点写了一篇博文,然后点击发表,结果系统显示"待审核".于是仅仅好qq联系csdn的客服,等到9点时候,csdn的客服上线了,然后回复说是链接达到5个以上须要审核,于是回到 ...
- php学习之道:php中soap的使用实例以及生成WSDL文件,提供自己主动生成WSDL文件的类库——SoapDiscovery.class.php类
1. web service普及: Webservice soap wsdl差别之个人见解 Web Service实现业务诉求: Web Service是真正"办事"的那个,提供 ...
- SQL Syscolumns
每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行.该表位于每个数据库中. 列名 数据类型 描述 name sysname 列名或过程参数的名称. id int 该列所属的表对象 I ...
- AOP 之 6.1 AOP基础 ——跟我学spring3(转)
http://jinnianshilongnian.iteye.com/blog/1418596
- svnkit添加节点
package com.repositoryclient.svnoptions; import org.tmatesoft.svn.core.SVNException; import org.tmat ...
- 7款开源Java反编译工具
今天我们要来分享一些关于Java的反编译工具,反编译听起来是一个非常高上大的技术词汇,通俗的说,反编译是一个对目标可执行程序进行逆向分析,从而得到原始代码的过程.尤其是像.NET.Java这样的运行在 ...
- Java调用cmd压缩文件
今天在做一个java调用windows的压缩命令时遇到一奇怪问题代码如下: String cmd ="C:/Program Files (x86)/WinRAR/rar.exe a c:/t ...