setDisplayOrientation示例代码是否正确?

mol*_*arm 17 android screen-orientation android-camera

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);
 }
Run Code Online (Sandbox Code Playgroud)

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

    int result = (360 + info.orientation - degrees) % 360;
    camera.setDisplayOrientation(result);
Run Code Online (Sandbox Code Playgroud)

(这意味着后置摄像头的计算对于前置摄像头也是正确的.)"补偿镜子"评论有点奇怪,因为镜像不能通过旋转来解除,该操作仅交换90°和270°旋转,这不是'对我来说真的很有意义.

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

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

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

dum*_*ers 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;
}
Run Code Online (Sandbox Code Playgroud)

然后

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);
}
Run Code Online (Sandbox Code Playgroud)