Skip to content

Commit

Permalink
Fix: rotation on some android devices (#398)
Browse files Browse the repository at this point in the history
* Fix: rotation on some android devices

* Update ImageResizer.java

* Add: Handle mirror exif orientation

* Update: limitations readme

---------

Co-authored-by: Ibrahim Sluma <22921411+MrLibya@users.noreply.github.com>
  • Loading branch information
MrLibya and MrLibya authored May 30, 2024
1 parent a2580cf commit 7bb6b04
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 19 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ The promise resolves with an object containing: `path`, `uri`, `name`, `size` (b
# Limitations

- 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`.
- 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).

## 👉 About Bam

Expand Down
54 changes: 35 additions & 19 deletions android/src/main/java/com/reactnativeimageresizer/ImageResizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,11 @@ private static Bitmap resizeImage(Bitmap image, int newWidth, int newHeight,
/**
* Rotate the specified bitmap with the given angle, in degrees.
*/
public static Bitmap rotateImage(Bitmap source, float angle)
public static Bitmap rotateImage(Bitmap source, Matrix matrix, float angle)
{
Bitmap retVal;

Matrix matrix = new Matrix();
matrix.postRotate(angle);

try {
retVal = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
} catch (OutOfMemoryError e) {
Expand Down Expand Up @@ -316,39 +315,57 @@ public static boolean copyExif(Context context, Uri imageUri, String dstPath){
/**
* Get orientation by reading Image metadata
*/
public static int getOrientation(Context context, Uri uri) {
public static Matrix getOrientationMatrix(Context context, Uri uri) {
try {
// ExifInterface(InputStream) only exists since Android N (r24)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
InputStream input = context.getContentResolver().openInputStream(uri);
ExifInterface ei = new ExifInterface(input);
return getOrientation(ei);
return getOrientationMatrix(ei);
}
File file = getFileFromUri(context, uri);
if (file.exists()) {
ExifInterface ei = new ExifInterface(file.getAbsolutePath());
return getOrientation(ei);
return getOrientationMatrix(ei);
}
} catch (Exception ignored) { }

return 0;
return new Matrix();
}

/**
* Convert metadata to degrees
*/
public static int getOrientation(ExifInterface exif) {
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
public static Matrix getOrientationMatrix(ExifInterface exif) {
Matrix matrix = new Matrix();
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
switch (orientation) {
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
matrix.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
return 90;
matrix.setRotate(90);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
return 180;
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(270);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
return 270;
default:
return 0;
}
matrix.setRotate(270);
break;
}
return matrix;
}

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

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

if (rotatedImage != rotatedImage) {
if (rotatedImage != sourceImage) {
sourceImage.recycle();
}

Expand Down

0 comments on commit 7bb6b04

Please # to comment.