欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android RenderScript实现高斯模糊

程序员文章站 2024-02-28 13:52:04
昨天看了下renderscript的官方文档,发现renderscript这厮有点牛逼。无意中发现scriptintrinsic这个抽象类,有些很有用的子类。其中有个子类叫...

昨天看了下renderscript的官方文档,发现renderscript这厮有点牛逼。无意中发现scriptintrinsic这个抽象类,有些很有用的子类。其中有个子类叫scriptintrinsicblur类,大致就是将图片实现高斯模糊。

scriptintrinsic的申明:

Android RenderScript实现高斯模糊

scriptintrinsicblur类的申明:

Android RenderScript实现高斯模糊

加上结合着看了下sdk中的samples,自己写了个高斯模糊。
( sample的具体位置为:
sdk目录/samples/android-19/renderscript/renderscriptintrinsic/renderscriptintrinsicsample/
)。

先上图。效果如下:

Android RenderScript实现高斯模糊

【注意!! 开始之前,我们需要导入需要的支持包。
支持包的具体路径为: sdk目录/buildtools/任意一个版本号/renderscript/lib/renderscript-v8.jar
另外:为了防止出现有的机型兼容问题,最好将renderscript-v8.jar同目录下的packaged目录下的所有库也一并拷贝到lib文件夹下】

例如:

Android RenderScript实现高斯模糊

好了。开始写代码。。

1、先申明常用成员变量。

private seekbar blurseekbar;//拖动条
private imageview img_blur;//显示模糊后bitmap的imageview
//原bitmap和高斯模糊后的bitmap
private bitmap bitmap_original, bitmap_blur;
//高斯模糊处理的asynctask
private renderscripttask mlatesttask = null;
//renderscript 对象(google的高性能并行计算类,他可以利用设备的gpu/cpu等计算资源)
private renderscript mrs;
//下面是两个renderscript的传入参数对象
private allocation minallocation;
private allocation moutallocation;
//高斯模糊处理实例
private scriptintrinsicblur mscriptblur;

2、加载两份bitmap,并初始化高斯模糊相关的对象。

@override
protected void oncreate(bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.activity_main);
  blurseekbar = (seekbar) findviewbyid(r.id.aty_main_seekbar);
  img_blur = (imageview) findviewbyid(r.id.aty_main_img_blur);

  bitmap_original = loadbitmap(r.drawable.meet_entry_guide_3);
  // 复制一份
  bitmap_blur = bitmap.createbitmap(bitmap_original.getwidth(),
      bitmap_original.getheight(), bitmap_original.getconfig());
  createblurescript();
  setseekbarlistening();//为seekbar设置拖拽监听
}

/**
 * helper to load bitmap from resource
 */
private bitmap loadbitmap(int resource) {
  final bitmapfactory.options options = new bitmapfactory.options();
  options.inpreferredconfig = bitmap.config.argb_8888;
  return bitmapfactory.decoderesource(getresources(), resource, options);
}

/**
 * 创建script
 */
private void createblurescript() {
  mrs = renderscript.create(this);
  minallocation = allocation.createfrombitmap(mrs, bitmap_original);
  moutallocation = allocation.createfrombitmap(mrs, bitmap_blur);

  /*
   * create intrinsics. renderscript has built-in features such as blur,
   * convolve filter etc. these intrinsics are handy for specific
   * operations without writing renderscript kernel. in the sample, it's
   * creating blur, convolve and matrix intrinsics.
   */
  mscriptblur = scriptintrinsicblur.create(mrs, element.u8_4(mrs));
}

3、完成高斯模糊处理代码。

private void performfilter(allocation inallocation,
      allocation outallocation, bitmap bitmapout, float value) {
  /*
   * 设置模糊程度。范围在0~25之间。否则会出错
   */
  mscriptblur.setradius(value);

  /*
   * invoke filter kernel
   */
  mscriptblur.setinput(inallocation);
  mscriptblur.foreach(outallocation);

  outallocation.copyto(bitmapout);
}

4、将处理后的bitmap设置到imageview中。

// request ui update
img_blur.setimagebitmap(bitmap_blur);
img_blur.invalidate();

基本工作也就完成了。剩下就是代码的相互调用了。

【 总 结 】
其实总起来,使用renderscript进行高斯模糊主要是分为三步:

1、创建并初始化需要的对象(初始化一次就ok)。

mrs = renderscript.create(this);
mscriptblur = scriptintrinsicblur.create(mrs, element.u8_4(mrs));
//renderscript的输入和输出参数对象
minallocation = allocation.createfrombitmap(mrs, bitmap_original);
moutallocation = allocation.createfrombitmap(mrs, bitmap_blur);

2、执行高斯模糊,并将结果拷贝出来。

/*
 * 设置模糊程度。范围在0~25之间。否则会出错(这个也可以只设置一次)
 */
mscriptblur.setradius(value);

/*
 * invoke filter kernel
 */
mscriptblur.setinput(inallocation);
mscriptblur.foreach(outallocation);
//将结果拷贝出来,拷贝到bitmapout对象中
outallocation.copyto(bitmapout);

3、回收renderscript对象

mrs.destory();
mrs = null; 

文章到此结束。

按照惯例:下面是我的完整的代码实现。

public class mainactivity extends activity {

  private seekbar blurseekbar;
  private imageview img_blur;
  private bitmap bitmap_original, bitmap_blur;

  private renderscripttask mlatesttask = null;

  private renderscript mrs;
  private allocation minallocation;
  private allocation moutallocation;
  private scriptintrinsicblur mscriptblur;

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);
    blurseekbar = (seekbar) findviewbyid(r.id.aty_main_seekbar);
    img_blur = (imageview) findviewbyid(r.id.aty_main_img_blur);
    bitmap_original = loadbitmap(r.drawable.meet_entry_guide_3);
    // 复制一份
    bitmap_blur = bitmap.createbitmap(bitmap_original.getwidth(),
        bitmap_original.getheight(), bitmap_original.getconfig());
    createblurescript();
    setseekbarlistening();
  }

  /**
   * 设置seekbar的监听
   */
  private void setseekbarlistening() {
    blurseekbar.setonseekbarchangelistener(new onseekbarchangelistener() {

      @override
      public void onstoptrackingtouch(seekbar seekbar) {
      }

      @override
      public void onstarttrackingtouch(seekbar seekbar) {

      }

      @override
      public void onprogresschanged(seekbar seekbar, int progress,
          boolean fromuser) {
        updateimage(progress);
      }
    });
  }

  /**
   * 创建script
   */
  private void createblurescript() {
    mrs = renderscript.create(this);
    minallocation = allocation.createfrombitmap(mrs, bitmap_original);
    moutallocation = allocation.createfrombitmap(mrs, bitmap_blur);

    /*
     * create intrinsics. renderscript has built-in features such as blur,
     * convolve filter etc. these intrinsics are handy for specific
     * operations without writing renderscript kernel. in the sample, it's
     * creating blur, convolve and matrix intrinsics.
     */
    mscriptblur = scriptintrinsicblur.create(mrs, element.u8_4(mrs));
  }

  private void performfilter(allocation inallocation,
      allocation outallocation, bitmap bitmapout, float value) {
    /*
     * set blur kernel size
     */
    mscriptblur.setradius(value);

    /*
     * invoke filter kernel
     */
    mscriptblur.setinput(inallocation);
    mscriptblur.foreach(outallocation);

    outallocation.copyto(bitmapout);
  }

  /*
   * in the asynctask, it invokes renderscript intrinsics to do a filtering.
   * after the filtering is done, an operation blocks at allication.copyto()
   * in asynctask thread. once all operation is finished at onpostexecute() in
   * ui thread, it can invalidate and update imageview ui.
   */
  private class renderscripttask extends asynctask<float, integer, integer> {
    boolean issued = false;

    protected integer doinbackground(float... values) {
      if (iscancelled() == false) {
        issued = true;
        performfilter(minallocation, moutallocation, bitmap_blur,
            values[0]);
      }
      return 0;
    }

    void updateview(integer result) {
      // request ui update
      img_blur.setimagebitmap(bitmap_blur);
      img_blur.invalidate();
    }

    protected void onpostexecute(integer result) {
      updateview(result);
    }

    protected void oncancelled(integer result) {
      if (issued) {
        updateview(result);
      }
    }
  }

  /*
   * invoke asynchtask and cancel previous task. when asynctasks are piled up
   * (typically in slow device with heavy kernel), only the latest (and
   * already started) task invokes renderscript operation.
   */
  private void updateimage(int progress) {
    float f = getblureparam(progress);

    if (mlatesttask != null)
      mlatesttask.cancel(false);
    mlatesttask = new renderscripttask();
    mlatesttask.execute(f);
  }

  /**
   * 模糊的值在1 ~ 25之间
   * 
   * @param progress
   *      seekbar的进度值(0 ~ 100)
   * @return 模糊值
   */
  private float getblureparam(int progress) {
    final float max = 25.0f;
    final float min = 1.f;
    return (float) ((max - min) * (progress / 100.0) + min);
  }

  /**
   * helper to load bitmap from resource
   */
  private bitmap loadbitmap(int resource) {
    final bitmapfactory.options options = new bitmapfactory.options();
    options.inpreferredconfig = bitmap.config.argb_8888;
    return bitmapfactory.decoderesource(getresources(), resource, options);
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。