Trigger media scan after file upload
[pub/Android/ownCloud.git] / src / com / owncloud / android / utils / BitmapUtils.java
index 687b5a4..4cc9fff 100644 (file)
@@ -1,5 +1,8 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012-2014 ownCloud Inc.
+/**
+ *   ownCloud Android client application
+ *
+ *   @author David A. Velasco
+ *   Copyright (C) 2015 ownCloud Inc.
  *
  *   This program is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
  */
 package com.owncloud.android.utils;
 
+import com.owncloud.android.lib.common.utils.Log_OC;
+
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
 import android.graphics.BitmapFactory.Options;
+import android.media.ExifInterface;
+import android.net.Uri;
+import android.webkit.MimeTypeMap;
+
+import java.io.File;
 
 /**
  * Utility class with methods for decoding Bitmaps.
- * 
- * @author David A. Velasco
  */
 public class BitmapUtils {
     
@@ -86,7 +95,9 @@ public class BitmapUtils {
         if (height > reqHeight || width > reqWidth) {
             final int halfHeight = height / 2;
             final int halfWidth = width / 2;
-    
+
+            // calculates the largest inSampleSize value (for smallest sample) that is a power of 2 and keeps both
+            // height and width **larger** than the requested height and width.
             while ((halfHeight / inSampleSize) > reqHeight
                     && (halfWidth / inSampleSize) > reqWidth) {
                 inSampleSize *= 2;
@@ -96,4 +107,164 @@ public class BitmapUtils {
         return inSampleSize;
     }
     
+    /**
+     * Rotate bitmap according to EXIF orientation. 
+     * Cf. http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/ 
+     * @param bitmap Bitmap to be rotated
+     * @param storagePath Path to source file of bitmap. Needed for EXIF information. 
+     * @return correctly EXIF-rotated bitmap
+     */
+    public static Bitmap rotateImage(Bitmap bitmap, String storagePath){
+        Bitmap resultBitmap = bitmap;
+
+        try
+        {
+            ExifInterface exifInterface = new ExifInterface(storagePath);
+            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
+
+            Matrix matrix = new Matrix();
+
+            // 1: nothing to do
+            
+            // 2
+            if (orientation == ExifInterface.ORIENTATION_FLIP_HORIZONTAL)
+            {
+                matrix.postScale(-1.0f, 1.0f);
+            }
+            // 3
+            else if (orientation == ExifInterface.ORIENTATION_ROTATE_180)
+            {
+                matrix.postRotate(180);
+            }
+            // 4
+            else if (orientation == ExifInterface.ORIENTATION_FLIP_VERTICAL)
+            {
+                matrix.postScale(1.0f, -1.0f);
+            }
+            // 5
+            else if (orientation == ExifInterface.ORIENTATION_TRANSPOSE)
+            {
+                matrix.postRotate(-90);
+                matrix.postScale(1.0f, -1.0f);
+            }
+            // 6
+            else if (orientation == ExifInterface.ORIENTATION_ROTATE_90)
+            {
+                matrix.postRotate(90);
+            }
+            // 7
+            else if (orientation == ExifInterface.ORIENTATION_TRANSVERSE)
+            {
+                matrix.postRotate(90);
+                matrix.postScale(1.0f, -1.0f);
+            }
+            // 8
+            else if (orientation == ExifInterface.ORIENTATION_ROTATE_270)
+            {
+                matrix.postRotate(270);
+            } 
+            
+            // Rotate the bitmap
+            resultBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+            if (resultBitmap != bitmap) {
+                bitmap.recycle();
+            }
+        }
+        catch (Exception exception)
+        {
+            Log_OC.e("BitmapUtil", "Could not rotate the image: " + storagePath);
+        }
+        return resultBitmap;
+    }
+
+    /**
+     *  Convert HSL values to a RGB Color.
+     *
+     *  @param h Hue is specified as degrees in the range 0 - 360.
+     *  @param s Saturation is specified as a percentage in the range 1 - 100.
+     *  @param l Lumanance is specified as a percentage in the range 1 - 100.
+     *  @paran alpha  the alpha value between 0 - 1
+     *  adapted from https://svn.codehaus.org/griffon/builders/gfxbuilder/tags/GFXBUILDER_0.2/
+     *  gfxbuilder-core/src/main/com/camick/awt/HSLColor.java
+     */
+    public static int[] HSLtoRGB(float h, float s, float l, float alpha)
+    {
+        if (s <0.0f || s > 100.0f)
+        {
+            String message = "Color parameter outside of expected range - Saturation";
+            throw new IllegalArgumentException( message );
+        }
+
+        if (l <0.0f || l > 100.0f)
+        {
+            String message = "Color parameter outside of expected range - Luminance";
+            throw new IllegalArgumentException( message );
+        }
+
+        if (alpha <0.0f || alpha > 1.0f)
+        {
+            String message = "Color parameter outside of expected range - Alpha";
+            throw new IllegalArgumentException( message );
+        }
+
+        //  Formula needs all values between 0 - 1.
+
+        h = h % 360.0f;
+        h /= 360f;
+        s /= 100f;
+        l /= 100f;
+
+        float q = 0;
+
+        if (l < 0.5)
+            q = l * (1 + s);
+        else
+            q = (l + s) - (s * l);
+
+        float p = 2 * l - q;
+
+        int r = Math.round(Math.max(0, HueToRGB(p, q, h + (1.0f / 3.0f)) * 256));
+        int g = Math.round(Math.max(0, HueToRGB(p, q, h) * 256));
+        int b = Math.round(Math.max(0, HueToRGB(p, q, h - (1.0f / 3.0f)) * 256));
+
+        int[] array = {r, g, b};
+        return array;
+    }
+
+    private static float HueToRGB(float p, float q, float h){
+               if (h < 0) h += 1;
+
+               if (h > 1 ) h -= 1;
+
+               if (6 * h < 1)
+               {
+                       return p + ((q - p) * 6 * h);
+               }
+
+               if (2 * h < 1 )
+               {
+                       return  q;
+               }
+
+               if (3 * h < 2)
+               {
+                       return p + ( (q - p) * 6 * ((2.0f / 3.0f) - h) );
+               }
+
+               return p;
+       }
+
+    /**
+     * Checks if file passed is an image
+     * @param file
+     * @return true/false
+     */
+    public static boolean isImage(File file) {
+        Uri selectedUri = Uri.fromFile(file);
+        String fileExtension = MimeTypeMap.getFileExtensionFromUrl(selectedUri.toString().toLowerCase());
+        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
+
+        return (mimeType != null && mimeType.startsWith("image/"));
+    }
+    
 }