【问题标题】:Is the setDisplayOrientation sample code correct?setDisplayOrientation 示例代码是否正确?
【发布时间】:2012-10-17 16:07:45
【问题描述】:

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

 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

编辑: Here 是我的相机相关代码,我已经在 Nexus One 和三星 Galaxy S Plus 上对其进行了测试。在my head-tracking 3D app 中使用,预览显示在左下角,并且应该始终具有正确的方向。

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

【问题讨论】:

  • 不幸的是,Android 文档中有很多错误,但它们正在变得更好。我测试了您的代码,并在我的设备上体验到了与您相同的体验。我建议你去这里:code.google.com/p/android/issues/…

标签: android android-camera screen-orientation


【解决方案1】:

你引用的sn-p,我在我的项目中使用和应用,在我的情况下没有问题。

对于我用于测试的所有设备(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) % 360result = 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);
}

【讨论】:

  • 感谢您的回答。第一行非常有趣(您说示例对您有用),但其余的无关紧要,抱歉。我的问题 (Camera.setDisplayOrientation()) 中的方法“不影响传入 onPreviewFrame(byte[], Camera)、JPEG 图片 或录制视频的字节数组的顺序。”我不想拍照或加载它们,我只需要正确方向的预览。
  • @MártonMolnár 是的,文档的方法对我有用,我可以在相机预览中获得正确的方向。请问你用的是什么设备?由于您的问题是询问预览方向,所以我也会更新我的答案,抱歉我一开始没有完全理解您的问题:)
  • @MártonMolnár 我可以看看您如何将代码应用到您的项目中吗?即你在哪里调用这个方法?谢谢
  • @MártonMolnár 根据我的经验,您应该将您的活动(您的相机所在的位置)设置为横向。
  • @MártonMolnár thx,但我想我仍然可以提供帮助,因为你说过你通过代码设置视图,那么你可以尝试:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 设置相机活动(比如@landry 说,这就是我想告诉你的)景观。希望您在我之前的评论中理解我的计算。
猜你喜欢
  • 2019-06-12
  • 1970-01-01
  • 2013-10-13
  • 1970-01-01
  • 2020-02-25
  • 1970-01-01
  • 2019-11-15
  • 1970-01-01
  • 2017-08-02
相关资源
最近更新 更多