From 48414e4e2841f1902524cf5940f52c3d066b6c3f Mon Sep 17 00:00:00 2001 From: Jorge Ruesga Date: Tue, 2 Sep 2014 03:18:42 +0200 Subject: gallery: use inJustDecodeBounds in ImageFilterBorder To avoid OOM exceptions loading the border drawable JIRA: BUGDUMP-20716 https://jira.cyanogenmod.org/browse/BUGDUMP-20716 Signed-off-by: Jorge Ruesga Change-Id: Ie3fdb34de83f4a863c0d1d23bb8162b2425955e9 --- src/com/android/gallery3d/data/DecodeUtils.java | 44 ++++++++++++++++++++++ .../filtershow/filters/ImageFilterBorder.java | 10 +++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/com/android/gallery3d/data/DecodeUtils.java b/src/com/android/gallery3d/data/DecodeUtils.java index fa709157d..825c4bbea 100644 --- a/src/com/android/gallery3d/data/DecodeUtils.java +++ b/src/com/android/gallery3d/data/DecodeUtils.java @@ -17,6 +17,7 @@ package com.android.gallery3d.data; import android.annotation.TargetApi; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; @@ -33,6 +34,7 @@ import com.android.gallery3d.ui.Log; import com.android.gallery3d.util.ThreadPool.CancelListener; import com.android.gallery3d.util.ThreadPool.JobContext; +import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.InputStream; @@ -309,4 +311,46 @@ public class DecodeUtils { decodeBounds(jc, fileDescriptor, options); return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight); } + + public static Bitmap decodeBitmap(Resources res, int resId, int reqWidth, int reqHeight) { + // First decode with inJustDecodeBounds=true to check dimensions + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeResource(res, resId, options); + + // Calculate inSampleSize (use 1024 as maximum size, the minimum supported + // by all the gles20 devices) + options.inSampleSize = calculateBitmapRatio( + options, + Math.min(reqWidth, 1024), + Math.min(reqHeight, 1024)); + + // Decode the bitmap with inSampleSize set + options.inJustDecodeBounds = false; + options.inPreferQualityOverSpeed = false; + options.inPurgeable = true; + options.inInputShareable = true; + options.inDither = true; + return BitmapFactory.decodeResource(res, resId, options); + } + + private static int calculateBitmapRatio(Options options, int reqWidth, int reqHeight) { + // Raw height and width of image + final int height = options.outHeight; + final int width = options.outWidth; + int inSampleSize = 1; + + if (height > reqHeight || width > reqWidth) { + // Calculate ratios of height and width to requested height and width + final int heightRatio = Math.round((float) height / (float) reqHeight); + final int widthRatio = Math.round((float) width / (float) reqWidth); + + // Choose the smallest ratio as inSampleSize value, this will guarantee + // a final image with both dimensions larger than or equal to the + // requested height and width. + inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; + } + + return inSampleSize; + } } diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java index a7286f0fa..a7bd539fc 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java @@ -18,12 +18,13 @@ package com.android.gallery3d.filtershow.filters; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import com.android.gallery3d.data.DecodeUtils; + import java.util.HashMap; public class ImageFilterBorder extends ImageFilter { @@ -57,7 +58,7 @@ public class ImageFilterBorder extends ImageFilter { Rect bounds = new Rect(0, 0, (int) (w * scale1), (int) (h * scale1)); Canvas canvas = new Canvas(bitmap); canvas.scale(scale2, scale2); - Drawable drawable = getDrawable(getParameters().getDrawableResource()); + Drawable drawable = getDrawable(getParameters().getDrawableResource(), w, h); drawable.setBounds(bounds); drawable.draw(canvas); return bitmap; @@ -80,10 +81,11 @@ public class ImageFilterBorder extends ImageFilter { } } - public Drawable getDrawable(int rsc) { + public Drawable getDrawable(int rsc, int reqWidth, int reqHeight) { Drawable drawable = mDrawables.get(rsc); if (drawable == null && mResources != null && rsc != 0) { - drawable = new BitmapDrawable(mResources, BitmapFactory.decodeResource(mResources, rsc)); + drawable = new BitmapDrawable(mResources, DecodeUtils.decodeBitmap( + mResources, rsc, reqWidth, reqHeight)); mDrawables.put(rsc, drawable); } return drawable; -- cgit v1.2.3