Bladeren bron

Minimized memory use in load of bitmaps for thumbnails generated from local files

David A. Velasco 10 jaren geleden
bovenliggende
commit
63de8e9229

+ 3 - 19
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -18,14 +18,10 @@
 package com.owncloud.android.ui.adapter;
 
 import java.io.File;
-import java.io.IOException;
 import java.lang.ref.WeakReference;
-//import java.net.URLEncoder;
 import java.util.Vector;
 
 import android.accounts.Account;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -51,23 +47,10 @@ import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
-import com.owncloud.android.lib.common.OwnCloudAccount;
-import com.owncloud.android.lib.common.OwnCloudClient;
-import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
-import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
 import com.owncloud.android.ui.activity.ComponentsGetter;
+import com.owncloud.android.utils.BitmapUtils;
 import com.owncloud.android.utils.DisplayUtils;
 
-/*
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.util.EntityUtils;
-*/
-
 
 /**
  * This Adapter populates a ListView with all files and folders in an ownCloud
@@ -171,7 +154,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                 ));
                 
                 if (file.isDown()){
-                    Bitmap bitmap = BitmapFactory.decodeFile(file.getStoragePath());
+                    Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
+                            file.getStoragePath(), px, px);
                     
                     if (bitmap != null) {
                         thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);

+ 99 - 0
src/com/owncloud/android/utils/BitmapUtils.java

@@ -0,0 +1,99 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2014 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,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.utils;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapFactory.Options;
+
+/**
+ * Utility class with methods for decoding Bitmaps.
+ * 
+ * @author David A. Velasco
+ */
+public class BitmapUtils {
+    
+    
+    /**
+     * Decodes a bitmap from a file containing it minimizing the memory use, known that the bitmap
+     * will be drawn in a surface of reqWidth x reqHeight
+     * 
+     * @param srcPath       Absolute path to the file containing the image.
+     * @param reqWidth      Width of the surface where the Bitmap will be drawn on, in pixels.
+     * @param reqHeight     Height of the surface where the Bitmap will be drawn on, in pixels.
+     * @return
+     */
+    public static Bitmap decodeSampledBitmapFromFile(String srcPath, int reqWidth, int reqHeight) {
+    
+        // set desired options that will affect the size of the bitmap
+        final Options options = new Options();
+        options.inScaled = true;
+        options.inPurgeable = true;
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
+            options.inPreferQualityOverSpeed = false;
+        }
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
+            options.inMutable = false;
+        }
+        
+        // make a false load of the bitmap to get its dimensions
+        options.inJustDecodeBounds = true;
+        
+        BitmapFactory.decodeFile(srcPath, options);   
+        
+        // calculate factor to subsample the bitmap
+        options.inSampleSize = calculateSampleFactor(options, reqWidth, reqHeight);
+
+        // decode bitmap with inSampleSize set
+        options.inJustDecodeBounds = false;
+        return BitmapFactory.decodeFile(srcPath, options);
+        
+    }    
+
+
+    /**
+     * 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. 
+     * 
+     * @param options       Bitmap decoding options; options.outHeight and options.inHeight should
+     *                      be set. 
+     * @param reqWidth      Width of the surface where the Bitmap will be drawn on, in pixels.
+     * @param reqHeight     Height of the surface where the Bitmap will be drawn on, in pixels.
+     * @return              The largest inSampleSize value that is a power of 2 and keeps both
+     *                      height and width larger than reqWidth and reqHeight.
+     */
+    private static int calculateSampleFactor(Options options, int reqWidth, int reqHeight) {
+        
+        final int height = options.outHeight;
+        final int width = options.outWidth;
+        int inSampleSize = 1;
+    
+        if (height > reqHeight || width > reqWidth) {
+            final int halfHeight = height / 2;
+            final int halfWidth = width / 2;
+    
+            while ((halfHeight / inSampleSize) > reqHeight
+                    && (halfWidth / inSampleSize) > reqWidth) {
+                inSampleSize *= 2;
+            }
+        }
+        
+        return inSampleSize;
+    }
+    
+}