代码来自:http://blog.csdn.net/huli870715/article/details/39378349 原文对三种方法做了测试,这里直接上最优代码。个人感觉效果仍然不是那么好,在ZTE Grand S II(骁龙800+2G RAM)上运行大概需要十几ms,第一次启动会更长。 布局:
Controller的代码:
@ViewById
ImageView image;
@ViewById
TextView text;
@AfterViews
public void afterViews()
{
applyBlur();
}
private void applyBlur() {
image.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
image.getViewTreeObserver().removeOnPreDrawListener(this);
image.buildDrawingCache();
Bitmap bmp = image.getDrawingCache();
blur2(bmp, text);
return true;
}
});
}
@Override
public void setTopBar() {
}
private void blur2(Bitmap bkg, View view) {
long startMs = System.currentTimeMillis();
float radius = 2;
float scaleFactor = 20;
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 = ImageUtil.fastblur(getActivity(), overlay, (int) radius);
view.setBackground(new BitmapDrawable(getResources(), overlay));
PToast.show("cost " + (System.currentTimeMillis() - startMs) + "ms");
}
fastblur:
/**
* Android api 17实现的虚化
* 某些机型上可能会Crash
*
* @param context
* @param sentBitmap
* @param radius 大于1小于等于25
* @return
*/
@SuppressLint(“NewApi”)
public static Bitmap fastblur(Context context, Bitmap sentBitmap, int radius) {
if (sentBitmap == null) {
return null;
}
if (Build.VERSION.SDK_INT > 16) {
Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
final RenderScript rs = RenderScript.create(context);
final Allocation input = Allocation.createFromBitmap(rs,
sentBitmap, Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
final Allocation output = Allocation.createTyped(rs,
input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs,
Element.U8_4(rs));
script.setRadius(radius /* e.g. 3.f */);
script.setInput(input);
script.forEach(output);
output.copyTo(bitmap);
return bitmap;
}
return stackblur(sentBitmap, radius);
}
/\*\*
\* 纯Java实现的虚化,适用老版本api,外部只需调fastblur,会自动判断
\*
\* @param sentBitmap
\* @param radius
\* @return
*/
private static Bitmap stackblur(Bitmap sentBitmap,
int radius) {
Bitmap bitmap = null;
try {
bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
} catch (OutOfMemoryError e) {
e.printStackTrace();
return sentBitmap;
}
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);
}