BitmapUtils.java 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /* ownCloud Android client application
  2. * Copyright (C) 2012-2014 ownCloud Inc.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. package com.owncloud.android.utils;
  18. import com.owncloud.android.lib.common.utils.Log_OC;
  19. import android.graphics.Bitmap;
  20. import android.graphics.BitmapFactory;
  21. import android.graphics.Matrix;
  22. import android.graphics.BitmapFactory.Options;
  23. import android.media.ExifInterface;
  24. import android.net.Uri;
  25. import android.webkit.MimeTypeMap;
  26. import java.io.File;
  27. /**
  28. * Utility class with methods for decoding Bitmaps.
  29. *
  30. * @author David A. Velasco
  31. */
  32. public class BitmapUtils {
  33. /**
  34. * Decodes a bitmap from a file containing it minimizing the memory use, known that the bitmap
  35. * will be drawn in a surface of reqWidth x reqHeight
  36. *
  37. * @param srcPath Absolute path to the file containing the image.
  38. * @param reqWidth Width of the surface where the Bitmap will be drawn on, in pixels.
  39. * @param reqHeight Height of the surface where the Bitmap will be drawn on, in pixels.
  40. * @return
  41. */
  42. public static Bitmap decodeSampledBitmapFromFile(String srcPath, int reqWidth, int reqHeight) {
  43. // set desired options that will affect the size of the bitmap
  44. final Options options = new Options();
  45. options.inScaled = true;
  46. options.inPurgeable = true;
  47. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
  48. options.inPreferQualityOverSpeed = false;
  49. }
  50. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
  51. options.inMutable = false;
  52. }
  53. // make a false load of the bitmap to get its dimensions
  54. options.inJustDecodeBounds = true;
  55. BitmapFactory.decodeFile(srcPath, options);
  56. // calculate factor to subsample the bitmap
  57. options.inSampleSize = calculateSampleFactor(options, reqWidth, reqHeight);
  58. // decode bitmap with inSampleSize set
  59. options.inJustDecodeBounds = false;
  60. return BitmapFactory.decodeFile(srcPath, options);
  61. }
  62. /**
  63. * Calculates a proper value for options.inSampleSize in order to decode a Bitmap minimizing
  64. * the memory overload and covering a target surface of reqWidth x reqHeight if the original
  65. * image is big enough.
  66. *
  67. * @param options Bitmap decoding options; options.outHeight and options.inHeight should
  68. * be set.
  69. * @param reqWidth Width of the surface where the Bitmap will be drawn on, in pixels.
  70. * @param reqHeight Height of the surface where the Bitmap will be drawn on, in pixels.
  71. * @return The largest inSampleSize value that is a power of 2 and keeps both
  72. * height and width larger than reqWidth and reqHeight.
  73. */
  74. private static int calculateSampleFactor(Options options, int reqWidth, int reqHeight) {
  75. final int height = options.outHeight;
  76. final int width = options.outWidth;
  77. int inSampleSize = 1;
  78. if (height > reqHeight || width > reqWidth) {
  79. final int halfHeight = height / 2;
  80. final int halfWidth = width / 2;
  81. while ((halfHeight / inSampleSize) > reqHeight
  82. && (halfWidth / inSampleSize) > reqWidth) {
  83. inSampleSize *= 2;
  84. }
  85. }
  86. return inSampleSize;
  87. }
  88. /**
  89. * Rotate bitmap according to EXIF orientation.
  90. * Cf. http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/
  91. * @param bitmap Bitmap to be rotated
  92. * @param storagePath Path to source file of bitmap. Needed for EXIF information.
  93. * @return correctly EXIF-rotated bitmap
  94. */
  95. public static Bitmap rotateImage(Bitmap bitmap, String storagePath){
  96. Bitmap resultBitmap = bitmap;
  97. try
  98. {
  99. ExifInterface exifInterface = new ExifInterface(storagePath);
  100. int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
  101. Matrix matrix = new Matrix();
  102. // 1: nothing to do
  103. // 2
  104. if (orientation == ExifInterface.ORIENTATION_FLIP_HORIZONTAL)
  105. {
  106. matrix.postScale(-1.0f, 1.0f);
  107. }
  108. // 3
  109. else if (orientation == ExifInterface.ORIENTATION_ROTATE_180)
  110. {
  111. matrix.postRotate(180);
  112. }
  113. // 4
  114. else if (orientation == ExifInterface.ORIENTATION_FLIP_VERTICAL)
  115. {
  116. matrix.postScale(1.0f, -1.0f);
  117. }
  118. // 5
  119. else if (orientation == ExifInterface.ORIENTATION_TRANSPOSE)
  120. {
  121. matrix.postRotate(-90);
  122. matrix.postScale(1.0f, -1.0f);
  123. }
  124. // 6
  125. else if (orientation == ExifInterface.ORIENTATION_ROTATE_90)
  126. {
  127. matrix.postRotate(90);
  128. }
  129. // 7
  130. else if (orientation == ExifInterface.ORIENTATION_TRANSVERSE)
  131. {
  132. matrix.postRotate(90);
  133. matrix.postScale(1.0f, -1.0f);
  134. }
  135. // 8
  136. else if (orientation == ExifInterface.ORIENTATION_ROTATE_270)
  137. {
  138. matrix.postRotate(270);
  139. }
  140. // Rotate the bitmap
  141. resultBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
  142. if (resultBitmap != bitmap) {
  143. bitmap.recycle();
  144. }
  145. }
  146. catch (Exception exception)
  147. {
  148. Log_OC.e("BitmapUtil", "Could not rotate the image: " + storagePath);
  149. }
  150. return resultBitmap;
  151. }
  152. /**
  153. * Checks if file passed is an image
  154. * @param file
  155. * @return true/false
  156. */
  157. public static boolean isImage(File file) {
  158. Uri selectedUri = Uri.fromFile(file);
  159. String fileExtension = MimeTypeMap.getFileExtensionFromUrl(selectedUri.toString());
  160. String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
  161. return (mimeType != null && mimeType.startsWith("image/"));
  162. }
  163. }