高斯模糊三种方法优劣性

来源:互联网 发布:买家怎么撤销淘宝介入 编辑:程序博客网 时间:2024/05/22 13:30
package com.example.test.qtest;import android.annotation.TargetApi;import android.content.Context;import android.graphics.Bitmap;import android.os.Build;import android.renderscript.Allocation;import android.renderscript.Element;import android.renderscript.RenderScript;import android.renderscript.ScriptIntrinsicBlur;/** * Created by scq on 17-2-10. */public class GaussianBlur {    private Context mContext;    public GaussianBlur(Context context) {        this.mContext = context;    }    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)    /**     * 高斯模糊     * 方法一 : RenderScript是Android在API 11之后加入的,用于高效的图片处理,包括模糊、混合、矩阵卷积计算等     * 优点:处理时间快     * 缺点:模糊程度比较低     * **/    public Bitmap blurRenderScriptBitmap(Bitmap bitmap){        //创建一个空位图,其大小与要模糊的位图大小相同        Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);        //实例化一个新的Renderscript        RenderScript rs = RenderScript.create(mContext);        //使用Renderscript创建一个内在模糊脚本        ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));        //使用Renderscript和in / out位图创建分配(in / out)        Allocation allIn = Allocation.createFromBitmap(rs, bitmap);        Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);        //设置模糊的半径 半径范围(1.0f ~ 25.0f)        blurScript.setRadius(25.0f);        //执行Renderscript        blurScript.setInput(allIn);        blurScript.forEach(allOut);        //将out Allocation创建的最终位图复制到outBitmap        allOut.copyTo(outBitmap);        //回收原始位图        bitmap.recycle();        //完成一切后,销毁Renderscript。        rs.destroy();        return outBitmap;    }    /**     * 高斯模糊     * 方法二 : 实现高斯模糊的效果,使用了特殊的算法     * 优点 : 比第三种可以快很多     * 缺点 : 比第一种(RenderScript)还是慢一些     * **/    public static Bitmap doFastBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {        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);    }    /**     * 高斯模糊     * 方法三 : 使用矩阵处理     * 优点 : 简单易懂     * 缺点 : 处理速度慢     * **/    public static void gaussBlur(int[] data, int width, int height, int radius,                                 float sigma) {        float pa = (float) (1 / (Math.sqrt(2 * Math.PI) * sigma));        float pb = -1.0f / (2 * sigma * sigma);        // generate the Gauss Matrix        float[] gaussMatrix = new float[radius * 2 + 1];        float gaussSum = 0f;        for (int i = 0, x = -radius; x <= radius; ++x, ++i) {            float g = (float) (pa * Math.exp(pb * x * x));            gaussMatrix[i] = g;            gaussSum += g;        }        for (int i = 0, length = gaussMatrix.length; i < length; ++i) {            gaussMatrix[i] /= gaussSum;        }        // x direction        for (int y = 0; y < height; ++y) {            for (int x = 0; x < width; ++x) {                float r = 0, g = 0, b = 0;                gaussSum = 0;                for (int j = -radius; j <= radius; ++j) {                    int k = x + j;                    if (k >= 0 && k < width) {                        int index = y * width + k;                        int color = data[index];                        int cr = (color & 0x00ff0000) >> 16;                        int cg = (color & 0x0000ff00) >> 8;                        int cb = (color & 0x000000ff);                        r += cr * gaussMatrix[j + radius];                        g += cg * gaussMatrix[j + radius];                        b += cb * gaussMatrix[j + radius];                        gaussSum += gaussMatrix[j + radius];                    }                }                int index = y * width + x;                int cr = (int) (r / gaussSum);                int cg = (int) (g / gaussSum);                int cb = (int) (b / gaussSum);                data[index] = cr << 16 | cg << 8 | cb | 0xff000000;            }        }        // y direction        for (int x = 0; x < width; ++x) {            for (int y = 0; y < height; ++y) {                float r = 0, g = 0, b = 0;                gaussSum = 0;                for (int j = -radius; j <= radius; ++j) {                    int k = y + j;                    if (k >= 0 && k < height) {                        int index = k * width + x;                        int color = data[index];                        int cr = (color & 0x00ff0000) >> 16;                        int cg = (color & 0x0000ff00) >> 8;                        int cb = (color & 0x000000ff);                        r += cr * gaussMatrix[j + radius];                        g += cg * gaussMatrix[j + radius];                        b += cb * gaussMatrix[j + radius];                        gaussSum += gaussMatrix[j + radius];                    }                }                int index = y * width + x;                int cr = (int) (r / gaussSum);                int cg = (int) (g / gaussSum);                int cb = (int) (b / gaussSum);                data[index] = cr << 16 | cg << 8 | cb | 0xff000000;            }        }    }}

0 0