Make wallpaper picker/cropper more robust
- don't crash if image passed to wallpaper picker is invalid - close input streams correctly Bug: 11413915 Bug: 11380658 Bug: 11362731 Change-Id: I973e6bdc532d24a64efd6d174e89fdac626d7ee3
This commit is contained in:
parent
88400d521e
commit
619a180be5
|
@ -30,6 +30,14 @@
|
|||
<string name="folder_name"></string>
|
||||
<!-- Button label on Wallpaper picker screen; user selects this button to set a specific wallpaper -->
|
||||
<string name="wallpaper_instructions">Set wallpaper</string>
|
||||
<!-- Error message when an image is selected as a wallpaper,
|
||||
but the wallpaper picker cannot load it -->
|
||||
<string name="image_load_fail">Coudn\'t load image</string>
|
||||
<!-- Error message when an image is selected as a wallpaper,
|
||||
but the wallpaper cropper cannot load it. The user will
|
||||
usually see this when using another app and trying to set
|
||||
an image as the wallpaper -->
|
||||
<string name="wallpaper_load_fail">Couldn\'t load image as wallpaper</string>
|
||||
<!-- Shown when wallpapers are selected in Wallpaper picker -->
|
||||
<!-- String indicating how many media item(s) is(are) selected
|
||||
eg. 1 selected [CHAR LIMIT=30] -->
|
||||
|
|
|
@ -62,7 +62,7 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
|
|||
File file = new File(a.getFilesDir(), imageFilename);
|
||||
BitmapRegionTileSource.FilePathBitmapSource bitmapSource =
|
||||
new BitmapRegionTileSource.FilePathBitmapSource(file.getAbsolutePath(), 1024);
|
||||
a.setCropViewTileSource(bitmapSource, false, true);
|
||||
a.setCropViewTileSource(bitmapSource, false, true, null);
|
||||
}
|
||||
@Override
|
||||
public void onSave(WallpaperPickerActivity a) {
|
||||
|
|
|
@ -41,10 +41,12 @@ import android.util.Log;
|
|||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.gallery3d.common.Utils;
|
||||
import com.android.gallery3d.exif.ExifInterface;
|
||||
import com.android.photos.BitmapRegionTileSource;
|
||||
import com.android.photos.BitmapRegionTileSource.BitmapSource;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -109,12 +111,24 @@ public class WallpaperCropActivity extends Activity {
|
|||
});
|
||||
|
||||
// Load image in background
|
||||
setCropViewTileSource(
|
||||
new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024), true, false);
|
||||
final BitmapRegionTileSource.UriBitmapSource bitmapSource =
|
||||
new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024);
|
||||
Runnable onLoad = new Runnable() {
|
||||
public void run() {
|
||||
if (bitmapSource.getLoadingState() != BitmapSource.State.LOADED) {
|
||||
Toast.makeText(WallpaperCropActivity.this,
|
||||
getString(R.string.wallpaper_load_fail),
|
||||
Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
setCropViewTileSource(bitmapSource, true, false, onLoad);
|
||||
}
|
||||
|
||||
public void setCropViewTileSource(final BitmapRegionTileSource.BitmapSource bitmapSource,
|
||||
final boolean touchEnabled, final boolean moveToLeft) {
|
||||
public void setCropViewTileSource(
|
||||
final BitmapRegionTileSource.BitmapSource bitmapSource, final boolean touchEnabled,
|
||||
final boolean moveToLeft, final Runnable postExecute) {
|
||||
final Context context = WallpaperCropActivity.this;
|
||||
final View progressView = findViewById(R.id.loading);
|
||||
final AsyncTask<Void, Void, Void> loadBitmapTask = new AsyncTask<Void, Void, Void>() {
|
||||
|
@ -127,13 +141,18 @@ public class WallpaperCropActivity extends Activity {
|
|||
protected void onPostExecute(Void arg) {
|
||||
if (!isCancelled()) {
|
||||
progressView.setVisibility(View.INVISIBLE);
|
||||
mCropView.setTileSource(
|
||||
new BitmapRegionTileSource(context, bitmapSource), null);
|
||||
mCropView.setTouchEnabled(touchEnabled);
|
||||
if (moveToLeft) {
|
||||
mCropView.moveToLeft();
|
||||
if (bitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
|
||||
mCropView.setTileSource(
|
||||
new BitmapRegionTileSource(context, bitmapSource), null);
|
||||
mCropView.setTouchEnabled(touchEnabled);
|
||||
if (moveToLeft) {
|
||||
mCropView.moveToLeft();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (postExecute != null) {
|
||||
postExecute.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
// We don't want to show the spinner every time we load an image, because that would be
|
||||
|
@ -235,10 +254,12 @@ public class WallpaperCropActivity extends Activity {
|
|||
InputStream is = context.getContentResolver().openInputStream(uri);
|
||||
BufferedInputStream bis = new BufferedInputStream(is);
|
||||
ei.readExif(bis);
|
||||
bis.close();
|
||||
} else {
|
||||
InputStream is = res.openRawResource(resId);
|
||||
BufferedInputStream bis = new BufferedInputStream(is);
|
||||
ei.readExif(bis);
|
||||
bis.close();
|
||||
}
|
||||
Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
|
||||
if (ori != null) {
|
||||
|
@ -408,7 +429,6 @@ public class WallpaperCropActivity extends Activity {
|
|||
String mInFilePath;
|
||||
byte[] mInImageBytes;
|
||||
int mInResId = 0;
|
||||
InputStream mInStream;
|
||||
RectF mCropBounds = null;
|
||||
int mOutWidth, mOutHeight;
|
||||
int mRotation;
|
||||
|
@ -481,37 +501,36 @@ public class WallpaperCropActivity extends Activity {
|
|||
}
|
||||
|
||||
// Helper to setup input stream
|
||||
private void regenerateInputStream() {
|
||||
private InputStream regenerateInputStream() {
|
||||
if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null) {
|
||||
Log.w(LOGTAG, "cannot read original file, no input URI, resource ID, or " +
|
||||
"image byte array given");
|
||||
} else {
|
||||
Utils.closeSilently(mInStream);
|
||||
try {
|
||||
if (mInUri != null) {
|
||||
mInStream = new BufferedInputStream(
|
||||
return new BufferedInputStream(
|
||||
mContext.getContentResolver().openInputStream(mInUri));
|
||||
} else if (mInFilePath != null) {
|
||||
mInStream = mContext.openFileInput(mInFilePath);
|
||||
return mContext.openFileInput(mInFilePath);
|
||||
} else if (mInImageBytes != null) {
|
||||
mInStream = new BufferedInputStream(
|
||||
new ByteArrayInputStream(mInImageBytes));
|
||||
return new BufferedInputStream(new ByteArrayInputStream(mInImageBytes));
|
||||
} else {
|
||||
mInStream = new BufferedInputStream(
|
||||
mResources.openRawResource(mInResId));
|
||||
return new BufferedInputStream(mResources.openRawResource(mInResId));
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Point getImageBounds() {
|
||||
regenerateInputStream();
|
||||
if (mInStream != null) {
|
||||
InputStream is = regenerateInputStream();
|
||||
if (is != null) {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeStream(mInStream, null, options);
|
||||
BitmapFactory.decodeStream(is, null, options);
|
||||
Utils.closeSilently(is);
|
||||
if (options.outWidth != 0 && options.outHeight != 0) {
|
||||
return new Point(options.outWidth, options.outHeight);
|
||||
}
|
||||
|
@ -529,22 +548,26 @@ public class WallpaperCropActivity extends Activity {
|
|||
public boolean cropBitmap() {
|
||||
boolean failure = false;
|
||||
|
||||
regenerateInputStream();
|
||||
|
||||
WallpaperManager wallpaperManager = null;
|
||||
if (mSetWallpaper) {
|
||||
wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
|
||||
}
|
||||
if (mSetWallpaper && mNoCrop && mInStream != null) {
|
||||
|
||||
|
||||
if (mSetWallpaper && mNoCrop) {
|
||||
try {
|
||||
wallpaperManager.setStream(mInStream);
|
||||
InputStream is = regenerateInputStream();
|
||||
if (is != null) {
|
||||
wallpaperManager.setStream(is);
|
||||
Utils.closeSilently(is);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.w(LOGTAG, "cannot write stream to wallpaper", e);
|
||||
failure = true;
|
||||
}
|
||||
return !failure;
|
||||
}
|
||||
if (mInStream != null) {
|
||||
} else {
|
||||
// Find crop bounds (scaled to original image size)
|
||||
Rect roundedTrueCrop = new Rect();
|
||||
Matrix rotateMatrix = new Matrix();
|
||||
|
@ -557,6 +580,11 @@ public class WallpaperCropActivity extends Activity {
|
|||
mCropBounds = new RectF(roundedTrueCrop);
|
||||
|
||||
Point bounds = getImageBounds();
|
||||
if (bounds == null) {
|
||||
Log.w(LOGTAG, "cannot get bounds for image");
|
||||
failure = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
float[] rotatedBounds = new float[] { bounds.x, bounds.y };
|
||||
rotateMatrix.mapPoints(rotatedBounds);
|
||||
|
@ -567,7 +595,6 @@ public class WallpaperCropActivity extends Activity {
|
|||
inverseRotateMatrix.mapRect(mCropBounds);
|
||||
mCropBounds.offset(bounds.x/2, bounds.y/2);
|
||||
|
||||
regenerateInputStream();
|
||||
}
|
||||
|
||||
mCropBounds.roundOut(roundedTrueCrop);
|
||||
|
@ -585,7 +612,14 @@ public class WallpaperCropActivity extends Activity {
|
|||
// Attempt to open a region decoder
|
||||
BitmapRegionDecoder decoder = null;
|
||||
try {
|
||||
decoder = BitmapRegionDecoder.newInstance(mInStream, true);
|
||||
InputStream is = regenerateInputStream();
|
||||
if (is == null) {
|
||||
Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString());
|
||||
failure = true;
|
||||
return false;
|
||||
}
|
||||
decoder = BitmapRegionDecoder.newInstance(is, false);
|
||||
Utils.closeSilently(is);
|
||||
} catch (IOException e) {
|
||||
Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
|
||||
}
|
||||
|
@ -603,14 +637,15 @@ public class WallpaperCropActivity extends Activity {
|
|||
|
||||
if (crop == null) {
|
||||
// BitmapRegionDecoder has failed, try to crop in-memory
|
||||
regenerateInputStream();
|
||||
InputStream is = regenerateInputStream();
|
||||
Bitmap fullSize = null;
|
||||
if (mInStream != null) {
|
||||
if (is != null) {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
if (scaleDownSampleSize > 1) {
|
||||
options.inSampleSize = scaleDownSampleSize;
|
||||
}
|
||||
fullSize = BitmapFactory.decodeStream(mInStream, null, options);
|
||||
fullSize = BitmapFactory.decodeStream(is, null, options);
|
||||
Utils.closeSilently(is);
|
||||
}
|
||||
if (fullSize != null) {
|
||||
mCropBounds.left /= scaleDownSampleSize;
|
||||
|
|
|
@ -67,8 +67,10 @@ import android.widget.HorizontalScrollView;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.photos.BitmapRegionTileSource;
|
||||
import com.android.photos.BitmapRegionTileSource.BitmapSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -84,7 +86,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
|
|||
private static final String TEMP_WALLPAPER_TILES = "TEMP_WALLPAPER_TILES";
|
||||
private static final String DEFAULT_WALLPAPER_THUMBNAIL_FILENAME = "default_thumb.jpg";
|
||||
|
||||
private View mSelectedThumb;
|
||||
private View mSelectedTile;
|
||||
private boolean mIgnoreNextTap;
|
||||
private OnClickListener mThumbnailOnClickListener;
|
||||
|
||||
|
@ -128,13 +130,39 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
|
|||
|
||||
public static class UriWallpaperInfo extends WallpaperTileInfo {
|
||||
private Uri mUri;
|
||||
private boolean mFirstClick = true;
|
||||
private BitmapRegionTileSource.UriBitmapSource mBitmapSource;
|
||||
public UriWallpaperInfo(Uri uri) {
|
||||
mUri = uri;
|
||||
}
|
||||
@Override
|
||||
public void onClick(WallpaperPickerActivity a) {
|
||||
a.setCropViewTileSource(new BitmapRegionTileSource.UriBitmapSource(
|
||||
a, mUri, BitmapRegionTileSource.MAX_PREVIEW_SIZE), true, false);
|
||||
public void onClick(final WallpaperPickerActivity a) {
|
||||
final Runnable onLoad;
|
||||
if (!mFirstClick) {
|
||||
onLoad = null;
|
||||
} else {
|
||||
mFirstClick = false;
|
||||
onLoad = new Runnable() {
|
||||
public void run() {
|
||||
if (mBitmapSource != null &&
|
||||
mBitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
a.selectTile(mView);
|
||||
} else {
|
||||
ViewGroup parent = (ViewGroup) mView.getParent();
|
||||
if (parent != null) {
|
||||
parent.removeView(mView);
|
||||
Toast.makeText(a,
|
||||
a.getString(R.string.image_load_fail),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
mBitmapSource = new BitmapRegionTileSource.UriBitmapSource(
|
||||
a, mUri, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
|
||||
a.setCropViewTileSource(mBitmapSource, true, false, onLoad);
|
||||
}
|
||||
@Override
|
||||
public void onSave(final WallpaperPickerActivity a) {
|
||||
|
@ -304,17 +332,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
|
|||
return;
|
||||
}
|
||||
WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();
|
||||
if (info.isSelectable()) {
|
||||
if (mSelectedThumb != null) {
|
||||
mSelectedThumb.setSelected(false);
|
||||
mSelectedThumb = null;
|
||||
}
|
||||
mSelectedThumb = v;
|
||||
v.setSelected(true);
|
||||
// TODO: Remove this once the accessibility framework and
|
||||
// services have better support for selection state.
|
||||
v.announceForAccessibility(
|
||||
getString(R.string.announce_selection, v.getContentDescription()));
|
||||
if (info.isSelectable() && v.getVisibility() == View.VISIBLE) {
|
||||
selectTile(v);
|
||||
}
|
||||
info.onClick(WallpaperPickerActivity.this);
|
||||
}
|
||||
|
@ -440,8 +459,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
|
|||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mSelectedThumb != null) {
|
||||
WallpaperTileInfo info = (WallpaperTileInfo) mSelectedThumb.getTag();
|
||||
if (mSelectedTile != null) {
|
||||
WallpaperTileInfo info = (WallpaperTileInfo) mSelectedTile.getTag();
|
||||
info.onSave(WallpaperPickerActivity.this);
|
||||
}
|
||||
}
|
||||
|
@ -520,15 +539,23 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
|
|||
CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
|
||||
c.setChecked(false);
|
||||
}
|
||||
mSelectedThumb.setSelected(true);
|
||||
mSelectedTile.setSelected(true);
|
||||
mActionMode = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public void setCropViewTileSource(final BitmapRegionTileSource.BitmapSource bitmapSource,
|
||||
final boolean touchEnabled, boolean moveToLeft) {
|
||||
super.setCropViewTileSource(bitmapSource, touchEnabled, moveToLeft);
|
||||
|
||||
private void selectTile(View v) {
|
||||
if (mSelectedTile != null) {
|
||||
mSelectedTile.setSelected(false);
|
||||
mSelectedTile = null;
|
||||
}
|
||||
mSelectedTile = v;
|
||||
v.setSelected(true);
|
||||
// TODO: Remove this once the accessibility framework and
|
||||
// services have better support for selection state.
|
||||
v.announceForAccessibility(
|
||||
getString(R.string.announce_selection, v.getContentDescription()));
|
||||
}
|
||||
|
||||
private void initializeScrollForRtl() {
|
||||
|
@ -692,8 +719,9 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
|
|||
private void addTemporaryWallpaperTile(final Uri uri) {
|
||||
mTempWallpaperTiles.add(uri);
|
||||
// Add a tile for the image picked from Gallery
|
||||
FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater().
|
||||
final FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater().
|
||||
inflate(R.layout.wallpaper_picker_item, mWallpapersView, false);
|
||||
pickedImageThumbnail.setVisibility(View.GONE);
|
||||
setWallpaperItemPaddingToZero(pickedImageThumbnail);
|
||||
mWallpapersView.addView(pickedImageThumbnail, 0);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import android.os.Build.VERSION_CODES;
|
|||
import android.util.Log;
|
||||
|
||||
import com.android.gallery3d.common.BitmapUtils;
|
||||
import com.android.gallery3d.common.Utils;
|
||||
import com.android.gallery3d.exif.ExifInterface;
|
||||
import com.android.gallery3d.glrenderer.BasicTexture;
|
||||
import com.android.gallery3d.glrenderer.BitmapTexture;
|
||||
|
@ -62,10 +63,12 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||
private Bitmap mPreview;
|
||||
private int mPreviewSize;
|
||||
private int mRotation;
|
||||
public enum State { NOT_LOADED, LOADED, ERROR_LOADING };
|
||||
private State mState = State.NOT_LOADED;
|
||||
public BitmapSource(int previewSize) {
|
||||
mPreviewSize = previewSize;
|
||||
}
|
||||
public void loadInBackground() {
|
||||
public boolean loadInBackground() {
|
||||
ExifInterface ei = new ExifInterface();
|
||||
if (readExif(ei)) {
|
||||
Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
|
||||
|
@ -74,21 +77,32 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||
}
|
||||
}
|
||||
mDecoder = loadBitmapRegionDecoder();
|
||||
int width = mDecoder.getWidth();
|
||||
int height = mDecoder.getHeight();
|
||||
if (mPreviewSize != 0) {
|
||||
int previewSize = Math.min(mPreviewSize, MAX_PREVIEW_SIZE);
|
||||
BitmapFactory.Options opts = new BitmapFactory.Options();
|
||||
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
|
||||
opts.inPreferQualityOverSpeed = true;
|
||||
if (mDecoder == null) {
|
||||
mState = State.ERROR_LOADING;
|
||||
return false;
|
||||
} else {
|
||||
int width = mDecoder.getWidth();
|
||||
int height = mDecoder.getHeight();
|
||||
if (mPreviewSize != 0) {
|
||||
int previewSize = Math.min(mPreviewSize, MAX_PREVIEW_SIZE);
|
||||
BitmapFactory.Options opts = new BitmapFactory.Options();
|
||||
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
|
||||
opts.inPreferQualityOverSpeed = true;
|
||||
|
||||
float scale = (float) previewSize / Math.max(width, height);
|
||||
opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
|
||||
opts.inJustDecodeBounds = false;
|
||||
mPreview = loadPreviewBitmap(opts);
|
||||
float scale = (float) previewSize / Math.max(width, height);
|
||||
opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
|
||||
opts.inJustDecodeBounds = false;
|
||||
mPreview = loadPreviewBitmap(opts);
|
||||
}
|
||||
mState = State.LOADED;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public State getLoadingState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
public BitmapRegionDecoder getBitmapRegionDecoder() {
|
||||
return mDecoder;
|
||||
}
|
||||
|
@ -156,7 +170,10 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||
@Override
|
||||
public BitmapRegionDecoder loadBitmapRegionDecoder() {
|
||||
try {
|
||||
return BitmapRegionDecoder.newInstance(regenerateInputStream(), true);
|
||||
InputStream is = regenerateInputStream();
|
||||
BitmapRegionDecoder regionDecoder = BitmapRegionDecoder.newInstance(is, false);
|
||||
Utils.closeSilently(is);
|
||||
return regionDecoder;
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
||||
return null;
|
||||
|
@ -168,7 +185,10 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||
@Override
|
||||
public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
|
||||
try {
|
||||
return BitmapFactory.decodeStream(regenerateInputStream(), null, options);
|
||||
InputStream is = regenerateInputStream();
|
||||
Bitmap b = BitmapFactory.decodeStream(is, null, options);
|
||||
Utils.closeSilently(is);
|
||||
return b;
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
||||
return null;
|
||||
|
@ -177,13 +197,15 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||
@Override
|
||||
public boolean readExif(ExifInterface ei) {
|
||||
try {
|
||||
ei.readExif(regenerateInputStream());
|
||||
InputStream is = regenerateInputStream();
|
||||
ei.readExif(is);
|
||||
Utils.closeSilently(is);
|
||||
return true;
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
Log.e("BitmapRegionTileSource", "Failure while reading URI " + mUri, e);
|
||||
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +226,10 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||
@Override
|
||||
public BitmapRegionDecoder loadBitmapRegionDecoder() {
|
||||
try {
|
||||
return BitmapRegionDecoder.newInstance(regenerateInputStream(), true);
|
||||
InputStream is = regenerateInputStream();
|
||||
BitmapRegionDecoder regionDecoder = BitmapRegionDecoder.newInstance(is, true);
|
||||
Utils.closeSilently(is);
|
||||
return regionDecoder;
|
||||
} catch (IOException e) {
|
||||
Log.e("BitmapRegionTileSource", "Error reading resource", e);
|
||||
return null;
|
||||
|
@ -217,7 +242,9 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||
@Override
|
||||
public boolean readExif(ExifInterface ei) {
|
||||
try {
|
||||
ei.readExif(regenerateInputStream());
|
||||
InputStream is = regenerateInputStream();
|
||||
ei.readExif(is);
|
||||
Utils.closeSilently(is);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e("BitmapRegionTileSource", "Error reading resource", e);
|
||||
|
@ -243,27 +270,29 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||
mTileSize = TiledImageRenderer.suggestedTileSize(context);
|
||||
mRotation = source.getRotation();
|
||||
mDecoder = source.getBitmapRegionDecoder();
|
||||
mWidth = mDecoder.getWidth();
|
||||
mHeight = mDecoder.getHeight();
|
||||
mOptions = new BitmapFactory.Options();
|
||||
mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
|
||||
mOptions.inPreferQualityOverSpeed = true;
|
||||
mOptions.inTempStorage = new byte[16 * 1024];
|
||||
int previewSize = source.getPreviewSize();
|
||||
if (previewSize != 0) {
|
||||
previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
|
||||
// Although this is the same size as the Bitmap that is likely already
|
||||
// loaded, the lifecycle is different and interactions are on a different
|
||||
// thread. Thus to simplify, this source will decode its own bitmap.
|
||||
Bitmap preview = decodePreview(source, previewSize);
|
||||
if (preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) {
|
||||
mPreview = new BitmapTexture(preview);
|
||||
} else {
|
||||
Log.w(TAG, String.format(
|
||||
"Failed to create preview of apropriate size! "
|
||||
+ " in: %dx%d, out: %dx%d",
|
||||
mWidth, mHeight,
|
||||
preview.getWidth(), preview.getHeight()));
|
||||
if (mDecoder != null) {
|
||||
mWidth = mDecoder.getWidth();
|
||||
mHeight = mDecoder.getHeight();
|
||||
mOptions = new BitmapFactory.Options();
|
||||
mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
|
||||
mOptions.inPreferQualityOverSpeed = true;
|
||||
mOptions.inTempStorage = new byte[16 * 1024];
|
||||
int previewSize = source.getPreviewSize();
|
||||
if (previewSize != 0) {
|
||||
previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
|
||||
// Although this is the same size as the Bitmap that is likely already
|
||||
// loaded, the lifecycle is different and interactions are on a different
|
||||
// thread. Thus to simplify, this source will decode its own bitmap.
|
||||
Bitmap preview = decodePreview(source, previewSize);
|
||||
if (preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) {
|
||||
mPreview = new BitmapTexture(preview);
|
||||
} else {
|
||||
Log.w(TAG, String.format(
|
||||
"Failed to create preview of apropriate size! "
|
||||
+ " in: %dx%d, out: %dx%d",
|
||||
mWidth, mHeight,
|
||||
preview.getWidth(), preview.getHeight()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue