相机的角度问题

2019-12-09  本文已影响0人  董成鹏

相机的安装角度, 旋转角度和屏幕角度

通过CameraInfo.orientation得到的是该相机出来图像需要顺时针旋转多少度才可以到手机的正常方向,可以认为是相机的安装角度, 这是一个固定值. 这个角度意味着 相机出来的图像, 需要顺时针旋转这么一个角度, 才能和手机屏幕的自然方向一样.取值为0,90,180,270.

最常见的相机安装情况是:面对屏幕, 后置相机头朝右安装(如果是面向背壳的话是头朝左安装), 前置相机也是头朝右安装.

比如后置相机(可以把后置相机看成人眼), 我们正对着屏幕, 后置相机的安装方向如上所说, 此时sensor向右旋转了90度(就是顺时针旋转了90度, 就相当于我们人眼睛向右旋转了90度). 那么输出的图像相对于正常的情况下就是向左旋转了90度(相当于逆时针旋转了90度), 那么此时我们需要把得到的图像顺时针旋转90度才能得到正常的图像, 所以此时CaemraInfo.orientation是90度

同理,对于前置摄像头安装方向也是如上, 前置摄像头并不相当于我们的眼睛, 它相当于一个镜子. 前置相机向右旋转了90度, 那么输出图像也是向右旋转了90度(也就是顺时针旋转了90度). 所以我们应该在顺时针旋转270度, 才能把图像恢复成正常的, 所以此时相机CameraInfo.orientation是270度.

Camera.Parameters.setRotation 这个方法是设置拍摄照片的时候,摄像头的旋转角度.

这个会影响照片的EXIF头部信息. 对我们相机预览什么的好像没影响, 主要是为了给相册用的, 相册会用到我们通过这个方法设置的值, 然后通过这个值进行旋转,从而使一张图片能够正常的在相册中显示.

也就是说这个值只要是保存在EXIF头部信息中给别人看的, 让别人知道拍摄时候摄像头的方向, 从而能正确展示图片

要通过setRotation给图片设置正确的旋转方向, 必须配合使用CameraInfo.orientationOrientationEventListener.(OrientationEventListener传入的参数是0-359之间的任意一个值)

我们要配合OrientationEventListenerCamera.CameraInfo.orientation来给图片的EXIF信息设置正确的旋转值, 这个值的含义是拍摄这张图片的时候摄像头相对于自然方向的旋转角度.

Listener中得到的值是屏幕相对于自然方向的旋转值.,CameraInfo.orienetation是可以认为是相机sensor的安装方向, 所以对于后置相机来说,Listener的值加上CameraInfo.orientation的值, 就是相机在拍摄一张照片的时候总共相对于自然方向的旋转值, 我们通过setRatation设置这两个角度的和,就可以给图片的EXIF信息设置正确的相机旋转信息

对于前置摄像头来说, 这两个的差值就是拍摄照片时候摄像头的旋转角度.

 public void onOrientationChanged(int orientation) {
     if (orientation == ORIENTATION_UNKNOWN) return;
     android.hardware.Camera.CameraInfo info =
            new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);
     orientation = (orientation + 45) / 90 * 90;
     int rotation = 0;
     if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
         rotation = (info.orientation - orientation + 360) % 360;
     } else {  // back-facing camera
         rotation = (info.orientation + orientation) % 360;
     }
     mParameters.setRotation(rotation);
 }

还以上面的例子, 对于后置摄像头来说, info.orientation是90, 如果orientation也是90, 说明此时手机也向右旋转了90度, 那么此时后置摄像头的头部是朝下的, 所以按照上面的公式可以得出来setRotation是180.

对于前置相机来说此时前置摄像头的头部也是朝下的, info.orientation是270, orientation是90, 计算出来setRotation也是180.

setDisplayOrentation

这个是设置屏幕相对于相机的旋转角度, 这个是和预览有关的, 通过设置这个值可以让预览在屏幕上始终是正确的.

这个方法的参数的含义是告诉系统, 应该把图像顺时针旋转多少度就可以正常显示图像了.

我们通过WindowManager.getDefaultDisplay得到屏幕相对于自然方向的当前的旋转角度, 通过CameraInfo.orientation得到相机的安装角度.

务必注意对于Display的getRotation方法也是只能得到四个值, 但是它有一点很特别的是:顺时针旋转90度, 得到的是270, 逆时针旋转90度, 得到的90. 正常情况下顺时针旋转90度是90, 逆时针旋转90度是270, 它正好反过来了

对于后置相机来说, 这两个的差值就是相机现在相对于屏幕的旋转角度.

还是上面的例子,对于后置摄像头来说, 如果屏幕没有旋转,是0度, 相机的安装角度CameraInfo.orientation是90度, 我们可以setDisplayOrientation(90), 就是告诉系统要把图片顺时针旋转90度就可以正常显示图片.

如果此时我们把手机顺时针旋转了90度,此时后置摄像头的头部是朝上的, 那么通过Display.getRotation得到的值是270度, 按照下面的计算方法, (info.orientation - degrees + 360) % 360, 得到的值是180, 我们setDisplayRotation(180)正好可以告诉系统说旋转180度图像就正常了.

如果我们把手机逆时针旋转了90度, 此时后置摄像头的头部是朝下的, 那么通过Display.getRotation得到的值是90度, 按照下面的计算方法, (info.orientation - degrees + 360) % 360, 得到的值是0, 正好可以告诉系统不需要旋转就可以得到正确的图像.

前置摄像头也是这样的逻辑.

 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);
 }
上一篇 下一篇

猜你喜欢

热点阅读