From 3b8d1c1940a3dfdf7cffd9206f669f68d5fb3696 Mon Sep 17 00:00:00 2001 From: Kristoffer K Date: Sun, 17 Jul 2016 21:43:11 +0200 Subject: [PATCH] Output path fix + orientation fix (#20) * rotateImage function rewrite * fix recycle * output path fix * only pass bitmap to functions * Orientation fix --- .../bamlab/rnimageresizer/ImageResizer.java | 180 +++++++++++++----- 1 file changed, 130 insertions(+), 50 deletions(-) diff --git a/android/src/main/java/fr/bamlab/rnimageresizer/ImageResizer.java b/android/src/main/java/fr/bamlab/rnimageresizer/ImageResizer.java index d4ce9ca..4aff027 100644 --- a/android/src/main/java/fr/bamlab/rnimageresizer/ImageResizer.java +++ b/android/src/main/java/fr/bamlab/rnimageresizer/ImageResizer.java @@ -2,14 +2,21 @@ package fr.bamlab.rnimageresizer; import android.content.Context; import android.content.ContentResolver; +import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.BitmapRegionDecoder; import android.graphics.Matrix; +import android.media.ExifInterface; import android.net.Uri; +import android.provider.MediaStore; +import android.util.Pair; +import java.io.Closeable; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; +import java.io.FileNotFoundException; import java.io.InputStream; import java.io.IOException; import java.util.Date; @@ -19,60 +26,39 @@ import java.util.Date; */ class ImageResizer { - private static Bitmap resizeImage(String imagePath, int maxWidth, int maxHeight, Context context) { - try { - Bitmap image; - if (!imagePath.startsWith("content://") && !imagePath.startsWith("file://")) { - image = BitmapFactory.decodeFile(imagePath); - } else { - ContentResolver cr = context.getContentResolver(); - Uri url = Uri.parse(imagePath); - InputStream input = cr.openInputStream(url); - image = BitmapFactory.decodeStream(input); - input.close(); - } + private static Bitmap resizeImage(Bitmap image, int maxWidth, int maxHeight, Context context) { - if (image == null) { - return null; // Can't load the image from the given path. - } - - if (maxHeight > 0 && maxWidth > 0) { - float width = image.getWidth(); - float height = image.getHeight(); - - float ratio = Math.min((float)maxWidth / width, (float)maxHeight / height); - - int finalWidth = (int) (width * ratio); - int finalHeight = (int) (height * ratio); - image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true); - } - - return image; - }catch (IOException ex) { - // No memory available for resizing. + if (image == null) { + return null; // Can't load the image from the given path. } - return null; + if (maxHeight > 0 && maxWidth > 0) { + float width = image.getWidth(); + float height = image.getHeight(); + + float ratio = Math.min((float)maxWidth / width, (float)maxHeight / height); + + int finalWidth = (int) (width * ratio); + int finalHeight = (int) (height * ratio); + image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true); + } + + return image; } - public static Bitmap rotateImage(Bitmap b, float degrees) + public static Bitmap rotateImage(Bitmap source, float angle) { - if (degrees != 0 && b != null) { - Matrix m = new Matrix(); - m.setRotate(degrees, - (float) b.getWidth() / 2, (float) b.getHeight() / 2); - try { - Bitmap b2 = Bitmap.createBitmap( - b, 0, 0, b.getWidth(), b.getHeight(), m, true); - if (b != b2) { - b.recycle(); - b = b2; - } - } catch (OutOfMemoryError ex) { - // No memory available for rotating. Return the original bitmap. - } + Bitmap retVal; + + Matrix matrix = new Matrix(); + matrix.postRotate(angle); + retVal = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); + //for memory purposes + if (retVal != source){ + source.recycle(); } - return b; + + return retVal; } private static String saveImage(Bitmap bitmap, File saveDirectory, String fileName, @@ -102,18 +88,112 @@ class ImageResizer { return newFile.getAbsolutePath(); } + + /** + * Get {@link File} object for the given Android URI.
+ * Use content resolver to get real path if direct path doesn't return valid file. + */ + private static File getFileFromUri(Context context, Uri uri) { + + // first try by direct path + File file = new File(uri.getPath()); + if (file.exists()) { + return file; + } + + // try reading real path from content resolver (gallery images) + Cursor cursor = null; + try { + String[] proj = {MediaStore.Images.Media.DATA}; + cursor = context.getContentResolver().query(uri, proj, null, null, null); + int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + cursor.moveToFirst(); + String realPath = cursor.getString(column_index); + file = new File(realPath); + } catch (Exception ignored) { + } finally { + if (cursor != null) { + cursor.close(); + } + } + + return file; + } + + + /** + * Rotate the given image by reading the Exif value of the image (uri).
+ * If no rotation is required the image will not be rotated.
+ * New bitmap is created and the old one is recycled. + */ + public static int getOrientation(Bitmap bitmap, Context context, Uri uri) { + try { + File file = getFileFromUri(context, uri); + if (file.exists()) { + ExifInterface ei = new ExifInterface(file.getAbsolutePath()); + return getOrientation(bitmap, ei); + } + } catch (Exception ignored) { + } + return 0; + } + + /** + * Rotate the given image by given Exif value.
+ * If no rotation is required the image will not be rotated.
+ * New bitmap is created and the old one is recycled. + */ + public static int getOrientation(Bitmap bitmap, ExifInterface exif) { + int degrees; + int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); + switch (orientation) { + case ExifInterface.ORIENTATION_ROTATE_90: + degrees = 90; + break; + case ExifInterface.ORIENTATION_ROTATE_180: + degrees = 180; + break; + case ExifInterface.ORIENTATION_ROTATE_270: + degrees = 270; + break; + default: + degrees = 0; + break; + } + return degrees; + } + public static String createResizedImage(Context context, String imagePath, int newWidth, int newHeight, Bitmap.CompressFormat compressFormat, int quality, int rotation, String outputPath) throws IOException { - Bitmap resizedImage = ImageResizer.rotateImage(ImageResizer.resizeImage(imagePath, newWidth, newHeight, context), rotation); + + + Bitmap image; + if (!imagePath.startsWith("content://") && !imagePath.startsWith("file://")) { + image = BitmapFactory.decodeFile(imagePath); + } else { + ContentResolver cr = context.getContentResolver(); + Uri url = Uri.parse(imagePath); + InputStream input = cr.openInputStream(url); + image = BitmapFactory.decodeStream(input); + input.close(); + } + + int orientation = getOrientation(image, context, Uri.parse(imagePath)); + rotation = orientation+rotation; + + //rotate & resize + Bitmap newImage = ImageResizer.resizeImage(ImageResizer.rotateImage(image, rotation), newWidth, newHeight, context); + //recycle old image + image.recycle(); File path = context.getCacheDir(); - if (outputPath != null || !outputPath.isEmpty()) { + if (outputPath != null ) { path = new File(outputPath); } - return ImageResizer.saveImage(resizedImage, path, + return ImageResizer.saveImage(newImage, path, Long.toString(new Date().getTime()), compressFormat, quality); } }