summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/WallpaperCropActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/WallpaperCropActivity.java')
-rw-r--r--src/com/android/launcher3/WallpaperCropActivity.java289
1 files changed, 289 insertions, 0 deletions
diff --git a/src/com/android/launcher3/WallpaperCropActivity.java b/src/com/android/launcher3/WallpaperCropActivity.java
new file mode 100644
index 000000000..087785ef5
--- /dev/null
+++ b/src/com/android/launcher3/WallpaperCropActivity.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.app.Activity;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.util.Log;
+
+import com.android.gallery3d.common.Utils;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+// LAUNCHER crop activity!
+public class WallpaperCropActivity extends Activity {
+ private static final String LOGTAG = "Launcher3.CropActivity";
+
+ private int mOutputX = 0;
+ private int mOutputY = 0;
+
+ protected static final String WALLPAPER_WIDTH_KEY = "wallpaper.width";
+ protected static final String WALLPAPER_HEIGHT_KEY = "wallpaper.height";
+ private static final int DEFAULT_COMPRESS_QUALITY = 90;
+ /**
+ * The maximum bitmap size we allow to be returned through the intent.
+ * Intents have a maximum of 1MB in total size. However, the Bitmap seems to
+ * have some overhead to hit so that we go way below the limit here to make
+ * sure the intent stays below 1MB.We should consider just returning a byte
+ * array instead of a Bitmap instance to avoid overhead.
+ */
+ public static final int MAX_BMAP_IN_INTENT = 750000;
+
+
+ protected class BitmapCropTask extends AsyncTask<Void, Void, Boolean> {
+ Uri mInUri = null;
+ InputStream mInStream;
+ RectF mCropBounds = null;
+ int mOutWidth, mOutHeight;
+ int mRotation = 0; // for now
+ protected final WallpaperManager mWPManager;
+ String mOutputFormat = "jpg"; // for now
+ boolean mSetWallpaper;
+ boolean mSaveCroppedBitmap;
+ Bitmap mCroppedBitmap;
+
+ public BitmapCropTask(Uri inUri, RectF cropBounds, int outWidth, int outHeight,
+ boolean setWallpaper, boolean saveCroppedBitmap) {
+ mInUri = inUri;
+ mCropBounds = cropBounds;
+ mOutWidth = outWidth;
+ mOutHeight = outHeight;
+ mWPManager = WallpaperManager.getInstance(getApplicationContext());
+ mSetWallpaper = setWallpaper;
+ mSaveCroppedBitmap = saveCroppedBitmap;
+ }
+
+ // Helper to setup input stream
+ private void regenerateInputStream() {
+ if (mInUri == null) {
+ Log.w(LOGTAG, "cannot read original file, no input URI given");
+ } else {
+ Utils.closeSilently(mInStream);
+ try {
+ mInStream = new BufferedInputStream(
+ getContentResolver().openInputStream(mInUri));
+ } catch (FileNotFoundException e) {
+ Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e);
+ }
+ }
+ }
+
+ public Point getImageBounds() {
+ regenerateInputStream();
+ if (mInStream != null) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeStream(mInStream, null, options);
+ if (options.outWidth != 0 && options.outHeight != 0) {
+ return new Point(options.outWidth, options.outHeight);
+ }
+ }
+ return null;
+ }
+
+ public void setCropBounds(RectF cropBounds) {
+ mCropBounds = cropBounds;
+ }
+
+ public Bitmap getCroppedBitmap() {
+ return mCroppedBitmap;
+ }
+ public boolean cropBitmap() {
+ boolean failure = false;
+
+ regenerateInputStream();
+
+ if (mInStream != null) {
+ // Find crop bounds (scaled to original image size)
+ Rect roundedTrueCrop = new Rect();
+ mCropBounds.roundOut(roundedTrueCrop);
+
+ if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) {
+ Log.w(LOGTAG, "crop has bad values for full size image");
+ failure = true;
+ return false;
+ }
+
+ // See how much we're reducing the size of the image
+ int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / mOutWidth,
+ roundedTrueCrop.height() / mOutHeight);
+
+ // Attempt to open a region decoder
+ BitmapRegionDecoder decoder = null;
+ try {
+ decoder = BitmapRegionDecoder.newInstance(mInStream, true);
+ } catch (IOException e) {
+ Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
+ }
+
+ Bitmap crop = null;
+ if (decoder != null) {
+ // Do region decoding to get crop bitmap
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ if (scaleDownSampleSize > 1) {
+ options.inSampleSize = scaleDownSampleSize;
+ }
+ crop = decoder.decodeRegion(roundedTrueCrop, options);
+ decoder.recycle();
+ }
+
+ if (crop == null) {
+ // BitmapRegionDecoder has failed, try to crop in-memory
+ regenerateInputStream();
+ Bitmap fullSize = null;
+ if (mInStream != null) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ if (scaleDownSampleSize > 1) {
+ options.inSampleSize = scaleDownSampleSize;
+ }
+ fullSize = BitmapFactory.decodeStream(mInStream, null, options);
+ }
+ if (fullSize != null) {
+ crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
+ roundedTrueCrop.top, roundedTrueCrop.width(),
+ roundedTrueCrop.height());
+ }
+ }
+
+ if (crop == null) {
+ Log.w(LOGTAG, "cannot decode file: " + mInUri.toString());
+ failure = true;
+ return false;
+ }
+ if (mOutputX > 0 && mOutputY > 0) {
+ Matrix m = new Matrix();
+ RectF cropRect = new RectF(0, 0, crop.getWidth(), crop.getHeight());
+ if (mRotation > 0) {
+ m.setRotate(mRotation);
+ m.mapRect(cropRect);
+ }
+ RectF returnRect = new RectF(0, 0, mOutputX, mOutputY);
+ m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
+ m.preRotate(mRotation);
+ Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(),
+ (int) returnRect.height(), Bitmap.Config.ARGB_8888);
+ if (tmp != null) {
+ Canvas c = new Canvas(tmp);
+ c.drawBitmap(crop, m, new Paint());
+ crop = tmp;
+ }
+ } else if (mRotation > 0) {
+ Matrix m = new Matrix();
+ m.setRotate(mRotation);
+ Bitmap tmp = Bitmap.createBitmap(crop, 0, 0, crop.getWidth(),
+ crop.getHeight(), m, true);
+ if (tmp != null) {
+ crop = tmp;
+ }
+ }
+
+ if (mSaveCroppedBitmap) {
+ mCroppedBitmap = crop;
+ }
+
+ // Get output compression format
+ CompressFormat cf =
+ convertExtensionToCompressFormat(getFileExtension(mOutputFormat));
+
+ // Compress to byte array
+ ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
+ if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
+ // If we need to set to the wallpaper, set it
+ if (mSetWallpaper && mWPManager != null) {
+ if (mWPManager == null) {
+ Log.w(LOGTAG, "no wallpaper manager");
+ failure = true;
+ } else {
+ try {
+ mWPManager.setStream(new ByteArrayInputStream(tmpOut
+ .toByteArray()));
+ updateWallpaperDimensions(mOutWidth, mOutHeight);
+ } catch (IOException e) {
+ Log.w(LOGTAG, "cannot write stream to wallpaper", e);
+ failure = true;
+ }
+ }
+ }
+ } else {
+ Log.w(LOGTAG, "cannot compress bitmap");
+ failure = true;
+ }
+ }
+ return !failure; // True if any of the operations failed
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ return cropBitmap();
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ setResult(Activity.RESULT_OK);
+ finish();
+ }
+ }
+
+ protected void updateWallpaperDimensions(int width, int height) {
+ String spKey = LauncherAppState.getSharedPreferencesKey();
+ SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sp.edit();
+ if (width != 0 && height != 0) {
+ editor.putInt(WALLPAPER_WIDTH_KEY, width);
+ editor.putInt(WALLPAPER_HEIGHT_KEY, height);
+ } else {
+ editor.remove(WALLPAPER_WIDTH_KEY);
+ editor.remove(WALLPAPER_HEIGHT_KEY);
+ }
+ editor.commit();
+ WallpaperPickerActivity.suggestWallpaperDimension(getResources(),
+ sp, getWindowManager(), WallpaperManager.getInstance(this));
+ }
+
+ protected static CompressFormat convertExtensionToCompressFormat(String extension) {
+ return extension.equals("png") ? CompressFormat.PNG : CompressFormat.JPEG;
+ }
+
+ protected static String getFileExtension(String requestFormat) {
+ String outputFormat = (requestFormat == null)
+ ? "jpg"
+ : requestFormat;
+ outputFormat = outputFormat.toLowerCase();
+ return (outputFormat.equals("png") || outputFormat.equals("gif"))
+ ? "png" // We don't support gif compression.
+ : "jpg";
+ }
+}