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°旋转这对我来说没有意义。
所以问题是:样本确实是错误的还是我错过了什么? 我在多个设备上尝试过它,包括后置和前置摄像头以及所有支持的方向,所以我知道我的代码工作正常。可能值得一提的一个小细节:我的所有设备都以info.orientation
的形式返回90°。
编辑: Here是我的相机相关代码,我在Nexus One和三星Galaxy S Plus上进行了测试。它在my head-tracking 3D app中使用,预览显示在左下角,并且应始终具有正确的方向。
解决方案(有点):看起来代码是正确的,但我的测试手机(三星Galaxy S Plus)为前置摄像头的CameraInfo.orientation返回了不正确的值。关于此预览在此模型上颠倒显示的许多相关讨论(示例here和here)。一种解决方法是包含一个手动旋转图像的选项。
答案 0 :(得分: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
适用于您,则问题可能是:
解决方案:
/**
*
* 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);
}