diff options
Diffstat (limited to 'src/com/android/gallery3d/filtershow/cache/ImageLoader.java')
-rw-r--r-- | src/com/android/gallery3d/filtershow/cache/ImageLoader.java | 150 |
1 files changed, 130 insertions, 20 deletions
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java index 698992ac9..df4f3fd3a 100644 --- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java +++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java @@ -91,6 +91,7 @@ public class ImageLoader { public static final int ORI_TRANSPOSE = ExifInterface.ORIENTATION_TRANSPOSE; public static final int ORI_TRANSVERSE = ExifInterface.ORIENTATION_TRANSVERSE; + private static final int BITMAP_LOAD_BACKOUT_ATTEMPTS = 5; private Context mContext = null; private Uri mUri = null; @@ -264,12 +265,12 @@ public class ImageLoader { bitmap.getHeight(), matrix, true); } - private Bitmap loadRegionBitmap(Uri uri, Rect bounds) { + private Bitmap loadRegionBitmap(Uri uri, BitmapFactory.Options options, Rect bounds) { InputStream is = null; try { is = mContext.getContentResolver().openInputStream(uri); BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false); - return decoder.decodeRegion(bounds, null); + return decoder.decodeRegion(bounds, options); } catch (FileNotFoundException e) { Log.e(LOGTAG, "FileNotFoundException: " + uri); } catch (Exception e) { @@ -369,11 +370,28 @@ public class ImageLoader { // FIXME: this currently does the loading + filtering on the UI thread -- // need to move this to a background thread. public Bitmap getScaleOneImageForPreset(ImageShow caller, ImagePreset imagePreset, Rect bounds, - boolean force) { + Rect destination, boolean force) { mLoadingLock.lock(); Bitmap bmp = mZoomCache.getImage(imagePreset, bounds); if (force || bmp == null) { - bmp = loadRegionBitmap(mUri, bounds); + BitmapFactory.Options options = null; + if (destination != null) { + options = new BitmapFactory.Options(); + if (bounds.width() > destination.width()) { + int sampleSize = 1; + int w = bounds.width(); + while (w > destination.width()) { + sampleSize *= 2; + w /= sampleSize; + } + options.inSampleSize = sampleSize; + } + } + bmp = loadRegionBitmap(mUri, options, bounds); + if (destination != null) { + mLoadingLock.unlock(); + return bmp; + } if (bmp != null) { // TODO: this workaround for RS might not be needed ultimately Bitmap bmp2 = bmp.copy(Bitmap.Config.ARGB_8888, true); @@ -406,28 +424,97 @@ public class ImageLoader { public static Bitmap loadMutableBitmap(Context context, Uri sourceUri) { BitmapFactory.Options options = new BitmapFactory.Options(); + return loadMutableBitmap(context, sourceUri, options); + } + + public static Bitmap loadMutableBitmap(Context context, Uri sourceUri, + BitmapFactory.Options options) { // TODO: on <3.x we need a copy of the bitmap (inMutable doesn't // exist) options.inMutable = true; + Bitmap bitmap = decodeUriWithBackouts(context, sourceUri, options); + if (bitmap == null) { + return null; + } + int orientation = ImageLoader.getOrientation(context, sourceUri); + bitmap = ImageLoader.rotateToPortrait(bitmap, orientation); + return bitmap; + } + + public static Bitmap decodeUriWithBackouts(Context context, Uri sourceUri, + BitmapFactory.Options options) { + boolean noBitmap = true; + int num_tries = 0; + InputStream is = getInputStream(context, sourceUri); + + if (options.inSampleSize < 1) { + options.inSampleSize = 1; + } + // Stopgap fix for low-memory devices. + Bitmap bmap = null; + while (noBitmap) { + if (is == null) { + return null; + } + try { + // Try to decode, downsample if low-memory. + bmap = BitmapFactory.decodeStream(is, null, options); + noBitmap = false; + } catch (java.lang.OutOfMemoryError e) { + // Try 5 times before failing for good. + if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) { + throw e; + } + is = null; + bmap = null; + System.gc(); + is = getInputStream(context, sourceUri); + options.inSampleSize *= 2; + } + } + Utils.closeSilently(is); + return bmap; + } + + private static InputStream getInputStream(Context context, Uri sourceUri) { InputStream is = null; - Bitmap bitmap = null; try { is = context.getContentResolver().openInputStream(sourceUri); - bitmap = BitmapFactory.decodeStream(is, null, options); } catch (FileNotFoundException e) { Log.w(LOGTAG, "could not load bitmap ", e); - is = null; - bitmap = null; - } finally { Utils.closeSilently(is); + is = null; } - if (bitmap == null) { - return null; + return is; + } + + public static Bitmap decodeResourceWithBackouts(Resources res, BitmapFactory.Options options, + int id) { + boolean noBitmap = true; + int num_tries = 0; + if (options.inSampleSize < 1) { + options.inSampleSize = 1; } - int orientation = ImageLoader.getOrientation(context, sourceUri); - bitmap = ImageLoader.rotateToPortrait(bitmap, orientation); - return bitmap; + // Stopgap fix for low-memory devices. + Bitmap bmap = null; + while (noBitmap) { + try { + // Try to decode, downsample if low-memory. + bmap = BitmapFactory.decodeResource( + res, id, options); + noBitmap = false; + } catch (java.lang.OutOfMemoryError e) { + // Try 5 times before failing for good. + if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) { + throw e; + } + bmap = null; + System.gc(); + options.inSampleSize *= 2; + } + } + return bmap; } public void returnFilteredResult(ImagePreset preset, @@ -451,13 +538,36 @@ public class ImageLoader { if (param == null || mUri == null) { return null; } - Bitmap bitmap = loadMutableBitmap(mContext, mUri); - if (bitmap == null) { - Log.w(LOGTAG, "Failed to save image!"); - return null; + BitmapFactory.Options options = new BitmapFactory.Options(); + boolean noBitmap = true; + int num_tries = 0; + if (options.inSampleSize < 1) { + options.inSampleSize = 1; } - bitmap = param.applyGeometry(bitmap); - return param.apply(bitmap); + Bitmap bitmap = null; + // Stopgap fix for low-memory devices. + while (noBitmap) { + try { + // Try to do bitmap operations, downsample if low-memory + bitmap = loadMutableBitmap(mContext, mUri, options); + if (bitmap == null) { + Log.w(LOGTAG, "Failed to save image!"); + return null; + } + bitmap = param.applyGeometry(bitmap); + bitmap = param.apply(bitmap); + noBitmap = false; + } catch (java.lang.OutOfMemoryError e) { + // Try 5 times before failing for good. + if (++num_tries >= 5) { + throw e; + } + bitmap = null; + System.gc(); + options.inSampleSize *= 2; + } + } + return bitmap; } }; |