Android 模糊效果 FastBlur
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver; public class FastBlur { public static void applyBlur(final View v) {
v.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
v.getViewTreeObserver().removeOnPreDrawListener(this);
v.buildDrawingCache();
Bitmap bmp = v.getDrawingCache();
blur(bmp, v);
return true;
}
});
} public static void blur(Bitmap bkg, View view) {
long startMs = System.currentTimeMillis();
float scaleFactor = 1;
float radius = 20;
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.setBackgroundDrawable(new BitmapDrawable(view.getResources(), overlay));
Log.e("TAG", System.currentTimeMillis() - startMs + "ms");
} public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) { 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);
}
}
Android 模糊效果 FastBlur的更多相关文章
- Android 模糊效果
(1)FastBlur http://www.cnblogs.com/CharlesGrant/p/4813735.html (2)StackBlur 基于RenderScript,StackBlur ...
- Android模糊效果总结
1. 软件模糊 用软件的方法.利用cpu计算,无sdk版本号要求. 效果图: 关键模糊代码 github链接 原文 链接 译文 链接 演示样例 代码 本文地址 :http://blog.csdn.ne ...
- Android 高仿微信语音聊天页面高斯模糊效果
目前的应用市场上,使用毛玻璃效果的APP随处可见,比如用过微信语音聊天的人可以发现,语音聊天页面就使用了高斯模糊效果. 先看下效果图: 仔细观察上图,我们可以发现,背景图以用户头像为模板,对其进行了高 ...
- Android Blur效果之FastBlur
Blur 自从iOS系统引入了Blur效果,也就是所谓的毛玻璃.模糊化效果,磨砂效果,各大系统就開始竞相模仿,这是一个怎样的效果呢,我们现来看一些图: 这些就是典型的Blur效果,在iOS和MIUI中 ...
- Android开发——高斯模糊效果的简单实现
0. 前言 在Android开发中,经常在音乐软件中看到高斯模糊效果. 在找遍了所有高斯模糊的算法代码后,发现stackblur的Java实现是最快的.效果如下所示. 1. 高斯模糊效果实现 Bit ...
- Android项目实战(五十七):Glide 高斯模糊效果
核心需要高斯模糊的库 compile 'jp.wasabeef:glide-transformations:2.0.1' 针对于3.7的版本 使用方法为: //加载背景, Glide.with(Mus ...
- android图片特效处理之模糊效果
这篇将讲到图片特效处理的模糊效果.跟前面一样是对像素点进行处理,算法是通用的,但耗时会更长,至于为什么,看了下面的代码你就会明白. 算法: 一.简单算法:将像素点周围八个点包括自身一共九个点的RGB值 ...
- android 图片特效处理之模糊效果
这篇将讲到图片特效处理的模糊效果.跟前面一样是对像素点进行处理,算法是通用的,但耗时会更长,至于为什么,看了下面的代码你就会明白. 算法: 一.简单算法:将像素点周围八个点包括自身一共九个点的RGB值 ...
- xamarin.android 图片高斯模糊效果
代码如下: private static float BITMAP_SCALE = 0.1f; private static float BLUR_RADIUS = 12.0f; public sta ...
随机推荐
- Java面试经典题:线程池专题
1.什么是线程池 线程池的基本思想是一种对象池,在程序启动时就开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理.当有线程任务时,从池中取一个,执行完成后线程对象归池, ...
- 最新Java面试题及答案整理
基础篇 一.基本功 面向对象特征 封装,继承,多态和抽象 1. 封装 封装给对象提供了隐藏内部特性和行为的能力.对象提供一些能被其他对象访问的方法来改变它内部的数据.在 Java 当中,有 3 种修饰 ...
- 详解MathType中如何更改公式颜色
在MathType数学公式编辑器中可以通过更改公式颜色,起到美化.标注公式的效果.本教程将详解MathType中如何更改公式颜色. 点击菜单栏中的样式->格式->颜色,用户就可以根据自己的 ...
- 在Linux上安装SVN服务
1.安装SVNyum install subversion 2.查看版本svnserve --version3.创建目录mkdir -p /web/svndata3.创建repo测试库svnadmin ...
- MySQL索引优化入门
索引简介 官方定义:索引(Index) 是帮助MySQL高效获取数据的数据结构.大家一定很好奇,索引为什么是一种数据结构,它又是怎么提高查询的速度?我们拿最常用的二叉树来分析索引的工作原理.看下面的图 ...
- layui文件上传进度条(模拟)
1.修改上传组件js(没测) https://blog.csdn.net/weixin_42457316/article/details/81017471 https://www.cnblogs.co ...
- Tomcat------如何配置域名和80端口
1.打开Tomcat的默认安装路径下的Service.xml文件 路径:C:\Program Files\Apache Software Foundation\Tomcat 8.0\conf\Serv ...
- 使用npm国内镜像
嫌npm指令速度慢的童鞋可以把npm的源转换成国内的即可提高响应速度: 镜像使用方法(三种办法任意一种都能解决问题,建议使用第1或者第3种,将配置写死,下次用的时候配置还在):1.通过config命令 ...
- 让树莓派自动上报IP地址到邮箱,二代B
由于我使用树莓派的场景大多数是在没有显示器.只用terminal连接它的情况下,所以,它的IP地址有时会在重启之后变掉(DHCP的),导致我无法通过terminal连接上它.然后我又要很麻烦地登录路由 ...
- flexbox父盒子justify-content属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...