Why does an image captured using camera intent gets rotated on some devices on Android?
Most phone cameras are landscape, meaning if you take the photo in portrait, the resulting photos will be rotated 90 degrees. In this case, the camera software should populate the Exif data with the orientation that the photo should be viewed in.
Note that the below solution depends on the camera software/device manufacturer populating the Exif data, so it will work in most cases, but it is not a 100% reliable solution.
ExifInterface ei = new ExifInterface(photoPath);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
Bitmap rotatedBitmap = null;
switch(orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotatedBitmap = rotateImage(bitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotatedBitmap = rotateImage(bitmap, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotatedBitmap = rotateImage(bitmap, 270);
break;
case ExifInterface.ORIENTATION_NORMAL:
default:
rotatedBitmap = bitmap;
}
Here is the rotateImage
method:
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
}
When i take a photo,It gets rotated 90 degrees anti clockwise
If you're opening camera through intent, the best to solve the rotation problem is to have a temporary fragment with the rotation icon to it. Let user rotate the image itself and post it to your final imageview.
You can also create a custom camera using Android cameraX api, which is a wrapper class to Camera2 Api and with the help of setTargetRotation you can solve the camera rotation problem.
Captured Photo orientation is changing in android
I had the same problem mostly with the Samsung handsets.Apparently Samsung phones set the EXIF orientation tag, rather than rotating individual pixels.Reading the Bitmap using BitmapFactory does not support this tag.What i found the solution to this problem was using ExifInterface in onActivityResult method of the activity.Which checks for orientation associated with URI of the captured image from the camera.
int rotate = 0;
try {
getContentResolver().notifyChange(imageUri, null);
File imageFile = new File(imagePath);
ExifInterface exif = new ExifInterface(
imageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
Log.v(Common.TAG, "Exif orientation: " + orientation);
} catch (Exception e) {
e.printStackTrace();
}
/****** Image rotation ****/
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
Bitmap cropped = Bitmap.createBitmap(scaled, x, y, width, height, matrix, true);
Photo rotated from camera (SAMSUNG device)
UPD 29.08.2018 I found that this method doesn't work with Samsung device based on Android 8+. I don't have Samsung s8 (for example) and can't understand why this again does not work there. If someone can test and check why this not work - let's try to fix this together.
I found how to fix: well it's really stupid and very hard for me.
First step get activity result
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
String _path = Environment.getExternalStorageDirectory() + File.separator + "TakenFromCamera.jpg";
String p1 = Environment.getExternalStorageDirectory().toString();
String fName = "/TakenFromCamera.jpg";
final int rotation = getImageOrientation(_path);
File file = resaveBitmap(p1, fName, rotation);
Bitmap mBitmap = BitmapFactory.decodeFile(_path);
Main steps it's getImageOrientation
before changes in file.
getImageOrientation
(by path)- resave file (if need send to server, if you need only for preview we can skip this step)
- get correct bitmap from file
For preview it's enough to perform only steps 1 and 3, and using this function - just rotate bitmap.
private Bitmap checkRotationFromCamera(Bitmap bitmap, String pathToFile, int rotate) {
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return rotatedBitmap;
}
getImageOrientation
public static int getImageOrientation(String imagePath) {
int rotate = 0;
try {
ExifInterface exif = new ExifInterface(imagePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return rotate;
}
and resaveBitmap if need
private File resaveBitmap(String path, String filename, int rotation) { //help for fix landscape photos
String extStorageDirectory = path;
OutputStream outStream = null;
File file = new File(filename);
if (file.exists()) {
file.delete();
file = new File(extStorageDirectory, filename);
}
try {
// make a new bitmap from your file
Bitmap bitmap = BitmapFactory.decodeFile(path + filename);
bitmap = checkRotationFromCamera(bitmap, path + filename, rotation);
bitmap = Bitmap.createScaledBitmap(bitmap, (int) ((float) bitmap.getWidth() * 0.3f), (int) ((float) bitmap.getHeight() * 0.3f), false);
bitmap = Utils.getCircleImage(bitmap);
outStream = new FileOutputStream(path + filename);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
Camera orientation issue in Android
There are quite a few similar topics and issues around here. Since you're not writing your own camera, I think it boils down to this:
some devices rotate the image before saving it, while others simply add the orientation tag in the photo's exif data.
I'd recommend checking the photo's exif data and looking particularly for
ExifInterface exif = new ExifInterface(SourceFileName); //Since API Level 5
String exifOrientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
Since the photo is displaying correctly in your app, i'm not sure where the problem is, but this should definitely set you on the right path!
Image Gets rotated captured from camera
You can't rotate your canvas after drawBitmap. You have to first rotate it and then use drawBitmap i.e
float rotation=0;
try {
ExifInterface exifInterface=new ExifInterface(selectedPhoto);
int orientation=exifInterface.getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90: {
rotation=-90f;
break;
}
case ExifInterface.ORIENTATION_ROTATE_180: {
rotation=-180f;
break;
}
case ExifInterface.ORIENTATION_ROTATE_270: {
rotation=90f;
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
canvas.save();
canvas.rotate(rotation);
//canvas is rotated now use drawBitmap
canvas.drawBitmap(image, 0, 0, null);
canvas.restore();
Related Topics
How to Change the Status Bar Color in Android
Passing Data Between a Fragment and Its Container Activity
How to Implement Endless List With Recyclerview
This App Won't Run Unless You Update Google Play Services (Via Bazaar)
Getting Exception "Illegalstateexception: Can Not Perform This Action After Onsaveinstancestate"
Android - Listen For Incoming Sms Messages
Difference Between Activity Context and Application Context
Imageview in Circular Through Xml
Retrieve a Fragment from a Viewpager
How Do We Use Runonuithread in Android
What Is the Main Purpose of Settag() Gettag() Methods of View
Repeat a Task With a Time Delay
Basic Communication Between Two Fragments
Same Navigation Drawer in Different Activities
How to Implement My Very Own Uri Scheme on Android
Android: How to Get the Current Foreground Activity (From a Service)