使用RenderScript来实现高斯模糊,兼容低版本

这两天看到公司工程里有用到高斯模糊,是通过java实现的,很慢,所以找了一些资料,看到RenderScript,性能很好,而且RenderScript是可以兼容低版本的,实现方式也是jni。兼容低版本的教程网上有很多,就是在sdk目录里把RenderScript v8包添加到自己的工程里,并且把jni的文件添加到自己的项目里。这里把只把代码和方法发出来。

/**
     * 初始化控件
     */
    private void initView(){
        iv_gaussian = (ImageView)findViewById(R.id.iv_gaussian);
        tv_time = (TextView)findViewById(R.id.tv_time);
        long timeStart = SystemClock.currentThreadTimeMillis();
        Bitmap bitmap = blurBitmap(getBitmapFromDrawable(),this);
        time = SystemClock.currentThreadTimeMillis()-timeStart;
        iv_gaussian.setImageBitmap(bitmap);
        tv_time.setText("耗时:"+time);
    }

    /**
     * 获取资源文件的bitmap
     * @return
     */
    private Bitmap getBitmapFromDrawable(){
        Resources res = getResources();
        return BitmapFactory.decodeResource(res, R.mipmap.bg_1,getScaleOptions(res,R.mipmap.bg_1,200,200));
    }

    /**
     * 执行高斯模糊
     *
     * @param bitmap
     * @param context
     * @return
     */
    public Bitmap blurBitmap(Bitmap bitmap, Context context) {
        // 用需要创建高斯模糊bitmap创建一个空的bitmap
        Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);

        // 初始化Renderscript,这个类提供了RenderScript context,
        // 在创建其他RS类之前必须要先创建这个类,他控制RenderScript的初始化,资源管理,释放
        RenderScript rs = RenderScript.create(context);

        // 创建高斯模糊对象
        ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));

        // 创建Allocations,此类是将数据传递给RenderScript内核的主要方法,
        // 并制定一个后备类型存储给定类型
        Allocation allIn = Allocation.createFromBitmap(rs, bitmap);
        Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);

        // 设定模糊度
        blurScript.setRadius(25.f);

        // Perform the Renderscript
        blurScript.setInput(allIn);
        blurScript.forEach(allOut);

        // Copy the final bitmap created by the out Allocation to the outBitmap
        allOut.copyTo(outBitmap);

        // recycle the original bitmap
        bitmap.recycle();

        // After finishing everything, we destroy the Renderscript.
        rs.destroy();
        return outBitmap;
    }

    /**
     * 获取压缩比例的options
     * @param width 图片的最大宽度
     * @param height 图片的最大高度
     * @return
     */
    private BitmapFactory.Options getScaleOptions(Resources res,int resId,int width,int height){
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        // 开始读入图片,此时把options.inJustDecodeBounds 设回true了
        newOpts.inJustDecodeBounds = true;
//        newOpts.inJustDecodeBounds = false;
        //空的bitmap,不占内存,只是为了拿到宽和高  不需要回收
        Bitmap bitmap = BitmapFactory.decodeResource(res,resId,newOpts);
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
        int be = 1;// be=1表示不缩放
        if (w > h && w > width) {// 如果宽度大的话根据宽度固定大小缩放
            be = (int) (newOpts.outWidth / width);
        } else if (w < h && h > height) {// 如果高度高的话根据宽度固定大小缩放
            be = (int) (newOpts.outHeight / height);
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;// 设置缩放比例
        LogUtils.showDebugLog("GaussianActivity","缩放比例:"+be);
        //因为外部的进行解码操作,所以这时候需要重新设为false
        newOpts.inJustDecodeBounds = false;
        return newOpts;
    }
 

执行高斯的代码是网上拷过来的,模糊半径最大只能设到25,可能对图片直接处理的时候会导致模糊的效果不太好,太清晰,但是可以通过降低图片的质量来实现更模糊的效果,不知道这个思路对不对,或者说性能上是不是会有什么不好影响,欢迎大家指正。


2016.4.14更新

昨天听同事说,图片的缩放会耗时,又看了一下代码,发现代码里有错误,现在订正过了,然后现在把时间的起始放到了缩放之前,耗时是70毫秒左右,图片大小是720*1080,缩放倍数是6

2016.6.24更新

jar包和.so版本的选择一定要选最新的,我现在用的是24.0.0,增加了x86-64的适配,体积也小了很多,老版本的在有些64位的机器上会闪退

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值