Skip to content

Commit 7bb6b04

Browse files
authored
Fix: rotation on some android devices (#398)
* Fix: rotation on some android devices * Update ImageResizer.java * Add: Handle mirror exif orientation * Update: limitations readme --------- Co-authored-by: Ibrahim Sluma <[email protected]>
1 parent a2580cf commit 7bb6b04

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ The promise resolves with an object containing: `path`, `uri`, `name`, `size` (b
9999
# Limitations
100100

101101
- If you are using `@react-native-camera-roll/camera-roll` **with new architecture enabled this library is not going to work**. If you try to display an image with the `uri` of the library using `<Image />` you are going to have the following error: `No suitable image URL loader found for ph://...`. This error come from the ReactNative `ImageLoader`, which is the one we are currently using. Help/PR for solving this are welcome. Until then, we recommend using `react-native-image-picker`.
102+
- Image EXIF orientation are correctly handled on Android only, But not yet on IOS [#402](https://github.com/bamlab/react-native-image-resizer/issues/402).
102103

103104
## 👉 About Bam
104105

android/src/main/java/com/reactnativeimageresizer/ImageResizer.java

+35-19
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,11 @@ private static Bitmap resizeImage(Bitmap image, int newWidth, int newHeight,
189189
/**
190190
* Rotate the specified bitmap with the given angle, in degrees.
191191
*/
192-
public static Bitmap rotateImage(Bitmap source, float angle)
192+
public static Bitmap rotateImage(Bitmap source, Matrix matrix, float angle)
193193
{
194194
Bitmap retVal;
195-
196-
Matrix matrix = new Matrix();
197195
matrix.postRotate(angle);
196+
198197
try {
199198
retVal = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
200199
} catch (OutOfMemoryError e) {
@@ -316,39 +315,57 @@ public static boolean copyExif(Context context, Uri imageUri, String dstPath){
316315
/**
317316
* Get orientation by reading Image metadata
318317
*/
319-
public static int getOrientation(Context context, Uri uri) {
318+
public static Matrix getOrientationMatrix(Context context, Uri uri) {
320319
try {
321320
// ExifInterface(InputStream) only exists since Android N (r24)
322321
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
323322
InputStream input = context.getContentResolver().openInputStream(uri);
324323
ExifInterface ei = new ExifInterface(input);
325-
return getOrientation(ei);
324+
return getOrientationMatrix(ei);
326325
}
327326
File file = getFileFromUri(context, uri);
328327
if (file.exists()) {
329328
ExifInterface ei = new ExifInterface(file.getAbsolutePath());
330-
return getOrientation(ei);
329+
return getOrientationMatrix(ei);
331330
}
332331
} catch (Exception ignored) { }
333332

334-
return 0;
333+
return new Matrix();
335334
}
336335

337336
/**
338337
* Convert metadata to degrees
339338
*/
340-
public static int getOrientation(ExifInterface exif) {
341-
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
339+
public static Matrix getOrientationMatrix(ExifInterface exif) {
340+
Matrix matrix = new Matrix();
341+
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
342342
switch (orientation) {
343+
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
344+
matrix.setScale(-1, 1);
345+
break;
346+
case ExifInterface.ORIENTATION_TRANSPOSE:
347+
matrix.setRotate(90);
348+
matrix.postScale(-1, 1);
349+
break;
343350
case ExifInterface.ORIENTATION_ROTATE_90:
344-
return 90;
351+
matrix.setRotate(90);
352+
break;
353+
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
354+
matrix.setRotate(180);
355+
matrix.postScale(-1, 1);
356+
break;
345357
case ExifInterface.ORIENTATION_ROTATE_180:
346-
return 180;
358+
matrix.setRotate(180);
359+
break;
360+
case ExifInterface.ORIENTATION_TRANSVERSE:
361+
matrix.setRotate(270);
362+
matrix.postScale(-1, 1);
363+
break;
347364
case ExifInterface.ORIENTATION_ROTATE_270:
348-
return 270;
349-
default:
350-
return 0;
351-
}
365+
matrix.setRotate(270);
366+
break;
367+
}
368+
return matrix;
352369
}
353370

354371
/**
@@ -549,15 +566,14 @@ public static Bitmap createResizedImage(Context context, Uri imageUri, int newWi
549566
// get wrong dimensions if we want the new dimensions to be after rotation.
550567
// NOTE: This will "fix" the image using it's exif info if it is rotated as well.
551568
Bitmap rotatedImage = sourceImage;
552-
int orientation = getOrientation(context, imageUri);
553-
rotation = orientation + rotation;
554-
rotatedImage = ImageResizer.rotateImage(sourceImage, rotation);
569+
Matrix matrix = getOrientationMatrix(context, imageUri);
570+
rotatedImage = ImageResizer.rotateImage(sourceImage, matrix, rotation);
555571

556572
if(rotatedImage == null){
557573
throw new IOException("Unable to rotate image. Most likely due to not enough memory.");
558574
}
559575

560-
if (rotatedImage != rotatedImage) {
576+
if (rotatedImage != sourceImage) {
561577
sourceImage.recycle();
562578
}
563579

0 commit comments

Comments
 (0)