最近研究了一下android摄像头开发相关的技术,也看了Google提供的Camera2Basic调用示例,以及网上一部分代码,但都是在TextureView等预览基础上实现,而我想要作的是在不预览的状况下,能获取到摄像头原始数据流,并由本身来决定是否绘制显示。通过一番折腾,初步实现了本身的目的——CamCap程序。java
其实主要就是在不预览的状况下获取到摄像头原始数据,目的嘛,一是为了灵活性,方便随时开启关闭预览,二是为了之后能够直接对数据进行处理,三是为了其余程序开发作一些准备。因而实现一下几个功能:android
查阅了一些资料,Android Java层因为从API21开始,已经废弃原Camera接口,因此这里采用Camera2接口。相比Camera接口来讲,第二代摄像头接口,调用复杂多了,可是灵活性也更高了,经过Google的Camera2Basic例子能够很清楚的了解到使用方式。这里把CamCap程序中的Camera2的调用顺序整理以下:c++
和其余程序同样,经过ImageReader来获取到CameraCaptureSession传递出来的数据,与Google例子不一样的是,我取消了把TextureView的传递,改成单独以ImageReader来获取图像流,并设置为YUV_420_888格式,以拿到原始数据。性能
打开摄像头ui
摄像头打开后,建立对话google
获取到YUV数据以后,就能够在UI界面上进行绘制了,经过简单了解,能够经过OpenGLES来绘制,也能够转为Bitmap直接在TextureView上绘制。这里为了简单,选择了后者。然然后来发现,android.graphics.Bitmap并不支持直接将YUV数据存入,只能转为RGB数据格式,才能存入Bitmap,进而在TextureView上绘制。YUV转换RGB,以前在C++上应用过不少次了,能够把现有代码修改一下放到java里运行,不过考虑到性能问题,决定仍是使用libyuv。libyuv是一款以c/c++为基础的,专作YUV与RGB格式转换的开源项目,性能很是高。3d
使用libyuv,须要经过NDK交叉编译,并经过JNI来调用。libyuv编译起来也很简单,首先下载libyuv源码,代码地址是:https://chromium.googlesource.com/libyuv/libyuv 。而后确保NDK已经安装(这个直接在AndroidStudio中就能安装好),以后把NDK目录添加到环境变量。最后,进入libyuv目录,调用ndk-build便可。libyuv项目里已经写好了Android.mk,因此,直接编译就好了(我是在Windows上)。code
注意!编译的时候遇到JPEG库没有指定的问题,若是不想依赖libjpeg,能够修改Android.mk,删除JPEG库相关编译项就能够解决。blog
在AndroidStudio上创建c++文件,封装libyuv接口,而后按照JNI规范暴露接口,同时在Java层封装类来调用native方法。接口
在绘制图像的时候,有个坑,那就是图像的旋转,这个是因为手机上的摄像头传感器的视野坐标,通常都是旋转了90度或270度的,因此,须要把摄像头采集到的画面,进行旋转,才能还原出正确的视野画面。传感器旋转方向经过如下值得到,
CameraManager.getCameraCharacteristics(camid).get(CameraCharacteristics.SENSOR_ORIENTATION)
根据这个值,构建Matrix将Bitmap进行旋转
Matrix构建代码以下:
与上面代码中相似,经过TextureView.lockCanvas(),获取到Canvas,调用drawBitmap()将图像写入,便可完成绘制。
开启预览时的4:3画面和16:9画面
关闭预览,同时能够继续拍照
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
haibindev.cnblogs.com,合做请联系QQ。(转载请注明做者和出处~)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++