Fix Image Orientation Using Exif Data on Android and iOS
Exchangeable image file format (officially Exif) is a standard that specifies formats for images, sound, and ancillary tags used by digital cameras (including smartphones). It contains metadata like camera parameters, image dimensions, and image orientation.
Most camera sensors have a shape where its width is larger than the height. If a photo is taken in portrait, the raw image data is still stored in the sensor’s dimension. When viewing the photo, we need to know how to display it correctly. This is when the orientation flag in Exif is needed. The camera’s orientation sensor will provide the orientation info.
Here is a diagram of the flags of orientation and the rotation needed for display (image source).

If the image is mirrored, then the flags are like the right graph in the following image:

Most image viewers and browsers will display images based on the orientation. Some image editors like GIMP will prompt the user whether to rotate the image.

What you’ll build: A utility function for Android (Java) and iOS (Swift) that reads the Exif orientation tag from a captured photo and rotates the image so it displays correctly in a mobile document scanning app.
Key Takeaways
- The Exif orientation tag tells viewers how to rotate a photo taken in portrait mode so it displays upright — the raw pixel data is always stored in the sensor’s native landscape orientation.
- On Android,
ExifInterfacereads the orientation from the file path (not from aBitmap), and aMatrix.postRotate()call applies the correction. - On iOS,
UIImage.imageOrientationalready carries the flag; redrawing into a new graphics context produces a normalized, orientation-free image. - Failing to handle Exif orientation is the most common cause of sideways or upside-down photos in document scanning and OCR workflows.
Common Developer Questions
- How do I fix a photo that displays sideways or upside-down on Android?
- Why does my iOS UIImage appear rotated after saving to disk?
- What is the Exif orientation tag and which values map to which rotations?
Prerequisites
To follow along with the code samples you will need:
- Android: Android Studio with API level 24+ (for
ExifInterface). - iOS: Xcode with a Swift 5+ project.
- Dynamsoft Document Normalizer (optional): Used in the sample repos for document boundary detection and cropping. Get a 30-day free trial license to try it.
Correct Image Orientation with Exif on Android and iOS
When developing a mobile document scanning app, we may need to rotate the images taken based on the orientation.
Here is the code to do this.
For Android (Java):
private Bitmap rotatedImageBasedOnExif(Bitmap bitmap, String path) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
ExifInterface exif = null;
try {
exif = new ExifInterface(path);
} catch (IOException e) {
return bitmap;
}
int rotate = 0;
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;
}
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
try (FileOutputStream out = new FileOutputStream(path)) {
rotated.compress(Bitmap.CompressFormat.JPEG, 100, out);
} catch (IOException e) {
e.printStackTrace();
}
return rotated;
}
return bitmap;
}
Please note that bitmap does not contain the Exif. You need to directly pass the path for ExifInterface.
For iOS (Swift):
static func normalizedImage(_ image:UIImage) -> UIImage {
if image.imageOrientation == UIImage.Orientation.up {
return image
}
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
image.draw(in: CGRect(x:0,y:0,width:image.size.width,height:image.size.height))
let normalized = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext();
return normalized
}
Common Issues and Edge Cases
- Bitmap does not carry Exif data on Android. If you load a JPEG into a
Bitmapand then try to read orientation from the bitmap object, you will always get the default value. Always pass the original file path toExifInterface. - Mirrored orientation flags (values 2, 4, 5, 7) are rare but real. Front-facing cameras on some devices produce mirrored Exif flags. The code samples above handle the four most common rotation values; extend the
switchwithMatrix.preScale(-1, 1)if you need to support mirrored orientations. - HEIF / HEIC images on iOS may behave differently. Apple’s HEIF container embeds orientation differently from JPEG Exif. If your app supports HEIF capture, test orientation correction separately for that format.
Source Code
Check out the Android and iOS document scanner demos to have a try:
Dynamsoft Document Normalizer is used for document boundary detection and cropping.