PS:2018/0807

  不可以使用生产者模式 去不断的textureView.getBitmap, 否则RenderThread线程会 非常奇怪的抛出异常(疑似当前Frame被释放,再get的native层空指针)。应该在TextureView.SurfaceTextureListener的onSurfaceTextureUpdated(SurfaceTexture surface) 回调内去textureView.getBitmap

PS:2018/05/07

   最近又发现TextureView的getBitmap方法 更快,比RenderScript还快。具体就是讲Camera 的Preview set到TextureView上,然后调用TextureView的getBitmap方法。推荐用生产者模式去getBitmap,我试验的是整幅图也就10+ms

 

Context

    YUV格式转换为Bitmap比较耗时,使用RenderScript从50ms降到3、4ms(和像素值、手机相关,但比例差不多)

    RenderScript耗时的地方是内存Allocation的分配,RenderScript的初始化,所以要设置为属性 缓存起来,不要重复创建。只要预览的宽高不变是不用变Allocation的大小的。

 

RenderScript

    简单讲就是 Android系统为 解决高计算作业问题 采用了基于 C语言风格的RenderScript。具体:系统利用GPU、CPU多核来处理并发调度,使程序员只专注于算法。系统自己提供了几个常用的RenderScript,高斯模糊、直方图、yuv格式转换。

    具体怎么看官网,不累述了,直接上代码

    参考博客:  Camera使用RenderScript   

 

代码

    private void initRenderScript() {        renderScript = RenderScript.create(this);        yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(renderScript, Element.U8_4(renderScript));        script = new ScriptC_rotator(renderScript);    }
    public Bitmap YUV_toRGB(byte[] yuvByteArray, int width, int height) {        Allocation in = getYuvAllocationIn(yuvByteArray);        Allocation out = getAllocationOut(width, height);        in.copyFrom(yuvByteArray);        yuvToRgbIntrinsic.setInput(in);        yuvToRgbIntrinsic.forEach(out);        Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);        out.copyTo(bmp);        bmp = rotate(bmp);        return bmp;    }
    private Allocation getYuvAllocationIn(byte[] yuvByteArray) {        if (mInAllocation == null || yuvByteArray.length != preYuvInLength) {            preYuvInLength = yuvByteArray.length;            Type.Builder yuvType = new Type.Builder(renderScript, Element.U8(renderScript)).setX(yuvByteArray.length);            mInAllocation =  Allocation.createTyped(renderScript, yuvType.create(), Allocation.USAGE_SCRIPT);        }        return mInAllocation;    }
    private Allocation getAllocationOut(int W, int H) {        if (preW != W || preH != H) {            preW = W;            preH = H;            Type.Builder rgbaType = new Type.Builder(renderScript, Element.RGBA_8888(renderScript)).setX(W).setY(H);            outAllocation = Allocation.createTyped(renderScript, rgbaType.create(), Allocation.USAGE_SCRIPT);        }        return outAllocation;    }

 

    public Bitmap rotate(Bitmap bitmap) {        Bitmap.Config config = bitmap.getConfig();        int targetHeight = bitmap.getWidth();        int targetWidth = bitmap.getHeight();        script.set_inWidth(bitmap.getWidth());        script.set_inHeight(bitmap.getHeight());        Allocation sourceAllocation = getFromRotateAllocation(bitmap);        sourceAllocation.copyFrom(bitmap);        script.set_inImage(sourceAllocation);        bitmap.recycle();        Bitmap target = Bitmap.createBitmap(targetWidth, targetHeight, config);        final Allocation targetAllocation = getToRotateAllocation(target);        script.forEach_rotate_270_clockwise(targetAllocation, targetAllocation);        targetAllocation.copyTo(target);        return target;    }

 

    private Allocation getFromRotateAllocation(Bitmap bitmap) {        int targetHeight = bitmap.getWidth();        int targetWidth = bitmap.getHeight();        if (targetHeight != preRotateHeight || targetWidth != preRotateWidth) {            preRotateHeight = targetHeight;            preRotateWidth = targetWidth;            fromRotateAllocation = Allocation.createFromBitmap(renderScript, bitmap,                    Allocation.MipmapControl.MIPMAP_NONE,                    Allocation.USAGE_SCRIPT);        }        return fromRotateAllocation;    }    private Allocation getToRotateAllocation(Bitmap bitmap) {        int targetHeight = bitmap.getWidth();        int targetWidth = bitmap.getHeight();        if (targetHeight != preRotateHeight || targetWidth != preRotateWidth) {            toRotateAllocation =  Allocation.createFromBitmap(renderScript, bitmap,                    Allocation.MipmapControl.MIPMAP_NONE,                    Allocation.USAGE_SCRIPT);        }        return toRotateAllocation;    }

Preview拿的是物理设备方向,所以用时需要旋转,旋转的RenderScript是自己写的。

main/rs/your.package.name(包名)/rotate.rs

#pragma version(1)#pragma rs java_package_name(your.package.name)rs_allocation inImage;int inWidth;int inHeight;uchar4 __attribute__ ((kernel)) rotate_90_clockwise (uchar4 in, uint32_t x, uint32_t y) {    uint32_t inX  = inWidth - 1 - y;    uint32_t inY = x;    const uchar4 *out = rsGetElementAt(inImage, inX, inY);    return *out;}uchar4 __attribute__ ((kernel)) rotate_270_clockwise (uchar4 in, uint32_t x, uint32_t y) {    uint32_t inX = y;    uint32_t inY = inHeight - 1 - x;    const uchar4 *out = rsGetElementAt(inImage, inX, inY);    return *out;}

#pragma rs java_package_name(your.package.name)  这一行里的your.package.name需要替换你放置rotate.rs的地方

build后系统自动生成ScriptC_rotator 类,上文的script就是ScriptC_rotator的对象

 

 

 

 

 

更多相关文章

  1. 获取设备上所有系统app信息
  2. Android(安卓)学生信息管理系统
  3. unix like系统的android反编译工具
  4. springmvc+mybatis 构建cms内容发布系统 ios android
  5. android编译系统makefile(Android.mk)写法 (zz)
  6. Android(安卓)Interfaces and Architecture 安卓接口和架构
  7. ubuntu环境下载android系统源码代码
  8. android 如何隐藏4.0以上系统下面的3按个虚拟按键?
  9. Android之系统架构

随机推荐

  1. android 根据TextView宽度 自动缩小字体
  2. 【Android】监听电话状态
  3. 《Android.Programming.Pushing.the.Limi
  4. Android使用GPS定位
  5. Design TIps for Android(安卓)Applicati
  6. Win8风格的按钮、ToggleButton、SeekBar
  7. android acitonbar(toolbar)自定义溢出菜
  8. Android的Layout及其Param
  9. android 系统自带的图标集合
  10. android 权限