17

Camera.setDisplayOrientation的文档页面包含以下代码示例,说明使用它将“使相机图像以与显示器相同的方向显示”:

 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);
 }

但是,我在使用它时遇到了问题,有时图像会上下颠倒。经过反复试验,我发现正确的代码是(替换方法的最后 8 行):

    int result = (360 + info.orientation - degrees) % 360;
    camera.setDisplayOrientation(result);

(这意味着后置摄像头的计算对于前置摄像头也是正确的。)“补偿镜子”评论有点奇怪,因为镜像不能通过旋转来撤消,该操作只能交换 90° 和 270° 旋转,这不会'对我来说真的没有意义。

所以问题是:样本确实是错误的还是我遗漏了什么? 我在多个设备上尝试过,包括后置和前置摄像头以及所有支持的方向,所以我知道我的代码正在运行。一个可能值得一提的小细节:我所有的设备都返回 90° 为info.orientation.

编辑: 是我的相机相关代码,我已经在 Nexus One 和三星 Galaxy S Plus 上对其进行了测试。它用于我的头部跟踪 3D 应用程序,预览显示在左下角,并且应该始终具有正确的方向。

解决方案(有点):看起来代码是正确的,但我的测试手机(三星 Galaxy S Plus)返回的前置摄像头的 CameraInfo.orientation 值不正确。有许多关于在此模型上颠倒显示的预览的相关讨论(此处此处的示例)。一种解决方法是包含一个手动旋转图像的选项。

4

1 回答 1

13

您引用的片段,我在我的项目中使用和应用,在我的情况下没有问题。

对于我用于测试的所有设备(Galaxy Note、Galaxy S III、Galaxy Nexus、Galaxy Ace II、Nexus S),info.Orientation前置摄像头均返回 270,后置摄像头返回 90。

与提问者讨论了几次后,我发现我误解了问题,所以我将答案分为两部分。

对于相机预览中的错误方向,请参考此解决方案:

相机预览方向错误的解决方法:

首先请确保info.Orientation前置摄像头返回 270,后置摄像头返回 90。然后请尝试将您的相机预览活动(或处理预览的类似类)方向设置为横向。

因此,当您浏览代码时,您会发现:

degree = 90用于屏幕方向,info.Orientation = 270用于前置摄像头。然后你会得到result = (270 - 90 + 360) % 360, result = 180,这意味着它将为你的前置摄像头视图顺时针旋转 180 度,这将纠正前置摄像头倒置的问题。

相机照片结果方向错误的解决方法:

如果这info.Orientation适用于您,那么问题可能是:

  1. 对于某些三星(或其他)设备(如 Galaxy Note、Galaxy SIII),相机只会写入方向标签,而不是旋转真实像素。
  2. 如果您使用前置摄像头并使用上面的代码,它将以正确的方向显示预览,但如果您拍摄,则会显示“倒置”图片。

解决方案:

/**
 *
 * Get the orientation from EXIF
 * @param filepath
 * @return orientation
 */
public int getExifOrientation(String filepath) {
    int degree = 0;
    ExifInterface exif = null;
    try {
        exif = new ExifInterface(filepath);
    } catch (IOException ex) {
        Log.e("EXIF info", "cannot read exif", ex);
    }
    if (exif != null) {
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
        if (orientation != -1) {
            // We only recognize a subset of orientation tag values.
            switch(orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                degree = 90;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                degree = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                degree = 270;
                break;
            }
        }
    } else {
        degree = 1;
    }
    Log.i("EXIF info", "Orientation degrees: " + degree);
    return degree;
}

然后

if (isFromCamera) {

    if (fromFrontCam) {
        // try change here if the orientation still wrong, -90 means rotate counter-clockwise 90 degrees.
        matrix.preRotate(-90);
     } else {
        matrix.preRotate(90);
     }
} else {
    // read EXIF data
    getExifOrientation(path)
    // don't forget to handle the situation that some devices won't write exif data
    matrix.preRotate(degree);
}
于 2012-11-01T11:58:27.037 回答