diff options
author | Michael Jurka <mikejurka@google.com> | 2013-10-30 14:59:37 +0100 |
---|---|---|
committer | Danesh M <daneshm90@gmail.com> | 2014-06-05 23:29:01 -0700 |
commit | 2d1b3ea4af56cb81639a9fa76643fe77b1ef3c54 (patch) | |
tree | d444ff541ce582224cc9073ce42555ae6f90718f | |
parent | 4b46f22ecc2755bbcb38b44ddf1d4ce4f214512b (diff) | |
download | android_packages_apps_Trebuchet-2d1b3ea4af56cb81639a9fa76643fe77b1ef3c54.tar.gz android_packages_apps_Trebuchet-2d1b3ea4af56cb81639a9fa76643fe77b1ef3c54.tar.bz2 android_packages_apps_Trebuchet-2d1b3ea4af56cb81639a9fa76643fe77b1ef3c54.zip |
Fix crashes for images that are not PNG or JPEG
Bug: 11341544
Change-Id: If2339b583e9a991f053a5f95f259156e3e4e9acd
-rw-r--r-- | src/com/android/launcher3/WallpaperCropActivity.java | 28 | ||||
-rw-r--r-- | src/com/android/photos/BitmapRegionTileSource.java | 152 |
2 files changed, 148 insertions, 32 deletions
diff --git a/src/com/android/launcher3/WallpaperCropActivity.java b/src/com/android/launcher3/WallpaperCropActivity.java index 491316d74..f9aec2b08 100644 --- a/src/com/android/launcher3/WallpaperCropActivity.java +++ b/src/com/android/launcher3/WallpaperCropActivity.java @@ -247,19 +247,19 @@ public class WallpaperCropActivity extends Activity { private static int getRotationFromExifHelper( String path, Resources res, int resId, Context context, Uri uri) { ExifInterface ei = new ExifInterface(); + InputStream is = null; + BufferedInputStream bis = null; try { if (path != null) { ei.readExif(path); } else if (uri != null) { - InputStream is = context.getContentResolver().openInputStream(uri); - BufferedInputStream bis = new BufferedInputStream(is); + is = context.getContentResolver().openInputStream(uri); + bis = new BufferedInputStream(is); ei.readExif(bis); - bis.close(); } else { - InputStream is = res.openRawResource(resId); - BufferedInputStream bis = new BufferedInputStream(is); + is = res.openRawResource(resId); + bis = new BufferedInputStream(is); ei.readExif(bis); - bis.close(); } Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION); if (ori != null) { @@ -267,6 +267,9 @@ public class WallpaperCropActivity extends Activity { } } catch (IOException e) { Log.w(LOGTAG, "Getting exif data failed", e); + } finally { + Utils.closeSilently(bis); + Utils.closeSilently(is); } return 0; } @@ -606,13 +609,13 @@ public class WallpaperCropActivity extends Activity { } // See how much we're reducing the size of the image - int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / mOutWidth, - roundedTrueCrop.height() / mOutHeight); - + int scaleDownSampleSize = Math.max(1, Math.min(roundedTrueCrop.width() / mOutWidth, + roundedTrueCrop.height() / mOutHeight)); // Attempt to open a region decoder BitmapRegionDecoder decoder = null; + InputStream is = null; try { - InputStream is = regenerateInputStream(); + is = regenerateInputStream(); if (is == null) { Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString()); failure = true; @@ -622,6 +625,9 @@ public class WallpaperCropActivity extends Activity { Utils.closeSilently(is); } catch (IOException e) { Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e); + } finally { + Utils.closeSilently(is); + is = null; } Bitmap crop = null; @@ -637,7 +643,7 @@ public class WallpaperCropActivity extends Activity { if (crop == null) { // BitmapRegionDecoder has failed, try to crop in-memory - InputStream is = regenerateInputStream(); + is = regenerateInputStream(); Bitmap fullSize = null; if (is != null) { BitmapFactory.Options options = new BitmapFactory.Options(); diff --git a/src/com/android/photos/BitmapRegionTileSource.java b/src/com/android/photos/BitmapRegionTileSource.java index b85caaa1c..2f203af53 100644 --- a/src/com/android/photos/BitmapRegionTileSource.java +++ b/src/com/android/photos/BitmapRegionTileSource.java @@ -24,6 +24,9 @@ import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; import android.graphics.Rect; import android.net.Uri; import android.os.Build; @@ -42,6 +45,103 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +interface SimpleBitmapRegionDecoder { + int getWidth(); + int getHeight(); + Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options); +} + +class SimpleBitmapRegionDecoderWrapper implements SimpleBitmapRegionDecoder { + BitmapRegionDecoder mDecoder; + private SimpleBitmapRegionDecoderWrapper(BitmapRegionDecoder decoder) { + mDecoder = decoder; + } + public static SimpleBitmapRegionDecoderWrapper newInstance( + String pathName, boolean isShareable) { + try { + BitmapRegionDecoder d = BitmapRegionDecoder.newInstance(pathName, isShareable); + if (d != null) { + return new SimpleBitmapRegionDecoderWrapper(d); + } + } catch (IOException e) { + Log.w("BitmapRegionTileSource", "getting decoder failed for path " + pathName, e); + return null; + } + return null; + } + public static SimpleBitmapRegionDecoderWrapper newInstance( + InputStream is, boolean isShareable) { + try { + BitmapRegionDecoder d = BitmapRegionDecoder.newInstance(is, isShareable); + if (d != null) { + return new SimpleBitmapRegionDecoderWrapper(d); + } + } catch (IOException e) { + Log.w("BitmapRegionTileSource", "getting decoder failed", e); + return null; + } + return null; + } + public int getWidth() { + return mDecoder.getWidth(); + } + public int getHeight() { + return mDecoder.getHeight(); + } + public Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options) { + return mDecoder.decodeRegion(wantRegion, options); + } +} + +class DumbBitmapRegionDecoder implements SimpleBitmapRegionDecoder { + //byte[] mStreamCopy; + Bitmap mBuffer; + Canvas mTempCanvas; + Paint mTempPaint; + private DumbBitmapRegionDecoder(Bitmap b) { + mBuffer = b; + } + public static DumbBitmapRegionDecoder newInstance(String pathName) { + Bitmap b = BitmapFactory.decodeFile(pathName); + if (b != null) { + return new DumbBitmapRegionDecoder(b); + } + return null; + } + public static DumbBitmapRegionDecoder newInstance(InputStream is) { + Bitmap b = BitmapFactory.decodeStream(is); + if (b != null) { + return new DumbBitmapRegionDecoder(b); + } + return null; + } + public int getWidth() { + return mBuffer.getWidth(); + } + public int getHeight() { + return mBuffer.getHeight(); + } + public Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options) { + if (mTempCanvas == null) { + mTempCanvas = new Canvas(); + mTempPaint = new Paint(); + mTempPaint.setFilterBitmap(true); + } + int sampleSize = Math.max(options.inSampleSize, 1); + Bitmap newBitmap = Bitmap.createBitmap( + wantRegion.width() / sampleSize, + wantRegion.height() / sampleSize, + Bitmap.Config.ARGB_8888); + mTempCanvas.setBitmap(newBitmap); + mTempCanvas.save(); + mTempCanvas.scale(1f / sampleSize, 1f / sampleSize); + mTempCanvas.drawBitmap(mBuffer, -wantRegion.left, -wantRegion.top, mTempPaint); + mTempCanvas.restore(); + mTempCanvas.setBitmap(null); + return newBitmap; + } +} + /** * A {@link com.android.photos.views.TiledImageRenderer.TileSource} using * {@link BitmapRegionDecoder} to wrap a local file @@ -59,7 +159,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2; public static abstract class BitmapSource { - private BitmapRegionDecoder mDecoder; + private SimpleBitmapRegionDecoder mDecoder; private Bitmap mPreview; private int mPreviewSize; private int mRotation; @@ -103,7 +203,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { return mState; } - public BitmapRegionDecoder getBitmapRegionDecoder() { + public SimpleBitmapRegionDecoder getBitmapRegionDecoder() { return mDecoder; } @@ -120,7 +220,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { } public abstract boolean readExif(ExifInterface ei); - public abstract BitmapRegionDecoder loadBitmapRegionDecoder(); + public abstract SimpleBitmapRegionDecoder loadBitmapRegionDecoder(); public abstract Bitmap loadPreviewBitmap(BitmapFactory.Options options); } @@ -131,13 +231,13 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { mPath = path; } @Override - public BitmapRegionDecoder loadBitmapRegionDecoder() { - try { - return BitmapRegionDecoder.newInstance(mPath, true); - } catch (IOException e) { - Log.w("BitmapRegionTileSource", "getting decoder failed", e); - return null; + public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() { + SimpleBitmapRegionDecoder d; + d = SimpleBitmapRegionDecoderWrapper.newInstance(mPath, true); + if (d == null) { + d = DumbBitmapRegionDecoder.newInstance(mPath); } + return d; } @Override public Bitmap loadPreviewBitmap(BitmapFactory.Options options) { @@ -168,11 +268,17 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { return new BufferedInputStream(is); } @Override - public BitmapRegionDecoder loadBitmapRegionDecoder() { + public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() { try { InputStream is = regenerateInputStream(); - BitmapRegionDecoder regionDecoder = BitmapRegionDecoder.newInstance(is, false); + SimpleBitmapRegionDecoder regionDecoder = + SimpleBitmapRegionDecoderWrapper.newInstance(is, false); Utils.closeSilently(is); + if (regionDecoder == null) { + is = regenerateInputStream(); + regionDecoder = DumbBitmapRegionDecoder.newInstance(is); + Utils.closeSilently(is); + } return regionDecoder; } catch (FileNotFoundException e) { Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e); @@ -196,8 +302,9 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { } @Override public boolean readExif(ExifInterface ei) { + InputStream is = null; try { - InputStream is = regenerateInputStream(); + is = regenerateInputStream(); ei.readExif(is); Utils.closeSilently(is); return true; @@ -207,6 +314,8 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { } catch (IOException e) { Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e); return false; + } finally { + Utils.closeSilently(is); } } } @@ -224,16 +333,17 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { return new BufferedInputStream(is); } @Override - public BitmapRegionDecoder loadBitmapRegionDecoder() { - try { - InputStream is = regenerateInputStream(); - BitmapRegionDecoder regionDecoder = BitmapRegionDecoder.newInstance(is, true); + public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() { + InputStream is = regenerateInputStream(); + SimpleBitmapRegionDecoder regionDecoder = + SimpleBitmapRegionDecoderWrapper.newInstance(is, false); + Utils.closeSilently(is); + if (regionDecoder == null) { + is = regenerateInputStream(); + regionDecoder = DumbBitmapRegionDecoder.newInstance(is); Utils.closeSilently(is); - return regionDecoder; - } catch (IOException e) { - Log.e("BitmapRegionTileSource", "Error reading resource", e); - return null; } + return regionDecoder; } @Override public Bitmap loadPreviewBitmap(BitmapFactory.Options options) { @@ -253,7 +363,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { } } - BitmapRegionDecoder mDecoder; + SimpleBitmapRegionDecoder mDecoder; int mWidth; int mHeight; int mTileSize; |