Passing the full image and crop hint when setting the wallpaper
Bug: 25454157
Change-Id: Ia0ae7dd4963b72cd7902622847deedfcb5a0eca2
diff --git a/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java b/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
index 027e947..153fa90 100644
--- a/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
+++ b/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
@@ -47,7 +47,7 @@
public class BitmapCropTask extends AsyncTask<Integer, Void, Boolean> {
public interface OnBitmapCroppedHandler {
- public void onBitmapCropped(byte[] imageBytes);
+ public void onBitmapCropped(byte[] imageBytes, Rect cropHint);
}
public interface OnEndCropHandler {
@@ -171,29 +171,42 @@
public boolean cropBitmap(int whichWallpaper) {
boolean failure = false;
-
- WallpaperManager wallpaperManager = null;
- if (mSetWallpaper) {
- wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
- }
-
-
if (mSetWallpaper && mNoCrop) {
try {
InputStream is = regenerateInputStream();
- if (is != null) {
- if (!Utilities.isNycOrAbove()) {
- wallpaperManager.setStream(is);
- } else {
- NycWallpaperUtils.setStream(mContext, is, null, true, whichWallpaper);
- }
- Utils.closeSilently(is);
- }
+ setWallpaper(is, null, whichWallpaper);
+ Utils.closeSilently(is);
} catch (IOException e) {
Log.w(LOGTAG, "cannot write stream to wallpaper", e);
failure = true;
}
return !failure;
+ } else if (mSetWallpaper && Utilities.isNycOrAbove()
+ && mRotation == 0 && mOutWidth > 0 && mOutHeight > 0) {
+ Rect hint = new Rect();
+ mCropBounds.roundOut(hint);
+
+ InputStream is = null;
+ try {
+ is = regenerateInputStream();
+ if (is == null) {
+ Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString());
+ failure = true;
+ return false;
+ }
+ WallpaperManager.getInstance(mContext).suggestDesiredDimensions(mOutWidth, mOutHeight);
+ setWallpaper(is, hint, whichWallpaper);
+
+ if (mOnBitmapCroppedHandler != null) {
+ mOnBitmapCroppedHandler.onBitmapCropped(null, hint);
+ }
+
+ failure = false;
+ } catch (IOException e) {
+ Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
+ } finally {
+ Utils.closeSilently(is);
+ }
} else {
// Find crop bounds (scaled to original image size)
Rect roundedTrueCrop = new Rect();
@@ -222,7 +235,6 @@
mCropBounds.offset(-rotatedBounds[0]/2, -rotatedBounds[1]/2);
inverseRotateMatrix.mapRect(mCropBounds);
mCropBounds.offset(bounds.x/2, bounds.y/2);
-
}
mCropBounds.roundOut(roundedTrueCrop);
@@ -369,18 +381,13 @@
ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
if (crop.compress(CompressFormat.JPEG, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
// If we need to set to the wallpaper, set it
- if (mSetWallpaper && wallpaperManager != null) {
+ if (mSetWallpaper) {
try {
byte[] outByteArray = tmpOut.toByteArray();
- if (!Utilities.isNycOrAbove()) {
- wallpaperManager.setStream(new ByteArrayInputStream(outByteArray));
- } else {
- NycWallpaperUtils.setStream(mContext,
- new ByteArrayInputStream(outByteArray), null, true,
- whichWallpaper);
- }
+ setWallpaper(new ByteArrayInputStream(outByteArray), null, whichWallpaper);
if (mOnBitmapCroppedHandler != null) {
- mOnBitmapCroppedHandler.onBitmapCropped(outByteArray);
+ mOnBitmapCroppedHandler.onBitmapCropped(outByteArray,
+ new Rect(0, 0, crop.getWidth(), crop.getHeight()));
}
} catch (IOException e) {
Log.w(LOGTAG, "cannot write stream to wallpaper", e);
@@ -409,4 +416,12 @@
mOnEndCropHandler.run(cropSucceeded);
}
}
+
+ private void setWallpaper(InputStream in, Rect crop, int whichWallpaper) throws IOException {
+ if (!Utilities.isNycOrAbove()) {
+ WallpaperManager.getInstance(mContext.getApplicationContext()).setStream(in);
+ } else {
+ NycWallpaperUtils.setStream(mContext, in, crop, true, whichWallpaper);
+ }
+ }
}
\ No newline at end of file
diff --git a/WallpaperPicker/src/com/android/launcher3/CropView.java b/WallpaperPicker/src/com/android/launcher3/CropView.java
index e98e23e..c1578c1 100644
--- a/WallpaperPicker/src/com/android/launcher3/CropView.java
+++ b/WallpaperPicker/src/com/android/launcher3/CropView.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Point;
+import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -148,12 +149,19 @@
updateMinScale(w, h, mRenderer.source, false);
}
- public void setScale(float scale) {
+ public void setScaleAndCenter(float scale, float x, float y) {
synchronized (mLock) {
mRenderer.scale = scale;
+ mCenterX = x;
+ mCenterY = y;
+ updateCenter();
}
}
+ public float getScale() {
+ return mRenderer.scale;
+ }
+
private void updateMinScale(int w, int h, TileSource source, boolean resetScale) {
synchronized (mLock) {
if (resetScale) {
@@ -189,17 +197,6 @@
public void onScaleEnd(ScaleGestureDetector detector) {
}
- /**
- * Offsets wallpaper preview according to the state it will be displayed in upon returning home.
- * @param offset Ranges from 0 to 1, where 0 is the leftmost parallax and 1 is the rightmost.
- */
- public void setParallaxOffset(float offset, RectF crop) {
- offset = Math.max(0, Math.min(offset, 1)); // Make sure the offset is in the correct range.
- float screenWidth = getWidth() / mRenderer.scale;
- mCenterX = screenWidth / 2 + offset * (crop.width() - screenWidth) + crop.left;
- updateCenter();
- }
-
public void moveToLeft() {
if (getWidth() == 0 || getHeight() == 0) {
final ViewTreeObserver observer = getViewTreeObserver();
@@ -222,6 +219,10 @@
mRenderer.centerY = Math.round(mCenterY);
}
+ public PointF getCenter() {
+ return new PointF(mCenterX, mCenterY);
+ }
+
public void setTouchEnabled(boolean enabled) {
mTouchEnabled = enabled;
}
diff --git a/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
index 64b0ac4..34226f7 100644
--- a/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
+++ b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
@@ -25,6 +25,8 @@
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
@@ -33,9 +35,14 @@
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
+import com.android.launcher3.WallpaperCropActivity.CropViewScaleAndOffsetProvider;
+import com.android.photos.views.TiledImageRenderer.TileSource;
+
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
@@ -48,15 +55,42 @@
public static class SavedWallpaperTile extends WallpaperPickerActivity.FileWallpaperInfo {
private int mDbId;
- public SavedWallpaperTile(int dbId, File target, Drawable thumb) {
+
+ // three floats representing scale, centerX and centerY of the crop view in order.
+ private Float[] mExtras;
+ public SavedWallpaperTile(int dbId, File target, Drawable thumb, Float[] extras) {
super(target, thumb);
mDbId = dbId;
+ mExtras = extras != null && extras.length == 3 ? extras : null;
}
@Override
public void onDelete(WallpaperPickerActivity a) {
a.getSavedImages().deleteImage(mDbId);
}
+
+ @Override
+ protected CropViewScaleAndOffsetProvider getCropViewScaleAndOffsetProvider() {
+ if (mExtras != null) {
+ return new CropViewScaleAndOffsetProvider() {
+ @Override
+ public void updateCropView(WallpaperCropActivity a, TileSource src) {
+ a.mCropView.setScaleAndCenter(mExtras[0], mExtras[1], mExtras[2]);
+ }
+ };
+ }
+ return null;
+ }
+
+ @Override
+ public void onSave(final WallpaperPickerActivity a) {
+ if (mExtras == null) {
+ super.onSave(a);
+ } else {
+ boolean shouldFadeOutOnFinish = a.getWallpaperParallaxOffset() == 0f;
+ a.cropImageAndSetWallpaper(Uri.fromFile(mFile), null, true, shouldFadeOutOnFinish);
+ }
+ }
}
public SavedWallpaperImages(Context context) {
@@ -74,7 +108,8 @@
Cursor result = db.query(ImageDb.TABLE_NAME,
new String[] { ImageDb.COLUMN_ID,
ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME,
- ImageDb.COLUMN_IMAGE_FILENAME}, // cols to return
+ ImageDb.COLUMN_IMAGE_FILENAME,
+ ImageDb.COLUMN_EXTRAS}, // cols to return
null, // select query
null, // args to select query
null,
@@ -88,9 +123,25 @@
Bitmap thumb = BitmapFactory.decodeFile(file.getAbsolutePath());
if (thumb != null) {
+
+ Float[] extras = null;
+ String extraStr = result.getString(3);
+ if (extraStr != null) {
+ String[] parts = extraStr.split(",");
+ extras = new Float[parts.length];
+ for (int i = 0; i < parts.length; i++) {
+ try {
+ extras[i] = Float.parseFloat(parts[i]);
+ } catch (Exception e) {
+ extras = null;
+ break;
+ }
+ }
+ }
+
mImages.add(new SavedWallpaperTile(result.getInt(0),
new File(mContext.getFilesDir(), result.getString(2)),
- new BitmapDrawable(thumb)));
+ new BitmapDrawable(thumb), extras));
}
}
result.close();
@@ -155,34 +206,55 @@
public void writeImage(Bitmap thumbnail, byte[] imageBytes) {
try {
- File imageFile = File.createTempFile("wallpaper", "", mContext.getFilesDir());
- FileOutputStream imageFileStream =
- mContext.openFileOutput(imageFile.getName(), Context.MODE_PRIVATE);
- imageFileStream.write(imageBytes);
- imageFileStream.close();
-
- File thumbFile = File.createTempFile("wallpaperthumb", "", mContext.getFilesDir());
- FileOutputStream thumbFileStream =
- mContext.openFileOutput(thumbFile.getName(), Context.MODE_PRIVATE);
- thumbnail.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
- thumbFileStream.close();
-
- SQLiteDatabase db = mDb.getWritableDatabase();
- ContentValues values = new ContentValues();
- values.put(ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME, thumbFile.getName());
- values.put(ImageDb.COLUMN_IMAGE_FILENAME, imageFile.getName());
- db.insert(ImageDb.TABLE_NAME, null, values);
+ writeImage(thumbnail, new ByteArrayInputStream(imageBytes), null);
} catch (IOException e) {
Log.e(TAG, "Failed writing images to storage " + e);
}
}
+ public void writeImage(Bitmap thumbnail, Uri uri, Float[] extras) {
+ try {
+ writeImage(thumbnail, mContext.getContentResolver().openInputStream(uri), extras);
+ } catch (IOException e) {
+ Log.e(TAG, "Failed writing images to storage " + e);
+ }
+ }
+
+ private void writeImage(Bitmap thumbnail, InputStream in, Float[] extras) throws IOException {
+ File imageFile = File.createTempFile("wallpaper", "", mContext.getFilesDir());
+ FileOutputStream imageFileStream =
+ mContext.openFileOutput(imageFile.getName(), Context.MODE_PRIVATE);
+ byte[] buf = new byte[4096]; // 4k
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ imageFileStream.write(buf, 0, len);
+ }
+ imageFileStream.close();
+ in.close();
+
+ File thumbFile = File.createTempFile("wallpaperthumb", "", mContext.getFilesDir());
+ FileOutputStream thumbFileStream =
+ mContext.openFileOutput(thumbFile.getName(), Context.MODE_PRIVATE);
+ thumbnail.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
+ thumbFileStream.close();
+
+ SQLiteDatabase db = mDb.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME, thumbFile.getName());
+ values.put(ImageDb.COLUMN_IMAGE_FILENAME, imageFile.getName());
+ if (extras != null) {
+ values.put(ImageDb.COLUMN_EXTRAS, TextUtils.join(",", extras));
+ }
+ db.insert(ImageDb.TABLE_NAME, null, values);
+ }
+
static class ImageDb extends SQLiteOpenHelper {
- final static int DB_VERSION = 1;
+ final static int DB_VERSION = 2;
final static String TABLE_NAME = "saved_wallpaper_images";
final static String COLUMN_ID = "id";
final static String COLUMN_IMAGE_THUMBNAIL_FILENAME = "image_thumbnail";
final static String COLUMN_IMAGE_FILENAME = "image";
+ final static String COLUMN_EXTRAS = "extras";
Context mContext;
@@ -209,15 +281,20 @@
COLUMN_ID + " INTEGER NOT NULL, " +
COLUMN_IMAGE_THUMBNAIL_FILENAME + " TEXT NOT NULL, " +
COLUMN_IMAGE_FILENAME + " TEXT NOT NULL, " +
+ COLUMN_EXTRAS + " TEXT, " +
"PRIMARY KEY (" + COLUMN_ID + " ASC) " +
");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (oldVersion != newVersion) {
+ if (oldVersion == 1) {
+ // Add extras column
+ db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + COLUMN_EXTRAS + " TEXT;");
+ } else if (oldVersion != newVersion) {
// Delete all the records; they'll be repopulated as this is a cache
db.execSQL("DELETE FROM " + TABLE_NAME);
+ onCreate(db);
}
}
}
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index 2f21145..f6c53ec 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -29,6 +29,7 @@
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Point;
+import android.graphics.PointF;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Build;
@@ -269,13 +270,7 @@
mCropView.moveToLeft();
}
if (req.scaleAndOffsetProvider != null) {
- TileSource src = req.result;
- Point wallpaperSize = WallpaperUtils.getDefaultWallpaperSize(
- getResources(), getWindowManager());
- RectF crop = Utils.getMaxCropRect(src.getImageWidth(), src.getImageHeight(),
- wallpaperSize.x, wallpaperSize.y, false /* leftAligned */);
- mCropView.setScale(req.scaleAndOffsetProvider.getScale(wallpaperSize, crop));
- mCropView.setParallaxOffset(req.scaleAndOffsetProvider.getParallaxOffset(), crop);
+ req.scaleAndOffsetProvider.updateCropView(this, req.result);
}
// Free last image
@@ -502,8 +497,32 @@
TileSource result;
}
- interface CropViewScaleAndOffsetProvider {
- float getScale(Point wallpaperSize, RectF crop);
- float getParallaxOffset();
+ public static class CropViewScaleAndOffsetProvider {
+ public float getScale(Point wallpaperSize, RectF crop) {
+ return 1f;
+ }
+
+ public float getParallaxOffset() {
+ return 0.5f;
+ }
+
+ public void updateCropView(WallpaperCropActivity a, TileSource src) {
+ Point wallpaperSize = WallpaperUtils.getDefaultWallpaperSize(
+ a.getResources(), a.getWindowManager());
+ RectF crop = Utils.getMaxCropRect(src.getImageWidth(), src.getImageHeight(),
+ wallpaperSize.x, wallpaperSize.y, false /* leftAligned */);
+
+ float scale = getScale(wallpaperSize, crop);
+ PointF center = a.mCropView.getCenter();
+
+ // Offsets wallpaper preview according to the state it will be displayed in upon
+ // returning home. Offset ranges from 0 to 1, where 0 is the leftmost parallax and
+ // 1 is the rightmost.
+ // Make sure the offset is in the correct range.
+ float offset = Math.max(0, Math.min(getParallaxOffset(), 1));
+ float screenWidth = a.mCropView.getWidth() / scale;
+ center.x = screenWidth / 2 + offset * (crop.width() - screenWidth) + crop.left;
+ a.mCropView.setScaleAndCenter(scale, center.x, center.y);
+ }
}
}
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index 5c6113f..40f0544 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -31,10 +31,13 @@
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
+import android.graphics.PointF;
import android.graphics.PorterDuff;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -83,6 +86,7 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
public class WallpaperPickerActivity extends WallpaperCropActivity {
@@ -174,12 +178,45 @@
public void onSave(final WallpaperPickerActivity a) {
boolean finishActivityWhenDone = true;
BitmapCropTask.OnBitmapCroppedHandler h = new BitmapCropTask.OnBitmapCroppedHandler() {
- public void onBitmapCropped(byte[] imageBytes) {
+ @Override
+ public void onBitmapCropped(byte[] imageBytes, Rect hint) {
+ Bitmap thumb = null;
Point thumbSize = getDefaultThumbnailSize(a.getResources());
- // rotation is set to 0 since imageBytes has already been correctly rotated
- Bitmap thumb = createThumbnail(
- thumbSize, null, null, imageBytes, null, 0, 0, true);
- a.getSavedImages().writeImage(thumb, imageBytes);
+ if (imageBytes != null) {
+ // rotation is set to 0 since imageBytes has already been correctly rotated
+ thumb = createThumbnail(
+ thumbSize, null, null, imageBytes, null, 0, 0, true);
+ a.getSavedImages().writeImage(thumb, imageBytes);
+ } else {
+ try {
+ // Generate thumb
+ Point size = getDefaultThumbnailSize(a.getResources());
+ Rect finalCropped = new Rect();
+ Utils.getMaxCropRect(hint.width(), hint.height(), size.x, size.y, false)
+ .roundOut(finalCropped);
+ finalCropped.offset(hint.left, hint.top);
+
+ InputStream in = a.getContentResolver().openInputStream(mUri);
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(in, true);
+
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inSampleSize = finalCropped.width() / size.x;
+ thumb = decoder.decodeRegion(finalCropped, options);
+ decoder.recycle();
+ Utils.closeSilently(in);
+ if (thumb != null) {
+ thumb = Bitmap.createScaledBitmap(thumb, size.x, size.y, true);
+ }
+ } catch (IOException e) { }
+ PointF center = a.mCropView.getCenter();
+
+ Float[] extras = new Float[] {
+ a.mCropView.getScale(),
+ center.x,
+ center.y
+ };
+ a.getSavedImages().writeImage(thumb, mUri, extras);
+ }
}
};
boolean shouldFadeOutOnFinish = a.getWallpaperParallaxOffset() == 0f;
@@ -196,7 +233,7 @@
}
public static class FileWallpaperInfo extends WallpaperTileInfo {
- private File mFile;
+ protected File mFile;
public FileWallpaperInfo(File target, Drawable thumb) {
mFile = target;
@@ -207,7 +244,8 @@
a.setWallpaperButtonEnabled(false);
final BitmapRegionTileSource.UriBitmapSource bitmapSource =
new BitmapRegionTileSource.UriBitmapSource(a.getContext(), Uri.fromFile(mFile));
- a.setCropViewTileSource(bitmapSource, false, true, null, new Runnable() {
+ a.setCropViewTileSource(bitmapSource, false, true, getCropViewScaleAndOffsetProvider(),
+ new Runnable() {
@Override
public void run() {
@@ -217,6 +255,11 @@
}
});
}
+
+ protected CropViewScaleAndOffsetProvider getCropViewScaleAndOffsetProvider() {
+ return null;
+ }
+
@Override
public void onSave(WallpaperPickerActivity a) {
boolean shouldFadeOutOnFinish = a.getWallpaperParallaxOffset() == 0f;
@@ -303,18 +346,7 @@
LoadRequest req = new LoadRequest();
req.moveToLeft = false;
req.touchEnabled = false;
- req.scaleAndOffsetProvider = new CropViewScaleAndOffsetProvider() {
-
- @Override
- public float getScale(Point wallpaperSize, RectF crop) {
- return 1f;
- }
-
- @Override
- public float getParallaxOffset() {
- return 0.5f;
- }
- };
+ req.scaleAndOffsetProvider = new CropViewScaleAndOffsetProvider();
req.result = new DrawableTileSource(a.getContext(),
defaultWallpaper, DrawableTileSource.MAX_PREVIEW_SIZE);
a.onLoadRequestComplete(req, true);