WallpaperCropActivity.java revision e72aa7f0a64ff55f747751b7972ccb8acebab7da
1e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka/* 2e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Copyright (C) 2013 The Android Open Source Project 3e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 4e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 5e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * you may not use this file except in compliance with the License. 6e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * You may obtain a copy of the License at 7e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 8e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * http://www.apache.org/licenses/LICENSE-2.0 9e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 10e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Unless required by applicable law or agreed to in writing, software 11e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 12e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * See the License for the specific language governing permissions and 14e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * limitations under the License. 15e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 16e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka/* Copied from Launcher3 */ 17e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkapackage com.android.wallpapercropper; 18e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 19e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.app.ActionBar; 20e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.app.Activity; 21e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.app.WallpaperManager; 22e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.content.Context; 23e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.content.Intent; 24e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.content.SharedPreferences; 25e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.content.res.Configuration; 26e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.content.res.Resources; 27e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Bitmap; 28e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Bitmap.CompressFormat; 29e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.BitmapFactory; 30e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.BitmapRegionDecoder; 31e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Canvas; 32e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Matrix; 33e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Paint; 34e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Point; 35e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Rect; 36e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.RectF; 37e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.net.Uri; 38e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.os.AsyncTask; 39e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.os.Bundle; 40e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.util.Log; 41e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.view.Display; 42e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.view.View; 43e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.view.WindowManager; 44e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 45e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport com.android.gallery3d.common.Utils; 46e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport com.android.photos.BitmapRegionTileSource; 47e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 48e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.io.BufferedInputStream; 49e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.io.ByteArrayInputStream; 50e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.io.ByteArrayOutputStream; 51e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.io.FileNotFoundException; 52e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.io.IOException; 53e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.io.InputStream; 54e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 55e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkapublic class WallpaperCropActivity extends Activity { 56e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String LOGTAG = "Launcher3.CropActivity"; 57e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 58e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected static final String WALLPAPER_WIDTH_KEY = "wallpaper.width"; 59e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected static final String WALLPAPER_HEIGHT_KEY = "wallpaper.height"; 60e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int DEFAULT_COMPRESS_QUALITY = 90; 61e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 62e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * The maximum bitmap size we allow to be returned through the intent. 63e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Intents have a maximum of 1MB in total size. However, the Bitmap seems to 64e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * have some overhead to hit so that we go way below the limit here to make 65e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * sure the intent stays below 1MB.We should consider just returning a byte 66e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * array instead of a Bitmap instance to avoid overhead. 67e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 68e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public static final int MAX_BMAP_IN_INTENT = 750000; 69e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final float WALLPAPER_SCREENS_SPAN = 2f; 70e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 71e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected CropView mCropView; 72e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected Uri mUri; 73e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 74e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 75e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void onCreate(Bundle savedInstanceState) { 76e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka super.onCreate(savedInstanceState); 77e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka init(); 78e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka if (!enableRotation()) { 79e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka setRequestedOrientation(Configuration.ORIENTATION_PORTRAIT); 80e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka } 81e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 82e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 83e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void init() { 84e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setContentView(R.layout.wallpaper_cropper); 85e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 86e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCropView = (CropView) findViewById(R.id.cropView); 87e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 88e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Intent cropIntent = this.getIntent(); 89e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final Uri imageUri = cropIntent.getData(); 90e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 91e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCropView.setTileSource(new BitmapRegionTileSource(this, imageUri, 1024, 0), null); 92e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCropView.setTouchEnabled(true); 93e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Action bar 94e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Show the custom action bar view 95e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final ActionBar actionBar = getActionBar(); 96e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka actionBar.setCustomView(R.layout.actionbar_set_wallpaper); 97e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka actionBar.getCustomView().setOnClickListener( 98e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new View.OnClickListener() { 99e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 100e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void onClick(View v) { 101e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean finishActivityWhenDone = true; 102e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropImageAndSetWallpaper(imageUri, null, finishActivityWhenDone); 103e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 104e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }); 105e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka TranslucentDecor transparentDecor = new TranslucentDecor(findViewById(R.id.wallpaper_root)); 106e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka transparentDecor.requestTranslucentDecor(true); 107e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka } 108e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka 109e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka public boolean enableRotation() { 110e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka return getResources().getBoolean(R.bool.allow_rotation); 111e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 112e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 113e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public static String getSharedPreferencesKey() { 114e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return WallpaperCropActivity.class.getName(); 115e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 116e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 117e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // As a ratio of screen height, the total distance we want the parallax effect to span 118e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // horizontally 119e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static float wallpaperTravelToScreenWidthRatio(int width, int height) { 120e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float aspectRatio = width / (float) height; 121e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 122e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // At an aspect ratio of 16/10, the wallpaper parallax effect should span 1.5 * screen width 123e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // At an aspect ratio of 10/16, the wallpaper parallax effect should span 1.2 * screen width 124e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // We will use these two data points to extrapolate how much the wallpaper parallax effect 125e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // to span (ie travel) at any aspect ratio: 126e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 127e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final float ASPECT_RATIO_LANDSCAPE = 16/10f; 128e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final float ASPECT_RATIO_PORTRAIT = 10/16f; 129e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f; 130e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f; 131e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 132e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // To find out the desired width at different aspect ratios, we use the following two 133e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // formulas, where the coefficient on x is the aspect ratio (width/height): 134e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // (16/10)x + y = 1.5 135e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // (10/16)x + y = 1.2 136e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // We solve for x and y and end up with a final formula: 137e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final float x = 138e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) / 139e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka (ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT); 140e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - x * ASPECT_RATIO_PORTRAIT; 141e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return x * aspectRatio + y; 142e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 143e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 144e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka static protected Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) { 145e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Point minDims = new Point(); 146e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Point maxDims = new Point(); 147e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims); 148e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 149e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int maxDim = Math.max(maxDims.x, maxDims.y); 1508b4836085b928f0ada3b3e6e1d1fd0530ffd6d57Michael Jurka int minDim = Math.max(minDims.x, minDims.y); 151e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 152e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { 153e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Point realSize = new Point(); 154e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka windowManager.getDefaultDisplay().getRealSize(realSize); 155e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka maxDim = Math.max(realSize.x, realSize.y); 1568b4836085b928f0ada3b3e6e1d1fd0530ffd6d57Michael Jurka minDim = Math.min(realSize.x, realSize.y); 157e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 158e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 159e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // We need to ensure that there is enough extra space in the wallpaper 160e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // for the intended 161e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // parallax effects 162e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final int defaultWidth, defaultHeight; 163e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (isScreenLarge(res)) { 164e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim)); 165e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka defaultHeight = maxDim; 166e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 167e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim); 168e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka defaultHeight = maxDim; 169e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 170e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return new Point(defaultWidth, defaultHeight); 171e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 172e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 173e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void setWallpaper(String filePath, final boolean finishActivityWhenDone) { 174e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka BitmapCropTask cropTask = new BitmapCropTask(this, 175e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka filePath, null, 0, 0, true, false, null); 176e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final Point bounds = cropTask.getImageBounds(); 177e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Runnable onEndCrop = new Runnable() { 178e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void run() { 179e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka updateWallpaperDimensions(bounds.x, bounds.y); 180e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (finishActivityWhenDone) { 181e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setResult(Activity.RESULT_OK); 182e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka finish(); 183e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 184e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 185e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 186e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropTask.setOnEndRunnable(onEndCrop); 187e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropTask.setNoCrop(true); 188e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropTask.execute(); 189e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 190e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 191e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void cropImageAndSetWallpaper( 192e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Resources res, int resId, final boolean finishActivityWhenDone) { 193e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // crop this image and scale it down to the default wallpaper size for 194e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // this device 195e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Point inSize = mCropView.getSourceDimensions(); 196e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Point outSize = getDefaultWallpaperSize(getResources(), 197e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka getWindowManager()); 198e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RectF crop = getMaxCropRect( 199e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka inSize.x, inSize.y, outSize.x, outSize.y, false); 200e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Runnable onEndCrop = new Runnable() { 201e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void run() { 202e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Passing 0, 0 will cause launcher to revert to using the 203e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // default wallpaper size 204e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka updateWallpaperDimensions(0, 0); 205e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (finishActivityWhenDone) { 206e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setResult(Activity.RESULT_OK); 207e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka finish(); 208e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 209e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 210e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 211e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka BitmapCropTask cropTask = new BitmapCropTask(this, res, resId, 212e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka crop, outSize.x, outSize.y, 213e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka true, false, onEndCrop); 214e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropTask.execute(); 215e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 216e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 217e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static boolean isScreenLarge(Resources res) { 218e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Configuration config = res.getConfiguration(); 219e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return config.smallestScreenWidthDp >= 720; 220e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 221e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 222e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void cropImageAndSetWallpaper(Uri uri, 223e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) { 224e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka // Get the crop 225e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Point inSize = mCropView.getSourceDimensions(); 226e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 227e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR; 228e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka 229e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Point minDims = new Point(); 230e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Point maxDims = new Point(); 231e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Display d = getWindowManager().getDefaultDisplay(); 232e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka d.getCurrentSizeRange(minDims, maxDims); 233e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 234e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Point displaySize = new Point(); 235e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka d.getSize(displaySize); 236e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 237e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int maxDim = Math.max(maxDims.x, maxDims.y); 238e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final int minDim = Math.min(minDims.x, minDims.y); 239e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka int defaultWallpaperWidth; 240e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (isScreenLarge(getResources())) { 241e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka defaultWallpaperWidth = (int) (maxDim * 242e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka wallpaperTravelToScreenWidthRatio(maxDim, minDim)); 243e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 244e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka defaultWallpaperWidth = Math.max((int) 245e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka (minDim * WALLPAPER_SCREENS_SPAN), maxDim); 246e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 247e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 248e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean isPortrait = displaySize.x < displaySize.y; 249e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int portraitHeight; 250e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (isPortrait) { 251e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka portraitHeight = mCropView.getHeight(); 252e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 253e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // TODO: how to actually get the proper portrait height? 254e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // This is not quite right: 255e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka portraitHeight = Math.max(maxDims.x, maxDims.y); 256e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 257e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (android.os.Build.VERSION.SDK_INT >= 258e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { 259e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Point realSize = new Point(); 260e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka d.getRealSize(realSize); 261e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka portraitHeight = Math.max(realSize.x, realSize.y); 262e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 263e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Get the crop 264e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RectF cropRect = mCropView.getCrop(); 265e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float cropScale = mCropView.getWidth() / (float) cropRect.width(); 266e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 267e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // ADJUST CROP WIDTH 268e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Extend the crop all the way to the right, for parallax 269e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka // (or all the way to the left, in RTL) 270e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka float extraSpace = ltr ? inSize.x - cropRect.right : cropRect.left; 271e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Cap the amount of extra width 272e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka float maxExtraSpace = defaultWallpaperWidth / cropScale - cropRect.width(); 273e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka extraSpace = Math.min(extraSpace, maxExtraSpace); 274e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 275e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka if (ltr) { 276e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka cropRect.right += extraSpace; 277e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka } else { 278e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka cropRect.left -= extraSpace; 279e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka } 280e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 281e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // ADJUST CROP HEIGHT 282e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (isPortrait) { 283e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.bottom = cropRect.top + portraitHeight / cropScale; 284e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { // LANDSCAPE 285e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float extraPortraitHeight = 286e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka portraitHeight / cropScale - cropRect.height(); 287e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float expandHeight = 288e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Math.min(Math.min(inSize.y - cropRect.bottom, cropRect.top), 289e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka extraPortraitHeight / 2); 290e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.top -= expandHeight; 291e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.bottom += expandHeight; 292e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 293e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final int outWidth = (int) Math.round(cropRect.width() * cropScale); 294e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final int outHeight = (int) Math.round(cropRect.height() * cropScale); 295e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 296e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Runnable onEndCrop = new Runnable() { 297e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void run() { 298e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka updateWallpaperDimensions(outWidth, outHeight); 299e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (finishActivityWhenDone) { 300e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setResult(Activity.RESULT_OK); 301e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka finish(); 302e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 303e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 304e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 305e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka BitmapCropTask cropTask = new BitmapCropTask(this, uri, 306e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect, outWidth, outHeight, true, false, onEndCrop); 307e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (onBitmapCroppedHandler != null) { 308e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropTask.setOnBitmapCropped(onBitmapCroppedHandler); 309e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 310e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropTask.execute(); 311e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 312e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 313e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public interface OnBitmapCroppedHandler { 314e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void onBitmapCropped(byte[] imageBytes); 315e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 316e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 317e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka protected static class BitmapCropTask extends AsyncTask<Void, Void, Boolean> { 318e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Uri mInUri = null; 319e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Context mContext; 320e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka String mInFilePath; 321e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka byte[] mInImageBytes; 322e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int mInResId = 0; 323e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka InputStream mInStream; 324e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RectF mCropBounds = null; 325e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int mOutWidth, mOutHeight; 326e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int mRotation = 0; // for now 327e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka String mOutputFormat = "jpg"; // for now 328e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean mSetWallpaper; 329e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean mSaveCroppedBitmap; 330e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap mCroppedBitmap; 331e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Runnable mOnEndRunnable; 332e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Resources mResources; 333e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka OnBitmapCroppedHandler mOnBitmapCroppedHandler; 334e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean mNoCrop; 335e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 336e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public BitmapCropTask(Context c, String filePath, 337e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RectF cropBounds, int outWidth, int outHeight, 338e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { 339e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mContext = c; 340e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mInFilePath = filePath; 341e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); 342e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 343e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 344e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public BitmapCropTask(byte[] imageBytes, 345e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RectF cropBounds, int outWidth, int outHeight, 346e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { 347e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mInImageBytes = imageBytes; 348e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); 349e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 350e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 351e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka public BitmapCropTask(Context c, Uri inUri, 352e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RectF cropBounds, int outWidth, int outHeight, 353e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { 354e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka mContext = c; 355e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mInUri = inUri; 356e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); 357e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 358e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 359e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka public BitmapCropTask(Context c, Resources res, int inResId, 360e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RectF cropBounds, int outWidth, int outHeight, 361e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { 362e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka mContext = c; 363e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mInResId = inResId; 364e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mResources = res; 365e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); 366e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 367e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 368e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void init(RectF cropBounds, int outWidth, int outHeight, 369e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { 370e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCropBounds = cropBounds; 371e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mOutWidth = outWidth; 372e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mOutHeight = outHeight; 373e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mSetWallpaper = setWallpaper; 374e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mSaveCroppedBitmap = saveCroppedBitmap; 375e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mOnEndRunnable = onEndRunnable; 376e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 377e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 378e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void setOnBitmapCropped(OnBitmapCroppedHandler handler) { 379e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mOnBitmapCroppedHandler = handler; 380e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 381e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 382e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void setNoCrop(boolean value) { 383e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mNoCrop = value; 384e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 385e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 386e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void setOnEndRunnable(Runnable onEndRunnable) { 387e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mOnEndRunnable = onEndRunnable; 388e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 389e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 390e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Helper to setup input stream 391e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void regenerateInputStream() { 392e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null) { 393e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.w(LOGTAG, "cannot read original file, no input URI, resource ID, or " + 394e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka "image byte array given"); 395e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 396e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Utils.closeSilently(mInStream); 397e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka try { 398e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mInUri != null) { 399e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mInStream = new BufferedInputStream( 400e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka mContext.getContentResolver().openInputStream(mInUri)); 401e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else if (mInFilePath != null) { 402e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mInStream = mContext.openFileInput(mInFilePath); 403e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else if (mInImageBytes != null) { 404e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mInStream = new BufferedInputStream( 405e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new ByteArrayInputStream(mInImageBytes)); 406e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 407e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mInStream = new BufferedInputStream( 408e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mResources.openRawResource(mInResId)); 409e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 410e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } catch (FileNotFoundException e) { 411e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e); 412e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 413e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 414e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 415e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 416e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public Point getImageBounds() { 417e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka regenerateInputStream(); 418e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mInStream != null) { 419e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka BitmapFactory.Options options = new BitmapFactory.Options(); 420e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka options.inJustDecodeBounds = true; 421e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka BitmapFactory.decodeStream(mInStream, null, options); 422e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (options.outWidth != 0 && options.outHeight != 0) { 423e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return new Point(options.outWidth, options.outHeight); 424e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 425e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 426e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 427e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 428e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 429e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void setCropBounds(RectF cropBounds) { 430e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCropBounds = cropBounds; 431e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 432e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 433e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public Bitmap getCroppedBitmap() { 434e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mCroppedBitmap; 435e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 436e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public boolean cropBitmap() { 437e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean failure = false; 438e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 439e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka regenerateInputStream(); 440e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 441e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka WallpaperManager wallpaperManager = null; 442e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka if (mSetWallpaper) { 443e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext()); 444e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka } 445e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka if (mSetWallpaper && mNoCrop && mInStream != null) { 446e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka try { 447e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka wallpaperManager.setStream(mInStream); 448e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } catch (IOException e) { 449e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.w(LOGTAG, "cannot write stream to wallpaper", e); 450e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka failure = true; 451e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 452e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return !failure; 453e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 454e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mInStream != null) { 455e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Find crop bounds (scaled to original image size) 456e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Rect roundedTrueCrop = new Rect(); 457e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCropBounds.roundOut(roundedTrueCrop); 458e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 459e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) { 460e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.w(LOGTAG, "crop has bad values for full size image"); 461e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka failure = true; 462e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return false; 463e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 464e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 465e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // See how much we're reducing the size of the image 466e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / mOutWidth, 467e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka roundedTrueCrop.height() / mOutHeight); 468e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 469e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Attempt to open a region decoder 470e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka BitmapRegionDecoder decoder = null; 471e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka try { 472e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka decoder = BitmapRegionDecoder.newInstance(mInStream, true); 473e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } catch (IOException e) { 474e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e); 475e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 476e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 477e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap crop = null; 478e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (decoder != null) { 479e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Do region decoding to get crop bitmap 480e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka BitmapFactory.Options options = new BitmapFactory.Options(); 481e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (scaleDownSampleSize > 1) { 482e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka options.inSampleSize = scaleDownSampleSize; 483e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 484e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka crop = decoder.decodeRegion(roundedTrueCrop, options); 485e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka decoder.recycle(); 486e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 487e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 488e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (crop == null) { 489e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // BitmapRegionDecoder has failed, try to crop in-memory 490e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka regenerateInputStream(); 491e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap fullSize = null; 492e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mInStream != null) { 493e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka BitmapFactory.Options options = new BitmapFactory.Options(); 494e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (scaleDownSampleSize > 1) { 495e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka options.inSampleSize = scaleDownSampleSize; 496e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 497e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka fullSize = BitmapFactory.decodeStream(mInStream, null, options); 498e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 499e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (fullSize != null) { 500e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left, 501e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka roundedTrueCrop.top, roundedTrueCrop.width(), 502e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka roundedTrueCrop.height()); 503e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 504e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 505e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 506e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (crop == null) { 507e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.w(LOGTAG, "cannot decode file: " + mInUri.toString()); 508e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka failure = true; 509e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return false; 510e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 511e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mOutWidth > 0 && mOutHeight > 0) { 512e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix m = new Matrix(); 513e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RectF cropRect = new RectF(0, 0, crop.getWidth(), crop.getHeight()); 514e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mRotation > 0) { 515e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka m.setRotate(mRotation); 516e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka m.mapRect(cropRect); 517e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 518e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RectF returnRect = new RectF(0, 0, mOutWidth, mOutHeight); 519e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL); 520e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka m.preRotate(mRotation); 521e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(), 522e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka (int) returnRect.height(), Bitmap.Config.ARGB_8888); 523e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (tmp != null) { 524e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Canvas c = new Canvas(tmp); 525e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka Paint p = new Paint(); 526e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka p.setFilterBitmap(true); 527e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka c.drawBitmap(crop, m, p); 528e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka crop = tmp; 529e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 530e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else if (mRotation > 0) { 531e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix m = new Matrix(); 532e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka m.setRotate(mRotation); 533e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap tmp = Bitmap.createBitmap(crop, 0, 0, crop.getWidth(), 534e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka crop.getHeight(), m, true); 535e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (tmp != null) { 536e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka crop = tmp; 537e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 538e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 539e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 540e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mSaveCroppedBitmap) { 541e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCroppedBitmap = crop; 542e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 543e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 544e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Get output compression format 545e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka CompressFormat cf = 546e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka convertExtensionToCompressFormat(getFileExtension(mOutputFormat)); 547e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 548e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Compress to byte array 549e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048); 550e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) { 551e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // If we need to set to the wallpaper, set it 552e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka if (mSetWallpaper && wallpaperManager != null) { 553e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka try { 554e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka byte[] outByteArray = tmpOut.toByteArray(); 555e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka wallpaperManager.setStream(new ByteArrayInputStream(outByteArray)); 556e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka if (mOnBitmapCroppedHandler != null) { 557e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka mOnBitmapCroppedHandler.onBitmapCropped(outByteArray); 558e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 559e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka } catch (IOException e) { 560e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka Log.w(LOGTAG, "cannot write stream to wallpaper", e); 561e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka failure = true; 562e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 563e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 564e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 565e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.w(LOGTAG, "cannot compress bitmap"); 566e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka failure = true; 567e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 568e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 569e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return !failure; // True if any of the operations failed 570e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 571e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 572e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 573e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected Boolean doInBackground(Void... params) { 574e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return cropBitmap(); 575e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 576e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 577e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 578e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void onPostExecute(Boolean result) { 579e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka if (mOnEndRunnable != null) { 580e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka mOnEndRunnable.run(); 581e72aa7f0a64ff55f747751b7972ccb8acebab7daMichael Jurka } 582e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 583e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 584e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 585e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void updateWallpaperDimensions(int width, int height) { 586e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka String spKey = getSharedPreferencesKey(); 587e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE); 588e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka SharedPreferences.Editor editor = sp.edit(); 589e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (width != 0 && height != 0) { 590e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka editor.putInt(WALLPAPER_WIDTH_KEY, width); 591e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka editor.putInt(WALLPAPER_HEIGHT_KEY, height); 592e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 593e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka editor.remove(WALLPAPER_WIDTH_KEY); 594e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka editor.remove(WALLPAPER_HEIGHT_KEY); 595e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 596e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka editor.commit(); 597e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 598e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka suggestWallpaperDimension(getResources(), 599e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka sp, getWindowManager(), WallpaperManager.getInstance(this)); 600e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 601e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 602e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka static public void suggestWallpaperDimension(Resources res, 603e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final SharedPreferences sharedPrefs, 604e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka WindowManager windowManager, 605e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final WallpaperManager wallpaperManager) { 606e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka final Point defaultWallpaperSize = 607e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka WallpaperCropActivity.getDefaultWallpaperSize(res, windowManager); 608e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 609e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new Thread("suggestWallpaperDimension") { 610e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void run() { 611e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // If we have saved a wallpaper width/height, use that instead 612e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, defaultWallpaperSize.x); 613e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, defaultWallpaperSize.y); 614e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight); 615e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 616e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }.start(); 617e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 618e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 619e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 620e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected static RectF getMaxCropRect( 621e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int inWidth, int inHeight, int outWidth, int outHeight, boolean leftAligned) { 622e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RectF cropRect = new RectF(); 623e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Get a crop rect that will fit this 624e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (inWidth / (float) inHeight > outWidth / (float) outHeight) { 625e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.top = 0; 626e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.bottom = inHeight; 627e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.left = (inWidth - (outWidth / (float) outHeight) * inHeight) / 2; 628e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.right = inWidth - cropRect.left; 629e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (leftAligned) { 630e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.right -= cropRect.left; 631e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.left = 0; 632e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 633e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 634e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.left = 0; 635e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.right = inWidth; 636e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.top = (inHeight - (outHeight / (float) outWidth) * inWidth) / 2; 637e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka cropRect.bottom = inHeight - cropRect.top; 638e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 639e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return cropRect; 640e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 641e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 642e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected static CompressFormat convertExtensionToCompressFormat(String extension) { 643e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return extension.equals("png") ? CompressFormat.PNG : CompressFormat.JPEG; 644e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 645e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 646e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected static String getFileExtension(String requestFormat) { 647e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka String outputFormat = (requestFormat == null) 648e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ? "jpg" 649e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka : requestFormat; 650e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka outputFormat = outputFormat.toLowerCase(); 651e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return (outputFormat.equals("png") || outputFormat.equals("gif")) 652e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ? "png" // We don't support gif compression. 653e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka : "jpg"; 654e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 655e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka} 656