diff options
Diffstat (limited to 'src/com/android/gallery3d/filtershow/crop/CropActivity.java')
-rw-r--r-- | src/com/android/gallery3d/filtershow/crop/CropActivity.java | 697 |
1 files changed, 0 insertions, 697 deletions
diff --git a/src/com/android/gallery3d/filtershow/crop/CropActivity.java b/src/com/android/gallery3d/filtershow/crop/CropActivity.java deleted file mode 100644 index 0a0c36703..000000000 --- a/src/com/android/gallery3d/filtershow/crop/CropActivity.java +++ /dev/null @@ -1,697 +0,0 @@ -/* - * 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.gallery3d.filtershow.crop; - -import android.app.ActionBar; -import android.app.Activity; -import android.app.WallpaperManager; -import android.content.Context; -import android.content.Intent; -import android.content.res.Configuration; -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.Rect; -import android.graphics.RectF; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Bundle; -import android.provider.MediaStore; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.WindowManager; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.tools.SaveImage; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Activity for cropping an image. - */ -public class CropActivity extends Activity { - private static final String LOGTAG = "CropActivity"; - public static final String CROP_ACTION = "com.android.camera.action.CROP"; - private CropExtras mCropExtras = null; - private LoadBitmapTask mLoadBitmapTask = null; - - private int mOutputX = 0; - private int mOutputY = 0; - private Bitmap mOriginalBitmap = null; - private RectF mOriginalBounds = null; - private int mOriginalRotation = 0; - private Uri mSourceUri = null; - private CropView mCropView = null; - private View mSaveButton = null; - private boolean finalIOGuard = false; - - private static final int SELECT_PICTURE = 1; // request code for picker - - 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; - - // Flags - private static final int DO_SET_WALLPAPER = 1; - private static final int DO_RETURN_DATA = 1 << 1; - private static final int DO_EXTRA_OUTPUT = 1 << 2; - - private static final int FLAG_CHECK = DO_SET_WALLPAPER | DO_RETURN_DATA | DO_EXTRA_OUTPUT; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Intent intent = getIntent(); - setResult(RESULT_CANCELED, new Intent()); - mCropExtras = getExtrasFromIntent(intent); - if (mCropExtras != null && mCropExtras.getShowWhenLocked()) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); - } - - setContentView(R.layout.crop_activity); - mCropView = (CropView) findViewById(R.id.cropView); - - ActionBar actionBar = getActionBar(); - actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); - actionBar.setCustomView(R.layout.filtershow_actionbar); - - View mSaveButton = actionBar.getCustomView(); - mSaveButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - startFinishOutput(); - } - }); - - if (intent.getData() != null) { - mSourceUri = intent.getData(); - startLoadBitmap(mSourceUri); - } else { - pickImage(); - } - } - - private void enableSave(boolean enable) { - if (mSaveButton != null) { - mSaveButton.setEnabled(enable); - } - } - - @Override - protected void onDestroy() { - if (mLoadBitmapTask != null) { - mLoadBitmapTask.cancel(false); - } - super.onDestroy(); - } - - @Override - public void onConfigurationChanged (Configuration newConfig) { - super.onConfigurationChanged(newConfig); - mCropView.configChanged(); - } - - /** - * Opens a selector in Gallery to chose an image for use when none was given - * in the CROP intent. - */ - private void pickImage() { - Intent intent = new Intent(); - intent.setType("image/*"); - intent.setAction(Intent.ACTION_GET_CONTENT); - startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)), - SELECT_PICTURE); - } - - /** - * Callback for pickImage(). - */ - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == RESULT_OK && requestCode == SELECT_PICTURE) { - mSourceUri = data.getData(); - startLoadBitmap(mSourceUri); - } - } - - /** - * Gets screen size metric. - */ - private int getScreenImageSize() { - DisplayMetrics outMetrics = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(outMetrics); - return (int) Math.max(outMetrics.heightPixels, outMetrics.widthPixels); - } - - /** - * Method that loads a bitmap in an async task. - */ - private void startLoadBitmap(Uri uri) { - if (uri != null) { - enableSave(false); - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.VISIBLE); - mLoadBitmapTask = new LoadBitmapTask(); - mLoadBitmapTask.execute(uri); - } else { - cannotLoadImage(); - done(); - } - } - - /** - * Method called on UI thread with loaded bitmap. - */ - private void doneLoadBitmap(Bitmap bitmap, RectF bounds, int orientation) { - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.GONE); - mOriginalBitmap = bitmap; - mOriginalBounds = bounds; - mOriginalRotation = orientation; - if (bitmap != null && bitmap.getWidth() != 0 && bitmap.getHeight() != 0) { - RectF imgBounds = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); - mCropView.initialize(bitmap, imgBounds, imgBounds, orientation); - if (mCropExtras != null) { - int aspectX = mCropExtras.getAspectX(); - int aspectY = mCropExtras.getAspectY(); - mOutputX = mCropExtras.getOutputX(); - mOutputY = mCropExtras.getOutputY(); - if (mOutputX > 0 && mOutputY > 0) { - mCropView.applyAspect(mOutputX, mOutputY); - - } - float spotX = mCropExtras.getSpotlightX(); - float spotY = mCropExtras.getSpotlightY(); - if (spotX > 0 && spotY > 0) { - mCropView.setWallpaperSpotlight(spotX, spotY); - } - if (aspectX > 0 && aspectY > 0) { - mCropView.applyAspect(aspectX, aspectY); - } - } - enableSave(true); - } else { - Log.w(LOGTAG, "could not load image for cropping"); - cannotLoadImage(); - setResult(RESULT_CANCELED, new Intent()); - done(); - } - } - - /** - * Display toast for image loading failure. - */ - private void cannotLoadImage() { - CharSequence text = getString(R.string.cannot_load_image); - Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT); - toast.show(); - } - - /** - * AsyncTask for loading a bitmap into memory. - * - * @see #startLoadBitmap(Uri) - * @see #doneLoadBitmap(Bitmap) - */ - private class LoadBitmapTask extends AsyncTask<Uri, Void, Bitmap> { - int mBitmapSize; - Context mContext; - Rect mOriginalBounds; - int mOrientation; - - public LoadBitmapTask() { - mBitmapSize = getScreenImageSize(); - mContext = getApplicationContext(); - mOriginalBounds = new Rect(); - mOrientation = 0; - } - - @Override - protected Bitmap doInBackground(Uri... params) { - Uri uri = params[0]; - Bitmap bmap = ImageLoader.loadConstrainedBitmap(uri, mContext, mBitmapSize, - mOriginalBounds, false); - mOrientation = ImageLoader.getMetadataRotation(mContext, uri); - return bmap; - } - - @Override - protected void onPostExecute(Bitmap result) { - doneLoadBitmap(result, new RectF(mOriginalBounds), mOrientation); - } - } - - private void startFinishOutput() { - if (finalIOGuard) { - return; - } else { - finalIOGuard = true; - } - enableSave(false); - Uri destinationUri = null; - int flags = 0; - if (mOriginalBitmap != null && mCropExtras != null) { - if (mCropExtras.getExtraOutput() != null) { - destinationUri = mCropExtras.getExtraOutput(); - if (destinationUri != null) { - flags |= DO_EXTRA_OUTPUT; - } - } - if (mCropExtras.getSetAsWallpaper()) { - flags |= DO_SET_WALLPAPER; - } - if (mCropExtras.getReturnData()) { - flags |= DO_RETURN_DATA; - } - } - if (flags == 0) { - destinationUri = SaveImage.makeAndInsertUri(this, mSourceUri); - if (destinationUri != null) { - flags |= DO_EXTRA_OUTPUT; - } - } - if ((flags & FLAG_CHECK) != 0 && mOriginalBitmap != null) { - RectF photo = new RectF(0, 0, mOriginalBitmap.getWidth(), mOriginalBitmap.getHeight()); - RectF crop = getBitmapCrop(photo); - startBitmapIO(flags, mOriginalBitmap, mSourceUri, destinationUri, crop, - photo, mOriginalBounds, - (mCropExtras == null) ? null : mCropExtras.getOutputFormat(), mOriginalRotation); - return; - } - setResult(RESULT_CANCELED, new Intent()); - done(); - return; - } - - private void startBitmapIO(int flags, Bitmap currentBitmap, Uri sourceUri, Uri destUri, - RectF cropBounds, RectF photoBounds, RectF currentBitmapBounds, String format, - int rotation) { - if (cropBounds == null || photoBounds == null || currentBitmap == null - || currentBitmap.getWidth() == 0 || currentBitmap.getHeight() == 0 - || cropBounds.width() == 0 || cropBounds.height() == 0 || photoBounds.width() == 0 - || photoBounds.height() == 0) { - return; // fail fast - } - if ((flags & FLAG_CHECK) == 0) { - return; // no output options - } - if ((flags & DO_SET_WALLPAPER) != 0) { - Toast.makeText(this, R.string.setting_wallpaper, Toast.LENGTH_LONG).show(); - } - - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.VISIBLE); - BitmapIOTask ioTask = new BitmapIOTask(sourceUri, destUri, format, flags, cropBounds, - photoBounds, currentBitmapBounds, rotation, mOutputX, mOutputY); - ioTask.execute(currentBitmap); - } - - private void doneBitmapIO(boolean success, Intent intent) { - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.GONE); - if (success) { - setResult(RESULT_OK, intent); - } else { - setResult(RESULT_CANCELED, intent); - } - done(); - } - - private class BitmapIOTask extends AsyncTask<Bitmap, Void, Boolean> { - - private final WallpaperManager mWPManager; - InputStream mInStream = null; - OutputStream mOutStream = null; - String mOutputFormat = null; - Uri mOutUri = null; - Uri mInUri = null; - int mFlags = 0; - RectF mCrop = null; - RectF mPhoto = null; - RectF mOrig = null; - Intent mResultIntent = null; - int mRotation = 0; - - // 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 = getContentResolver().openInputStream(mInUri); - } catch (FileNotFoundException e) { - Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e); - } - } - } - - public BitmapIOTask(Uri sourceUri, Uri destUri, String outputFormat, int flags, - RectF cropBounds, RectF photoBounds, RectF originalBitmapBounds, int rotation, - int outputX, int outputY) { - mOutputFormat = outputFormat; - mOutStream = null; - mOutUri = destUri; - mInUri = sourceUri; - mFlags = flags; - mCrop = cropBounds; - mPhoto = photoBounds; - mOrig = originalBitmapBounds; - mWPManager = WallpaperManager.getInstance(getApplicationContext()); - mResultIntent = new Intent(); - mRotation = (rotation < 0) ? -rotation : rotation; - mRotation %= 360; - mRotation = 90 * (int) (mRotation / 90); // now mRotation is a multiple of 90 - mOutputX = outputX; - mOutputY = outputY; - - if ((flags & DO_EXTRA_OUTPUT) != 0) { - if (mOutUri == null) { - Log.w(LOGTAG, "cannot write file, no output URI given"); - } else { - try { - mOutStream = getContentResolver().openOutputStream(mOutUri); - } catch (FileNotFoundException e) { - Log.w(LOGTAG, "cannot write file: " + mOutUri.toString(), e); - } - } - } - - if ((flags & (DO_EXTRA_OUTPUT | DO_SET_WALLPAPER)) != 0) { - regenerateInputStream(); - } - } - - @Override - protected Boolean doInBackground(Bitmap... params) { - boolean failure = false; - Bitmap img = params[0]; - - // Set extra for crop bounds - if (mCrop != null && mPhoto != null && mOrig != null) { - RectF trueCrop = CropMath.getScaledCropBounds(mCrop, mPhoto, mOrig); - Matrix m = new Matrix(); - m.setRotate(mRotation); - m.mapRect(trueCrop); - if (trueCrop != null) { - Rect rounded = new Rect(); - trueCrop.roundOut(rounded); - mResultIntent.putExtra(CropExtras.KEY_CROPPED_RECT, rounded); - } - } - - // Find the small cropped bitmap that is returned in the intent - if ((mFlags & DO_RETURN_DATA) != 0) { - assert (img != null); - Bitmap ret = getCroppedImage(img, mCrop, mPhoto); - if (ret != null) { - ret = getDownsampledBitmap(ret, MAX_BMAP_IN_INTENT); - } - if (ret == null) { - Log.w(LOGTAG, "could not downsample bitmap to return in data"); - failure = true; - } else { - if (mRotation > 0) { - Matrix m = new Matrix(); - m.setRotate(mRotation); - Bitmap tmp = Bitmap.createBitmap(ret, 0, 0, ret.getWidth(), - ret.getHeight(), m, true); - if (tmp != null) { - ret = tmp; - } - } - mResultIntent.putExtra(CropExtras.KEY_DATA, ret); - } - } - - // Do the large cropped bitmap and/or set the wallpaper - if ((mFlags & (DO_EXTRA_OUTPUT | DO_SET_WALLPAPER)) != 0 && mInStream != null) { - // Find crop bounds (scaled to original image size) - RectF trueCrop = CropMath.getScaledCropBounds(mCrop, mPhoto, mOrig); - if (trueCrop == null) { - Log.w(LOGTAG, "cannot find crop for full size image"); - failure = true; - return false; - } - Rect roundedTrueCrop = new Rect(); - trueCrop.roundOut(roundedTrueCrop); - - if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) { - Log.w(LOGTAG, "crop has bad values for full size image"); - failure = true; - return false; - } - - // 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(); - options.inMutable = true; - 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) { - fullSize = BitmapFactory.decodeStream(mInStream); - } - 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; - } - } - // Get output compression format - CompressFormat cf = - convertExtensionToCompressFormat(getFileExtension(mOutputFormat)); - - // If we only need to output to a URI, compress straight to file - if (mFlags == DO_EXTRA_OUTPUT) { - if (mOutStream == null - || !crop.compress(cf, DEFAULT_COMPRESS_QUALITY, mOutStream)) { - Log.w(LOGTAG, "failed to compress bitmap to file: " + mOutUri.toString()); - failure = true; - } else { - mResultIntent.setData(mOutUri); - } - } else { - // Compress to byte array - ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048); - if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) { - - // If we need to output to a Uri, write compressed - // bitmap out - if ((mFlags & DO_EXTRA_OUTPUT) != 0) { - if (mOutStream == null) { - Log.w(LOGTAG, - "failed to compress bitmap to file: " + mOutUri.toString()); - failure = true; - } else { - try { - mOutStream.write(tmpOut.toByteArray()); - mResultIntent.setData(mOutUri); - } catch (IOException e) { - Log.w(LOGTAG, - "failed to compress bitmap to file: " - + mOutUri.toString(), e); - failure = true; - } - } - } - - // If we need to set to the wallpaper, set it - if ((mFlags & DO_SET_WALLPAPER) != 0 && mWPManager != null) { - if (mWPManager == null) { - Log.w(LOGTAG, "no wallpaper manager"); - failure = true; - } else { - try { - mWPManager.setStream(new ByteArrayInputStream(tmpOut - .toByteArray())); - } 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 void onPostExecute(Boolean result) { - Utils.closeSilently(mOutStream); - Utils.closeSilently(mInStream); - doneBitmapIO(result.booleanValue(), mResultIntent); - } - - } - - private void done() { - finish(); - } - - protected static Bitmap getCroppedImage(Bitmap image, RectF cropBounds, RectF photoBounds) { - RectF imageBounds = new RectF(0, 0, image.getWidth(), image.getHeight()); - RectF crop = CropMath.getScaledCropBounds(cropBounds, photoBounds, imageBounds); - if (crop == null) { - return null; - } - Rect intCrop = new Rect(); - crop.roundOut(intCrop); - return Bitmap.createBitmap(image, intCrop.left, intCrop.top, intCrop.width(), - intCrop.height()); - } - - protected static Bitmap getDownsampledBitmap(Bitmap image, int max_size) { - if (image == null || image.getWidth() == 0 || image.getHeight() == 0 || max_size < 16) { - throw new IllegalArgumentException("Bad argument to getDownsampledBitmap()"); - } - int shifts = 0; - int size = CropMath.getBitmapSize(image); - while (size > max_size) { - shifts++; - size /= 4; - } - Bitmap ret = Bitmap.createScaledBitmap(image, image.getWidth() >> shifts, - image.getHeight() >> shifts, true); - if (ret == null) { - return null; - } - // Handle edge case for rounding. - if (CropMath.getBitmapSize(ret) > max_size) { - return Bitmap.createScaledBitmap(ret, ret.getWidth() >> 1, ret.getHeight() >> 1, true); - } - return ret; - } - - /** - * Gets the crop extras from the intent, or null if none exist. - */ - protected static CropExtras getExtrasFromIntent(Intent intent) { - Bundle extras = intent.getExtras(); - if (extras != null) { - return new CropExtras(extras.getInt(CropExtras.KEY_OUTPUT_X, 0), - extras.getInt(CropExtras.KEY_OUTPUT_Y, 0), - extras.getBoolean(CropExtras.KEY_SCALE, true) && - extras.getBoolean(CropExtras.KEY_SCALE_UP_IF_NEEDED, false), - extras.getInt(CropExtras.KEY_ASPECT_X, 0), - extras.getInt(CropExtras.KEY_ASPECT_Y, 0), - extras.getBoolean(CropExtras.KEY_SET_AS_WALLPAPER, false), - extras.getBoolean(CropExtras.KEY_RETURN_DATA, false), - (Uri) extras.getParcelable(MediaStore.EXTRA_OUTPUT), - extras.getString(CropExtras.KEY_OUTPUT_FORMAT), - extras.getBoolean(CropExtras.KEY_SHOW_WHEN_LOCKED, false), - extras.getFloat(CropExtras.KEY_SPOTLIGHT_X), - extras.getFloat(CropExtras.KEY_SPOTLIGHT_Y)); - } - return null; - } - - 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"; - } - - private RectF getBitmapCrop(RectF imageBounds) { - RectF crop = mCropView.getCrop(); - RectF photo = mCropView.getPhoto(); - if (crop == null || photo == null) { - Log.w(LOGTAG, "could not get crop"); - return null; - } - RectF scaledCrop = CropMath.getScaledCropBounds(crop, photo, imageBounds); - return scaledCrop; - } -} |