WallpaperCropActivity.java revision eadbfc564d84aaf1d800da3d0d6edf6312f89648
1104c45677660586026a7e74ef8c47d396403d50eMichael Jurka/*
2104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Copyright (C) 2013 The Android Open Source Project
3104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *
4104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License");
5104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * you may not use this file except in compliance with the License.
6104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * You may obtain a copy of the License at
7104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *
8104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *      http://www.apache.org/licenses/LICENSE-2.0
9104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *
10104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Unless required by applicable law or agreed to in writing, software
11104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS,
12104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * See the License for the specific language governing permissions and
14104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * limitations under the License.
15104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */
16104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
17104c45677660586026a7e74ef8c47d396403d50eMichael Jurkapackage com.android.launcher3;
18104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
19104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.app.Activity;
20104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.app.WallpaperManager;
21104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.content.Context;
22104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.content.SharedPreferences;
23eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurkaimport android.content.res.Resources;
24104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Bitmap;
25104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Bitmap.CompressFormat;
26104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.BitmapFactory;
27104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.BitmapRegionDecoder;
28104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Canvas;
29104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Matrix;
30104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Paint;
31104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Point;
32104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Rect;
33104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.RectF;
34104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.net.Uri;
35104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.os.AsyncTask;
36104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.util.Log;
37104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
38104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport com.android.gallery3d.common.Utils;
39104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
40104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.BufferedInputStream;
41104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.ByteArrayInputStream;
42104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.ByteArrayOutputStream;
43104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.FileNotFoundException;
44104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.IOException;
45104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.InputStream;
46104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
47104c45677660586026a7e74ef8c47d396403d50eMichael Jurka// LAUNCHER crop activity!
48104c45677660586026a7e74ef8c47d396403d50eMichael Jurkapublic class WallpaperCropActivity extends Activity {
49104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private static final String LOGTAG = "Launcher3.CropActivity";
50104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
51104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected static final String WALLPAPER_WIDTH_KEY = "wallpaper.width";
52104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected static final String WALLPAPER_HEIGHT_KEY = "wallpaper.height";
53104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private static final int DEFAULT_COMPRESS_QUALITY = 90;
54104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
55104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * The maximum bitmap size we allow to be returned through the intent.
56104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Intents have a maximum of 1MB in total size. However, the Bitmap seems to
57104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * have some overhead to hit so that we go way below the limit here to make
58104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * sure the intent stays below 1MB.We should consider just returning a byte
59104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * array instead of a Bitmap instance to avoid overhead.
60104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
61104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static final int MAX_BMAP_IN_INTENT = 750000;
62104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
63104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
64104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected class BitmapCropTask extends AsyncTask<Void, Void, Boolean> {
65104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        Uri mInUri = null;
66fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka        int mInResId = 0;
67104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        InputStream mInStream;
68104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        RectF mCropBounds = null;
69104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        int mOutWidth, mOutHeight;
70104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        int mRotation = 0; // for now
71104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        protected final WallpaperManager mWPManager;
72104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        String mOutputFormat = "jpg"; // for now
73104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        boolean mSetWallpaper;
74104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        boolean mSaveCroppedBitmap;
75104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        Bitmap mCroppedBitmap;
76fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka        Runnable mOnEndRunnable;
77eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        Resources mResources;
78104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
79eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        public BitmapCropTask(Uri inUri,
80eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka                RectF cropBounds, int outWidth, int outHeight,
81fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
82104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            mInUri = inUri;
83104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            mCropBounds = cropBounds;
84104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            mOutWidth = outWidth;
85104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            mOutHeight = outHeight;
86104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            mWPManager = WallpaperManager.getInstance(getApplicationContext());
87104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            mSetWallpaper = setWallpaper;
88104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            mSaveCroppedBitmap = saveCroppedBitmap;
89fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka            mOnEndRunnable = onEndRunnable;
90fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka        }
91fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka
92eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        public BitmapCropTask(Resources res, int inResId,
93eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka                RectF cropBounds, int outWidth, int outHeight,
94fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
95fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka            mInResId = inResId;
96fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka            mCropBounds = cropBounds;
97fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka            mOutWidth = outWidth;
98fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka            mOutHeight = outHeight;
99fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka            mWPManager = WallpaperManager.getInstance(getApplicationContext());
100fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka            mSetWallpaper = setWallpaper;
101fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka            mSaveCroppedBitmap = saveCroppedBitmap;
102fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka            mOnEndRunnable = onEndRunnable;
103eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            mResources = res;
104104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
105104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
106104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        // Helper to setup input stream
107104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        private void regenerateInputStream() {
108fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka            if (mInUri == null && mInResId == 0) {
109fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                Log.w(LOGTAG, "cannot read original file, no input URI or resource ID given");
110104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            } else {
111104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                Utils.closeSilently(mInStream);
112104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                try {
113fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                    if (mInUri != null) {
114fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                        mInStream = new BufferedInputStream(
115fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                                getContentResolver().openInputStream(mInUri));
116fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                    } else {
117fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                        mInStream = new BufferedInputStream(
118eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka                                mResources.openRawResource(mInResId));
119fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                    }
120104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                } catch (FileNotFoundException e) {
121104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e);
122104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
123104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
124104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
125104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
126104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        public Point getImageBounds() {
127104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            regenerateInputStream();
128104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (mInStream != null) {
129104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                BitmapFactory.Options options = new BitmapFactory.Options();
130104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                options.inJustDecodeBounds = true;
131104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                BitmapFactory.decodeStream(mInStream, null, options);
132104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                if (options.outWidth != 0 && options.outHeight != 0) {
133104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    return new Point(options.outWidth, options.outHeight);
134104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
135104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
136104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return null;
137104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
138104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
139104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        public void setCropBounds(RectF cropBounds) {
140104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            mCropBounds = cropBounds;
141104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
142104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
143104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        public Bitmap getCroppedBitmap() {
144104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return mCroppedBitmap;
145104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
146104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        public boolean cropBitmap() {
147104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            boolean failure = false;
148104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
149104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            regenerateInputStream();
150104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
151104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (mInStream != null) {
152104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                // Find crop bounds (scaled to original image size)
153104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                Rect roundedTrueCrop = new Rect();
154104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                mCropBounds.roundOut(roundedTrueCrop);
155104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
156104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) {
157104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    Log.w(LOGTAG, "crop has bad values for full size image");
158104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    failure = true;
159104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    return false;
160104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
161104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
162104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                // See how much we're reducing the size of the image
163104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / mOutWidth,
164104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        roundedTrueCrop.height() / mOutHeight);
165104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
166104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                // Attempt to open a region decoder
167104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                BitmapRegionDecoder decoder = null;
168104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                try {
169104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    decoder = BitmapRegionDecoder.newInstance(mInStream, true);
170104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                } catch (IOException e) {
171104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
172104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
173104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
174104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                Bitmap crop = null;
175104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                if (decoder != null) {
176104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    // Do region decoding to get crop bitmap
177104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    BitmapFactory.Options options = new BitmapFactory.Options();
178104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    if (scaleDownSampleSize > 1) {
179104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        options.inSampleSize = scaleDownSampleSize;
180104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    }
181104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    crop = decoder.decodeRegion(roundedTrueCrop, options);
182104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    decoder.recycle();
183104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
184104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
185104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                if (crop == null) {
186104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    // BitmapRegionDecoder has failed, try to crop in-memory
187104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    regenerateInputStream();
188104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    Bitmap fullSize = null;
189104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    if (mInStream != null) {
190104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        BitmapFactory.Options options = new BitmapFactory.Options();
191104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        if (scaleDownSampleSize > 1) {
192104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                            options.inSampleSize = scaleDownSampleSize;
193104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        }
194104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        fullSize = BitmapFactory.decodeStream(mInStream, null, options);
195104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    }
196104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    if (fullSize != null) {
197104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
198104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                                roundedTrueCrop.top, roundedTrueCrop.width(),
199104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                                roundedTrueCrop.height());
200104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    }
201104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
202104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
203104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                if (crop == null) {
204104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    Log.w(LOGTAG, "cannot decode file: " + mInUri.toString());
205104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    failure = true;
206104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    return false;
207104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
208fd471c0b4f028948d5aaefe37d4b9582b4b4372fMichael Jurka                if (mOutWidth > 0 && mOutHeight > 0) {
209104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    Matrix m = new Matrix();
210104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    RectF cropRect = new RectF(0, 0, crop.getWidth(), crop.getHeight());
211104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    if (mRotation > 0) {
212104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        m.setRotate(mRotation);
213104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        m.mapRect(cropRect);
214104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    }
215fd471c0b4f028948d5aaefe37d4b9582b4b4372fMichael Jurka                    RectF returnRect = new RectF(0, 0, mOutWidth, mOutHeight);
216104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
217104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    m.preRotate(mRotation);
218104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(),
219104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                            (int) returnRect.height(), Bitmap.Config.ARGB_8888);
220104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    if (tmp != null) {
221104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        Canvas c = new Canvas(tmp);
222104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        c.drawBitmap(crop, m, new Paint());
223104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        crop = tmp;
224104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    }
225104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                } else if (mRotation > 0) {
226104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    Matrix m = new Matrix();
227104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    m.setRotate(mRotation);
228104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    Bitmap tmp = Bitmap.createBitmap(crop, 0, 0, crop.getWidth(),
229104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                            crop.getHeight(), m, true);
230104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    if (tmp != null) {
231104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        crop = tmp;
232104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    }
233104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
234104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
235104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                if (mSaveCroppedBitmap) {
236104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    mCroppedBitmap = crop;
237104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
238104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
239104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                // Get output compression format
240104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                CompressFormat cf =
241104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        convertExtensionToCompressFormat(getFileExtension(mOutputFormat));
242104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
243104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                // Compress to byte array
244104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
245104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
246104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    // If we need to set to the wallpaper, set it
247104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    if (mSetWallpaper && mWPManager != null) {
248104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        if (mWPManager == null) {
249104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                            Log.w(LOGTAG, "no wallpaper manager");
250104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                            failure = true;
251104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        } else {
252104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                            try {
253104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                                mWPManager.setStream(new ByteArrayInputStream(tmpOut
254104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                                        .toByteArray()));
255104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                            } catch (IOException e) {
256104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                                Log.w(LOGTAG, "cannot write stream to wallpaper", e);
257104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                                failure = true;
258104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                            }
259104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        }
260104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    }
261fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                    if (mOnEndRunnable != null) {
262fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                        mOnEndRunnable.run();
263fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka                    }
264104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                } else {
265104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    Log.w(LOGTAG, "cannot compress bitmap");
266104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    failure = true;
267104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
268104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
269104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return !failure; // True if any of the operations failed
270104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
271104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
272104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        @Override
273104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        protected Boolean doInBackground(Void... params) {
274104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return cropBitmap();
275104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
276104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
277104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        @Override
278104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        protected void onPostExecute(Boolean result) {
279104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            setResult(Activity.RESULT_OK);
280104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            finish();
281104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
282104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
283104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
284104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected void updateWallpaperDimensions(int width, int height) {
285104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        String spKey = LauncherAppState.getSharedPreferencesKey();
286104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE);
287104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        SharedPreferences.Editor editor = sp.edit();
288104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (width != 0 && height != 0) {
289104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            editor.putInt(WALLPAPER_WIDTH_KEY, width);
290104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            editor.putInt(WALLPAPER_HEIGHT_KEY, height);
291104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else {
292104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            editor.remove(WALLPAPER_WIDTH_KEY);
293104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            editor.remove(WALLPAPER_HEIGHT_KEY);
294104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
295104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        editor.commit();
296fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4dbMichael Jurka
297104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        WallpaperPickerActivity.suggestWallpaperDimension(getResources(),
298104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                sp, getWindowManager(), WallpaperManager.getInstance(this));
299104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
300104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
301104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected static CompressFormat convertExtensionToCompressFormat(String extension) {
302104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return extension.equals("png") ? CompressFormat.PNG : CompressFormat.JPEG;
303104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
304104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
305104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected static String getFileExtension(String requestFormat) {
306104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        String outputFormat = (requestFormat == null)
307104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                ? "jpg"
308104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                : requestFormat;
309104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        outputFormat = outputFormat.toLowerCase();
310104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return (outputFormat.equals("png") || outputFormat.equals("gif"))
311104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                ? "png" // We don't support gif compression.
312104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                : "jpg";
313104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
314104c45677660586026a7e74ef8c47d396403d50eMichael Jurka}
315