Android图片高斯模糊的一些方法

原文:http://gqdy365.iteye.com/blog/2193913

这几天项目中需要模仿一下iOS版本的微博菜单弹出界面,如下图: 

 

用微博的同学都知道这个效果吧,这篇文章先实现模糊效果,进入、退出动画后面文章分析; 

一、说一下实现思路,很简单的: 
1、截图:就是获取我们app得截图 
获取我们Activity得根view即DecorView,关于DecorView,sdk里面是这么说明的: 
Java代码   收藏代码
  1. Retrieve the top-level window decor view (containing the standard window frame/decorations and the client's content inside of that), which can be added as a window to the window manager.   

就是说获取最顶层的window,可以添加到window manager里面; 
拿到view之后可以调用view的getDrawingCache方法获取bitmap截图; 

2、对图片做高斯模糊; 
高斯模糊在Photoshop里面用的比较多,可以用来去痘痘。 
大致原理是:对指定像素和其周围像素进行加权平均来得到最终结果,使用高斯分布作为滤波器。 
这儿可以了解详细的算法原理:http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html 


二、代码实现: 
代码比较简单,我自己加了注释贴出来了: 
Java代码   收藏代码
  1. private void applyBlur() {  
  2.     View view = getWindow().getDecorView();  
  3.     view.setDrawingCacheEnabled(true);  
  4.     view.buildDrawingCache(true);  
  5.     /** 
  6.      * 获取当前窗口快照,相当于截屏 
  7.      */  
  8.     Bitmap bmp1 = view.getDrawingCache();  
  9.     int height = getOtherHeight();  
  10.     /** 
  11.      * 除去状态栏和标题栏 
  12.      */  
  13.     Bitmap bmp2 = Bitmap.createBitmap(bmp1, 0, height,bmp1.getWidth(), bmp1.getHeight() - height);  
  14.     blur(bmp2, text);  
  15. }  
  16.   
  17. @SuppressLint("NewApi")  
  18. private void blur(Bitmap bkg, View view) {  
  19.     long startMs = System.currentTimeMillis();  
  20.     float scaleFactor = 8;//图片缩放比例;  
  21.     float radius = 20;//模糊程度  
  22.   
  23.     Bitmap overlay = Bitmap.createBitmap(  
  24.             (int) (view.getMeasuredWidth() / scaleFactor),  
  25.             (int) (view.getMeasuredHeight() / scaleFactor),  
  26.             Bitmap.Config.ARGB_8888);  
  27.     Canvas canvas = new Canvas(overlay);  
  28.     canvas.translate(-view.getLeft() / scaleFactor, -view.getTop()/ scaleFactor);  
  29.     canvas.scale(1 / scaleFactor, 1 / scaleFactor);  
  30.     Paint paint = new Paint();  
  31.     paint.setFlags(Paint.FILTER_BITMAP_FLAG);  
  32.     canvas.drawBitmap(bkg, 00, paint);  
  33.   
  34.       
  35.     overlay = FastBlur.doBlur(overlay, (int) radius, true);  
  36.     view.setBackground(new BitmapDrawable(getResources(), overlay));  
  37.     /** 
  38.      * 打印高斯模糊处理时间,如果时间大约16ms,用户就能感到到卡顿,时间越长卡顿越明显,如果对模糊完图片要求不高,可是将scaleFactor设置大一些。 
  39.      */  
  40.     Log.i("jerome""blur time:" + (System.currentTimeMillis() - startMs));  
  41. }  
  42.   
  43. /** 
  44.  * 获取系统状态栏和软件标题栏,部分软件没有标题栏,看自己软件的配置; 
  45.  * @return 
  46.  */  
  47. private int getOtherHeight() {  
  48.     Rect frame = new Rect();  
  49.     getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);  
  50.     int statusBarHeight = frame.top;  
  51.     int contentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();  
  52.     int titleBarHeight = contentTop - statusBarHeight;  
  53.     return statusBarHeight + titleBarHeight;  
  54. }  


我这里用了外国开源项目中的一个Java算法,地址:https://github.com/paveldudka/blurring 
Java代码   收藏代码
  1. package com.jerome.popdemo;  
  2.   
  3. import android.graphics.Bitmap;  
  4.   
  5. /** 
  6.  * Created by paveld on 3/6/14. 
  7.  */  
  8. public class FastBlur {  
  9.   
  10.     public static Bitmap doBlur(Bitmap sentBitmap, int radius,  
  11.             boolean canReuseInBitmap) {  
  12.         Bitmap bitmap;  
  13.         if (canReuseInBitmap) {  
  14.             bitmap = sentBitmap;  
  15.         } else {  
  16.             bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);  
  17.         }  
  18.   
  19.         if (radius < 1) {  
  20.             return (null);  
  21.         }  
  22.   
  23.         int w = bitmap.getWidth();  
  24.         int h = bitmap.getHeight();  
  25.   
  26.         int[] pix = new int[w * h];  
  27.         bitmap.getPixels(pix, 0, w, 00, w, h);  
  28.   
  29.         int wm = w - 1;  
  30.         int hm = h - 1;  
  31.         int wh = w * h;  
  32.         int div = radius + radius + 1;  
  33.   
  34.         int r[] = new int[wh];  
  35.         int g[] = new int[wh];  
  36.         int b[] = new int[wh];  
  37.         int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;  
  38.         int vmin[] = new int[Math.max(w, h)];  
  39.   
  40.         int divsum = (div + 1) >> 1;  
  41.         divsum *= divsum;  
  42.         int dv[] = new int[256 * divsum];  
  43.         for (i = 0; i < 256 * divsum; i++) {  
  44.             dv[i] = (i / divsum);  
  45.         }  
  46.   
  47.         yw = yi = 0;  
  48.   
  49.         int[][] stack = new int[div][3];  
  50.         int stackpointer;  
  51.         int stackstart;  
  52.         int[] sir;  
  53.         int rbs;  
  54.         int r1 = radius + 1;  
  55.         int routsum, goutsum, boutsum;  
  56.         int rinsum, ginsum, binsum;  
  57.   
  58.         for (y = 0; y < h; y++) {  
  59.             rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;  
  60.             for (i = -radius; i <= radius; i++) {  
  61.                 p = pix[yi + Math.min(wm, Math.max(i, 0))];  
  62.                 sir = stack[i + radius];  
  63.                 sir[0] = (p & 0xff0000) >> 16;  
  64.                 sir[1] = (p & 0x00ff00) >> 8;  
  65.                 sir[2] = (p & 0x0000ff);  
  66.                 rbs = r1 - Math.abs(i);  
  67.                 rsum += sir[0] * rbs;  
  68.                 gsum += sir[1] * rbs;  
  69.                 bsum += sir[2] * rbs;  
  70.                 if (i > 0) {  
  71.                     rinsum += sir[0];  
  72.                     ginsum += sir[1];  
  73.                     binsum += sir[2];  
  74.                 } else {  
  75.                     routsum += sir[0];  
  76.                     goutsum += sir[1];  
  77.                     boutsum += sir[2];  
  78.                 }  
  79.             }  
  80.             stackpointer = radius;  
  81.   
  82.             for (x = 0; x < w; x++) {  
  83.   
  84.                 r[yi] = dv[rsum];  
  85.                 g[yi] = dv[gsum];  
  86.                 b[yi] = dv[bsum];  
  87.   
  88.                 rsum -= routsum;  
  89.                 gsum -= goutsum;  
  90.                 bsum -= boutsum;  
  91.   
  92.                 stackstart = stackpointer - radius + div;  
  93.                 sir = stack[stackstart % div];  
  94.   
  95.                 routsum -= sir[0];  
  96.                 goutsum -= sir[1];  
  97.                 boutsum -= sir[2];  
  98.   
  99.                 if (y == 0) {  
  100.                     vmin[x] = Math.min(x + radius + 1, wm);  
  101.                 }  
  102.                 p = pix[yw + vmin[x]];  
  103.   
  104.                 sir[0] = (p & 0xff0000) >> 16;  
  105.                 sir[1] = (p & 0x00ff00) >> 8;  
  106.                 sir[2] = (p & 0x0000ff);  
  107.   
  108.                 rinsum += sir[0];  
  109.                 ginsum += sir[1];  
  110.                 binsum += sir[2];  
  111.   
  112.                 rsum += rinsum;  
  113.                 gsum += ginsum;  
  114.                 bsum += binsum;  
  115.   
  116.                 stackpointer = (stackpointer + 1) % div;  
  117.                 sir = stack[(stackpointer) % div];  
  118.   
  119.                 routsum += sir[0];  
  120.                 goutsum += sir[1];  
  121.                 boutsum += sir[2];  
  122.   
  123.                 rinsum -= sir[0];  
  124.                 ginsum -= sir[1];  
  125.                 binsum -= sir[2];  
  126.   
  127.                 yi++;  
  128.             }  
  129.             yw += w;  
  130.         }  
  131.         for (x = 0; x < w; x++) {  
  132.             rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;  
  133.             yp = -radius * w;  
  134.             for (i = -radius; i <= radius; i++) {  
  135.                 yi = Math.max(0, yp) + x;  
  136.   
  137.                 sir = stack[i + radius];  
  138.   
  139.                 sir[0] = r[yi];  
  140.                 sir[1] = g[yi];  
  141.                 sir[2] = b[yi];  
  142.   
  143.                 rbs = r1 - Math.abs(i);  
  144.   
  145.                 rsum += r[yi] * rbs;  
  146.                 gsum += g[yi] * rbs;  
  147.                 bsum += b[yi] * rbs;  
  148.   
  149.                 if (i > 0) {  
  150.                     rinsum += sir[0];  
  151.                     ginsum += sir[1];  
  152.                     binsum += sir[2];  
  153.                 } else {  
  154.                     routsum += sir[0];  
  155.                     goutsum += sir[1];  
  156.                     boutsum += sir[2];  
  157.                 }  
  158.   
  159.                 if (i < hm) {  
  160.                     yp += w;  
  161.                 }  
  162.             }  
  163.             yi = x;  
  164.             stackpointer = radius;  
  165.             for (y = 0; y < h; y++) {  
  166.                 // Preserve alpha channel: ( 0xff000000 & pix[yi] )  
  167.                 pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16)  
  168.                         | (dv[gsum] << 8) | dv[bsum];  
  169.   
  170.                 rsum -= routsum;  
  171.                 gsum -= goutsum;  
  172.                 bsum -= boutsum;  
  173.   
  174.                 stackstart = stackpointer - radius + div;  
  175.                 sir = stack[stackstart % div];  
  176.   
  177.                 routsum -= sir[0];  
  178.                 goutsum -= sir[1];  
  179.                 boutsum -= sir[2];  
  180.   
  181.                 if (x == 0) {  
  182.                     vmin[y] = Math.min(y + r1, hm) * w;  
  183.                 }  
  184.                 p = x + vmin[y];  
  185.   
  186.                 sir[0] = r[p];  
  187.                 sir[1] = g[p];  
  188.                 sir[2] = b[p];  
  189.   
  190.                 rinsum += sir[0];  
  191.                 ginsum += sir[1];  
  192.                 binsum += sir[2];  
  193.   
  194.                 rsum += rinsum;  
  195.                 gsum += ginsum;  
  196.                 bsum += binsum;  
  197.   
  198.                 stackpointer = (stackpointer + 1) % div;  
  199.                 sir = stack[stackpointer];  
  200.   
  201.                 routsum += sir[0];  
  202.                 goutsum += sir[1];  
  203.                 boutsum += sir[2];  
  204.   
  205.                 rinsum -= sir[0];  
  206.                 ginsum -= sir[1];  
  207.                 binsum -= sir[2];  
  208.   
  209.                 yi += w;  
  210.             }  
  211.         }  
  212.   
  213.         bitmap.setPixels(pix, 0, w, 00, w, h);  
  214.   
  215.         return (bitmap);  
  216.     }  
  217. }  


如果用C/C++实现jni调用,效果会高一些,可以参考:https://github.com/qiujuer/ImageBlurring/blob/master/README-ZH.md 
Java代码   收藏代码
  1. /************************************************* 
  2. Copyright:  Copyright QIUJUER 2013. 
  3. Author:     Qiujuer 
  4. Date:       2014-04-18 
  5. Description:实现图片模糊处理 
  6. **************************************************/  
  7. #include<malloc.h>  
  8.   
  9. #define ABS(a) ((a)<(0)?(-a):(a))  
  10. #define MAX(a,b) ((a)>(b)?(a):(b))  
  11. #define MIN(a,b) ((a)<(b)?(a):(b))  
  12.   
  13. /************************************************* 
  14. Function:       StackBlur(堆栈模糊) 
  15. Description:    使用堆栈方式进行图片像素模糊处理 
  16. Calls:          malloc 
  17. Table Accessed: NULL 
  18. Table Updated:  NULL 
  19. Input:          像素点集合,图片宽,图片高,模糊半径 
  20. Output:         返回模糊后的像素点集合 
  21. Return:         返回模糊后的像素点集合 
  22. Others:         NULL 
  23. *************************************************/  
  24. static int* StackBlur(int* pix, int w, int h, int radius) {  
  25.     int wm = w - 1;  
  26.     int hm = h - 1;  
  27.     int wh = w * h;  
  28.     int div = radius + radius + 1;  
  29.   
  30.     int *r = (int *)malloc(wh * sizeof(int));  
  31.     int *g = (int *)malloc(wh * sizeof(int));  
  32.     int *b = (int *)malloc(wh * sizeof(int));  
  33.     int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;  
  34.   
  35.     int *vmin = (int *)malloc(MAX(w,h) * sizeof(int));  
  36.   
  37.     int divsum = (div + 1) >> 1;  
  38.     divsum *= divsum;  
  39.     int *dv = (int *)malloc(256 * divsum * sizeof(int));  
  40.     for (i = 0; i < 256 * divsum; i++) {  
  41.         dv[i] = (i / divsum);  
  42.     }  
  43.   
  44.     yw = yi = 0;  
  45.   
  46.     int(*stack)[3] = (int(*)[3])malloc(div * 3 * sizeof(int));  
  47.     int stackpointer;  
  48.     int stackstart;  
  49.     int *sir;  
  50.     int rbs;  
  51.     int r1 = radius + 1;  
  52.     int routsum, goutsum, boutsum;  
  53.     int rinsum, ginsum, binsum;  
  54.   
  55.     for (y = 0; y < h; y++) {  
  56.         rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;  
  57.         for (i = -radius; i <= radius; i++) {  
  58.             p = pix[yi + (MIN(wm, MAX(i, 0)))];  
  59.             sir = stack[i + radius];  
  60.             sir[0] = (p & 0xff0000) >> 16;  
  61.             sir[1] = (p & 0x00ff00) >> 8;  
  62.             sir[2] = (p & 0x0000ff);  
  63.   
  64.             rbs = r1 - ABS(i);  
  65.             rsum += sir[0] * rbs;  
  66.             gsum += sir[1] * rbs;  
  67.             bsum += sir[2] * rbs;  
  68.             if (i > 0) {  
  69.                 rinsum += sir[0];  
  70.                 ginsum += sir[1];  
  71.                 binsum += sir[2];  
  72.             }  
  73.             else {  
  74.                 routsum += sir[0];  
  75.                 goutsum += sir[1];  
  76.                 boutsum += sir[2];  
  77.             }  
  78.         }  
  79.         stackpointer = radius;  
  80.   
  81.         for (x = 0; x < w; x++) {  
  82.   
  83.             r[yi] = dv[rsum];  
  84.             g[yi] = dv[gsum];  
  85.             b[yi] = dv[bsum];  
  86.   
  87.             rsum -= routsum;  
  88.             gsum -= goutsum;  
  89.             bsum -= boutsum;  
  90.   
  91.             stackstart = stackpointer - radius + div;  
  92.             sir = stack[stackstart % div];  
  93.   
  94.             routsum -= sir[0];  
  95.             goutsum -= sir[1];  
  96.             boutsum -= sir[2];  
  97.   
  98.             if (y == 0) {  
  99.                 vmin[x] = MIN(x + radius + 1, wm);  
  100.             }  
  101.             p = pix[yw + vmin[x]];  
  102.   
  103.             sir[0] = (p & 0xff0000) >> 16;  
  104.             sir[1] = (p & 0x00ff00) >> 8;  
  105.             sir[2] = (p & 0x0000ff);  
  106.   
  107.             rinsum += sir[0];  
  108.             ginsum += sir[1];  
  109.             binsum += sir[2];  
  110.   
  111.             rsum += rinsum;  
  112.             gsum += ginsum;  
  113.             bsum += binsum;  
  114.   
  115.             stackpointer = (stackpointer + 1) % div;  
  116.             sir = stack[(stackpointer) % div];  
  117.   
  118.             routsum += sir[0];  
  119.             goutsum += sir[1];  
  120.             boutsum += sir[2];  
  121.   
  122.             rinsum -= sir[0];  
  123.             ginsum -= sir[1];  
  124.             binsum -= sir[2];  
  125.   
  126.             yi++;  
  127.         }  
  128.         yw += w;  
  129.     }  
  130.     for (x = 0; x < w; x++) {  
  131.         rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;  
  132.         yp = -radius * w;  
  133.         for (i = -radius; i <= radius; i++) {  
  134.             yi = MAX(0, yp) + x;  
  135.   
  136.             sir = stack[i + radius];  
  137.   
  138.             sir[0] = r[yi];  
  139.             sir[1] = g[yi];  
  140.             sir[2] = b[yi];  
  141.   
  142.             rbs = r1 - ABS(i);  
  143.   
  144.             rsum += r[yi] * rbs;  
  145.             gsum += g[yi] * rbs;  
  146.             bsum += b[yi] * rbs;  
  147.   
  148.             if (i > 0) {  
  149.                 rinsum += sir[0];  
  150.                 ginsum += sir[1];  
  151.                 binsum += sir[2];  
  152.             }  
  153.             else {  
  154.                 routsum += sir[0];  
  155.                 goutsum += sir[1];  
  156.                 boutsum += sir[2];  
  157.             }  
  158.   
  159.             if (i < hm) {  
  160.                 yp += w;  
  161.             }  
  162.         }  
  163.         yi = x;  
  164.         stackpointer = radius;  
  165.         for (y = 0; y < h; y++) {  
  166.             // Preserve alpha channel: ( 0xff000000 & pix[yi] )  
  167.             pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];  
  168.   
  169.             rsum -= routsum;  
  170.             gsum -= goutsum;  
  171.             bsum -= boutsum;  
  172.   
  173.             stackstart = stackpointer - radius + div;  
  174.             sir = stack[stackstart % div];  
  175.   
  176.             routsum -= sir[0];  
  177.             goutsum -= sir[1];  
  178.             boutsum -= sir[2];  
  179.   
  180.             if (x == 0) {  
  181.                 vmin[y] = MIN(y + r1, hm) * w;  
  182.             }  
  183.             p = x + vmin[y];  
  184.   
  185.             sir[0] = r[p];  
  186.             sir[1] = g[p];  
  187.             sir[2] = b[p];  
  188.   
  189.             rinsum += sir[0];  
  190.             ginsum += sir[1];  
  191.             binsum += sir[2];  
  192.   
  193.             rsum += rinsum;  
  194.             gsum += ginsum;  
  195.             bsum += binsum;  
  196.   
  197.             stackpointer = (stackpointer + 1) % div;  
  198.             sir = stack[stackpointer];  
  199.   
  200.             routsum += sir[0];  
  201.             goutsum += sir[1];  
  202.             boutsum += sir[2];  
  203.   
  204.             rinsum -= sir[0];  
  205.             ginsum -= sir[1];  
  206.             binsum -= sir[2];  
  207.   
  208.             yi += w;  
  209.         }  
  210.     }  
  211.   
  212.     free(r);  
  213.     free(g);  
  214.     free(b);  
  215.     free(vmin);  
  216.     free(dv);  
  217.     free(stack);  
  218.     return(pix);  
  219. }  

最后来一张屌丝做demo专业效果图: 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值