I am developing a camera application for Android API 16 to 21 which main and only purpose is to take portrait photo. I am able to take picture with several devices (Nexus 4, Nexus 5, HTC...) and have them correctly oriented (meaning that my preview equals the taken picture both in size and orientation).
However I have tested my application on several other devices and some of them are giving me alot of trouble: Samsung Galaxy S3/S4/S5.
On these three devices, the preview is correctly displayed, however the pictures returned by the method onPictureTaken(final byte[] jpeg, Camera camera)
are always sideways.
This is the Bitmap created from byte[] jpeg
and displayed in the ImageView to my user just before saving it to the disk:
And here is the image once saved on the disk:
As you can see the image is completly stretched in the preview and wrongly rotated once saved on the disk.
Here is my CameraPreview class (I obfuscated other methods since they had nothing to do with camera parameters):
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
{
private SurfaceHolder surfaceHolder;
private Camera camera;
// Removed unnecessary code
public void surfaceCreated(SurfaceHolder holder)
{
camera.setPreviewDisplay(holder);
setCameraParameters();
camera.startPreview();
}
private void setCameraParameters()
{
Camera.Parameters parameters = camera.getParameters();
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
DisplayMetrics metrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(metrics);
int rotation = windowManager.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 rotate = (info.orientation - degrees + 360) % 360;
parameters.setRotation(rotate);
// Save Parameters
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
}
}
How come this exact piece of code works for other devices except Samsung's one ?
I tried to find answers on the following SO posts but nothing could help me so far: this one and this other one.
EDIT
Implementing Joey Chong's answer does not changes anything:
public void onPictureTaken(final byte[] data, Camera camera)
{
try
{
File pictureFile = new File(...);
Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
FileOutputStream fos = new FileOutputStream(pictureFile);
realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
int orientation = -1;
ExifInterface exif = new ExifInterface(pictureFile.toString());
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (exifOrientation)
{
case ExifInterface.ORIENTATION_ROTATE_270:
orientation = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
orientation = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
orientation = 90;
break;
case ExifInterface.ORIENTATION_NORMAL:
orientation = 0;
break;
default:
break;
}
fos.close();
}
Here are the EXIF results I get for a working device:
- Orientation: 0
And here the results for the S4:
- Orientation: 0