From f027cdc7fd74175b76976f15da7d0f838f974321 Mon Sep 17 00:00:00 2001 From: Alex Knop Date: Thu, 6 Feb 2025 10:31:46 -0500 Subject: [PATCH] fix scaling Signed-off-by: Alex Knop --- .../ui/preview/PreviewImageFragment.kt | 12 +-- .../owncloud/android/utils/BitmapUtils.java | 87 +++++++++++++++++++ 2 files changed, 89 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt index 842a5d4b62c9..72d12ee54bb8 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt @@ -529,11 +529,7 @@ class PreviewImageFragment : FileFragment(), Injectable { } try { - bitmapResult = BitmapUtils.decodeSampledBitmapFromFile( - storagePath, - minWidth, - minHeight - ) + bitmapResult = BitmapUtils.retrieveBitmapFromFile(storagePath, minWidth, minHeight); if (isCancelled) { return LoadImage(bitmapResult, null, ocFile) @@ -543,12 +539,8 @@ class PreviewImageFragment : FileFragment(), Injectable { mErrorMessageId = R.string.preview_image_error_unknown_format Log_OC.e(TAG, "File could not be loaded as a bitmap: $storagePath") break - } else { - if (MimeType.JPEG.equals(ocFile.mimeType, ignoreCase = true)) { - // Rotate image, obeying exif tag. - bitmapResult = BitmapUtils.rotateImage(bitmapResult, storagePath) - } } + } catch (e: OutOfMemoryError) { mErrorMessageId = R.string.common_error_out_memory if (i < maxDownScale - 1) { diff --git a/app/src/main/java/com/owncloud/android/utils/BitmapUtils.java b/app/src/main/java/com/owncloud/android/utils/BitmapUtils.java index e899c52e9d50..60aa8d97a61f 100644 --- a/app/src/main/java/com/owncloud/android/utils/BitmapUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/BitmapUtils.java @@ -114,7 +114,44 @@ public static Bitmap decodeSampledBitmapFromFile(String srcPath, int reqWidth, i return BitmapFactory.decodeFile(srcPath, options); } + /** + * Decodes a bitmap from a file containing it minimizing the memory use. Scales image to screen size. + * + * @param storagePath Absolute path to the file containing the image. + */ + public static Bitmap retrieveBitmapFromFile(String storagePath, int minWidth, int minHeight){ + // Get the original dimensions of the bitmap + var bitmapResolution = getImageResolution(storagePath); + var originalWidth = bitmapResolution[0]; + var originalHeight = bitmapResolution[1]; + + // Detect Orientation and swap height/width if the image is to be rotated + var shouldRotate = detectRotateImage(storagePath); + if (shouldRotate) { + // Swap the width and height + var tempWidth = originalWidth; + originalWidth = originalHeight; + originalHeight = tempWidth; + } + + var bitmapResult = decodeSampledBitmapFromFile( + storagePath, originalWidth, originalHeight); + + // Calculate the scaling factors based on screen dimensions + var widthScaleFactor = (float) minWidth/ bitmapResult.getWidth(); + var heightScaleFactor = (float) minHeight / bitmapResult.getHeight(); + + // Use the smaller scaling factor to maintain aspect ratio + var scaleFactor = Math.min(widthScaleFactor, heightScaleFactor); + // Calculate the new scaled width and height + var scaledWidth = (int) (bitmapResult.getWidth() * scaleFactor); + var scaledHeight = (int) (bitmapResult.getHeight() * scaleFactor); + + bitmapResult = scaleBitmap(bitmapResult,scaledWidth,scaledHeight); + + return bitmapResult; + } /** * Calculates a proper value for options.inSampleSize in order to decode a Bitmap minimizing the memory overload and * covering a target surface of reqWidth x reqHeight if the original image is big enough. @@ -162,6 +199,18 @@ public static Bitmap scaleBitmap(Bitmap bitmap, float px, int width, int height, return Bitmap.createScaledBitmap(bitmap, w, h, true); } + /** + * scales a given bitmap depending on the given size parameters. + * + * @param bitmap the bitmap to be scaled + * @param width the width + * @param height the height + * @return the scaled bitmap + */ + public static Bitmap scaleBitmap(Bitmap bitmap, int width, int height) { + return Bitmap.createScaledBitmap(bitmap, width, height, true); + } + /** * Rotate bitmap according to EXIF orientation. Cf. http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/ * @@ -230,6 +279,44 @@ public static Bitmap rotateImage(Bitmap bitmap, String storagePath) { return resultBitmap; } + /** + * Detect if Image will be rotated according to EXIF orientation. Cf. http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/ + * + * @param storagePath Path to source file of bitmap. Needed for EXIF information. + * @return true if image's orientation determines it will be rotated to where height and width change + */ + public static boolean detectRotateImage(String storagePath) { + try { + ExifInterface exifInterface = new ExifInterface(storagePath); + int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1); + + if (orientation != ExifInterface.ORIENTATION_NORMAL) { + switch (orientation) { + // 5 + case ExifInterface.ORIENTATION_TRANSPOSE: { + return true; + } + // 6 + case ExifInterface.ORIENTATION_ROTATE_90: { + return true; + } + // 7 + case ExifInterface.ORIENTATION_TRANSVERSE: { + return true; + } + // 8 + case ExifInterface.ORIENTATION_ROTATE_270: { + return true; + } + } + } + } + catch (Exception exception) { + Log_OC.e("BitmapUtil", "Could not read orientation at: " + storagePath); + } + return false; + } + public static int[] getImageResolution(String srcPath) { Options options = new Options(); options.inJustDecodeBounds = true;