Android ImageView 模糊动画

Android ImageView blur animation(Android ImageView 模糊动画)

本文介绍了Android ImageView 模糊动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望将模糊动画添加到 ImageView,但要设置持续时间.因此,例如,我希望图像随着时间的推移而变得模糊.

I'm looking to add a blur animation to an ImageView, but with a set duration. So, for example I want an image to blur out over time.

我已经有了模糊图像的方法,但我需要让它在 2 秒内从模糊变为无模糊.

I already have the method to blur the image, but what I need is to make it go from blur to none blur over, say, 2 seconds.

谁能帮帮我?

这是我目前必须模糊图像的方法.

This is the method I currently have to blur the image.

public Bitmap blur(Bitmap sentBitmap, int radius) {

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

推荐答案

模糊效果在 Android 上总是很困难.本质上,您必须在外观和性能之间做出决定.模糊看起来越好,花费的时间就越长,如果模糊本身不是瞬时的,那么你就无法真正为模糊设置动画.

Blur effects are always difficult on Android. Essentially you have to decide between looks and performance. The better the blur looks the longer it takes, and if the blurring itself is not instantaneous then you cannot really animate the blur.

你原来的模糊算法产生了非常好的结果,但正因为如此它也很慢,使得模糊动画变得不可能.为了演示如何有效地模糊此图像,我通过缩小位图创建了一个简单的模糊动画:

You original blurring algorithm produces really good results, but because of that it is also very slow making a blur animation impossible. Just to demonstrate what it would take to effectively blur this image I have created a simple blur animation by scaling the bitmap down:

public class BlurAnimation extends Animation {

    private final ImageView imageView;
    private final Bitmap bitmap;
    private final float startValue;
    private final float stopValue;
    private final float difValue;

    private BlurAnimation(ImageView imageView, Bitmap bitmap, int startValue, int stopValue) {
        this.imageView = imageView;
        this.bitmap = bitmap;
        this.startValue = startValue;
        this.stopValue = stopValue;
        this.difValue = stopValue - startValue;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);

        int current = (int)(this.difValue * interpolatedTime + this.startValue + 0.5f);
        Bitmap blurred = quickBlur(this.bitmap, current);
        this.imageView.setImageBitmap(blurred);
    }

    public Bitmap quickBlur(Bitmap bitmap, int factor) {
        if(factor <= 0) {
            return Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
        }
        return Bitmap.createScaledBitmap(bitmap, bitmap.getWidth() / factor, bitmap.getHeight() / factor, true);
    }
}

这工作得很好(尽管仍有一些滞后),但结果无法与您的模糊算法进行比较,它看起来很糟糕:

This works quite well (even though there is still some lag), but the results cannot be compared with your blur algorithm, it just looks terrible:

所以你看,在模糊图像时很难将性能和美观结合起来,但首先有一些选项RenderScript.RenderScript 非常快,并且具有内置的高斯模糊滤镜.我从未使用过它,但据我所知,它可能是您问题的解决方案.

So you see, it is very difficult to combine performance and good looks when it comes to blurring an image, but there are some options first and foremost RenderScript. RenderScript is very fast and has a built in gaussian blur filter. I have never used it, but from what I hear it might be the solution to your problem.

您也可以尝试加载已缩小版本的图像,这将产生与上述 gif 相同的效果,但速度会更快.缺点是在 Animation 中使用它还是有问题的,但如果你只需要一张模糊的图像并且你并不真正关心质量,那么你应该选择这个选项.

You can also try to load already scaled down versions of an image, this would produce the same effect as in the gif above, but would be even faster. The drawback is that using this in an Animation is again problematic, but if you just need a blurred image and you don't really care about quality then you should go for this option.

您可以在此答案中找到有关 RenderScript 和其他快速模糊选项的更多信息

You can find more information about RenderScript and other fast blur options in this answer

这篇关于Android ImageView 模糊动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:Android ImageView 模糊动画

基础教程推荐