【问题标题】:Android blur on view-level视图级别的 Android 模糊
【发布时间】:2015-02-11 19:35:59
【问题描述】:

我正在整个互联网上寻找一种在 LinearLayout 后面获得漂亮模糊的方法。 那里有很多库(android-stackblur / BlurBehind / ...),但它们大多在 Activity 级别模糊,或者需要模糊图像。

让事情变得复杂的是我使用视频作为背景,并且在 LinearLayout 的底部有一些按钮,如果我可以在 LinearLayout 上实现模糊效果会很棒。

有用的库有什么提示吗?

【问题讨论】:

    标签: android blur


    【解决方案1】:

    我要做一张GoogleMap的模糊图片,我用的是fastblur算法,是下一个:

    public static Bitmap fastblur(Bitmap sentBitmap, int radius)
    {
    
    // Stack Blur v1.0 from
    // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
    //
    // Java Author: Mario Klingemann <mario at quasimondo.com>
    // http://incubator.quasimondo.com
    // created Feburary 29, 2004
    // Android port : Yahel Bouaziz <yahel at kayenko.com>
    // http://www.kayenko.com
    // ported april 5th, 2012
    
    // This is a compromise between Gaussian Blur and Box blur
    // It creates much better looking blurs than Box Blur, but is
    // 7x faster than my Gaussian Blur implementation.
    //
    // I called it Stack Blur because this describes best how this
    // filter works internally: it creates a kind of moving stack
    // of colors whilst scanning through the image. Thereby it
    // just has to add one new block of color to the right side
    // of the stack and remove the leftmost color. The remaining
    // colors on the topmost layer of the stack are either added on
    // or reduced by one, depending on if they are on the right or
    // on the left side of the stack.
    //
    // If you are using this algorithm in your code please add
    // the following line:
    //
    // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
    
    Bitmap 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];
    Log.e("pix", w + " " + h + " " + pix.length);
    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;
        }
    }
    
    Log.e("pix", w + " " + h + " " + pix.length);
    bitmap.setPixels(pix, 0, w, 0, 0, w, h);
    
    return (bitmap);
    }
    

    我认为视频是不同的,但对于地图,您可以拍摄快照并返回位图:

    private void captureMapScreen()
    {
        SnapshotReadyCallback callback = new SnapshotReadyCallback()
        {
    
        @Override
        public void onSnapshotReady(Bitmap snapshot)
        {
            final Bitmap snap = snapshot;
    
            Thread thread = new Thread(new Runnable()
            {
    
            @Override
            public void run()
            {
                Bitmap blurTemplate = Bitmap.createScaledBitmap(snap, snap.getWidth() / 10, snap.getHeight() / 10, false);
    
                final Bitmap image = MyApplication.fastblur(blurTemplate, 8);
    
                getActivity().runOnUiThread(new Runnable()
                {
    
                @Override
                public void run()
                {
                    v_blur.setBackgroundDrawable(new BitmapDrawable(getActivity().getResources(), image));
    
                }
                });
    
            }
            });
            thread.start();
        }
        };
    
        map.snapshot(callback);
    
    }
    

    您可以尝试获取视频的快照,然后尝试我上面所说的。并非所有设备都以相同的方式工作,例如华为设备在快照方面有点棘手。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2014-09-18
      • 1970-01-01
      • 2021-05-23
      • 2012-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-26
      • 2016-09-01
      相关资源
      最近更新 更多