美文网首页Android知识
Android 中实现毛玻璃效果

Android 中实现毛玻璃效果

作者: 温暖的外星 | 来源:发表于2016-05-18 08:40 被阅读323次

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

            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;

                }

            }

    相关文章

      网友评论

        本文标题:Android 中实现毛玻璃效果

        本文链接:https://www.haomeiwen.com/subject/auxwrttx.html