2  *   ownCloud Android client application 
   4  *   @author David A. Velasco 
   5  *   Copyright (C) 2015 ownCloud Inc. 
   7  *   This program is free software: you can redistribute it and/or modify 
   8  *   it under the terms of the GNU General Public License version 2, 
   9  *   as published by the Free Software Foundation. 
  11  *   This program is distributed in the hope that it will be useful, 
  12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  14  *   GNU General Public License for more details. 
  16  *   You should have received a copy of the GNU General Public License 
  17  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  20 package com
.owncloud
.android
.utils
; 
  22 import com
.owncloud
.android
.lib
.common
.utils
.Log_OC
; 
  24 import android
.graphics
.Bitmap
; 
  25 import android
.graphics
.BitmapFactory
; 
  26 import android
.graphics
.Matrix
; 
  27 import android
.graphics
.BitmapFactory
.Options
; 
  28 import android
.media
.ExifInterface
; 
  29 import android
.net
.Uri
; 
  30 import android
.webkit
.MimeTypeMap
; 
  35  * Utility class with methods for decoding Bitmaps. 
  37 public class BitmapUtils 
{ 
  41      * Decodes a bitmap from a file containing it minimizing the memory use, known that the bitmap 
  42      * will be drawn in a surface of reqWidth x reqHeight 
  44      * @param srcPath       Absolute path to the file containing the image. 
  45      * @param reqWidth      Width of the surface where the Bitmap will be drawn on, in pixels. 
  46      * @param reqHeight     Height of the surface where the Bitmap will be drawn on, in pixels. 
  49     public static Bitmap 
decodeSampledBitmapFromFile(String srcPath
, int reqWidth
, int reqHeight
) { 
  51         // set desired options that will affect the size of the bitmap 
  52         final Options options 
= new Options(); 
  53         options
.inScaled 
= true
; 
  54         options
.inPurgeable 
= true
; 
  55         if (android
.os
.Build
.VERSION
.SDK_INT 
>= android
.os
.Build
.VERSION_CODES
.GINGERBREAD_MR1
) { 
  56             options
.inPreferQualityOverSpeed 
= false
; 
  58         if (android
.os
.Build
.VERSION
.SDK_INT 
>= android
.os
.Build
.VERSION_CODES
.HONEYCOMB
) { 
  59             options
.inMutable 
= false
; 
  62         // make a false load of the bitmap to get its dimensions 
  63         options
.inJustDecodeBounds 
= true
; 
  65         BitmapFactory
.decodeFile(srcPath
, options
);    
  67         // calculate factor to subsample the bitmap 
  68         options
.inSampleSize 
= calculateSampleFactor(options
, reqWidth
, reqHeight
); 
  70         // decode bitmap with inSampleSize set 
  71         options
.inJustDecodeBounds 
= false
; 
  72         return BitmapFactory
.decodeFile(srcPath
, options
); 
  78      * Calculates a proper value for options.inSampleSize in order to decode a Bitmap minimizing  
  79      * the memory overload and covering a target surface of reqWidth x reqHeight if the original 
  80      * image is big enough.  
  82      * @param options       Bitmap decoding options; options.outHeight and options.inHeight should 
  84      * @param reqWidth      Width of the surface where the Bitmap will be drawn on, in pixels. 
  85      * @param reqHeight     Height of the surface where the Bitmap will be drawn on, in pixels. 
  86      * @return              The largest inSampleSize value that is a power of 2 and keeps both 
  87      *                      height and width larger than reqWidth and reqHeight. 
  89     private static int calculateSampleFactor(Options options
, int reqWidth
, int reqHeight
) { 
  91         final int height 
= options
.outHeight
; 
  92         final int width 
= options
.outWidth
; 
  95         if (height 
> reqHeight 
|| width 
> reqWidth
) { 
  96             final int halfHeight 
= height 
/ 2; 
  97             final int halfWidth 
= width 
/ 2; 
  99             while ((halfHeight 
/ inSampleSize
) > reqHeight
 
 100                     && (halfWidth 
/ inSampleSize
) > reqWidth
) { 
 109      * Rotate bitmap according to EXIF orientation.  
 110      * Cf. http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/  
 111      * @param bitmap Bitmap to be rotated 
 112      * @param storagePath Path to source file of bitmap. Needed for EXIF information.  
 113      * @return correctly EXIF-rotated bitmap 
 115     public static Bitmap 
rotateImage(Bitmap bitmap
, String storagePath
){ 
 116         Bitmap resultBitmap 
= bitmap
; 
 120             ExifInterface exifInterface 
= new ExifInterface(storagePath
); 
 121             int orientation 
= exifInterface
.getAttributeInt(ExifInterface
.TAG_ORIENTATION
, 1); 
 123             Matrix matrix 
= new Matrix(); 
 128             if (orientation 
== ExifInterface
.ORIENTATION_FLIP_HORIZONTAL
) 
 130                 matrix
.postScale(-1.0f
, 1.0f
); 
 133             else if (orientation 
== ExifInterface
.ORIENTATION_ROTATE_180
) 
 135                 matrix
.postRotate(180); 
 138             else if (orientation 
== ExifInterface
.ORIENTATION_FLIP_VERTICAL
) 
 140                 matrix
.postScale(1.0f
, -1.0f
); 
 143             else if (orientation 
== ExifInterface
.ORIENTATION_TRANSPOSE
) 
 145                 matrix
.postRotate(-90); 
 146                 matrix
.postScale(1.0f
, -1.0f
); 
 149             else if (orientation 
== ExifInterface
.ORIENTATION_ROTATE_90
) 
 151                 matrix
.postRotate(90); 
 154             else if (orientation 
== ExifInterface
.ORIENTATION_TRANSVERSE
) 
 156                 matrix
.postRotate(90); 
 157                 matrix
.postScale(1.0f
, -1.0f
); 
 160             else if (orientation 
== ExifInterface
.ORIENTATION_ROTATE_270
) 
 162                 matrix
.postRotate(270); 
 166             resultBitmap 
= Bitmap
.createBitmap(bitmap
, 0, 0, bitmap
.getWidth(), bitmap
.getHeight(), matrix
, true
); 
 167             if (resultBitmap 
!= bitmap
) { 
 171         catch (Exception exception
) 
 173             Log_OC
.e("BitmapUtil", "Could not rotate the image: " + storagePath
); 
 179      * Checks if file passed is an image 
 183     public static boolean isImage(File file
) { 
 184         Uri selectedUri 
= Uri
.fromFile(file
); 
 185         String fileExtension 
= MimeTypeMap
.getFileExtensionFromUrl(selectedUri
.toString().toLowerCase()); 
 186         String mimeType 
= MimeTypeMap
.getSingleton().getMimeTypeFromExtension(fileExtension
); 
 188         return (mimeType 
!= null 
&& mimeType
.startsWith("image/"));