diff options
Diffstat (limited to 'src/com/android/gallery3d/filtershow/crop')
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)); - } - - } -} |