美文网首页Android 实战技术应用程序员
Android - 高斯模糊处理头像作为背景图的两种高效便捷方法

Android - 高斯模糊处理头像作为背景图的两种高效便捷方法

作者: Kris_liu | 来源:发表于2017-09-13 22:41 被阅读162次

    第一种是最简单方便的结合强大的Glide图片加载框架的使用(推荐)

    先来看看效果图吧!

    这种是使用头像作为背景模糊背景使用的,根据项目需求,单独背景什么的都行:

    个人中心头像背景图 我的模块fragment界面

    Glide框架结合使用

    第一步添加下面依赖并同步

    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'jp.wasabeef:glide-transformations:2.0.1'
    

    第二步glide代码的使用如下

       //头像
     final String photo = MapUtil.getValueStr(data, "fileUrl");
     Glide.with(mContext)
          .load(photo)
          .dontAnimate()
          //加载过程中的图片显示
          .placeholder(R.mipmap.bg4)
          //加载失败中的图片显示
          //如果重试3次(下载源代码可以根据需要修改)还是无法成功加载图片,则用错误占位符图片显示。
        .error(R.mipmap.bg4)
        //第二个参数是圆角半径,第三个是模糊程度,2-5之间个人感觉比较好。
        .bitmapTransform(new BlurTransformation(PersonalActivity.this, 14, 1))
    .into(iv_person_bg);
    

    这种方法是不是很简单一行代码解决问题
    .bitmapTransform(new BlurTransformation(PersonalActivity.this, 14, 1))

    第二种方法稍微麻烦点,效果都一样

    方法中会用到这个类

    package teacherlove.zontonec.com.ztteacherlove.helper;
    
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URL;
    
    /**
    *
    *   @data 创建时间: 2017/8/24
    *
    *   @author 创建人: kris_liutao
    *
    *   @description  功能描述: 高斯模糊处理背景图
    *
    */
    
    public class BlurImageview {
    
        /**
         * 根据imagepath获取bitmap
         */
        /**
         * 得到本地或者网络上的bitmap url - 网络或者本地图片的绝对路径,比如:
         * A.网络路径: url="http://blog.foreverlove.us/girl2.png" ;
         * B.本地路径:url="file://mnt/sdcard/photo/image.png";
         * C.支持的图片格式 ,png, jpg,bmp,gif等等
         * @param url
         * @return
         */
        public static int IO_BUFFER_SIZE = 2 * 1024;
    
        public static Bitmap GetUrlBitmap(String url, int scaleRatio) {
    
            int blurRadius = 8;//通常设置为8就行。
            if (scaleRatio <= 0) {
                scaleRatio = 10;
            }
    
    
            Bitmap originBitmap = null;
            InputStream in = null;
            BufferedOutputStream out = null;
            try {
                in = new BufferedInputStream(new URL(url).openStream(), IO_BUFFER_SIZE);
                final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
                out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
                copy(in, out);
                out.flush();
                byte[] data = dataStream.toByteArray();
                originBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
    
                Bitmap scaledBitmap = Bitmap.createScaledBitmap(originBitmap,
                        originBitmap.getWidth() / scaleRatio,
                        originBitmap.getHeight() / scaleRatio,
                        false);
                Bitmap blurBitmap = doBlur(scaledBitmap, blurRadius, true);
                return blurBitmap;
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    
        private static void copy(InputStream in, OutputStream out)
                throws IOException {
            byte[] b = new byte[IO_BUFFER_SIZE];
            int read;
            while ((read = in.read(b)) != -1) {
                out.write(b, 0, read);
            }
        }
    
    
        //    把本地图片毛玻璃化
        public static Bitmap toBlur(Bitmap originBitmap, int scaleRatio) {
            //        int scaleRatio = 10;
            // 增大scaleRatio缩放比,使用一样更小的bitmap去虚化可以到更好的得模糊效果,而且有利于占用内存的减小;
            int blurRadius = 8;//通常设置为8就行。
            //增大blurRadius,可以得到更高程度的虚化,不过会导致CPU更加intensive
    
           /* 其中前三个参数很明显,其中宽高我们可以选择为原图尺寸的1/10;
            第四个filter是指缩放的效果,filter为true则会得到一个边缘平滑的bitmap,
            反之,则会得到边缘锯齿、pixelrelated的bitmap。
            这里我们要对缩放的图片进行虚化,所以无所谓边缘效果,filter=false。*/
            if (scaleRatio <= 0) {
                scaleRatio = 10;
            }
            Bitmap scaledBitmap = Bitmap.createScaledBitmap(originBitmap,
                    originBitmap.getWidth() / scaleRatio,
                    originBitmap.getHeight() / scaleRatio,
                    false);
            Bitmap blurBitmap = doBlur(scaledBitmap, blurRadius, true);
            return blurBitmap;
        }
    
        public static Bitmap doBlur(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);
        }
    
    }
    

    然后在需要加载高斯模糊图的地方使用下面这个方法

     final String pattern = "2";//此处参数可以随意设置根据个人需求而言
     new Thread(new Runnable() {
     @Override
     public void run() {
     int scaleRatio = 0;
     if (TextUtils.isEmpty(pattern)) {
     scaleRatio = 0;
     } else if (scaleRatio < 0) {
     scaleRatio = 10;
     } else {
     scaleRatio = Integer.parseInt(pattern);
     }
     //下面的这个方法必须在子线程中执行
     final Bitmap blurBitmap = BlurImageview.GetUrlBitmap(photo, scaleRatio);
    
    //刷新ui必须在主线程中执行
                                            App.runOnUIThread(new Runnable() {
     @Override
    public void run() {                                           iv_person_bg.setScaleType(ImageView.ScaleType.CENTER_CROP);                                               iv_person_bg.setImageBitmap(blurBitmap);
                  }
             });
         }
    }).start();
    
    

    这个刷新UI我给写在Application类的子类App下面了

       /**
         * 在主线程中刷新UI的方法
         *
         * @param r
         */
        public static void runOnUIThread(Runnable r) {
            App.getMainHandler().post(r);
        }
    
        //用来在主线程中刷新ui
        private static Handler mHandler;
    
        public static Handler getMainHandler() {
            return mHandler;
        }
    

    到此,就是所有使用到的代码,简简单单完成高斯模糊0.0

    CSDN请移步到

    http://blog.csdn.net/First_CooMan##

    相关文章

      网友评论

      • Jsonjia:你好,你们的app叫什么名字,我想下载看看,谢谢
        Kris_liu:@small_Master 嗯呢 最近在搞另外的项目 所以这个就先搁置着的 :smiley:
        Jsonjia:@Kris_liu 好的,没事,期待你的app上线
        Kris_liu:@small_Master sorry啊! 这款app今年不打算上线了,下载不了,如果你想学习高斯模糊处理图片的话,这两种方法是最方便快捷的:smile:

      本文标题:Android - 高斯模糊处理头像作为背景图的两种高效便捷方法

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