diff --git a/android/widgets/src/main/java/org/nativescript/widgets/BorderDrawable.java b/android/widgets/src/main/java/org/nativescript/widgets/BorderDrawable.java index 2f7c859..4ee7b12 100644 --- a/android/widgets/src/main/java/org/nativescript/widgets/BorderDrawable.java +++ b/android/widgets/src/main/java/org/nativescript/widgets/BorderDrawable.java @@ -261,7 +261,7 @@ public void refresh(int borderTopColor, Fetcher fetcher = Fetcher.getInstance(context); // TODO: Implement option to pass load-mode like in ImageView class. boolean loadAsync = backgroundImageUri.startsWith("http"); - fetcher.loadImage(backgroundImageUri, this, 0, 0, true, loadAsync, null); + fetcher.loadImage(backgroundImageUri, this, 0, 0, false, true, loadAsync, null); } } diff --git a/android/widgets/src/main/java/org/nativescript/widgets/Image/Fetcher.java b/android/widgets/src/main/java/org/nativescript/widgets/Image/Fetcher.java index 37c179a..73007d2 100644 --- a/android/widgets/src/main/java/org/nativescript/widgets/Image/Fetcher.java +++ b/android/widgets/src/main/java/org/nativescript/widgets/Image/Fetcher.java @@ -19,10 +19,13 @@ import android.annotation.TargetApi; import android.content.Context; import android.content.res.Resources; +import android.graphics.Matrix; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.media.ExifInterface; import android.os.Build; import android.util.Log; +import android.util.TypedValue; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -31,7 +34,6 @@ import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -156,7 +158,7 @@ protected void closeCacheInternal() { * @param data The data to load the bitmap, in this case, a regular http URL * @return The downloaded and resized bitmap */ - private Bitmap processHttp(String data, int decodeWidth, int decodeHeight) { + private Bitmap processHttp(String data, int decodeWidth, int decodeHeight, boolean keepAspectRatio) { final String key = Cache.hashKeyForDisk(data); FileDescriptor fileDescriptor = null; FileInputStream fileInputStream = null; @@ -179,8 +181,7 @@ private Bitmap processHttp(String data, int decodeWidth, int decodeHeight) { } DiskLruCache.Editor editor = mHttpDiskCache.edit(key); if (editor != null) { - if (downloadUrlToStream(data, - editor.newOutputStream(DISK_CACHE_INDEX))) { + if (downloadUrlToStream(data, editor.newOutputStream(DISK_CACHE_INDEX))) { editor.commit(); } else { editor.abort(); @@ -189,8 +190,7 @@ private Bitmap processHttp(String data, int decodeWidth, int decodeHeight) { snapshot = mHttpDiskCache.get(key); } if (snapshot != null) { - fileInputStream = - (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX); + fileInputStream = (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX); fileDescriptor = fileInputStream.getFD(); } } catch (IOException e) { @@ -210,8 +210,8 @@ private Bitmap processHttp(String data, int decodeWidth, int decodeHeight) { Bitmap bitmap = null; if (fileDescriptor != null) { - bitmap = decodeSampledBitmapFromDescriptor(fileDescriptor, decodeWidth, - decodeHeight, getCache()); + bitmap = decodeSampledBitmapFromDescriptor(fileDescriptor, decodeWidth, decodeHeight, keepAspectRatio, + getCache()); } if (fileInputStream != null) { try { @@ -222,14 +222,15 @@ private Bitmap processHttp(String data, int decodeWidth, int decodeHeight) { return bitmap; } - private Bitmap processHttpNoCache(String data, int decodeWidth, int decodeHeight) { + private Bitmap processHttpNoCache(String data, int decodeWidth, int decodeHeight, boolean keepAspectRatio) { ByteArrayOutputStreamInternal outputStream = null; Bitmap bitmap = null; try { outputStream = new ByteArrayOutputStreamInternal(); if (downloadUrlToStream(data, outputStream)) { - bitmap = decodeSampledBitmapFromByteArray(outputStream.getBuffer(), decodeWidth, decodeHeight, getCache()); + bitmap = decodeSampledBitmapFromByteArray(outputStream.getBuffer(), decodeWidth, decodeHeight, + keepAspectRatio, getCache()); } } catch (IllegalStateException e) { Log.e(TAG, "processHttpNoCache - " + e); @@ -246,28 +247,30 @@ private Bitmap processHttpNoCache(String data, int decodeWidth, int decodeHeight } @Override - protected Bitmap processBitmap(String uri, int decodeWidth, int decodeHeight, boolean useCache) { + protected Bitmap processBitmap(String uri, int decodeWidth, int decodeHeight, boolean keepAspectRatio, + boolean useCache) { if (debuggable > 0) { Log.v(TAG, "process: " + uri); } if (uri.startsWith(FILE_PREFIX)) { String filename = uri.substring(FILE_PREFIX.length()); - return decodeSampledBitmapFromFile(filename, decodeWidth, decodeHeight, getCache()); + return decodeSampledBitmapFromFile(filename, decodeWidth, decodeHeight, keepAspectRatio, getCache()); } else if (uri.startsWith(RESOURCE_PREFIX)) { String resPath = uri.substring(RESOURCE_PREFIX.length()); int resId = mResources.getIdentifier(resPath, "drawable", mPackageName); if (resId > 0) { - return decodeSampledBitmapFromResource(mResources, resId, decodeWidth, decodeHeight, getCache()); + return decodeSampledBitmapFromResource(mResources, resId, decodeWidth, decodeHeight, keepAspectRatio, + getCache()); } else { Log.v(TAG, "Missing Image with resourceID: " + uri); return null; } } else { if (useCache && mHttpDiskCache != null) { - return processHttp(uri, decodeWidth, decodeHeight); + return processHttp(uri, decodeWidth, decodeHeight, keepAspectRatio); } else { - return processHttpNoCache(uri, decodeWidth, decodeHeight); + return processHttpNoCache(uri, decodeWidth, decodeHeight, keepAspectRatio); } } } @@ -342,8 +345,8 @@ public byte[] getBuffer() { * @return A bitmap sampled down from the original with the same aspect ratio and dimensions * that are equal to or greater than the requested width and height */ - public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, - int reqWidth, int reqHeight, Cache cache) { + public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight, + boolean keepAspectRatio, Cache cache) { // BEGIN_INCLUDE (read_bitmap_dimensions) // First decode with inJustDecodeBounds=true to check dimensions @@ -351,14 +354,7 @@ public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); - // If requested width/height were not specified - decode in full size. - if (reqWidth > 0 && reqHeight > 0) { - // Calculate inSampleSize - options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); - } - else { - options.inSampleSize = 1; - } + options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight); // END_INCLUDE (read_bitmap_dimensions) @@ -369,7 +365,74 @@ public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; - return BitmapFactory.decodeResource(res, resId, options); + Bitmap bitmap = null; + InputStream is = null; + + try { + final TypedValue value = new TypedValue(); + is = res.openRawResource(resId, value); + + bitmap = BitmapFactory.decodeResourceStream(res, value, is, null, options); + } catch (Exception e) { + /* do nothing. + If the exception happened on open, bm will be null. + If it happened on close, bm is still valid. + */ + } + + if (bitmap == null && options != null && options.inBitmap != null) { + throw new IllegalArgumentException("Problem decoding into existing bitmap"); + } + + ExifInterface ei = getExifInterface(is); + + return scaleAndRotateBitmap(bitmap, ei, reqWidth, reqHeight, keepAspectRatio); + } + + @TargetApi(Build.VERSION_CODES.N) + private static ExifInterface getExifInterface(InputStream is) { + ExifInterface ei = null; + try { + if (Utils.hasN()) { + ei = new ExifInterface(is); + } + } catch (final Exception e) { + Log.e(TAG, "Error in reading bitmap - " + e); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + } + } + } + + return ei; + } + + @TargetApi(Build.VERSION_CODES.N) + private static ExifInterface getExifInterface(FileDescriptor fd) { + ExifInterface ei = null; + try { + if (Utils.hasN()) { + ei = new ExifInterface(fd); + } + } catch (final Exception e) { + Log.e(TAG, "Error in reading bitmap - " + e); + } + + return ei; + } + + private static ExifInterface getExifInterface(String fileName) { + ExifInterface ei = null; + try { + ei = new ExifInterface(fileName); + } catch (final Exception e) { + Log.e(TAG, "Error in reading bitmap - " + e); + } + + return ei; } /** @@ -382,22 +445,15 @@ public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, * @return A bitmap sampled down from the original with the same aspect ratio and dimensions * that are equal to or greater than the requested width and height */ - public static Bitmap decodeSampledBitmapFromFile(String filename, - int reqWidth, int reqHeight, Cache cache) { + public static Bitmap decodeSampledBitmapFromFile(String fileName, int reqWidth, int reqHeight, + boolean keepAspectRatio, Cache cache) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(filename, options); + BitmapFactory.decodeFile(fileName, options); - // If requested width/height were not specified - decode in full size. - if (reqWidth > 0 && reqHeight > 0) { - // Calculate inSampleSize - options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); - } - else { - options.inSampleSize = 1; - } + options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight); // If we're running on Honeycomb or newer, try to use inBitmap if (Utils.hasHoneycomb()) { @@ -406,7 +462,68 @@ public static Bitmap decodeSampledBitmapFromFile(String filename, // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; - return BitmapFactory.decodeFile(filename, options); + + final Bitmap bitmap = BitmapFactory.decodeFile(fileName, options); + ExifInterface ei = getExifInterface(fileName); + + return scaleAndRotateBitmap(bitmap, ei, reqWidth, reqHeight, keepAspectRatio); + } + + private static Bitmap scaleAndRotateBitmap(Bitmap bitmap, ExifInterface ei, int reqWidth, int reqHeight, + boolean keepAspectRatio) { + if (bitmap == null) { + return null; + } + + int sourceWidth = bitmap.getWidth(); + int sourceHeight = bitmap.getHeight(); + reqWidth = reqWidth > 0 ? reqWidth : sourceWidth; + reqHeight = reqHeight > 0 ? reqHeight : sourceHeight; + + // scale + if (reqWidth != sourceWidth || reqHeight != sourceHeight) { + if (keepAspectRatio) { + double widthCoef = (double) sourceWidth / (double) reqWidth; + double heightCoef = (double) sourceHeight / (double) reqHeight; + double aspectCoef = widthCoef > heightCoef ? widthCoef : heightCoef; + + reqWidth = (int) Math.floor(sourceWidth / aspectCoef); + reqHeight = (int) Math.floor(sourceHeight / aspectCoef); + } + + bitmap = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, true); + } + + // rotate + if (ei != null) { + final Matrix matrix = new Matrix(); + final int rotationAngle = calculateRotationAngle(ei); + if (rotationAngle != 0) { + matrix.postRotate(rotationAngle); + bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); + } + } + + return bitmap; + } + + private static int calculateRotationAngle(ExifInterface ei) { + int rotationAngle = 0; + final int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); + + switch (orientation) { + case ExifInterface.ORIENTATION_ROTATE_90: + rotationAngle = 90; + break; + case ExifInterface.ORIENTATION_ROTATE_180: + rotationAngle = 180; + break; + case ExifInterface.ORIENTATION_ROTATE_270: + rotationAngle = 270; + break; + } + + return rotationAngle; } /** @@ -419,22 +536,15 @@ public static Bitmap decodeSampledBitmapFromFile(String filename, * @return A bitmap sampled down from the original with the same aspect ratio and dimensions * that are equal to or greater than the requested width and height */ - public static Bitmap decodeSampledBitmapFromDescriptor( - FileDescriptor fileDescriptor, int reqWidth, int reqHeight, Cache cache) { + public static Bitmap decodeSampledBitmapFromDescriptor(FileDescriptor fileDescriptor, int reqWidth, int reqHeight, + boolean keepAspectRatio, Cache cache) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options); - // If requested width/height were not specified - decode in full size. - if (reqWidth > 0 && reqHeight > 0) { - // Calculate inSampleSize - options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); - } - else { - options.inSampleSize = 1; - } + options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; @@ -448,32 +558,27 @@ public static Bitmap decodeSampledBitmapFromDescriptor( try { // This can throw an error on a corrupted image when using an inBitmap results = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options); - } - catch (Exception e) { + } catch (Exception e) { // clear the inBitmap and try again options.inBitmap = null; results = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options); // If image is broken, rather than an issue with the inBitmap, we will get a NULL out in this case... } - return results; + + ExifInterface ei = getExifInterface(fileDescriptor); + + return scaleAndRotateBitmap(results, ei, reqWidth, reqHeight, keepAspectRatio); } - public static Bitmap decodeSampledBitmapFromByteArray( - byte[] buffer, int reqWidth, int reqHeight, Cache cache) { + public static Bitmap decodeSampledBitmapFromByteArray(byte[] buffer, int reqWidth, int reqHeight, + boolean keepAspectRatio, Cache cache) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(buffer, 0, buffer.length, options); - // If requested width/height were not specified - decode in full size. - if (reqWidth > 0 && reqHeight > 0) { - // Calculate inSampleSize - options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); - } - else { - options.inSampleSize = 1; - } + options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; @@ -483,7 +588,12 @@ public static Bitmap decodeSampledBitmapFromByteArray( addInBitmapOptions(options, cache); } - return BitmapFactory.decodeByteArray(buffer, 0, buffer.length, options); + final Bitmap bitmap = BitmapFactory.decodeByteArray(buffer, 0, buffer.length, options); + + InputStream is = new ByteArrayInputStream(buffer); + ExifInterface ei = getExifInterface(is); + + return scaleAndRotateBitmap(bitmap, ei, reqWidth, reqHeight, keepAspectRatio); } /** @@ -492,20 +602,20 @@ public static Bitmap decodeSampledBitmapFromByteArray( * the closest inSampleSize that is a power of 2 and will result in the final decoded bitmap * having a width and height equal to or larger than the requested width and height. * - * @param options An options object with out* params already populated (run through a decode* - * method with inJustDecodeBounds==true + * @param imageWidth The original width of the resulting bitmap + * @param imageHeight The original height of the resulting bitmap * @param reqWidth The requested width of the resulting bitmap * @param reqHeight The requested height of the resulting bitmap * @return The value to be used for inSampleSize */ - public static int calculateInSampleSize(BitmapFactory.Options options, - int reqWidth, int reqHeight) { + public static int calculateInSampleSize(int imageWidth, int imageHeight, int reqWidth, int reqHeight) { // BEGIN_INCLUDE (calculate_sample_size) // Raw height and width of image - final int height = options.outHeight; - final int width = options.outWidth; + final int height = imageHeight; + final int width = imageWidth; + reqWidth = reqWidth > 0 ? reqWidth : width; + reqHeight = reqHeight > 0 ? reqHeight : height; int inSampleSize = 1; - if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; @@ -513,8 +623,7 @@ public static int calculateInSampleSize(BitmapFactory.Options options, // Calculate the largest inSampleSize value 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) { + while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } @@ -524,14 +633,14 @@ public static int calculateInSampleSize(BitmapFactory.Options options, // end up being too large to fit comfortably in memory, so we should // be more aggressive with sample down the image (=larger inSampleSize). - long totalPixels = width * height / inSampleSize; + long totalPixels = (width / inSampleSize) * (height / inSampleSize); // Anything more than 2x the requested pixels we'll sample down further final long totalReqPixelsCap = reqWidth * reqHeight * 2; while (totalPixels > totalReqPixelsCap) { inSampleSize *= 2; - totalPixels /= 2; + totalPixels = (width / inSampleSize) * (height / inSampleSize); } } return inSampleSize; diff --git a/android/widgets/src/main/java/org/nativescript/widgets/Image/Utils.java b/android/widgets/src/main/java/org/nativescript/widgets/Image/Utils.java index 30302d9..c105422 100644 --- a/android/widgets/src/main/java/org/nativescript/widgets/Image/Utils.java +++ b/android/widgets/src/main/java/org/nativescript/widgets/Image/Utils.java @@ -52,4 +52,8 @@ public static boolean hasJellyBean() { public static boolean hasKitKat() { return Build.VERSION.SDK_INT >= VERSION_CODES.KITKAT; } + + public static boolean hasN() { + return Build.VERSION.SDK_INT >= VERSION_CODES.N; + } } \ No newline at end of file diff --git a/android/widgets/src/main/java/org/nativescript/widgets/Image/Worker.java b/android/widgets/src/main/java/org/nativescript/widgets/Image/Worker.java index 62bd060..7ef53e6 100644 --- a/android/widgets/src/main/java/org/nativescript/widgets/Image/Worker.java +++ b/android/widgets/src/main/java/org/nativescript/widgets/Image/Worker.java @@ -95,7 +95,7 @@ public void removeBitmap(String uri) { * @param owner The owner to bind the downloaded image to. * @param listener A listener that will be called back once the image has been loaded. */ - public void loadImage(String uri, BitmapOwner owner, int decodeWidth, int decodeHeight, boolean useCache, boolean async, OnImageLoadedListener listener) { + public void loadImage(String uri, BitmapOwner owner, int decodeWidth, int decodeHeight, boolean keepAspectRatio, boolean useCache, boolean async, OnImageLoadedListener listener) { if (uri == null) { return; } @@ -111,7 +111,7 @@ public void loadImage(String uri, BitmapOwner owner, int decodeWidth, int decode if (value == null && !async) { // Decode sync. - value = processBitmap(uri, decodeWidth, decodeHeight, useCache); + value = processBitmap(uri, decodeWidth, decodeHeight, keepAspectRatio, useCache); if (value != null) { if (mCache != null && useCache) { if (debuggable > 0) { @@ -135,7 +135,7 @@ public void loadImage(String uri, BitmapOwner owner, int decodeWidth, int decode listener.onImageLoaded(true); } } else if (cancelPotentialWork(uri, owner)) { - final BitmapWorkerTask task = new BitmapWorkerTask(uri, owner, decodeWidth, decodeHeight, useCache, listener); + final BitmapWorkerTask task = new BitmapWorkerTask(uri, owner, decodeWidth, decodeHeight, keepAspectRatio, useCache, listener); final AsyncDrawable asyncDrawable = new AsyncDrawable(mResources, mLoadingBitmap, task); owner.setDrawable(asyncDrawable); @@ -194,7 +194,7 @@ public void setExitTasksEarly(boolean exitTasksEarly) { * {@link Worker#loadImage(String, BitmapOwner, int, int, boolean, boolean, OnImageLoadedListener)} * @return The processed bitmap */ - protected abstract Bitmap processBitmap(String uri, int decodeWidth, int decodeHeight, boolean useCache); + protected abstract Bitmap processBitmap(String uri, int decodeWidth, int decodeHeight, boolean keepAspectRatio, boolean useCache); /** * @return The {@link Cache} object currently being used by this Worker. @@ -263,18 +263,20 @@ private static BitmapWorkerTask getBitmapWorkerTask(BitmapOwner owner) { private class BitmapWorkerTask extends AsyncTask { private int mDecodeWidth; private int mDecodeHeight; + private boolean mKeepAspectRatio; private String mUri; private boolean mCacheImage; private final WeakReference imageViewReference; private final OnImageLoadedListener mOnImageLoadedListener; - public BitmapWorkerTask(String uri, BitmapOwner owner, int decodeWidth, int decodeHeight, boolean cacheImage) { - this(uri, owner, decodeWidth, decodeHeight, cacheImage, null); + public BitmapWorkerTask(String uri, BitmapOwner owner, int decodeWidth, int decodeHeight, boolean keepAspectRatio, boolean cacheImage) { + this(uri, owner, decodeWidth, decodeHeight, keepAspectRatio, cacheImage, null); } - public BitmapWorkerTask(String uri, BitmapOwner owner, int decodeWidth, int decodeHeight, boolean cacheImage, OnImageLoadedListener listener) { + public BitmapWorkerTask(String uri, BitmapOwner owner, int decodeWidth, int decodeHeight, boolean keepAspectRatio, boolean cacheImage, OnImageLoadedListener listener) { mDecodeWidth = decodeWidth; mDecodeHeight = decodeHeight; + mKeepAspectRatio = keepAspectRatio; mCacheImage = cacheImage; mUri = uri; imageViewReference = new WeakReference(owner); @@ -308,7 +310,7 @@ protected Bitmap doInBackground(Void... params) { // process method (as implemented by a subclass) if (bitmap == null && !isCancelled() && getAttachedOwner() != null && !mExitTasksEarly) { - bitmap = processBitmap(mUri, mDecodeWidth, mDecodeHeight, mCacheImage); + bitmap = processBitmap(mUri, mDecodeWidth, mDecodeHeight, mKeepAspectRatio, mCacheImage); } // If the bitmap was processed and the image cache is available, then add the processed diff --git a/android/widgets/src/main/java/org/nativescript/widgets/ImageView.java b/android/widgets/src/main/java/org/nativescript/widgets/ImageView.java index 8344d9e..d45fdb5 100644 --- a/android/widgets/src/main/java/org/nativescript/widgets/ImageView.java +++ b/android/widgets/src/main/java/org/nativescript/widgets/ImageView.java @@ -30,6 +30,7 @@ public class ImageView extends android.widget.ImageView implements BitmapOwner { private String mUri; private int mDecodeWidth; private int mDecodeHeight; + private boolean mKeepAspectRatio; private boolean mUseCache; private boolean mAsync; private Worker.OnImageLoadedListener mListener; @@ -162,9 +163,14 @@ private void computeScaleFactor(int measureWidth, int measureHeight, boolean wid } public void setUri(String uri, int decodeWidth, int decodeHeight, boolean useCache, boolean async) { + this.setUri(uri, decodeWidth, decodeHeight, false, useCache, async); + } + + public void setUri(String uri, int decodeWidth, int decodeHeight, boolean keepAspectRatio, boolean useCache, boolean async) { mUri = uri; mDecodeWidth = decodeWidth; mDecodeHeight = decodeHeight; + mKeepAspectRatio = keepAspectRatio; mUseCache = useCache; mAsync = async; @@ -188,7 +194,7 @@ private void loadImage() { Fetcher fetcher = Fetcher.getInstance(this.getContext()); if (mUri != null && fetcher != null) { // Get the Bitmap from cache. - fetcher.loadImage(mUri, this, mDecodeWidth, mDecodeHeight, mUseCache, mAsync, mListener); + fetcher.loadImage(mUri, this, mDecodeWidth, mDecodeHeight, mKeepAspectRatio, mUseCache, mAsync, mListener); } }