Android 相机预览需要注意的几点

栏目: Android · 发布时间: 5年前

内容简介:手机 Camera 的图像数据都是来自于摄像头硬件的图像传感器(Image Sensor),这个 Sensor 被固定到手机之后是有一个默认的取景方向的,这个方向如下图所示,坐标原点位于手机横放时的左上角:拍照得到的图片方向是与图像 Sensor 的方向一致的。

Camera 预览方向

手机 Camera 的图像数据都是来自于摄像头硬件的图像传感器(Image Sensor),这个 Sensor 被固定到手机之后是有一个默认的取景方向的,这个方向如下图所示,坐标原点位于手机横放时的左上角:

Android 相机预览需要注意的几点

由于手机屏幕可以 360 度旋转,为了保证用户无论怎么旋转手机都能看到“正确”的预览画面。Android 系统底层根据当前手机屏幕的方向对图像 Sensor 采集到的数据进行了旋转处理后才传输给显示系统。因此,你在打开 Camera 应用后,无论怎么旋转手机都能看到“正确”的画面。

Android 系统提供一个 API 来手动设置 Camera 的预览方向,叫 setDisplayOrientation 。默认情况下这个值是0,与图像 Sensor 方向一致,所以对于横屏应用来说就不需要更改这个 Camera 预览方向。

但是,如果你的应用是竖屏应用,就必须通过这个 API 将 Camera 的预览方向旋转 90 度,让摄像头预览方向与手机屏幕方向保持一致,这样才会得到正确的预览画面。

当然要处理 Camera 方向不可能通过一个简单的 setDisplayOrientation(90) 就能搞定所有问题。比如前置摄像头的话预览要水平翻转才行,同样的情况下你可能要 setDisplayOrientation(270) 。具体的可参考官方文档的建议进行处理:

/**
 * If you want to make the camera image show in the same orientation as the display, you can use the following code.
 */
 public static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {
     android.hardware.Camera.CameraInfo info =
             new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);
     int rotation = activity.getWindowManager().getDefaultDisplay()
             .getRotation();
     int degrees = 0;
     switch (rotation) {
         case Surface.ROTATION_0: degrees = 0; break;
         case Surface.ROTATION_90: degrees = 90; break;
         case Surface.ROTATION_180: degrees = 180; break;
         case Surface.ROTATION_270: degrees = 270; break;
     }

     int result;
     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
         result = (info.orientation + degrees) % 360;
         result = (360 - result) % 360;  // compensate the mirror
     } else {  // back-facing
         result = (info.orientation - degrees + 360) % 360;
     }
     camera.setDisplayOrientation(result);
 }复制代码

真实的图像方向

当你点击拍照按钮,得到的图片方向不一定与画面中的预览方向一致,这是因为拍摄的照片是将图像 Sensor 采集到的数据直接存储到 SDCard上的,因此 Camera 的拍照方向与图像 Sensor 方向一致。

拍照得到的图片方向是与图像 Sensor 的方向一致的。 setDisplayOrientation 这个 API 修改的仅仅是 Camera 的预览方向而已,并不会影响到 PreviewCallback 回调、生成的 JPEG 图片和录像文件的方向,这些数据的方向依然会跟图像 Sensor 的方向一致。

在Camera类的的PreviewCallback回调中,这个接口回调的是相机的真实图像,而不是预览图像,并且它是YUV格式的,所以,如果需要将PreviewCallback回调的图像转换成一个bitmap需要使用YuvImage。

@Override
public void onPreviewFrame(final byte[] data, Camera camera) {
    camera.setPreviewCallback(null);

    if (mCamera == null)
        return;

    Camera.Parameters parameters = camera.getParameters();
    int width = parameters.getPreviewSize().width;
    int height = parameters.getPreviewSize().height;

    YuvImage yuv = new YuvImage(data, parameters.getPreviewFormat(), width, height, null);

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    yuv.compressToJpeg(new Rect(0, 0, width, height), 50, out);
    byte[] bytes = out.toByteArray();
    final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    this.mCamera.setPreviewCallback(this);
}
复制代码

上面说过,PreviewCallback回调图片方向跟 Sensor 的方向一致,所以需要进行旋转。

private byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight)
{
	byte [] yuv = new byte[imageWidth*imageHeight*3/2];
	// Rotate the Y luma
	int i = 0;
	for(int x = 0;x < imageWidth;x++)
	{
		for(int y = imageHeight-1;y >= 0;y--)
		{
			yuv[i] = data[y*imageWidth+x];
			i++;
		}
	}
	// Rotate the U and V color components
	i = imageWidth*imageHeight*3/2-1;
	for(int x = imageWidth-1;x > 0;x=x-2)
	{
		for(int y = 0;y < imageHeight/2;y++)
		{
			yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+x];
			i--;
			yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+(x-1)];
			i--;
		}
	}
	return yuv;
}
复制代码

参考文章:

https://www.jianshu.com/p/7d88ec1347b6

https://blog.csdn.net/illidantao/article/details/51366047

https://www.51dev.com/android/8993

https://stackoverflow.com/questions/14167976/rotate-an-yuv-byte-array-on-android

https://www.cnblogs.com/cq-jiang/p/7823462.html

https://blog.csdn.net/xx326664162/article/details/78534241


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

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

精益数据分析

精益数据分析

[加] 阿利斯泰尔·克罗尔、[加] 本杰明·尤科维奇 / 韩知白、王鹤达 / 人民邮电出版社 / 2014-12 / 79.00元

本书展示了如何验证自己的设想、找到真正的客户、打造能赚钱的产品,以及提升企业知名度。30多个案例分析,全球100多位知名企业家的真知灼见,为你呈现来之不易、经过实践检验的创业心得和宝贵经验,值得每位创业家和企业家一读。 深入理解精益创业、数据分析基础,和数据驱动的思维模式 如何将六个典型的商业模式应用到各种规模的新企业 找到你的第一关键指标 确定底线,找到出发点 在大......一起来看看 《精益数据分析》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具