summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/filtershow/crop
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/filtershow/crop')
-rw-r--r--src/com/android/gallery3d/filtershow/crop/BoundedRect.java368
-rw-r--r--src/com/android/gallery3d/filtershow/crop/CropActivity.java697
-rw-r--r--src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java168
-rw-r--r--src/com/android/gallery3d/filtershow/crop/CropExtras.java121
-rw-r--r--src/com/android/gallery3d/filtershow/crop/CropMath.java260
-rw-r--r--src/com/android/gallery3d/filtershow/crop/CropObject.java330
-rw-r--r--src/com/android/gallery3d/filtershow/crop/CropView.java378
7 files changed, 0 insertions, 2322 deletions
diff --git a/src/com/android/gallery3d/filtershow/crop/BoundedRect.java b/src/com/android/gallery3d/filtershow/crop/BoundedRect.java
deleted file mode 100644
index 13b8d6de1..000000000
--- a/src/com/android/gallery3d/filtershow/crop/BoundedRect.java
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (C) 2012 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.graphics.Matrix;
-import android.graphics.Rect;
-import android.graphics.RectF;
-
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
-
-import java.util.Arrays;
-
-/**
- * Maintains invariant that inner rectangle is constrained to be within the
- * outer, rotated rectangle.
- */
-public class BoundedRect {
- private float rot;
- private RectF outer;
- private RectF inner;
- private float[] innerRotated;
-
- public BoundedRect(float rotation, Rect outerRect, Rect innerRect) {
- rot = rotation;
- outer = new RectF(outerRect);
- inner = new RectF(innerRect);
- innerRotated = CropMath.getCornersFromRect(inner);
- rotateInner();
- if (!isConstrained())
- reconstrain();
- }
-
- public BoundedRect(float rotation, RectF outerRect, RectF innerRect) {
- rot = rotation;
- outer = new RectF(outerRect);
- inner = new RectF(innerRect);
- innerRotated = CropMath.getCornersFromRect(inner);
- rotateInner();
- if (!isConstrained())
- reconstrain();
- }
-
- public void resetTo(float rotation, RectF outerRect, RectF innerRect) {
- rot = rotation;
- outer.set(outerRect);
- inner.set(innerRect);
- innerRotated = CropMath.getCornersFromRect(inner);
- rotateInner();
- if (!isConstrained())
- reconstrain();
- }
-
- /**
- * Sets inner, and re-constrains it to fit within the rotated bounding rect.
- */
- public void setInner(RectF newInner) {
- if (inner.equals(newInner))
- return;
- inner = newInner;
- innerRotated = CropMath.getCornersFromRect(inner);
- rotateInner();
- if (!isConstrained())
- reconstrain();
- }
-
- /**
- * Sets rotation, and re-constrains inner to fit within the rotated bounding rect.
- */
- public void setRotation(float rotation) {
- if (rotation == rot)
- return;
- rot = rotation;
- innerRotated = CropMath.getCornersFromRect(inner);
- rotateInner();
- if (!isConstrained())
- reconstrain();
- }
-
- public void setToInner(RectF r) {
- r.set(inner);
- }
-
- public void setToOuter(RectF r) {
- r.set(outer);
- }
-
- public RectF getInner() {
- return new RectF(inner);
- }
-
- public RectF getOuter() {
- return new RectF(outer);
- }
-
- /**
- * Tries to move the inner rectangle by (dx, dy). If this would cause it to leave
- * the bounding rectangle, snaps the inner rectangle to the edge of the bounding
- * rectangle.
- */
- public void moveInner(float dx, float dy) {
- Matrix m0 = getInverseRotMatrix();
-
- RectF translatedInner = new RectF(inner);
- translatedInner.offset(dx, dy);
-
- float[] translatedInnerCorners = CropMath.getCornersFromRect(translatedInner);
- float[] outerCorners = CropMath.getCornersFromRect(outer);
-
- m0.mapPoints(translatedInnerCorners);
- float[] correction = {
- 0, 0
- };
-
- // find correction vectors for corners that have moved out of bounds
- for (int i = 0; i < translatedInnerCorners.length; i += 2) {
- float correctedInnerX = translatedInnerCorners[i] + correction[0];
- float correctedInnerY = translatedInnerCorners[i + 1] + correction[1];
- if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) {
- float[] badCorner = {
- correctedInnerX, correctedInnerY
- };
- float[] nearestSide = CropMath.closestSide(badCorner, outerCorners);
- float[] correctionVec =
- GeometryMathUtils.shortestVectorFromPointToLine(badCorner, nearestSide);
- correction[0] += correctionVec[0];
- correction[1] += correctionVec[1];
- }
- }
-
- for (int i = 0; i < translatedInnerCorners.length; i += 2) {
- float correctedInnerX = translatedInnerCorners[i] + correction[0];
- float correctedInnerY = translatedInnerCorners[i + 1] + correction[1];
- if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) {
- float[] correctionVec = {
- correctedInnerX, correctedInnerY
- };
- CropMath.getEdgePoints(outer, correctionVec);
- correctionVec[0] -= correctedInnerX;
- correctionVec[1] -= correctedInnerY;
- correction[0] += correctionVec[0];
- correction[1] += correctionVec[1];
- }
- }
-
- // Set correction
- for (int i = 0; i < translatedInnerCorners.length; i += 2) {
- float correctedInnerX = translatedInnerCorners[i] + correction[0];
- float correctedInnerY = translatedInnerCorners[i + 1] + correction[1];
- // update translated corners with correction vectors
- translatedInnerCorners[i] = correctedInnerX;
- translatedInnerCorners[i + 1] = correctedInnerY;
- }
-
- innerRotated = translatedInnerCorners;
- // reconstrain to update inner
- reconstrain();
- }
-
- /**
- * Attempts to resize the inner rectangle. If this would cause it to leave
- * the bounding rect, clips the inner rectangle to fit.
- */
- public void resizeInner(RectF newInner) {
- Matrix m = getRotMatrix();
- Matrix m0 = getInverseRotMatrix();
-
- float[] outerCorners = CropMath.getCornersFromRect(outer);
- m.mapPoints(outerCorners);
- float[] oldInnerCorners = CropMath.getCornersFromRect(inner);
- float[] newInnerCorners = CropMath.getCornersFromRect(newInner);
- RectF ret = new RectF(newInner);
-
- for (int i = 0; i < newInnerCorners.length; i += 2) {
- float[] c = {
- newInnerCorners[i], newInnerCorners[i + 1]
- };
- float[] c0 = Arrays.copyOf(c, 2);
- m0.mapPoints(c0);
- if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) {
- float[] outerSide = CropMath.closestSide(c, outerCorners);
- float[] pathOfCorner = {
- newInnerCorners[i], newInnerCorners[i + 1],
- oldInnerCorners[i], oldInnerCorners[i + 1]
- };
- float[] p = GeometryMathUtils.lineIntersect(pathOfCorner, outerSide);
- if (p == null) {
- // lines are parallel or not well defined, so don't resize
- p = new float[2];
- p[0] = oldInnerCorners[i];
- p[1] = oldInnerCorners[i + 1];
- }
- // relies on corners being in same order as method
- // getCornersFromRect
- switch (i) {
- case 0:
- case 1:
- ret.left = (p[0] > ret.left) ? p[0] : ret.left;
- ret.top = (p[1] > ret.top) ? p[1] : ret.top;
- break;
- case 2:
- case 3:
- ret.right = (p[0] < ret.right) ? p[0] : ret.right;
- ret.top = (p[1] > ret.top) ? p[1] : ret.top;
- break;
- case 4:
- case 5:
- ret.right = (p[0] < ret.right) ? p[0] : ret.right;
- ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom;
- break;
- case 6:
- case 7:
- ret.left = (p[0] > ret.left) ? p[0] : ret.left;
- ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom;
- break;
- default:
- break;
- }
- }
- }
- float[] retCorners = CropMath.getCornersFromRect(ret);
- m0.mapPoints(retCorners);
- innerRotated = retCorners;
- // reconstrain to update inner
- reconstrain();
- }
-
- /**
- * Attempts to resize the inner rectangle. If this would cause it to leave
- * the bounding rect, clips the inner rectangle to fit while maintaining
- * aspect ratio.
- */
- public void fixedAspectResizeInner(RectF newInner) {
- Matrix m = getRotMatrix();
- Matrix m0 = getInverseRotMatrix();
-
- float aspectW = inner.width();
- float aspectH = inner.height();
- float aspRatio = aspectW / aspectH;
- float[] corners = CropMath.getCornersFromRect(outer);
-
- m.mapPoints(corners);
- float[] oldInnerCorners = CropMath.getCornersFromRect(inner);
- float[] newInnerCorners = CropMath.getCornersFromRect(newInner);
-
- // find fixed corner
- int fixed = -1;
- if (inner.top == newInner.top) {
- if (inner.left == newInner.left)
- fixed = 0; // top left
- else if (inner.right == newInner.right)
- fixed = 2; // top right
- } else if (inner.bottom == newInner.bottom) {
- if (inner.right == newInner.right)
- fixed = 4; // bottom right
- else if (inner.left == newInner.left)
- fixed = 6; // bottom left
- }
- // no fixed corner, return without update
- if (fixed == -1)
- return;
- float widthSoFar = newInner.width();
- int moved = -1;
- for (int i = 0; i < newInnerCorners.length; i += 2) {
- float[] c = {
- newInnerCorners[i], newInnerCorners[i + 1]
- };
- float[] c0 = Arrays.copyOf(c, 2);
- m0.mapPoints(c0);
- if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) {
- moved = i;
- if (moved == fixed)
- continue;
- float[] l2 = CropMath.closestSide(c, corners);
- float[] l1 = {
- newInnerCorners[i], newInnerCorners[i + 1],
- oldInnerCorners[i], oldInnerCorners[i + 1]
- };
- float[] p = GeometryMathUtils.lineIntersect(l1, l2);
- if (p == null) {
- // lines are parallel or not well defined, so set to old
- // corner
- p = new float[2];
- p[0] = oldInnerCorners[i];
- p[1] = oldInnerCorners[i + 1];
- }
- // relies on corners being in same order as method
- // getCornersFromRect
- float fixed_x = oldInnerCorners[fixed];
- float fixed_y = oldInnerCorners[fixed + 1];
- float newWidth = Math.abs(fixed_x - p[0]);
- float newHeight = Math.abs(fixed_y - p[1]);
- newWidth = Math.max(newWidth, aspRatio * newHeight);
- if (newWidth < widthSoFar)
- widthSoFar = newWidth;
- }
- }
-
- float heightSoFar = widthSoFar / aspRatio;
- RectF ret = new RectF(inner);
- if (fixed == 0) {
- ret.right = ret.left + widthSoFar;
- ret.bottom = ret.top + heightSoFar;
- } else if (fixed == 2) {
- ret.left = ret.right - widthSoFar;
- ret.bottom = ret.top + heightSoFar;
- } else if (fixed == 4) {
- ret.left = ret.right - widthSoFar;
- ret.top = ret.bottom - heightSoFar;
- } else if (fixed == 6) {
- ret.right = ret.left + widthSoFar;
- ret.top = ret.bottom - heightSoFar;
- }
- float[] retCorners = CropMath.getCornersFromRect(ret);
- m0.mapPoints(retCorners);
- innerRotated = retCorners;
- // reconstrain to update inner
- reconstrain();
- }
-
- // internal methods
-
- private boolean isConstrained() {
- for (int i = 0; i < 8; i += 2) {
- if (!CropMath.inclusiveContains(outer, innerRotated[i], innerRotated[i + 1]))
- return false;
- }
- return true;
- }
-
- private void reconstrain() {
- // innerRotated has been changed to have incorrect values
- CropMath.getEdgePoints(outer, innerRotated);
- Matrix m = getRotMatrix();
- float[] unrotated = Arrays.copyOf(innerRotated, 8);
- m.mapPoints(unrotated);
- inner = CropMath.trapToRect(unrotated);
- }
-
- private void rotateInner() {
- Matrix m = getInverseRotMatrix();
- m.mapPoints(innerRotated);
- }
-
- private Matrix getRotMatrix() {
- Matrix m = new Matrix();
- m.setRotate(rot, outer.centerX(), outer.centerY());
- return m;
- }
-
- private Matrix getInverseRotMatrix() {
- Matrix m = new Matrix();
- m.setRotate(-rot, outer.centerX(), outer.centerY());
- return m;
- }
-}
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;
- }
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java b/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java
deleted file mode 100644
index b0d324cbb..000000000
--- a/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java
+++ /dev/null
@@ -1,168 +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.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.RectF;
-import android.graphics.Region;
-import android.graphics.drawable.Drawable;
-
-public abstract class CropDrawingUtils {
-
- public static void drawRuleOfThird(Canvas canvas, RectF bounds) {
- Paint p = new Paint();
- p.setStyle(Paint.Style.STROKE);
- p.setColor(Color.argb(128, 255, 255, 255));
- p.setStrokeWidth(2);
- float stepX = bounds.width() / 3.0f;
- float stepY = bounds.height() / 3.0f;
- float x = bounds.left + stepX;
- float y = bounds.top + stepY;
- for (int i = 0; i < 2; i++) {
- canvas.drawLine(x, bounds.top, x, bounds.bottom, p);
- x += stepX;
- }
- for (int j = 0; j < 2; j++) {
- canvas.drawLine(bounds.left, y, bounds.right, y, p);
- y += stepY;
- }
- }
-
- public static void drawCropRect(Canvas canvas, RectF bounds) {
- Paint p = new Paint();
- p.setStyle(Paint.Style.STROKE);
- p.setColor(Color.WHITE);
- p.setStrokeWidth(3);
- canvas.drawRect(bounds, p);
- }
-
- public static void drawIndicator(Canvas canvas, Drawable indicator, int indicatorSize,
- float centerX, float centerY) {
- int left = (int) centerX - indicatorSize / 2;
- int top = (int) centerY - indicatorSize / 2;
- indicator.setBounds(left, top, left + indicatorSize, top + indicatorSize);
- indicator.draw(canvas);
- }
-
- public static void drawIndicators(Canvas canvas, Drawable cropIndicator, int indicatorSize,
- RectF bounds, boolean fixedAspect, int selection) {
- boolean notMoving = (selection == CropObject.MOVE_NONE);
- if (fixedAspect) {
- if ((selection == CropObject.TOP_LEFT) || notMoving) {
- drawIndicator(canvas, cropIndicator, indicatorSize, bounds.left, bounds.top);
- }
- if ((selection == CropObject.TOP_RIGHT) || notMoving) {
- drawIndicator(canvas, cropIndicator, indicatorSize, bounds.right, bounds.top);
- }
- if ((selection == CropObject.BOTTOM_LEFT) || notMoving) {
- drawIndicator(canvas, cropIndicator, indicatorSize, bounds.left, bounds.bottom);
- }
- if ((selection == CropObject.BOTTOM_RIGHT) || notMoving) {
- drawIndicator(canvas, cropIndicator, indicatorSize, bounds.right, bounds.bottom);
- }
- } else {
- if (((selection & CropObject.MOVE_TOP) != 0) || notMoving) {
- drawIndicator(canvas, cropIndicator, indicatorSize, bounds.centerX(), bounds.top);
- }
- if (((selection & CropObject.MOVE_BOTTOM) != 0) || notMoving) {
- drawIndicator(canvas, cropIndicator, indicatorSize, bounds.centerX(), bounds.bottom);
- }
- if (((selection & CropObject.MOVE_LEFT) != 0) || notMoving) {
- drawIndicator(canvas, cropIndicator, indicatorSize, bounds.left, bounds.centerY());
- }
- if (((selection & CropObject.MOVE_RIGHT) != 0) || notMoving) {
- drawIndicator(canvas, cropIndicator, indicatorSize, bounds.right, bounds.centerY());
- }
- }
- }
-
- public static void drawWallpaperSelectionFrame(Canvas canvas, RectF cropBounds, float spotX,
- float spotY, Paint p, Paint shadowPaint) {
- float sx = cropBounds.width() * spotX;
- float sy = cropBounds.height() * spotY;
- float cx = cropBounds.centerX();
- float cy = cropBounds.centerY();
- RectF r1 = new RectF(cx - sx / 2, cy - sy / 2, cx + sx / 2, cy + sy / 2);
- float temp = sx;
- sx = sy;
- sy = temp;
- RectF r2 = new RectF(cx - sx / 2, cy - sy / 2, cx + sx / 2, cy + sy / 2);
- canvas.save();
- canvas.clipRect(cropBounds);
- canvas.clipRect(r1, Region.Op.DIFFERENCE);
- canvas.clipRect(r2, Region.Op.DIFFERENCE);
- canvas.drawPaint(shadowPaint);
- canvas.restore();
- Path path = new Path();
- path.moveTo(r1.left, r1.top);
- path.lineTo(r1.right, r1.top);
- path.moveTo(r1.left, r1.top);
- path.lineTo(r1.left, r1.bottom);
- path.moveTo(r1.left, r1.bottom);
- path.lineTo(r1.right, r1.bottom);
- path.moveTo(r1.right, r1.top);
- path.lineTo(r1.right, r1.bottom);
- path.moveTo(r2.left, r2.top);
- path.lineTo(r2.right, r2.top);
- path.moveTo(r2.right, r2.top);
- path.lineTo(r2.right, r2.bottom);
- path.moveTo(r2.left, r2.bottom);
- path.lineTo(r2.right, r2.bottom);
- path.moveTo(r2.left, r2.top);
- path.lineTo(r2.left, r2.bottom);
- canvas.drawPath(path, p);
- }
-
- public static void drawShadows(Canvas canvas, Paint p, RectF innerBounds, RectF outerBounds) {
- canvas.drawRect(outerBounds.left, outerBounds.top, innerBounds.right, innerBounds.top, p);
- canvas.drawRect(innerBounds.right, outerBounds.top, outerBounds.right, innerBounds.bottom,
- p);
- canvas.drawRect(innerBounds.left, innerBounds.bottom, outerBounds.right,
- outerBounds.bottom, p);
- canvas.drawRect(outerBounds.left, innerBounds.top, innerBounds.left, outerBounds.bottom, p);
- }
-
- public static Matrix getBitmapToDisplayMatrix(RectF imageBounds, RectF displayBounds) {
- Matrix m = new Matrix();
- CropDrawingUtils.setBitmapToDisplayMatrix(m, imageBounds, displayBounds);
- return m;
- }
-
- public static boolean setBitmapToDisplayMatrix(Matrix m, RectF imageBounds,
- RectF displayBounds) {
- m.reset();
- return m.setRectToRect(imageBounds, displayBounds, Matrix.ScaleToFit.CENTER);
- }
-
- public static boolean setImageToScreenMatrix(Matrix dst, RectF image,
- RectF screen, int rotation) {
- RectF rotatedImage = new RectF();
- dst.setRotate(rotation, image.centerX(), image.centerY());
- if (!dst.mapRect(rotatedImage, image)) {
- return false; // fails for rotations that are not multiples of 90
- // degrees
- }
- boolean rToR = dst.setRectToRect(rotatedImage, screen, Matrix.ScaleToFit.CENTER);
- boolean rot = dst.preRotate(rotation, image.centerX(), image.centerY());
- return rToR && rot;
- }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropExtras.java b/src/com/android/gallery3d/filtershow/crop/CropExtras.java
deleted file mode 100644
index 60fe9af53..000000000
--- a/src/com/android/gallery3d/filtershow/crop/CropExtras.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2012 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.net.Uri;
-
-public class CropExtras {
-
- public static final String KEY_CROPPED_RECT = "cropped-rect";
- public static final String KEY_OUTPUT_X = "outputX";
- public static final String KEY_OUTPUT_Y = "outputY";
- public static final String KEY_SCALE = "scale";
- public static final String KEY_SCALE_UP_IF_NEEDED = "scaleUpIfNeeded";
- public static final String KEY_ASPECT_X = "aspectX";
- public static final String KEY_ASPECT_Y = "aspectY";
- public static final String KEY_SET_AS_WALLPAPER = "set-as-wallpaper";
- public static final String KEY_RETURN_DATA = "return-data";
- public static final String KEY_DATA = "data";
- public static final String KEY_SPOTLIGHT_X = "spotlightX";
- public static final String KEY_SPOTLIGHT_Y = "spotlightY";
- public static final String KEY_SHOW_WHEN_LOCKED = "showWhenLocked";
- public static final String KEY_OUTPUT_FORMAT = "outputFormat";
-
- private int mOutputX = 0;
- private int mOutputY = 0;
- private boolean mScaleUp = true;
- private int mAspectX = 0;
- private int mAspectY = 0;
- private boolean mSetAsWallpaper = false;
- private boolean mReturnData = false;
- private Uri mExtraOutput = null;
- private String mOutputFormat = null;
- private boolean mShowWhenLocked = false;
- private float mSpotlightX = 0;
- private float mSpotlightY = 0;
-
- public CropExtras(int outputX, int outputY, boolean scaleUp, int aspectX, int aspectY,
- boolean setAsWallpaper, boolean returnData, Uri extraOutput, String outputFormat,
- boolean showWhenLocked, float spotlightX, float spotlightY) {
- mOutputX = outputX;
- mOutputY = outputY;
- mScaleUp = scaleUp;
- mAspectX = aspectX;
- mAspectY = aspectY;
- mSetAsWallpaper = setAsWallpaper;
- mReturnData = returnData;
- mExtraOutput = extraOutput;
- mOutputFormat = outputFormat;
- mShowWhenLocked = showWhenLocked;
- mSpotlightX = spotlightX;
- mSpotlightY = spotlightY;
- }
-
- public CropExtras(CropExtras c) {
- this(c.mOutputX, c.mOutputY, c.mScaleUp, c.mAspectX, c.mAspectY, c.mSetAsWallpaper,
- c.mReturnData, c.mExtraOutput, c.mOutputFormat, c.mShowWhenLocked,
- c.mSpotlightX, c.mSpotlightY);
- }
-
- public int getOutputX() {
- return mOutputX;
- }
-
- public int getOutputY() {
- return mOutputY;
- }
-
- public boolean getScaleUp() {
- return mScaleUp;
- }
-
- public int getAspectX() {
- return mAspectX;
- }
-
- public int getAspectY() {
- return mAspectY;
- }
-
- public boolean getSetAsWallpaper() {
- return mSetAsWallpaper;
- }
-
- public boolean getReturnData() {
- return mReturnData;
- }
-
- public Uri getExtraOutput() {
- return mExtraOutput;
- }
-
- public String getOutputFormat() {
- return mOutputFormat;
- }
-
- public boolean getShowWhenLocked() {
- return mShowWhenLocked;
- }
-
- public float getSpotlightX() {
- return mSpotlightX;
- }
-
- public float getSpotlightY() {
- return mSpotlightY;
- }
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropMath.java b/src/com/android/gallery3d/filtershow/crop/CropMath.java
deleted file mode 100644
index 02c65310e..000000000
--- a/src/com/android/gallery3d/filtershow/crop/CropMath.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (C) 2012 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.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.graphics.RectF;
-
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
-
-import java.util.Arrays;
-
-public class CropMath {
-
- /**
- * Gets a float array of the 2D coordinates representing a rectangles
- * corners.
- * The order of the corners in the float array is:
- * 0------->1
- * ^ |
- * | v
- * 3<-------2
- *
- * @param r the rectangle to get the corners of
- * @return the float array of corners (8 floats)
- */
-
- public static float[] getCornersFromRect(RectF r) {
- float[] corners = {
- r.left, r.top,
- r.right, r.top,
- r.right, r.bottom,
- r.left, r.bottom
- };
- return corners;
- }
-
- /**
- * Returns true iff point (x, y) is within or on the rectangle's bounds.
- * RectF's "contains" function treats points on the bottom and right bound
- * as not being contained.
- *
- * @param r the rectangle
- * @param x the x value of the point
- * @param y the y value of the point
- * @return
- */
- public static boolean inclusiveContains(RectF r, float x, float y) {
- return !(x > r.right || x < r.left || y > r.bottom || y < r.top);
- }
-
- /**
- * Takes an array of 2D coordinates representing corners and returns the
- * smallest rectangle containing those coordinates.
- *
- * @param array array of 2D coordinates
- * @return smallest rectangle containing coordinates
- */
- public static RectF trapToRect(float[] array) {
- RectF r = new RectF(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY,
- Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
- for (int i = 1; i < array.length; i += 2) {
- float x = array[i - 1];
- float y = array[i];
- r.left = (x < r.left) ? x : r.left;
- r.top = (y < r.top) ? y : r.top;
- r.right = (x > r.right) ? x : r.right;
- r.bottom = (y > r.bottom) ? y : r.bottom;
- }
- r.sort();
- return r;
- }
-
- /**
- * If edge point [x, y] in array [x0, y0, x1, y1, ...] is outside of the
- * image bound rectangle, clamps it to the edge of the rectangle.
- *
- * @param imageBound the rectangle to clamp edge points to.
- * @param array an array of points to clamp to the rectangle, gets set to
- * the clamped values.
- */
- public static void getEdgePoints(RectF imageBound, float[] array) {
- if (array.length < 2)
- return;
- for (int x = 0; x < array.length; x += 2) {
- array[x] = GeometryMathUtils.clamp(array[x], imageBound.left, imageBound.right);
- array[x + 1] = GeometryMathUtils.clamp(array[x + 1], imageBound.top, imageBound.bottom);
- }
- }
-
- /**
- * Takes a point and the corners of a rectangle and returns the two corners
- * representing the side of the rectangle closest to the point.
- *
- * @param point the point which is being checked
- * @param corners the corners of the rectangle
- * @return two corners representing the side of the rectangle
- */
- public static float[] closestSide(float[] point, float[] corners) {
- int len = corners.length;
- float oldMag = Float.POSITIVE_INFINITY;
- float[] bestLine = null;
- for (int i = 0; i < len; i += 2) {
- float[] line = {
- corners[i], corners[(i + 1) % len],
- corners[(i + 2) % len], corners[(i + 3) % len]
- };
- float mag = GeometryMathUtils.vectorLength(
- GeometryMathUtils.shortestVectorFromPointToLine(point, line));
- if (mag < oldMag) {
- oldMag = mag;
- bestLine = line;
- }
- }
- return bestLine;
- }
-
- /**
- * Checks if a given point is within a rotated rectangle.
- *
- * @param point 2D point to check
- * @param bound rectangle to rotate
- * @param rot angle of rotation about rectangle center
- * @return true if point is within rotated rectangle
- */
- public static boolean pointInRotatedRect(float[] point, RectF bound, float rot) {
- Matrix m = new Matrix();
- float[] p = Arrays.copyOf(point, 2);
- m.setRotate(rot, bound.centerX(), bound.centerY());
- Matrix m0 = new Matrix();
- if (!m.invert(m0))
- return false;
- m0.mapPoints(p);
- return inclusiveContains(bound, p[0], p[1]);
- }
-
- /**
- * Checks if a given point is within a rotated rectangle.
- *
- * @param point 2D point to check
- * @param rotatedRect corners of a rotated rectangle
- * @param center center of the rotated rectangle
- * @return true if point is within rotated rectangle
- */
- public static boolean pointInRotatedRect(float[] point, float[] rotatedRect, float[] center) {
- RectF unrotated = new RectF();
- float angle = getUnrotated(rotatedRect, center, unrotated);
- return pointInRotatedRect(point, unrotated, angle);
- }
-
- /**
- * Resizes rectangle to have a certain aspect ratio (center remains
- * stationary).
- *
- * @param r rectangle to resize
- * @param w new width aspect
- * @param h new height aspect
- */
- public static void fixAspectRatio(RectF r, float w, float h) {
- float scale = Math.min(r.width() / w, r.height() / h);
- float centX = r.centerX();
- float centY = r.centerY();
- float hw = scale * w / 2;
- float hh = scale * h / 2;
- r.set(centX - hw, centY - hh, centX + hw, centY + hh);
- }
-
- /**
- * Resizes rectangle to have a certain aspect ratio (center remains
- * stationary) while constraining it to remain within the original rect.
- *
- * @param r rectangle to resize
- * @param w new width aspect
- * @param h new height aspect
- */
- public static void fixAspectRatioContained(RectF r, float w, float h) {
- float origW = r.width();
- float origH = r.height();
- float origA = origW / origH;
- float a = w / h;
- float finalW = origW;
- float finalH = origH;
- if (origA < a) {
- finalH = origW / a;
- r.top = r.centerY() - finalH / 2;
- r.bottom = r.top + finalH;
- } else {
- finalW = origH * a;
- r.left = r.centerX() - finalW / 2;
- r.right = r.left + finalW;
- }
- }
-
- /**
- * Stretches/Scales/Translates photoBounds to match displayBounds, and
- * and returns an equivalent stretched/scaled/translated cropBounds or null
- * if the mapping is invalid.
- * @param cropBounds cropBounds to transform
- * @param photoBounds original bounds containing crop bounds
- * @param displayBounds final bounds for crop
- * @return the stretched/scaled/translated crop bounds that fit within displayBounds
- */
- public static RectF getScaledCropBounds(RectF cropBounds, RectF photoBounds,
- RectF displayBounds) {
- Matrix m = new Matrix();
- m.setRectToRect(photoBounds, displayBounds, Matrix.ScaleToFit.FILL);
- RectF trueCrop = new RectF(cropBounds);
- if (!m.mapRect(trueCrop)) {
- return null;
- }
- return trueCrop;
- }
-
- /**
- * Returns the size of a bitmap in bytes.
- * @param bmap bitmap whose size to check
- * @return bitmap size in bytes
- */
- public static int getBitmapSize(Bitmap bmap) {
- return bmap.getRowBytes() * bmap.getHeight();
- }
-
- /**
- * Constrains rotation to be in [0, 90, 180, 270] rounding down.
- * @param rotation any rotation value, in degrees
- * @return integer rotation in [0, 90, 180, 270]
- */
- public static int constrainedRotation(float rotation) {
- int r = (int) ((rotation % 360) / 90);
- r = (r < 0) ? (r + 4) : r;
- return r * 90;
- }
-
- private static float getUnrotated(float[] rotatedRect, float[] center, RectF unrotated) {
- float dy = rotatedRect[1] - rotatedRect[3];
- float dx = rotatedRect[0] - rotatedRect[2];
- float angle = (float) (Math.atan(dy / dx) * 180 / Math.PI);
- Matrix m = new Matrix();
- m.setRotate(-angle, center[0], center[1]);
- float[] unrotatedRect = new float[rotatedRect.length];
- m.mapPoints(unrotatedRect, rotatedRect);
- unrotated.set(trapToRect(unrotatedRect));
- return angle;
- }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropObject.java b/src/com/android/gallery3d/filtershow/crop/CropObject.java
deleted file mode 100644
index b98ed1bfd..000000000
--- a/src/com/android/gallery3d/filtershow/crop/CropObject.java
+++ /dev/null
@@ -1,330 +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.graphics.Rect;
-import android.graphics.RectF;
-
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
-
-public class CropObject {
- private BoundedRect mBoundedRect;
- private float mAspectWidth = 1;
- private float mAspectHeight = 1;
- private boolean mFixAspectRatio = false;
- private float mRotation = 0;
- private float mTouchTolerance = 45;
- private float mMinSideSize = 20;
-
- public static final int MOVE_NONE = 0;
- // Sides
- public static final int MOVE_LEFT = 1;
- public static final int MOVE_TOP = 2;
- public static final int MOVE_RIGHT = 4;
- public static final int MOVE_BOTTOM = 8;
- public static final int MOVE_BLOCK = 16;
-
- // Corners
- public static final int TOP_LEFT = MOVE_TOP | MOVE_LEFT;
- public static final int TOP_RIGHT = MOVE_TOP | MOVE_RIGHT;
- public static final int BOTTOM_RIGHT = MOVE_BOTTOM | MOVE_RIGHT;
- public static final int BOTTOM_LEFT = MOVE_BOTTOM | MOVE_LEFT;
-
- private int mMovingEdges = MOVE_NONE;
-
- public CropObject(Rect outerBound, Rect innerBound, int outerAngle) {
- mBoundedRect = new BoundedRect(outerAngle % 360, outerBound, innerBound);
- }
-
- public CropObject(RectF outerBound, RectF innerBound, int outerAngle) {
- mBoundedRect = new BoundedRect(outerAngle % 360, outerBound, innerBound);
- }
-
- public void resetBoundsTo(RectF inner, RectF outer) {
- mBoundedRect.resetTo(0, outer, inner);
- }
-
- public void getInnerBounds(RectF r) {
- mBoundedRect.setToInner(r);
- }
-
- public void getOuterBounds(RectF r) {
- mBoundedRect.setToOuter(r);
- }
-
- public RectF getInnerBounds() {
- return mBoundedRect.getInner();
- }
-
- public RectF getOuterBounds() {
- return mBoundedRect.getOuter();
- }
-
- public int getSelectState() {
- return mMovingEdges;
- }
-
- public boolean isFixedAspect() {
- return mFixAspectRatio;
- }
-
- public void rotateOuter(int angle) {
- mRotation = angle % 360;
- mBoundedRect.setRotation(mRotation);
- clearSelectState();
- }
-
- public boolean setInnerAspectRatio(float width, float height) {
- if (width <= 0 || height <= 0) {
- throw new IllegalArgumentException("Width and Height must be greater than zero");
- }
- RectF inner = mBoundedRect.getInner();
- CropMath.fixAspectRatioContained(inner, width, height);
- if (inner.width() < mMinSideSize || inner.height() < mMinSideSize) {
- return false;
- }
- mAspectWidth = width;
- mAspectHeight = height;
- mFixAspectRatio = true;
- mBoundedRect.setInner(inner);
- clearSelectState();
- return true;
- }
-
- public void setTouchTolerance(float tolerance) {
- if (tolerance <= 0) {
- throw new IllegalArgumentException("Tolerance must be greater than zero");
- }
- mTouchTolerance = tolerance;
- }
-
- public void setMinInnerSideSize(float minSide) {
- if (minSide <= 0) {
- throw new IllegalArgumentException("Min dide must be greater than zero");
- }
- mMinSideSize = minSide;
- }
-
- public void unsetAspectRatio() {
- mFixAspectRatio = false;
- clearSelectState();
- }
-
- public boolean hasSelectedEdge() {
- return mMovingEdges != MOVE_NONE;
- }
-
- public static boolean checkCorner(int selected) {
- return selected == TOP_LEFT || selected == TOP_RIGHT || selected == BOTTOM_RIGHT
- || selected == BOTTOM_LEFT;
- }
-
- public static boolean checkEdge(int selected) {
- return selected == MOVE_LEFT || selected == MOVE_TOP || selected == MOVE_RIGHT
- || selected == MOVE_BOTTOM;
- }
-
- public static boolean checkBlock(int selected) {
- return selected == MOVE_BLOCK;
- }
-
- public static boolean checkValid(int selected) {
- return selected == MOVE_NONE || checkBlock(selected) || checkEdge(selected)
- || checkCorner(selected);
- }
-
- public void clearSelectState() {
- mMovingEdges = MOVE_NONE;
- }
-
- public int wouldSelectEdge(float x, float y) {
- int edgeSelected = calculateSelectedEdge(x, y);
- if (edgeSelected != MOVE_NONE && edgeSelected != MOVE_BLOCK) {
- return edgeSelected;
- }
- return MOVE_NONE;
- }
-
- public boolean selectEdge(int edge) {
- if (!checkValid(edge)) {
- // temporary
- throw new IllegalArgumentException("bad edge selected");
- // return false;
- }
- if ((mFixAspectRatio && !checkCorner(edge)) && !checkBlock(edge) && edge != MOVE_NONE) {
- // temporary
- throw new IllegalArgumentException("bad corner selected");
- // return false;
- }
- mMovingEdges = edge;
- return true;
- }
-
- public boolean selectEdge(float x, float y) {
- int edgeSelected = calculateSelectedEdge(x, y);
- if (mFixAspectRatio) {
- edgeSelected = fixEdgeToCorner(edgeSelected);
- }
- if (edgeSelected == MOVE_NONE) {
- return false;
- }
- return selectEdge(edgeSelected);
- }
-
- public boolean moveCurrentSelection(float dX, float dY) {
- if (mMovingEdges == MOVE_NONE) {
- return false;
- }
- RectF crop = mBoundedRect.getInner();
-
- float minWidthHeight = mMinSideSize;
-
- int movingEdges = mMovingEdges;
- if (movingEdges == MOVE_BLOCK) {
- mBoundedRect.moveInner(dX, dY);
- return true;
- } else {
- float dx = 0;
- float dy = 0;
-
- if ((movingEdges & MOVE_LEFT) != 0) {
- dx = Math.min(crop.left + dX, crop.right - minWidthHeight) - crop.left;
- }
- if ((movingEdges & MOVE_TOP) != 0) {
- dy = Math.min(crop.top + dY, crop.bottom - minWidthHeight) - crop.top;
- }
- if ((movingEdges & MOVE_RIGHT) != 0) {
- dx = Math.max(crop.right + dX, crop.left + minWidthHeight)
- - crop.right;
- }
- if ((movingEdges & MOVE_BOTTOM) != 0) {
- dy = Math.max(crop.bottom + dY, crop.top + minWidthHeight)
- - crop.bottom;
- }
-
- if (mFixAspectRatio) {
- float[] l1 = {
- crop.left, crop.bottom
- };
- float[] l2 = {
- crop.right, crop.top
- };
- if (movingEdges == TOP_LEFT || movingEdges == BOTTOM_RIGHT) {
- l1[1] = crop.top;
- l2[1] = crop.bottom;
- }
- float[] b = {
- l1[0] - l2[0], l1[1] - l2[1]
- };
- float[] disp = {
- dx, dy
- };
- float[] bUnit = GeometryMathUtils.normalize(b);
- float sp = GeometryMathUtils.scalarProjection(disp, bUnit);
- dx = sp * bUnit[0];
- dy = sp * bUnit[1];
- RectF newCrop = fixedCornerResize(crop, movingEdges, dx, dy);
-
- mBoundedRect.fixedAspectResizeInner(newCrop);
- } else {
- if ((movingEdges & MOVE_LEFT) != 0) {
- crop.left += dx;
- }
- if ((movingEdges & MOVE_TOP) != 0) {
- crop.top += dy;
- }
- if ((movingEdges & MOVE_RIGHT) != 0) {
- crop.right += dx;
- }
- if ((movingEdges & MOVE_BOTTOM) != 0) {
- crop.bottom += dy;
- }
- mBoundedRect.resizeInner(crop);
- }
- }
- return true;
- }
-
- // Helper methods
-
- private int calculateSelectedEdge(float x, float y) {
- RectF cropped = mBoundedRect.getInner();
-
- float left = Math.abs(x - cropped.left);
- float right = Math.abs(x - cropped.right);
- float top = Math.abs(y - cropped.top);
- float bottom = Math.abs(y - cropped.bottom);
-
- int edgeSelected = MOVE_NONE;
- // Check left or right.
- if ((left <= mTouchTolerance) && ((y + mTouchTolerance) >= cropped.top)
- && ((y - mTouchTolerance) <= cropped.bottom) && (left < right)) {
- edgeSelected |= MOVE_LEFT;
- }
- else if ((right <= mTouchTolerance) && ((y + mTouchTolerance) >= cropped.top)
- && ((y - mTouchTolerance) <= cropped.bottom)) {
- edgeSelected |= MOVE_RIGHT;
- }
-
- // Check top or bottom.
- if ((top <= mTouchTolerance) && ((x + mTouchTolerance) >= cropped.left)
- && ((x - mTouchTolerance) <= cropped.right) && (top < bottom)) {
- edgeSelected |= MOVE_TOP;
- }
- else if ((bottom <= mTouchTolerance) && ((x + mTouchTolerance) >= cropped.left)
- && ((x - mTouchTolerance) <= cropped.right)) {
- edgeSelected |= MOVE_BOTTOM;
- }
- return edgeSelected;
- }
-
- private static RectF fixedCornerResize(RectF r, int moving_corner, float dx, float dy) {
- RectF newCrop = null;
- // Fix opposite corner in place and move sides
- if (moving_corner == BOTTOM_RIGHT) {
- newCrop = new RectF(r.left, r.top, r.left + r.width() + dx, r.top + r.height()
- + dy);
- } else if (moving_corner == BOTTOM_LEFT) {
- newCrop = new RectF(r.right - r.width() + dx, r.top, r.right, r.top + r.height()
- + dy);
- } else if (moving_corner == TOP_LEFT) {
- newCrop = new RectF(r.right - r.width() + dx, r.bottom - r.height() + dy,
- r.right, r.bottom);
- } else if (moving_corner == TOP_RIGHT) {
- newCrop = new RectF(r.left, r.bottom - r.height() + dy, r.left
- + r.width() + dx, r.bottom);
- }
- return newCrop;
- }
-
- private static int fixEdgeToCorner(int moving_edges) {
- if (moving_edges == MOVE_LEFT) {
- moving_edges |= MOVE_TOP;
- }
- if (moving_edges == MOVE_TOP) {
- moving_edges |= MOVE_LEFT;
- }
- if (moving_edges == MOVE_RIGHT) {
- moving_edges |= MOVE_BOTTOM;
- }
- if (moving_edges == MOVE_BOTTOM) {
- moving_edges |= MOVE_RIGHT;
- }
- return moving_edges;
- }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropView.java b/src/com/android/gallery3d/filtershow/crop/CropView.java
deleted file mode 100644
index bbb7cfd4c..000000000
--- a/src/com/android/gallery3d/filtershow/crop/CropView.java
+++ /dev/null
@@ -1,378 +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.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.DashPathEffect;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.NinePatchDrawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.gallery3d.R;
-
-
-public class CropView extends View {
- private static final String LOGTAG = "CropView";
-
- private RectF mImageBounds = new RectF();
- private RectF mScreenBounds = new RectF();
- private RectF mScreenImageBounds = new RectF();
- private RectF mScreenCropBounds = new RectF();
- private Rect mShadowBounds = new Rect();
-
- private Bitmap mBitmap;
- private Paint mPaint = new Paint();
-
- private NinePatchDrawable mShadow;
- private CropObject mCropObj = null;
- private Drawable mCropIndicator;
- private int mIndicatorSize;
- private int mRotation = 0;
- private boolean mMovingBlock = false;
- private Matrix mDisplayMatrix = null;
- private Matrix mDisplayMatrixInverse = null;
- private boolean mDirty = false;
-
- private float mPrevX = 0;
- private float mPrevY = 0;
- private float mSpotX = 0;
- private float mSpotY = 0;
- private boolean mDoSpot = false;
-
- private int mShadowMargin = 15;
- private int mMargin = 32;
- private int mOverlayShadowColor = 0xCF000000;
- private int mOverlayWPShadowColor = 0x5F000000;
- private int mWPMarkerColor = 0x7FFFFFFF;
- private int mMinSideSize = 90;
- private int mTouchTolerance = 40;
- private float mDashOnLength = 20;
- private float mDashOffLength = 10;
-
- private enum Mode {
- NONE, MOVE
- }
-
- private Mode mState = Mode.NONE;
-
- public CropView(Context context) {
- super(context);
- setup(context);
- }
-
- public CropView(Context context, AttributeSet attrs) {
- super(context, attrs);
- setup(context);
- }
-
- public CropView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- setup(context);
- }
-
- private void setup(Context context) {
- Resources rsc = context.getResources();
- mShadow = (NinePatchDrawable) rsc.getDrawable(R.drawable.geometry_shadow);
- mCropIndicator = rsc.getDrawable(R.drawable.camera_crop);
- mIndicatorSize = (int) rsc.getDimension(R.dimen.crop_indicator_size);
- mShadowMargin = (int) rsc.getDimension(R.dimen.shadow_margin);
- mMargin = (int) rsc.getDimension(R.dimen.preview_margin);
- mMinSideSize = (int) rsc.getDimension(R.dimen.crop_min_side);
- mTouchTolerance = (int) rsc.getDimension(R.dimen.crop_touch_tolerance);
- mOverlayShadowColor = (int) rsc.getColor(R.color.crop_shadow_color);
- mOverlayWPShadowColor = (int) rsc.getColor(R.color.crop_shadow_wp_color);
- mWPMarkerColor = (int) rsc.getColor(R.color.crop_wp_markers);
- mDashOnLength = rsc.getDimension(R.dimen.wp_selector_dash_length);
- mDashOffLength = rsc.getDimension(R.dimen.wp_selector_off_length);
- }
-
- public void initialize(Bitmap image, RectF newCropBounds, RectF newPhotoBounds, int rotation) {
- mBitmap = image;
- if (mCropObj != null) {
- RectF crop = mCropObj.getInnerBounds();
- RectF containing = mCropObj.getOuterBounds();
- if (crop != newCropBounds || containing != newPhotoBounds
- || mRotation != rotation) {
- mRotation = rotation;
- mCropObj.resetBoundsTo(newCropBounds, newPhotoBounds);
- clearDisplay();
- }
- } else {
- mRotation = rotation;
- mCropObj = new CropObject(newPhotoBounds, newCropBounds, 0);
- clearDisplay();
- }
- }
-
- public RectF getCrop() {
- return mCropObj.getInnerBounds();
- }
-
- public RectF getPhoto() {
- return mCropObj.getOuterBounds();
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- float x = event.getX();
- float y = event.getY();
- if (mDisplayMatrix == null || mDisplayMatrixInverse == null) {
- return true;
- }
- float[] touchPoint = {
- x, y
- };
- mDisplayMatrixInverse.mapPoints(touchPoint);
- x = touchPoint[0];
- y = touchPoint[1];
- switch (event.getActionMasked()) {
- case (MotionEvent.ACTION_DOWN):
- if (mState == Mode.NONE) {
- if (!mCropObj.selectEdge(x, y)) {
- mMovingBlock = mCropObj.selectEdge(CropObject.MOVE_BLOCK);
- }
- mPrevX = x;
- mPrevY = y;
- mState = Mode.MOVE;
- }
- break;
- case (MotionEvent.ACTION_UP):
- if (mState == Mode.MOVE) {
- mCropObj.selectEdge(CropObject.MOVE_NONE);
- mMovingBlock = false;
- mPrevX = x;
- mPrevY = y;
- mState = Mode.NONE;
- }
- break;
- case (MotionEvent.ACTION_MOVE):
- if (mState == Mode.MOVE) {
- float dx = x - mPrevX;
- float dy = y - mPrevY;
- mCropObj.moveCurrentSelection(dx, dy);
- mPrevX = x;
- mPrevY = y;
- }
- break;
- default:
- break;
- }
- invalidate();
- return true;
- }
-
- private void reset() {
- Log.w(LOGTAG, "crop reset called");
- mState = Mode.NONE;
- mCropObj = null;
- mRotation = 0;
- mMovingBlock = false;
- clearDisplay();
- }
-
- private void clearDisplay() {
- mDisplayMatrix = null;
- mDisplayMatrixInverse = null;
- invalidate();
- }
-
- protected void configChanged() {
- mDirty = true;
- }
-
- public void applyFreeAspect() {
- mCropObj.unsetAspectRatio();
- invalidate();
- }
-
- public void applyOriginalAspect() {
- RectF outer = mCropObj.getOuterBounds();
- float w = outer.width();
- float h = outer.height();
- if (w > 0 && h > 0) {
- applyAspect(w, h);
- mCropObj.resetBoundsTo(outer, outer);
- } else {
- Log.w(LOGTAG, "failed to set aspect ratio original");
- }
- }
-
- public void applySquareAspect() {
- applyAspect(1, 1);
- }
-
- public void applyAspect(float x, float y) {
- if (x <= 0 || y <= 0) {
- throw new IllegalArgumentException("Bad arguments to applyAspect");
- }
- // If we are rotated by 90 degrees from horizontal, swap x and y
- if (((mRotation < 0) ? -mRotation : mRotation) % 180 == 90) {
- float tmp = x;
- x = y;
- y = tmp;
- }
- if (!mCropObj.setInnerAspectRatio(x, y)) {
- Log.w(LOGTAG, "failed to set aspect ratio");
- }
- invalidate();
- }
-
- public void setWallpaperSpotlight(float spotlightX, float spotlightY) {
- mSpotX = spotlightX;
- mSpotY = spotlightY;
- if (mSpotX > 0 && mSpotY > 0) {
- mDoSpot = true;
- }
- }
-
- public void unsetWallpaperSpotlight() {
- mDoSpot = false;
- }
-
- /**
- * Rotates first d bits in integer x to the left some number of times.
- */
- private int bitCycleLeft(int x, int times, int d) {
- int mask = (1 << d) - 1;
- int mout = x & mask;
- times %= d;
- int hi = mout >> (d - times);
- int low = (mout << times) & mask;
- int ret = x & ~mask;
- ret |= low;
- ret |= hi;
- return ret;
- }
-
- /**
- * Find the selected edge or corner in screen coordinates.
- */
- private int decode(int movingEdges, float rotation) {
- int rot = CropMath.constrainedRotation(rotation);
- switch (rot) {
- case 90:
- return bitCycleLeft(movingEdges, 1, 4);
- case 180:
- return bitCycleLeft(movingEdges, 2, 4);
- case 270:
- return bitCycleLeft(movingEdges, 3, 4);
- default:
- return movingEdges;
- }
- }
-
- @Override
- public void onDraw(Canvas canvas) {
- if (mBitmap == null) {
- return;
- }
- if (mDirty) {
- mDirty = false;
- clearDisplay();
- }
-
- mImageBounds = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
- mScreenBounds = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
- mScreenBounds.inset(mMargin, mMargin);
-
- // If crop object doesn't exist, create it and update it from master
- // state
- if (mCropObj == null) {
- reset();
- mCropObj = new CropObject(mImageBounds, mImageBounds, 0);
- }
-
- // If display matrix doesn't exist, create it and its dependencies
- if (mDisplayMatrix == null || mDisplayMatrixInverse == null) {
- mDisplayMatrix = new Matrix();
- mDisplayMatrix.reset();
- if (!CropDrawingUtils.setImageToScreenMatrix(mDisplayMatrix, mImageBounds, mScreenBounds,
- mRotation)) {
- Log.w(LOGTAG, "failed to get screen matrix");
- mDisplayMatrix = null;
- return;
- }
- mDisplayMatrixInverse = new Matrix();
- mDisplayMatrixInverse.reset();
- if (!mDisplayMatrix.invert(mDisplayMatrixInverse)) {
- Log.w(LOGTAG, "could not invert display matrix");
- mDisplayMatrixInverse = null;
- return;
- }
- // Scale min side and tolerance by display matrix scale factor
- mCropObj.setMinInnerSideSize(mDisplayMatrixInverse.mapRadius(mMinSideSize));
- mCropObj.setTouchTolerance(mDisplayMatrixInverse.mapRadius(mTouchTolerance));
- }
-
- mScreenImageBounds.set(mImageBounds);
-
- // Draw background shadow
- if (mDisplayMatrix.mapRect(mScreenImageBounds)) {
- int margin = (int) mDisplayMatrix.mapRadius(mShadowMargin);
- mScreenImageBounds.roundOut(mShadowBounds);
- mShadowBounds.set(mShadowBounds.left - margin, mShadowBounds.top -
- margin, mShadowBounds.right + margin, mShadowBounds.bottom + margin);
- mShadow.setBounds(mShadowBounds);
- mShadow.draw(canvas);
- }
-
- mPaint.setAntiAlias(true);
- mPaint.setFilterBitmap(true);
- // Draw actual bitmap
- canvas.drawBitmap(mBitmap, mDisplayMatrix, mPaint);
-
- mCropObj.getInnerBounds(mScreenCropBounds);
-
- if (mDisplayMatrix.mapRect(mScreenCropBounds)) {
-
- // Draw overlay shadows
- Paint p = new Paint();
- p.setColor(mOverlayShadowColor);
- p.setStyle(Paint.Style.FILL);
- CropDrawingUtils.drawShadows(canvas, p, mScreenCropBounds, mScreenImageBounds);
-
- // Draw crop rect and markers
- CropDrawingUtils.drawCropRect(canvas, mScreenCropBounds);
- if (!mDoSpot) {
- CropDrawingUtils.drawRuleOfThird(canvas, mScreenCropBounds);
- } else {
- Paint wpPaint = new Paint();
- wpPaint.setColor(mWPMarkerColor);
- wpPaint.setStrokeWidth(3);
- wpPaint.setStyle(Paint.Style.STROKE);
- wpPaint.setPathEffect(new DashPathEffect(new float[]
- {mDashOnLength, mDashOnLength + mDashOffLength}, 0));
- p.setColor(mOverlayWPShadowColor);
- CropDrawingUtils.drawWallpaperSelectionFrame(canvas, mScreenCropBounds,
- mSpotX, mSpotY, wpPaint, p);
- }
- CropDrawingUtils.drawIndicators(canvas, mCropIndicator, mIndicatorSize,
- mScreenCropBounds, mCropObj.isFixedAspect(), decode(mCropObj.getSelectState(), mRotation));
- }
-
- }
-}