Android 中实现毛玻璃效果

- 关于高斯模糊效果的实现

        public class BitmapLoader {

            private Context mContext;


            public BitmapLoader(Context context) {

                this.mContext = context.getApplicationContext();

            }


            private static volatile BitmapLoader sInst = null;


            public static BitmapLoader getInstance(Context context) {

                BitmapLoader inst = sInst;

                if (inst == null) {

                    synchronized (BitmapLoader.class) {

                        inst = sInst;

                        if (inst == null) {

                            inst = new BitmapLoader(context);

                            sInst = inst;

                        }

                    }

                }

                return inst;

            }


            public Drawable getDrawable(Activity activity, int blurRadius) {

                if (activity == null) {

                    L.e("getDrawable : Activity == null");

                    return null;

                }

                View adverView = activity.getWindow().getDecorView();

                if (adverView == null) {

                    L.e("getDrawable : adverView == null");

                    return null;

                }

                // 获取状态栏的高度

                Rect rect = new Rect();

                adverView.getWindowVisibleDisplayFrame(rect);

                int statusBarHeights = rect.top;

                Display display = activity.getWindowManager().getDefaultDisplay();


                // 获取屏幕宽和高

                int widths = display.getWidth();

                int heights = display.getHeight();


                adverView.setDrawingCacheEnabled(true);

                adverView.buildDrawingCache();

                Bitmap bitmap = Bitmap.createBitmap(adverView.getDrawingCache(false), 0, statusBarHeights, widths, heights - statusBarHeights);

                if (bitmap == null) {

                    return null;

                }

                L.i("getDrawable_bitmap_" + bitmap);

                Drawable drawable = new BitmapDrawable(doBlur(ImageUtility.getImageThumbnail(bitmap), blurRadius));

                L.i("getDrawable_drawable_" + drawable);

                if (bitmap != null) bitmap.recycle();

                return drawable;

            }


            /***

            * 高斯模糊

            * 优化

            *

            * @param mBitmap

            * @return

            */

            private Bitmap doBlur(Bitmap mBitmap, int blurRadius) {

                if (mBitmap == null) {

                    return null;

                }

                int width = mBitmap.getWidth();

                int height = mBitmap.getHeight();

                Bitmap scaledBitmap = Bitmap.createScaledBitmap(mBitmap, width, height, true);

                if (mBitmap != null) mBitmap.recycle();

                return doBlur(scaledBitmap, blurRadius, false);

            }


            /**

            * 高斯模糊核心算法

            */

            private Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {

                if (sentBitmap == null) {

                    return sentBitmap;

                }

                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);

            }


            /**

            * 高斯模糊核心算法

            *

            * @param in

            * @param out

            * @param width

            * @param height

            * @param radius

            */

            private void blur(int[] in, int[] out, int width, int height, float radius) {

                int widthMinus1 = width - 1;

                int r = (int) radius;

                int tableSize = 2 * r + 1;

                int divide[] = new int[256 * tableSize];


                for (int i = 0; i < 256 * tableSize; i++)

                    divide[i] = i / tableSize;


                int inIndex = 0;


                for (int y = 0; y < height; y++) {

                    int outIndex = y;

                    int ta = 0, tr = 0, tg = 0, tb = 0;


                    for (int i = -r; i <= r; i++) {

                        int rgb = in[inIndex + clamp(i, 0, width - 1)];

                        ta += (rgb >> 24) & 0xff;

                        tr += (rgb >> 16) & 0xff;

                        tg += (rgb >> 8) & 0xff;

                        tb += rgb & 0xff;

                    }


                    for (int x = 0; x < width; x++) {

                        out[outIndex] = (divide[ta] << 24) | (divide[tr] << 16) | (divide[tg] << 8) | divide[tb];


                        int i1 = x + r + 1;

                        if (i1 > widthMinus1)

                            i1 = widthMinus1;

                        int i2 = x - r;

                        if (i2 < 0)

                            i2 = 0;

                        int rgb1 = in[inIndex + i1];

                        int rgb2 = in[inIndex + i2];


                        ta += ((rgb1 >> 24) & 0xff) - ((rgb2 >> 24) & 0xff);

                        tr += ((rgb1 & 0xff0000) - (rgb2 & 0xff0000)) >> 16;

                        tg += ((rgb1 & 0xff00) - (rgb2 & 0xff00)) >> 8;

                        tb += (rgb1 & 0xff) - (rgb2 & 0xff);

                        outIndex += height;

                    }

                    inIndex += width;

                }

            }


            private void blurFractional(int[] in, int[] out, int width, int height, float radius) {

                radius -= (int) radius;

                float f = 1.0f / (1 + 2 * radius);

                int inIndex = 0;

                for (int y = 0; y < height; y++) {

                    int outIndex = y;

                    out[outIndex] = in[0];

                    outIndex += height;

                    for (int x = 1; x < width - 1; x++) {

                        int i = inIndex + x;

                        int rgb1 = in[i - 1];

                        int rgb2 = in[i];

                        int rgb3 = in[i + 1];

                        int a1 = (rgb1 >> 24) & 0xff;

                        int r1 = (rgb1 >> 16) & 0xff;

                        int g1 = (rgb1 >> 8) & 0xff;

                        int b1 = rgb1 & 0xff;

                        int a2 = (rgb2 >> 24) & 0xff;

                        int r2 = (rgb2 >> 16) & 0xff;

                        int g2 = (rgb2 >> 8) & 0xff;

                        int b2 = rgb2 & 0xff;

                        int a3 = (rgb3 >> 24) & 0xff;

                        int r3 = (rgb3 >> 16) & 0xff;

                        int g3 = (rgb3 >> 8) & 0xff;

                        int b3 = rgb3 & 0xff;

                        a1 = a2 + (int) ((a1 + a3) * radius);

                        r1 = r2 + (int) ((r1 + r3) * radius);

                        g1 = g2 + (int) ((g1 + g3) * radius);

                        b1 = b2 + (int) ((b1 + b3) * radius);

                        a1 *= f;

                        r1 *= f;

                        g1 *= f;

                        b1 *= f;

                        out[outIndex] = (a1 << 24) | (r1 << 16) | (g1 << 8) | b1;

                        outIndex += height;

                    }

                    out[outIndex] = in[width - 1];

                    inIndex += width;

                }

            }


            private int clamp(int x, int a, int b) {

                return (x < a) ? a : (x > b) ? b : x;

            }


        }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容