Android camera角度问题

转载:相机角度

1. android相机简介

由于Android系统的开放策略,Android手机呈现碎片化的趋势,兼容性问题一直是Android App 开发者头疼的难题。本文以Android相机预览方向为例,探索在Android机型适配上的一些思路。

1.1 相机架构

先了解下Camera的框架,它是分层的结构。由上向下分别是

1)应用层2)Camera系统的Java类3)Camera的JNI代码4)Camera的本地框架5)Camera服务部分6)Camera HAL(Hardware Abstraction Layer)硬件抽象层

图一Camera architecture

其中Camera HAL主要的接口文件为CameraHardwareInterface.h ,需要各个系统根据自己的情况实现。由于设备底层硬件的千变万化,android框架不可能提供统一的硬件驱动以及接口实现,只能提供标准的接口,因此硬件提供商需要自己开发设备驱动,并去实现android框架提供的接口。

而实际上,由于机器的硬件配置不同,厂商的底层实现不同,Andriod版本的不同,在一部手机上调试正常的程序,不一定能在其他机型上正常运行。其中与摄像头相关的适配问题包括摄像头个数、preview size大小、预览方向、闪光灯、对焦方式、帧率等等。

本文以相机预览方向为例,探讨这个问题产生的原因,以及一些可行的解决方法。

2. 相机预览方向适配问题的产生

2.1相机的安装方向

相机图像数据都是来自于相机硬件的图像传感器(Image Sensor),这个Sensor被固定到手机之后是有一个默认的取景方向,且不会改变。比如MI3手机的屏幕“自然”方向和后置相机的图像传感器方向是如图二所示的。

图二MI3手机的屏幕“自然”方向和后置相机的图像传感器方向

在MI3手机上,对于一个横屏应用来说,屏幕“自然”方向和后置相机的图像传感器方向一致,因此看到的图像是正的,如图三所示。而对于一个竖屏应用来说,屏幕“自然”方向和后置相机的图像传感器方向是不一致,从图像传感器的角度看,它看到的图像是侧过来的,如图四所示,需要将相机预览图像顺时针旋转90度,才和屏幕“自然”方向一致。在Android系统中,提供camera.setDisplayOrientation(angle)方法,用来设置相机预览图像顺时针旋转的角度。

图三MI3手机横屏的相机应用

图四MI3手机竖屏的相机应用

2.2相机的安装方向如何获取?

Android官方提供orientation这个属性来读取,官方定义如图五所示:orientation表示相机图像的方向。它的值是相机图像顺时针旋转到设备自然方向一致时的角度。例如假设设备是竖屏的。后置相机传感器是横屏安装的。当你面向屏幕时,如果后置相机传感器顶边的和设备自然方向的右边是平行的,则后置相机的orientation是90。如果前置相机传感器顶边和设备自然方向的右边是平行的,则前置相机的orientation是270。

int android.hardware.Camera.CameraInfo.orientationpublic int orientation

Added in API level 9

The orientation of the camera image. The value is the angle that the camera image needs to be rotated clockwise so it shows correctly on the display in its natural orientation. It should be 0, 90, 180, or 270. 

For example, suppose a device has a naturally tall screen. The back-facing camera sensor is mounted in landscape. You are looking at the screen. If the top side of the camera sensor is aligned with the right edge of the screen in natural orientation, the value should be 90. If the top side of a front-facing camera sensor is aligned with the right of the screen, the value should be 270. 

图五camerainfo.orientation定义

以MI3为例,通过程序调用取到的后置相机的orientation是90,前置相机的orientation是270。我理解的orientation是相机采集的图像顺时针旋转到屏幕自然方向的角度。图六所示是MI3手机的后置相机和前置相机对准同一个小人,后置前置相机采集到的图像及前置相机预览的图像。需要特别说明的是,对于前置相机来说,相机预览的图像是相机采集到的图像的镜像, 关注图六中小人头发在前置采集到的图像和预览的图像中头发的不同。因此在MI3手机上做竖屏应用时,对于后置相机的预览方向,只需要旋转后置相机的orientation,即90度即可和屏幕方向保持一致;对于前置相机的预览方向,由于系统对前置相机采集到的图像做了镜像,因此需要旋转270-180,也是90度即可和屏幕方向保持一致。

图六MI3手机上orientation的例子。

2.3官方推荐的相机预览方向适配做法

通过orientation属性的含义可以知道,我们可以用它和应用的方向来做相机预览方向的适配,图七是官方网站推荐的代码。但并不是所有手机的orientation值都靠谱,比如VIVO V1手机第一次获取后置相机的CameraInfo的orientation值是90,而当执行了mCamera = Camera.open();之后再获取CameraInfo的orientation值就是0,而且以后获取的都是 0 ,除非重启手机。无论是这款手机上的哪个应用,只要执行了一次Camera.open()之后,其他所有程序中获取CameraInfo的orientation都是是0。因此按照此方法做适配不能解决所有手机上的问题。

图七 Android官方推荐的相机预览方向的适配做法

3. 相机预览方向适配

####3.1方案一:App端添加兼容性代码

思路是在App端对特殊的手机添加兼容性代码,如下所示。这样可以解决部分问题,但当版本发出后,又发现问题只能等版本升级修复;同时由于手机型号,系统版本的很多组合,而且客户端要维护一套很长的代码。很自然的想到把相机预览方向的角度做成后台配置,就有了方案二。

if (is VIVO V1 mobile) {
	camera.setDisplayOrientation(90);
} else if (is MotoXPro mobile) {
	camera.setDisplayOrientation(270);
} else {
	Android官方推荐的相机预览方向适配做法
}
3.2方案二:Server端动态配置

为了解决方案一的弊端,可以将相机预览方向顺时针旋转的角度抽取出来,作为一个变量从server端下发。这样可以做到机型无关,版本发布后,出现问题可以通过Server端上线新的配置来解决。但新机型上问题的发现,确认,解决,上线均需要一定的人力耗费,而且有滞后性。还有没有更好的解决方案呢?

if (get angle from server) {
	camera.setDisplayOrientation(angle);
} else {
	Android官方推荐的相机预览方向适配做法
}
3.3方案三:Server端动态配置与用户自助引导相结合

公司一直提倡开发人员有产品思维。从产品的角度说,用户在使用相机应用时,他是知道相机预览方向是正确的还是错误的,我们可以给用户一个旋转相机预览方向的按钮,当用户发现方向不对时,通过自助点击按钮解决问题。如下图所示

图八 发生问题时,引导用户自助旋转相机预览方向

这样即具有方案二的优点,同时又可以实时解决用户的问题,不需要用户等待我们后台下发正确的配置。进一步的,如果发现用户点击了旋转按钮,同时正确使用了相机功能,可以将本机型对应的angle上报给Server端。Server端可以自动或辅助人工以更新配置。对于QQ安全中心APP来说,在人脸验证过程需要打开前置相机,如果用户本次人脸验证点击了旋转预览方向按钮,同时又通过了人脸验证,我们可以认为用户正确使用了相机功能,Server端可以自动更新用户上报的angle,使和该用户同机型的其他用户都受益。

if (get angle from server) {
	camera.setDisplayOrientation(angle);
} else {
	Android官方推荐的相机预览方向适配做法
}
...
if (user click rotate icon) {
	angle = angle + 90;
	camera.setDisplayOrientation(angle);
}
...
report(angle);

4 结语

在做相机相关的App时,需要考虑的适配问题还有很多,远不止相机预览方向这一种。总的思路就是能实时解决的就不滞后,能动态配置的就不要写死在App端,有时可以换个角度,考虑技术和产品相结合的方案。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值