Android磨砂图片处理(FastBlur)

常用的图片有png和jpg这2种,这里也只针对这2种图片做简单介绍。项目中使用的网络请求主要是XUtils3,但是对jpg格式图片,磨砂处理有个问题,针对解决办法,下面会有详细说明:
关于XUtils3在Android Studio中的使用:

http://blog.csdn.net/u014620028/article/details/51063377

先看效果图:
第一张:
Android磨砂图片处理(FastBlur)_第1张图片

第二张:
Android磨砂图片处理(FastBlur)_第2张图片

说明:
1、每张图中,上面的2张,都是png图片。下面2张,都是jpg图片
2、 左下角的jpg图片,都是用的下面的第一种处理方法;右下角的jpg图片,都是用的下面的第二种处理方法
3、 左上角的png图片,都是用的下面的第一种处理方法;右上角的png图片,都是用的下面的第二种处理方法
4、第一次加载的时候,用XUtils3得到网络jpg图片,然后进行磨砂处理,就会出现图一种右下角的情况。但是,退出去,然后清理缓存,再次进入,就没问题了。即:只要从第二次开始,就会一直正常。但是使用第一种处理方式,一直正常

使用下面说的第一种获取bitmap方法,获取到后,再进行磨砂处理,就不会出现上面效果图中的问题了

代码:
对图片进行磨砂处理的代码:(2种处理方法,我用的第二种,这2种方法效果一样)

package com.chen.bitmapdemo;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;


public class FastBlur {
    /**
     * Android api 17实现的虚化
     * 某些机型上可能会Crash
     *
     * @param context
     * @param sentBitmap
     * @param radius     大于1小于等于25
     * @return
     */
    @SuppressLint("NewApi")
    public static Bitmap fastblur(Context context, Bitmap sentBitmap, int radius) {
        if (sentBitmap == null) {
            return null;
        }
        if (Build.VERSION.SDK_INT > 16) {
            Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);

            final RenderScript rs = RenderScript.create(context);
            final Allocation input = Allocation.createFromBitmap(rs,
                    sentBitmap, Allocation.MipmapControl.MIPMAP_NONE,
                    Allocation.USAGE_SCRIPT);
            final Allocation output = Allocation.createTyped(rs,
                    input.getType());
            final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs,
                    Element.U8_4(rs));
            script.setRadius(radius /* e.g. 3.f */);
            script.setInput(input);
            script.forEach(output);
            output.copyTo(bitmap);
            return bitmap;
        }
        return stackblur(context, sentBitmap, radius);
    }

    /**
     * 纯Java实现的虚化,适用老版本api,外部只需调上面的fastblur方法,会自动判断
     *
     * @param context
     * @param sentBitmap
     * @param radius
     * @return
     */
    private static Bitmap stackblur(Context context, Bitmap sentBitmap, int radius) {
        try {
            Bitmap bitmap = null;
            try {
                bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
                return sentBitmap;
            }
            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);
        } catch (Exception e) {
            return BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
        }
    }

    /**
     * 图片缩放比例
     */
    private static final float BITMAP_SCALE = 0.4F;
    /**
     * 最大模糊度(在0-25之间),值越大,越模糊
     */
    private static final float BLUR_RADIUS = 23F;

    /**
     * 模糊图片的具体算法
     *
     * @param context 上下文对象
     * @param image   需要模糊的图片
     * @return 模糊处理后的图片
     */
    public static Bitmap blur(Context context, Bitmap image) {
        try {
            //计算图片缩小后的长度
            int width = Math.round(image.getWidth() * BITMAP_SCALE);
            int height = Math.round(image.getHeight() * BITMAP_SCALE);
            //将缩小后的图片做为预渲染图片
            Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
            //创建一张渲染后的输出图片
            Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
            //创建RenderScript内核对象
            RenderScript rs = RenderScript.create(context);
            //创建一个模糊效果的RenderScript的工具对象
            ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
            //由于RenderScript并没有使用VM来分配内存
            //所以需要使用Allocation类来创建和分配内容空间
            //创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去
            Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
            Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
            //设置渲染的模糊程度,25f是最大模糊层
            blurScript.setRadius(BLUR_RADIUS);
            //设置blurScript对象的输入内存
            blurScript.setInput(tmpIn);
            //将输出数据保存到输出内存中
            blurScript.forEach(tmpOut);
            //将数据填充到Allocation中
            tmpOut.copyTo(outputBitmap);
            return outputBitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return image;
        } catch (OutOfMemoryError error) {
            return image;
        }
    }
}

要将图片进行磨砂处理,先要拿到bitmap,获取bitmap的2中方法:
1、

private void getImgBitmap(String path) {
        new AsyncTask() {
            @Override
            protected Bitmap doInBackground(String... params) {
                URL url = null;
                try {
                    url = new URL(params[0]);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setConnectTimeout(5000);
                    conn.setRequestMethod("GET");
                    Log.e("chen", "图片请求状态码=====" + conn.getResponseCode());
                    if (conn.getResponseCode() == 200) {
                        InputStream inStream = conn.getInputStream();
                        Bitmap bitmap = BitmapFactory.decodeStream(inStream);
                        return bitmap;
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (ProtocolException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                if (bitmap == null) {
                    bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.default_iv);
                }

                bitmap = FastBlur.blur(MainActivity.this, bitmap);
                if (bitmap != null)
                    show_iv_png_1.setImageBitmap(bitmap);
                else
                    show_iv_png_1.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.default_iv));
            }
        }.execute(path);
    }

第2种方法:

private void getLoadBitmap(String iconUrl) {

        if (Util.checkStringIsEmpty(iconUrl)) {
            show_iv_png_2.setBackgroundResource(R.mipmap.default_iv);
        } else {

            ImageOptions imageOptions = new ImageOptions.Builder()
                    .setImageScaleType(ImageView.ScaleType.FIT_XY)
                    .setFailureDrawableId(R.mipmap.default_iv)
                    .setCrop(true)
                    .setUseMemCache(true)
                    .build();
            x.image().loadDrawable(iconUrl, imageOptions, new Callback.CommonCallback() {

                @Override
                public void onSuccess(Drawable result) {

                    Log.e("下载==png==", "onSuccess");

                    BitmapDrawable bd = (BitmapDrawable) result;
                    bitmap_png = bd.getBitmap();
                    //                    Bitmap cirBitMap = UIUtils.createCircleImage(bg_bitmap, 0);
                    show_iv_png_2.setImageBitmap(FastBlur.blur(MainActivity.this, bitmap_png));
                }

                @Override
                public void onError(Throwable ex, boolean isOnCallback) {
                    Log.e("下载==png==", "onError");
                    show_iv_png_2.setImageResource(R.mipmap.default_iv);
                }

                @Override
                public void onCancelled(CancelledException cex) {

                }

                @Override
                public void onFinished() {

                }
            });
        }
    }

你可能感兴趣的:(Android笔记)