Skip to content

Commit 60e0e8e

Browse files
authored
fix(orientation): fix width/height info using EXIF data (#343)
1 parent af97725 commit 60e0e8e

1 file changed

Lines changed: 38 additions & 23 deletions

File tree

android/src/main/java/com/reactnativecommunity/cameraroll/CameraRollModule.java

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import android.media.MediaScannerConnection;
1818
import android.net.Uri;
1919
import android.os.AsyncTask;
20+
import android.os.Build;
2021
import android.os.Environment;
2122
import android.provider.MediaStore;
2223
import android.provider.MediaStore.Images;
@@ -25,7 +26,6 @@
2526

2627
import com.facebook.common.logging.FLog;
2728
import com.facebook.react.bridge.GuardedAsyncTask;
28-
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
2929
import com.facebook.react.bridge.NativeModule;
3030
import com.facebook.react.bridge.Promise;
3131
import com.facebook.react.bridge.ReactApplicationContext;
@@ -637,9 +637,7 @@ private static boolean putPlayableDuration(
637637
// Do nothing. We can't handle this, and this is usually a system problem
638638
}
639639
try {
640-
int timeInMillisec =
641-
Integer.parseInt(
642-
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
640+
int timeInMillisec = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
643641
playableDuration = timeInMillisec / 1000;
644642
} catch (NumberFormatException e) {
645643
success = false;
@@ -684,19 +682,16 @@ private static boolean putImageSize(
684682
}
685683

686684
boolean success = true;
685+
@Nullable AssetFileDescriptor photoDescriptor = null;
686+
687+
/* Read height and width data from the gallery cursor columns */
687688
int width = media.getInt(widthIndex);
688689
int height = media.getInt(heightIndex);
689690

691+
/* If the columns don't contain the size information, read the media file */
690692
if (width <= 0 || height <= 0) {
691-
@Nullable AssetFileDescriptor photoDescriptor = null;
692693
try {
693694
photoDescriptor = resolver.openAssetFileDescriptor(photoUri, "r");
694-
} catch (FileNotFoundException e) {
695-
success = false;
696-
FLog.e(ReactConstants.TAG, "Could not open asset file " + photoUri.toString(), e);
697-
}
698-
699-
if (photoDescriptor != null) {
700695
if (isVideo) {
701696
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
702697
try {
@@ -705,12 +700,8 @@ private static boolean putImageSize(
705700
// Do nothing. We can't handle this, and this is usually a system problem
706701
}
707702
try {
708-
width =
709-
Integer.parseInt(
710-
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
711-
height =
712-
Integer.parseInt(
713-
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
703+
width = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
704+
height = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
714705
} catch (NumberFormatException e) {
715706
success = false;
716707
FLog.e(
@@ -722,21 +713,45 @@ private static boolean putImageSize(
722713
retriever.release();
723714
} else {
724715
BitmapFactory.Options options = new BitmapFactory.Options();
725-
// Set inJustDecodeBounds to true so we don't actually load the Bitmap, but only get its
726-
// dimensions instead.
716+
// Set inJustDecodeBounds to true so we don't actually load the Bitmap in memory,
717+
// but only get its dimensions
727718
options.inJustDecodeBounds = true;
728719
BitmapFactory.decodeFileDescriptor(photoDescriptor.getFileDescriptor(), null, options);
729720
width = options.outWidth;
730721
height = options.outHeight;
731722
}
723+
} catch (FileNotFoundException e) {
724+
success = false;
725+
FLog.e(ReactConstants.TAG, "Could not open asset file " + photoUri.toString(), e);
726+
}
727+
}
732728

733-
try {
734-
photoDescriptor.close();
735-
} catch (IOException e) {
736-
// Do nothing. We can't handle this, and this is usually a system problem
729+
/* Read the EXIF photo data to update height and width in case a rotation is encoded */
730+
if (success && !isVideo && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
731+
try {
732+
if (photoDescriptor == null) photoDescriptor = resolver.openAssetFileDescriptor(photoUri, "r");
733+
ExifInterface exif = new ExifInterface(photoDescriptor.getFileDescriptor());
734+
int rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
735+
if (rotation == ExifInterface.ORIENTATION_ROTATE_90 || rotation == ExifInterface.ORIENTATION_ROTATE_270) {
736+
// swap values
737+
int temp = width;
738+
width = height;
739+
height = temp;
737740
}
741+
} catch (FileNotFoundException e) {
742+
success = false;
743+
FLog.e(ReactConstants.TAG, "Could not open asset file " + photoUri.toString(), e);
744+
} catch (IOException e) {
745+
FLog.e(ReactConstants.TAG, "Could not get exif data for file " + photoUri.toString(), e);
738746
}
747+
}
739748

749+
if (photoDescriptor != null) {
750+
try {
751+
photoDescriptor.close();
752+
} catch (IOException e) {
753+
// Do nothing. We can't handle this, and this is usually a system problem
754+
}
740755
}
741756

742757
image.putInt("width", width);

0 commit comments

Comments
 (0)