Android学习笔记 - Camera(1)

 背景

在APP开发中会有很多业务使用到Camera,对于一些基础的功能,调用系统的拍摄功能就可以满足要求。但是需要自定义UI界面时,例如将摄像头捕获的视图展示在页面上的时候就需要使用到Camera这个类了。

本篇会介绍哪些知识点:

  1. 什么是SurfaceView?有什么作用?何为双缓冲机制?
  2. 相机涉及到方向的概念,如何旋转到正确的方向?
  3. Camera常用的API及相关属性。
  4. Camera的调用流程。
  5. 如何设置参数,适配预览区域大小?
  6. 如何切换前后摄像头。

SurfaceView

1、为什么需要SurfaceView

Android系统默认设定的刷新频率是60FPS(每隔16.6ms底层会发出VSYNC信号重绘界面)。但是当页面绘制过于复杂,就没有办法保证60FPS,则会出现卡顿现象。其中View,ViewGroup,Animator刷新UI界面的动作都是在主线程中执行的。如果页面逻辑过于复杂时,可能出现页面卡顿,甚至可能出现ANR问题。为了解决这个问题,便引入了SurfaceView(主要用于游戏、视频等视觉效果复杂、刷新率较高的场景)。

SurfaceView的改进是引入了双缓冲机制和多线程绘制。

2、双缓冲机制

如果不用画布,直接在窗口上绘制就是无缓冲绘图。

使用一个画布,先将所有的内容绘制到画布上面,后一次性绘制到窗口上就是单缓冲绘图,其中画布是一个缓冲区。

使用两个画布,先在一个画布上面绘制所有的图像,待绘制完以后在将该画布上面所有的内容拷贝到正式绘制的画布上,这就是双缓冲绘图。

双缓冲绘图比单缓冲绘图的优势在于 拷贝比直接绘制的效率要高

在SurfaceView中,一般会开启一个新的线程,然后在新线程中通过SurfaceHolder的lockCanvas方法获取得Canvas(缓冲画布)进行绘制,绘制完以后在通过SurfaceHolder的unlockCanvasAndPost方法释放canvas并提交修改,下次刷新显示新内容即可。

3、Surface、SurfaceView、SurfaceHolder三者的关系

它们三者是典型的MVC模型。

Surface:Model层,持有缓冲画布Canvas和绘图内容相关的各种信息。

SurfaceView:View层,与用户进行交互,将Surface的内容显示给用户。

SurfaceHolder:Controller层,通过SurfaceHolder控制Surface中的数据。


相机方向

1、自然方向

人自然站立的方向。

2、设备方向

设备方向是设备与自然方向的顺时针夹角,例如手机竖着拿正对屏幕的方向是手机的自然方向,即设备方向为0°,如果手机横着拿正对屏幕且顶部在右边,则设备方向为90°。以此类推。

获取方向可以通过

int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();

或者通过OrientationEventListener 监听旋转。

3、摄像头方向

手机Camera的图像数据都是来自于摄像头硬件的图像传感器(Image Sensor),摄像头的方向取决于图像传感器的安装方向。安装之后,有一个默认的取景方向,且不会被改变。但为什么手机旋转以后预览画面也会跟着旋转到自然方向呢?是因为Android系统底层根据当前手机屏幕的方向对图像Sensor采集到的数据进行了旋转处理,然后才送给显示系统。

手机后置摄像头一般都是横屏安装的。

CameraInfo.orientation 表示相机图像的方向。它的值是相机图像顺时针旋转到自然方向的角度。

4、预览方向

通过setDisplayOrientation设置预览方向,默认情况是0°,即预览方向与摄像头方向一致,对于横屏应用,不需要设置预览方向。而对于竖屏应用则设置预览方向旋转90,与手机屏幕方向保持一致,这样才能得到正确的预览方向。

5、拍摄方向

相机采集图像后需要进行顺时针旋转的角度,即相机属性的orientation的值。当点击拍照时,得到的照片方向不一定与预览方向一致,因为通过setDisplayOrientation仅仅修改了预览图像的方向,不会影响到实际拍摄图像的方向,需要修改拍摄图像方向可以通过camera.setRotation实现。


适配预览区域大小

一般手机会提供多个预览和拍照尺寸,通过接口getSupportedPreviewSizes和getSupportedPictureSizes可以获得这些尺寸列表。如果previewSize比例与预览(SurfaceView)比例不一致,则看到的预览图像会变形拉伸。如何适配不同预览区大小解决拉伸问题,一般有2种方案:

一是根据previewSize比例修改SurfaceView的比例,调整预览区比例(只调整宽或高)为预览尺寸比例,从而使图像不发生变形。

二是根据SurfaceView大小固定,然后根据其比例选择最佳的(比例最接近的)预览尺寸。


切换前后摄像头

通过camera.open(int cameraId)获取camera实例时便可以通过cameraId指定摄像头。

Camera.CameraInfo.CAMERA_FACING_FRONT = 1  前置摄像头

Camera.CameraInfo.CAMERA_FACING_BACK = 0 后者摄像头

注:切换摄像头便是重新获取新的camera实例,所以在切换时需要将前一个实例释放掉。


Camera常见的API及属性

camera是Android摄像头硬件的相机类,位于硬件包"android.hardware.Camera"下,它主要用于摄像头捕获照片、启动/停止预览图片、拍照、获取视频帧等。

camera常见的API

  • static Camera open():打开camera,返回一个camera实例。
  • static Camera open(int cameraId):根据cameraId打开camera,返回一个camera实例。
  • final void release():释放掉camera的资源。
  • static int getNumberOfCameras():获取当前设备支持camera硬件个数。
  • Camera.Parameters getParameters():获取camera的各项参数设置类。
  • void setParameters(Camera.Parameters params):通过param将camera的各项参数写入到camera中。
  • final void setDisplayOrientation(int degrees):设置预览的旋转度。
  • final void setPreviewDisplay(SurfaceHolder holder):设置camera预览的surfaceHolder。
  • final void startPreview():开始camera的预览。
  • final void stopPreview():结束camera的预览。
  • final void autoFocus(Camera.AutoFocusCallback cb):自动对焦。
  • final takePicture(Camera.ShutterCallback shutter,Camera.PictureCallback raw,Camera.PictureCallback jpeg):拍照。
  • final void lock():锁定Camera硬件,使其他应用无法访问
  • final void unlock():解锁Camera硬件,使其他应用可以访问。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值