Merge "Make wallpaper cropper more robust " into klp-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0a1988b647
@ -17,4 +17,9 @@
|
|||||||
<string name="crop_wallpaper">Crop wallpaper</string>
|
<string name="crop_wallpaper">Crop wallpaper</string>
|
||||||
<!-- Button label on Wallpaper picker screen; user selects this button to set a specific wallpaper -->
|
<!-- Button label on Wallpaper picker screen; user selects this button to set a specific wallpaper -->
|
||||||
<string name="wallpaper_instructions">Set wallpaper</string>
|
<string name="wallpaper_instructions">Set wallpaper</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>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -31,6 +31,7 @@ import android.os.Build.VERSION_CODES;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.gallery3d.common.BitmapUtils;
|
import com.android.gallery3d.common.BitmapUtils;
|
||||||
|
import com.android.gallery3d.common.Utils;
|
||||||
import com.android.gallery3d.exif.ExifInterface;
|
import com.android.gallery3d.exif.ExifInterface;
|
||||||
import com.android.gallery3d.glrenderer.BasicTexture;
|
import com.android.gallery3d.glrenderer.BasicTexture;
|
||||||
import com.android.gallery3d.glrenderer.BitmapTexture;
|
import com.android.gallery3d.glrenderer.BitmapTexture;
|
||||||
@ -41,6 +42,85 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
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[] streamCopy;
|
||||||
|
Bitmap mBuffer;
|
||||||
|
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) {
|
||||||
|
System.out.println("DECODING WITH SAMPLE LEVEL OF " + options.inSampleSize);
|
||||||
|
return Bitmap.createBitmap(
|
||||||
|
mBuffer, wantRegion.left, wantRegion.top, wantRegion.width(), wantRegion.height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link com.android.photos.views.TiledImageRenderer.TileSource} using
|
* A {@link com.android.photos.views.TiledImageRenderer.TileSource} using
|
||||||
* {@link BitmapRegionDecoder} to wrap a local file
|
* {@link BitmapRegionDecoder} to wrap a local file
|
||||||
@ -58,14 +138,16 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
|
public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
|
||||||
|
|
||||||
public static abstract class BitmapSource {
|
public static abstract class BitmapSource {
|
||||||
private BitmapRegionDecoder mDecoder;
|
private SimpleBitmapRegionDecoder mDecoder;
|
||||||
private Bitmap mPreview;
|
private Bitmap mPreview;
|
||||||
private int mPreviewSize;
|
private int mPreviewSize;
|
||||||
private int mRotation;
|
private int mRotation;
|
||||||
|
public enum State { NOT_LOADED, LOADED, ERROR_LOADING };
|
||||||
|
private State mState = State.NOT_LOADED;
|
||||||
public BitmapSource(int previewSize) {
|
public BitmapSource(int previewSize) {
|
||||||
mPreviewSize = previewSize;
|
mPreviewSize = previewSize;
|
||||||
}
|
}
|
||||||
public void loadInBackground() {
|
public boolean loadInBackground() {
|
||||||
ExifInterface ei = new ExifInterface();
|
ExifInterface ei = new ExifInterface();
|
||||||
if (readExif(ei)) {
|
if (readExif(ei)) {
|
||||||
Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
|
Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
|
||||||
@ -74,6 +156,10 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mDecoder = loadBitmapRegionDecoder();
|
mDecoder = loadBitmapRegionDecoder();
|
||||||
|
if (mDecoder == null) {
|
||||||
|
mState = State.ERROR_LOADING;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
int width = mDecoder.getWidth();
|
int width = mDecoder.getWidth();
|
||||||
int height = mDecoder.getHeight();
|
int height = mDecoder.getHeight();
|
||||||
if (mPreviewSize != 0) {
|
if (mPreviewSize != 0) {
|
||||||
@ -87,9 +173,16 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
opts.inJustDecodeBounds = false;
|
opts.inJustDecodeBounds = false;
|
||||||
mPreview = loadPreviewBitmap(opts);
|
mPreview = loadPreviewBitmap(opts);
|
||||||
}
|
}
|
||||||
|
mState = State.LOADED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BitmapRegionDecoder getBitmapRegionDecoder() {
|
public State getLoadingState() {
|
||||||
|
return mState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleBitmapRegionDecoder getBitmapRegionDecoder() {
|
||||||
return mDecoder;
|
return mDecoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +199,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean readExif(ExifInterface ei);
|
public abstract boolean readExif(ExifInterface ei);
|
||||||
public abstract BitmapRegionDecoder loadBitmapRegionDecoder();
|
public abstract SimpleBitmapRegionDecoder loadBitmapRegionDecoder();
|
||||||
public abstract Bitmap loadPreviewBitmap(BitmapFactory.Options options);
|
public abstract Bitmap loadPreviewBitmap(BitmapFactory.Options options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,13 +210,13 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
mPath = path;
|
mPath = path;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public BitmapRegionDecoder loadBitmapRegionDecoder() {
|
public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
|
||||||
try {
|
SimpleBitmapRegionDecoder d;
|
||||||
return BitmapRegionDecoder.newInstance(mPath, true);
|
d = SimpleBitmapRegionDecoderWrapper.newInstance(mPath, true);
|
||||||
} catch (IOException e) {
|
if (d == null) {
|
||||||
Log.w("BitmapRegionTileSource", "getting decoder failed", e);
|
d = DumbBitmapRegionDecoder.newInstance(mPath);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
|
public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
|
||||||
@ -154,9 +247,17 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
return new BufferedInputStream(is);
|
return new BufferedInputStream(is);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public BitmapRegionDecoder loadBitmapRegionDecoder() {
|
public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
|
||||||
try {
|
try {
|
||||||
return BitmapRegionDecoder.newInstance(regenerateInputStream(), true);
|
InputStream is = regenerateInputStream();
|
||||||
|
SimpleBitmapRegionDecoder regionDecoder =
|
||||||
|
SimpleBitmapRegionDecoderWrapper.newInstance(is, false);
|
||||||
|
Utils.closeSilently(is);
|
||||||
|
if (regionDecoder == null) {
|
||||||
|
is = regenerateInputStream();
|
||||||
|
regionDecoder = DumbBitmapRegionDecoder.newInstance(is);
|
||||||
|
}
|
||||||
|
return regionDecoder;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
||||||
return null;
|
return null;
|
||||||
@ -168,7 +269,10 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
@Override
|
@Override
|
||||||
public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
|
public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
|
||||||
try {
|
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) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
||||||
return null;
|
return null;
|
||||||
@ -177,13 +281,15 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
@Override
|
@Override
|
||||||
public boolean readExif(ExifInterface ei) {
|
public boolean readExif(ExifInterface ei) {
|
||||||
try {
|
try {
|
||||||
ei.readExif(regenerateInputStream());
|
InputStream is = regenerateInputStream();
|
||||||
|
ei.readExif(is);
|
||||||
|
Utils.closeSilently(is);
|
||||||
return true;
|
return true;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
||||||
return false;
|
return false;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("BitmapRegionTileSource", "Failure while reading URI " + mUri, e);
|
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,13 +308,16 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
return new BufferedInputStream(is);
|
return new BufferedInputStream(is);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public BitmapRegionDecoder loadBitmapRegionDecoder() {
|
public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
|
||||||
try {
|
InputStream is = regenerateInputStream();
|
||||||
return BitmapRegionDecoder.newInstance(regenerateInputStream(), true);
|
SimpleBitmapRegionDecoder regionDecoder =
|
||||||
} catch (IOException e) {
|
SimpleBitmapRegionDecoderWrapper.newInstance(is, false);
|
||||||
Log.e("BitmapRegionTileSource", "Error reading resource", e);
|
Utils.closeSilently(is);
|
||||||
return null;
|
if (regionDecoder == null) {
|
||||||
|
is = regenerateInputStream();
|
||||||
|
regionDecoder = DumbBitmapRegionDecoder.newInstance(is);
|
||||||
}
|
}
|
||||||
|
return regionDecoder;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
|
public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
|
||||||
@ -217,7 +326,9 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
@Override
|
@Override
|
||||||
public boolean readExif(ExifInterface ei) {
|
public boolean readExif(ExifInterface ei) {
|
||||||
try {
|
try {
|
||||||
ei.readExif(regenerateInputStream());
|
InputStream is = regenerateInputStream();
|
||||||
|
ei.readExif(is);
|
||||||
|
Utils.closeSilently(is);
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("BitmapRegionTileSource", "Error reading resource", e);
|
Log.e("BitmapRegionTileSource", "Error reading resource", e);
|
||||||
@ -226,7 +337,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BitmapRegionDecoder mDecoder;
|
SimpleBitmapRegionDecoder mDecoder;
|
||||||
int mWidth;
|
int mWidth;
|
||||||
int mHeight;
|
int mHeight;
|
||||||
int mTileSize;
|
int mTileSize;
|
||||||
@ -243,6 +354,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
mTileSize = TiledImageRenderer.suggestedTileSize(context);
|
mTileSize = TiledImageRenderer.suggestedTileSize(context);
|
||||||
mRotation = source.getRotation();
|
mRotation = source.getRotation();
|
||||||
mDecoder = source.getBitmapRegionDecoder();
|
mDecoder = source.getBitmapRegionDecoder();
|
||||||
|
if (mDecoder != null) {
|
||||||
mWidth = mDecoder.getWidth();
|
mWidth = mDecoder.getWidth();
|
||||||
mHeight = mDecoder.getHeight();
|
mHeight = mDecoder.getHeight();
|
||||||
mOptions = new BitmapFactory.Options();
|
mOptions = new BitmapFactory.Options();
|
||||||
@ -267,6 +379,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTileSize() {
|
public int getTileSize() {
|
||||||
|
@ -41,10 +41,12 @@ import android.util.Log;
|
|||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.gallery3d.common.Utils;
|
import com.android.gallery3d.common.Utils;
|
||||||
import com.android.gallery3d.exif.ExifInterface;
|
import com.android.gallery3d.exif.ExifInterface;
|
||||||
import com.android.photos.BitmapRegionTileSource;
|
import com.android.photos.BitmapRegionTileSource;
|
||||||
|
import com.android.photos.BitmapRegionTileSource.BitmapSource;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@ -109,12 +111,24 @@ public class WallpaperCropActivity extends Activity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Load image in background
|
// Load image in background
|
||||||
setCropViewTileSource(
|
final BitmapRegionTileSource.UriBitmapSource bitmapSource =
|
||||||
new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024), true, false);
|
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,
|
public void setCropViewTileSource(
|
||||||
final boolean touchEnabled, final boolean moveToLeft) {
|
final BitmapRegionTileSource.BitmapSource bitmapSource, final boolean touchEnabled,
|
||||||
|
final boolean moveToLeft, final Runnable postExecute) {
|
||||||
final Context context = WallpaperCropActivity.this;
|
final Context context = WallpaperCropActivity.this;
|
||||||
final View progressView = findViewById(R.id.loading);
|
final View progressView = findViewById(R.id.loading);
|
||||||
final AsyncTask<Void, Void, Void> loadBitmapTask = new AsyncTask<Void, Void, Void>() {
|
final AsyncTask<Void, Void, Void> loadBitmapTask = new AsyncTask<Void, Void, Void>() {
|
||||||
@ -127,6 +141,7 @@ public class WallpaperCropActivity extends Activity {
|
|||||||
protected void onPostExecute(Void arg) {
|
protected void onPostExecute(Void arg) {
|
||||||
if (!isCancelled()) {
|
if (!isCancelled()) {
|
||||||
progressView.setVisibility(View.INVISIBLE);
|
progressView.setVisibility(View.INVISIBLE);
|
||||||
|
if (bitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
|
||||||
mCropView.setTileSource(
|
mCropView.setTileSource(
|
||||||
new BitmapRegionTileSource(context, bitmapSource), null);
|
new BitmapRegionTileSource(context, bitmapSource), null);
|
||||||
mCropView.setTouchEnabled(touchEnabled);
|
mCropView.setTouchEnabled(touchEnabled);
|
||||||
@ -135,6 +150,10 @@ public class WallpaperCropActivity extends Activity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (postExecute != null) {
|
||||||
|
postExecute.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// We don't want to show the spinner every time we load an image, because that would be
|
// We don't want to show the spinner every time we load an image, because that would be
|
||||||
// annoying; instead, only start showing the spinner if loading the image has taken
|
// annoying; instead, only start showing the spinner if loading the image has taken
|
||||||
@ -235,10 +254,12 @@ public class WallpaperCropActivity extends Activity {
|
|||||||
InputStream is = context.getContentResolver().openInputStream(uri);
|
InputStream is = context.getContentResolver().openInputStream(uri);
|
||||||
BufferedInputStream bis = new BufferedInputStream(is);
|
BufferedInputStream bis = new BufferedInputStream(is);
|
||||||
ei.readExif(bis);
|
ei.readExif(bis);
|
||||||
|
bis.close();
|
||||||
} else {
|
} else {
|
||||||
InputStream is = res.openRawResource(resId);
|
InputStream is = res.openRawResource(resId);
|
||||||
BufferedInputStream bis = new BufferedInputStream(is);
|
BufferedInputStream bis = new BufferedInputStream(is);
|
||||||
ei.readExif(bis);
|
ei.readExif(bis);
|
||||||
|
bis.close();
|
||||||
}
|
}
|
||||||
Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
|
Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
|
||||||
if (ori != null) {
|
if (ori != null) {
|
||||||
@ -408,7 +429,6 @@ public class WallpaperCropActivity extends Activity {
|
|||||||
String mInFilePath;
|
String mInFilePath;
|
||||||
byte[] mInImageBytes;
|
byte[] mInImageBytes;
|
||||||
int mInResId = 0;
|
int mInResId = 0;
|
||||||
InputStream mInStream;
|
|
||||||
RectF mCropBounds = null;
|
RectF mCropBounds = null;
|
||||||
int mOutWidth, mOutHeight;
|
int mOutWidth, mOutHeight;
|
||||||
int mRotation;
|
int mRotation;
|
||||||
@ -481,37 +501,36 @@ public class WallpaperCropActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper to setup input stream
|
// Helper to setup input stream
|
||||||
private void regenerateInputStream() {
|
private InputStream regenerateInputStream() {
|
||||||
if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null) {
|
if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null) {
|
||||||
Log.w(LOGTAG, "cannot read original file, no input URI, resource ID, or " +
|
Log.w(LOGTAG, "cannot read original file, no input URI, resource ID, or " +
|
||||||
"image byte array given");
|
"image byte array given");
|
||||||
} else {
|
} else {
|
||||||
Utils.closeSilently(mInStream);
|
|
||||||
try {
|
try {
|
||||||
if (mInUri != null) {
|
if (mInUri != null) {
|
||||||
mInStream = new BufferedInputStream(
|
return new BufferedInputStream(
|
||||||
mContext.getContentResolver().openInputStream(mInUri));
|
mContext.getContentResolver().openInputStream(mInUri));
|
||||||
} else if (mInFilePath != null) {
|
} else if (mInFilePath != null) {
|
||||||
mInStream = mContext.openFileInput(mInFilePath);
|
return mContext.openFileInput(mInFilePath);
|
||||||
} else if (mInImageBytes != null) {
|
} else if (mInImageBytes != null) {
|
||||||
mInStream = new BufferedInputStream(
|
return new BufferedInputStream(new ByteArrayInputStream(mInImageBytes));
|
||||||
new ByteArrayInputStream(mInImageBytes));
|
|
||||||
} else {
|
} else {
|
||||||
mInStream = new BufferedInputStream(
|
return new BufferedInputStream(mResources.openRawResource(mInResId));
|
||||||
mResources.openRawResource(mInResId));
|
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e);
|
Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Point getImageBounds() {
|
public Point getImageBounds() {
|
||||||
regenerateInputStream();
|
InputStream is = regenerateInputStream();
|
||||||
if (mInStream != null) {
|
if (is != null) {
|
||||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
options.inJustDecodeBounds = true;
|
options.inJustDecodeBounds = true;
|
||||||
BitmapFactory.decodeStream(mInStream, null, options);
|
BitmapFactory.decodeStream(is, null, options);
|
||||||
|
Utils.closeSilently(is);
|
||||||
if (options.outWidth != 0 && options.outHeight != 0) {
|
if (options.outWidth != 0 && options.outHeight != 0) {
|
||||||
return new Point(options.outWidth, options.outHeight);
|
return new Point(options.outWidth, options.outHeight);
|
||||||
}
|
}
|
||||||
@ -529,22 +548,26 @@ public class WallpaperCropActivity extends Activity {
|
|||||||
public boolean cropBitmap() {
|
public boolean cropBitmap() {
|
||||||
boolean failure = false;
|
boolean failure = false;
|
||||||
|
|
||||||
regenerateInputStream();
|
|
||||||
|
|
||||||
WallpaperManager wallpaperManager = null;
|
WallpaperManager wallpaperManager = null;
|
||||||
if (mSetWallpaper) {
|
if (mSetWallpaper) {
|
||||||
wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
|
wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
|
||||||
}
|
}
|
||||||
if (mSetWallpaper && mNoCrop && mInStream != null) {
|
|
||||||
|
|
||||||
|
if (mSetWallpaper && mNoCrop) {
|
||||||
try {
|
try {
|
||||||
wallpaperManager.setStream(mInStream);
|
InputStream is = regenerateInputStream();
|
||||||
|
if (is != null) {
|
||||||
|
wallpaperManager.setStream(is);
|
||||||
|
Utils.closeSilently(is);
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(LOGTAG, "cannot write stream to wallpaper", e);
|
Log.w(LOGTAG, "cannot write stream to wallpaper", e);
|
||||||
failure = true;
|
failure = true;
|
||||||
}
|
}
|
||||||
return !failure;
|
return !failure;
|
||||||
}
|
} else {
|
||||||
if (mInStream != null) {
|
|
||||||
// Find crop bounds (scaled to original image size)
|
// Find crop bounds (scaled to original image size)
|
||||||
Rect roundedTrueCrop = new Rect();
|
Rect roundedTrueCrop = new Rect();
|
||||||
Matrix rotateMatrix = new Matrix();
|
Matrix rotateMatrix = new Matrix();
|
||||||
@ -557,6 +580,11 @@ public class WallpaperCropActivity extends Activity {
|
|||||||
mCropBounds = new RectF(roundedTrueCrop);
|
mCropBounds = new RectF(roundedTrueCrop);
|
||||||
|
|
||||||
Point bounds = getImageBounds();
|
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 };
|
float[] rotatedBounds = new float[] { bounds.x, bounds.y };
|
||||||
rotateMatrix.mapPoints(rotatedBounds);
|
rotateMatrix.mapPoints(rotatedBounds);
|
||||||
@ -567,7 +595,6 @@ public class WallpaperCropActivity extends Activity {
|
|||||||
inverseRotateMatrix.mapRect(mCropBounds);
|
inverseRotateMatrix.mapRect(mCropBounds);
|
||||||
mCropBounds.offset(bounds.x/2, bounds.y/2);
|
mCropBounds.offset(bounds.x/2, bounds.y/2);
|
||||||
|
|
||||||
regenerateInputStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mCropBounds.roundOut(roundedTrueCrop);
|
mCropBounds.roundOut(roundedTrueCrop);
|
||||||
@ -585,7 +612,14 @@ public class WallpaperCropActivity extends Activity {
|
|||||||
// Attempt to open a region decoder
|
// Attempt to open a region decoder
|
||||||
BitmapRegionDecoder decoder = null;
|
BitmapRegionDecoder decoder = null;
|
||||||
try {
|
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) {
|
} catch (IOException e) {
|
||||||
Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), 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) {
|
if (crop == null) {
|
||||||
// BitmapRegionDecoder has failed, try to crop in-memory
|
// BitmapRegionDecoder has failed, try to crop in-memory
|
||||||
regenerateInputStream();
|
InputStream is = regenerateInputStream();
|
||||||
Bitmap fullSize = null;
|
Bitmap fullSize = null;
|
||||||
if (mInStream != null) {
|
if (is != null) {
|
||||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
if (scaleDownSampleSize > 1) {
|
if (scaleDownSampleSize > 1) {
|
||||||
options.inSampleSize = scaleDownSampleSize;
|
options.inSampleSize = scaleDownSampleSize;
|
||||||
}
|
}
|
||||||
fullSize = BitmapFactory.decodeStream(mInStream, null, options);
|
fullSize = BitmapFactory.decodeStream(is, null, options);
|
||||||
|
Utils.closeSilently(is);
|
||||||
}
|
}
|
||||||
if (fullSize != null) {
|
if (fullSize != null) {
|
||||||
mCropBounds.left /= scaleDownSampleSize;
|
mCropBounds.left /= scaleDownSampleSize;
|
||||||
|
Reference in New Issue
Block a user