Skip to content

Commit 7d73985

Browse files
Merge pull request #14501 from alexknop/fixScaling
Fix Image Scaling/Rotating
2 parents 69f1353 + ffedbd3 commit 7d73985

File tree

2 files changed

+88
-11
lines changed

2 files changed

+88
-11
lines changed

app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ import com.owncloud.android.ui.fragment.FileFragment
6464
import com.owncloud.android.ui.preview.PreviewMediaFragment.Companion.newInstance
6565
import com.owncloud.android.utils.BitmapUtils
6666
import com.owncloud.android.utils.DisplayUtils
67-
import com.owncloud.android.utils.MimeType
6867
import com.owncloud.android.utils.MimeTypeUtil
6968
import com.owncloud.android.utils.theme.ViewThemeUtils
7069
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
@@ -529,11 +528,7 @@ class PreviewImageFragment : FileFragment(), Injectable {
529528
}
530529

531530
try {
532-
bitmapResult = BitmapUtils.decodeSampledBitmapFromFile(
533-
storagePath,
534-
minWidth,
535-
minHeight
536-
)
531+
bitmapResult = BitmapUtils.retrieveBitmapFromFile(storagePath, minWidth, minHeight)
537532

538533
if (isCancelled) {
539534
return LoadImage(bitmapResult, null, ocFile)
@@ -543,11 +538,6 @@ class PreviewImageFragment : FileFragment(), Injectable {
543538
mErrorMessageId = R.string.preview_image_error_unknown_format
544539
Log_OC.e(TAG, "File could not be loaded as a bitmap: $storagePath")
545540
break
546-
} else {
547-
if (MimeType.JPEG.equals(ocFile.mimeType, ignoreCase = true)) {
548-
// Rotate image, obeying exif tag.
549-
bitmapResult = BitmapUtils.rotateImage(bitmapResult, storagePath)
550-
}
551541
}
552542
} catch (e: OutOfMemoryError) {
553543
mErrorMessageId = R.string.common_error_out_memory

app/src/main/java/com/owncloud/android/utils/BitmapUtils.java

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,44 @@ public static Bitmap decodeSampledBitmapFromFile(String srcPath, int reqWidth, i
114114
return BitmapFactory.decodeFile(srcPath, options);
115115
}
116116

117+
/**
118+
* Decodes a bitmap from a file containing it minimizing the memory use. Scales image to screen size.
119+
*
120+
* @param storagePath Absolute path to the file containing the image.
121+
*/
122+
public static Bitmap retrieveBitmapFromFile(String storagePath, int minWidth, int minHeight){
123+
// Get the original dimensions of the bitmap
124+
var bitmapResolution = getImageResolution(storagePath);
125+
var originalWidth = bitmapResolution[0];
126+
var originalHeight = bitmapResolution[1];
127+
128+
// Detect Orientation and swap height/width if the image is to be rotated
129+
var shouldRotate = detectRotateImage(storagePath);
130+
if (shouldRotate) {
131+
// Swap the width and height
132+
var tempWidth = originalWidth;
133+
originalWidth = originalHeight;
134+
originalHeight = tempWidth;
135+
}
136+
137+
var bitmapResult = decodeSampledBitmapFromFile(
138+
storagePath, originalWidth, originalHeight);
139+
140+
// Calculate the scaling factors based on screen dimensions
141+
var widthScaleFactor = (float) minWidth/ bitmapResult.getWidth();
142+
var heightScaleFactor = (float) minHeight / bitmapResult.getHeight();
143+
144+
// Use the smaller scaling factor to maintain aspect ratio
145+
var scaleFactor = Math.min(widthScaleFactor, heightScaleFactor);
117146

147+
// Calculate the new scaled width and height
148+
var scaledWidth = (int) (bitmapResult.getWidth() * scaleFactor);
149+
var scaledHeight = (int) (bitmapResult.getHeight() * scaleFactor);
150+
151+
bitmapResult = scaleBitmap(bitmapResult,scaledWidth,scaledHeight);
152+
153+
return bitmapResult;
154+
}
118155
/**
119156
* Calculates a proper value for options.inSampleSize in order to decode a Bitmap minimizing the memory overload and
120157
* 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,
162199
return Bitmap.createScaledBitmap(bitmap, w, h, true);
163200
}
164201

202+
/**
203+
* scales a given bitmap depending on the given size parameters.
204+
*
205+
* @param bitmap the bitmap to be scaled
206+
* @param width the width
207+
* @param height the height
208+
* @return the scaled bitmap
209+
*/
210+
public static Bitmap scaleBitmap(Bitmap bitmap, int width, int height) {
211+
return Bitmap.createScaledBitmap(bitmap, width, height, true);
212+
}
213+
165214
/**
166215
* Rotate bitmap according to EXIF orientation. Cf. http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/
167216
*
@@ -230,6 +279,44 @@ public static Bitmap rotateImage(Bitmap bitmap, String storagePath) {
230279
return resultBitmap;
231280
}
232281

282+
/**
283+
* 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/
284+
*
285+
* @param storagePath Path to source file of bitmap. Needed for EXIF information.
286+
* @return true if image's orientation determines it will be rotated to where height and width change
287+
*/
288+
public static boolean detectRotateImage(String storagePath) {
289+
try {
290+
ExifInterface exifInterface = new ExifInterface(storagePath);
291+
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
292+
293+
if (orientation != ExifInterface.ORIENTATION_NORMAL) {
294+
switch (orientation) {
295+
// 5
296+
case ExifInterface.ORIENTATION_TRANSPOSE: {
297+
return true;
298+
}
299+
// 6
300+
case ExifInterface.ORIENTATION_ROTATE_90: {
301+
return true;
302+
}
303+
// 7
304+
case ExifInterface.ORIENTATION_TRANSVERSE: {
305+
return true;
306+
}
307+
// 8
308+
case ExifInterface.ORIENTATION_ROTATE_270: {
309+
return true;
310+
}
311+
}
312+
}
313+
}
314+
catch (Exception exception) {
315+
Log_OC.e("BitmapUtil", "Could not read orientation at: " + storagePath);
316+
}
317+
return false;
318+
}
319+
233320
public static int[] getImageResolution(String srcPath) {
234321
Options options = new Options();
235322
options.inJustDecodeBounds = true;

0 commit comments

Comments
 (0)