The documentation page for Camera.setDisplayOrientation contains the following code sample stating that using it will "make the camera image show in the same orientation as the display":
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);
}
However, I had problems using it, sometimes the image would appear upside down. After some trial-and-error, I found that the correct code would be (replacing the last 8 lines of the method):
int result = (360 + info.orientation - degrees) % 360;
camera.setDisplayOrientation(result);
(Which means the calculation for back-facing cameras is correct for front cameras too.) The "compensate the mirror" comment is a bit weird since mirroring cannot be undone by rotating, that operation only swaps 90° and 270° rotations which doesn't really make sense to me.
So the question is: is the sample wrong indeed or am I missing something? I tried it on multiple devices, both back and front cameras and all supported orientations, so I know that my code IS working. One little detail that might be worth mentioning: all my devices returned 90° as info.orientation
.
EDIT: Here is my camera-related code, I have tested it on a Nexus One and a Samsung Galaxy S Plus. It is used in my head-tracking 3D app, the preview is shown in the lower left corner and should always have the correct orientation.
SOLUTION (sort of): It looks like the code is correct, but my testing phone (Samsung Galaxy S Plus) returns an incorrect value for the front camera's CameraInfo.orientation. There are many related discussions about the preview being shown upside down on this model (examples here and here). A way to fix is to include an option to manually rotate the image.
camera2 API for new applications. This class was deprecated in API level 21. We recommend using the new android.
The expression deviceOrientationDegrees * sign + 360 converts device rotation from counterclockwise to clockwise for back-facing cameras (for example, converting 270 degrees counterclockwise to 90 degrees clockwise).
The snippet you've quoted, which I used and applied in my project, is no problem in my circumstances.
For all the devices (Galaxy Note, Galaxy S III, Galaxy Nexus, Galaxy Ace II, Nexus S) I used for test, info.Orientation
all return 270 on front camera, and 90 on back camera.
After a few discuss with the question raiser, I found I misunderstood the questions, so I divide the answer in two parts.
For the wrong orientation in camera preview, please refer to this solution:
First please ensure info.Orientation
will return 270 on front camera, 90 on back camera.
Then please try set your camera preview activity (or similar class that handles the preview) orientation to landscape.
Thus, when you go through the code, you'll find:
degree = 90
for screen orientation, info.Orientation = 270
for the front camera. Then you'll get result = (270 - 90 + 360) % 360
, result = 180
, which means it will rotate clock wise 180 for your front camera view that will correct the front camera upside-down issue.
If this info.Orientation
applies to you, then the problem may be:
Solution:
/**
*
* 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;
}
Then
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With