diff --git a/sample/src/main/java/com/yalantis/ucrop/sample/SampleActivity.java b/sample/src/main/java/com/yalantis/ucrop/sample/SampleActivity.java
index 3f8f919b0..c4446326f 100644
--- a/sample/src/main/java/com/yalantis/ucrop/sample/SampleActivity.java
+++ b/sample/src/main/java/com/yalantis/ucrop/sample/SampleActivity.java
@@ -366,6 +366,7 @@ Tune everything (ノ◕ヮ◕)ノ*:・゚✧
options.setCropGridColor(Color.GREEN);
options.setCropGridColumnCount(2);
options.setCropGridRowCount(1);
+ options.setCropViewRectInImageSpace(new RectF(100, 100, 500, 500));
options.setToolbarCropDrawable(R.drawable.your_crop_icon);
options.setToolbarCancelDrawable(R.drawable.your_cancel_icon);
diff --git a/ucrop/src/main/java/com/yalantis/ucrop/UCrop.java b/ucrop/src/main/java/com/yalantis/ucrop/UCrop.java
index 357ace2d9..cd94612e9 100644
--- a/ucrop/src/main/java/com/yalantis/ucrop/UCrop.java
+++ b/ucrop/src/main/java/com/yalantis/ucrop/UCrop.java
@@ -6,6 +6,7 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.RectF;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -280,6 +281,7 @@ public static class Options {
public static final String EXTRA_CROP_GRID_COLUMN_COUNT = EXTRA_PREFIX + ".CropGridColumnCount";
public static final String EXTRA_CROP_GRID_COLOR = EXTRA_PREFIX + ".CropGridColor";
public static final String EXTRA_CROP_GRID_STROKE_WIDTH = EXTRA_PREFIX + ".CropGridStrokeWidth";
+ public static final String EXTRA_CROP_VIEW_RECT_IN_IMAGE_SPACE = EXTRA_PREFIX + ".CropViewRectInImageSpace";
public static final String EXTRA_TOOL_BAR_COLOR = EXTRA_PREFIX + ".ToolbarColor";
public static final String EXTRA_STATUS_BAR_COLOR = EXTRA_PREFIX + ".StatusBarColor";
@@ -433,6 +435,29 @@ public void setCropGridStrokeWidth(@IntRange(from = 0) int width) {
mOptionBundle.putInt(EXTRA_CROP_GRID_STROKE_WIDTH, width);
}
+ /**
+ *
This method will accept a RectF with coordinates from the image space.
+ *
+ * Example: Useful if you want want to process the image and detect objects within before
+ * opening uCrop in order to highlight desired cropping area, like for example document
+ * detection and you want to display the cropping Rect over the detected document when
+ * uCrop starts.
+ *
+ * Passing your desired RectF will result in the
+ * {@link com.yalantis.ucrop.view.OverlayView}'s highlighting the desired area.
+ * This rect will be automatically converted to a RectF that corresponds with the image's
+ * coordinates inside the view.
+ *
+ * This must be used in combination with {@link #setMaxBitmapSize} to set a greater bitmap
+ * size, otherwise bigger images will be downscaled and coordinates of objects detected
+ * in input image space won't match with the new downscaled image ones.
+ *
+ * @param rect - desired crop view rect in image space.
+ */
+ public void setCropViewRectInImageSpace(@NonNull RectF rect) {
+ mOptionBundle.putParcelable(EXTRA_CROP_VIEW_RECT_IN_IMAGE_SPACE, rect);
+ }
+
/**
* @param color - desired resolved color of the toolbar
*/
diff --git a/ucrop/src/main/java/com/yalantis/ucrop/UCropActivity.java b/ucrop/src/main/java/com/yalantis/ucrop/UCropActivity.java
index a48969fcc..66136c112 100644
--- a/ucrop/src/main/java/com/yalantis/ucrop/UCropActivity.java
+++ b/ucrop/src/main/java/com/yalantis/ucrop/UCropActivity.java
@@ -4,6 +4,7 @@
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
+import android.graphics.RectF;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -27,6 +28,7 @@
import com.yalantis.ucrop.callback.BitmapCropCallback;
import com.yalantis.ucrop.model.AspectRatio;
+import com.yalantis.ucrop.util.RectUtils;
import com.yalantis.ucrop.util.SelectedStateListDrawable;
import com.yalantis.ucrop.view.CropImageView;
import com.yalantis.ucrop.view.GestureCropImageView;
@@ -380,6 +382,17 @@ public void onScale(float currentScale) {
@Override
public void onLoadComplete() {
mUCropView.animate().alpha(1).setDuration(300).setInterpolator(new AccelerateInterpolator());
+ if (getIntent().hasExtra(UCrop.Options.EXTRA_CROP_VIEW_RECT_IN_IMAGE_SPACE)) {
+ RectF rectInImageSpace = getIntent().getParcelableExtra(UCrop.Options.EXTRA_CROP_VIEW_RECT_IN_IMAGE_SPACE);
+
+ int viewWidth = mGestureCropImageView.getWidth();
+ int viewHeight = mGestureCropImageView.getHeight();
+
+ Drawable drawable = mGestureCropImageView.getDrawable();
+
+ RectF cropViewRect = RectUtils.convertImageSpaceRectToCropViewRect(rectInImageSpace, viewWidth, viewHeight, drawable);
+ mOverlayView.setCropViewRect(cropViewRect);
+ }
mBlockingView.setClickable(false);
mShowLoader = false;
supportInvalidateOptionsMenu();
diff --git a/ucrop/src/main/java/com/yalantis/ucrop/UCropFragment.java b/ucrop/src/main/java/com/yalantis/ucrop/UCropFragment.java
index 9d33f8089..89f5a2e51 100644
--- a/ucrop/src/main/java/com/yalantis/ucrop/UCropFragment.java
+++ b/ucrop/src/main/java/com/yalantis/ucrop/UCropFragment.java
@@ -4,6 +4,8 @@
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
@@ -19,6 +21,7 @@
import com.yalantis.ucrop.callback.BitmapCropCallback;
import com.yalantis.ucrop.model.AspectRatio;
+import com.yalantis.ucrop.util.RectUtils;
import com.yalantis.ucrop.util.SelectedStateListDrawable;
import com.yalantis.ucrop.view.CropImageView;
import com.yalantis.ucrop.view.GestureCropImageView;
@@ -284,6 +287,17 @@ public void onScale(float currentScale) {
@Override
public void onLoadComplete() {
mUCropView.animate().alpha(1).setDuration(300).setInterpolator(new AccelerateInterpolator());
+ if (getArguments().containsKey(UCrop.Options.EXTRA_CROP_VIEW_RECT_IN_IMAGE_SPACE)) {
+ RectF rectInImageSpace = getArguments().getParcelable(UCrop.Options.EXTRA_CROP_VIEW_RECT_IN_IMAGE_SPACE);
+
+ int viewWidth = mGestureCropImageView.getWidth();
+ int viewHeight = mGestureCropImageView.getHeight();
+
+ Drawable drawable = mGestureCropImageView.getDrawable();
+
+ RectF cropViewRect = RectUtils.convertImageSpaceRectToCropViewRect(rectInImageSpace, viewWidth, viewHeight, drawable);
+ mOverlayView.setCropViewRect(cropViewRect);
+ }
mBlockingView.setClickable(false);
callback.loadingProgress(false);
}
diff --git a/ucrop/src/main/java/com/yalantis/ucrop/util/RectUtils.java b/ucrop/src/main/java/com/yalantis/ucrop/util/RectUtils.java
index 050e8dd2a..a84c2b300 100644
--- a/ucrop/src/main/java/com/yalantis/ucrop/util/RectUtils.java
+++ b/ucrop/src/main/java/com/yalantis/ucrop/util/RectUtils.java
@@ -1,6 +1,7 @@
package com.yalantis.ucrop.util;
import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
public class RectUtils {
@@ -69,4 +70,32 @@ public static RectF trapToRect(float[] array) {
return r;
}
+ /**
+ * Takes an rect in image space (received rect can only be in image space, since you can't
+ * know the view's width and height from the outside). So in case you want to process the image
+ * outside uCrop, you will only have coordinates in image space and not in uCrop's view space.
+ * Those need to be converted.
+ *
+ * @param rectInImageSpace RectF in image space
+ * @param viewWidth The view's width
+ * @param viewHeight The view's height
+ * @param drawable The drawable object to retrieve drawable width and height
+ *
+ * @return A new RectF object representing how the RectF should be drawn on screen.
+ */
+ public static RectF convertImageSpaceRectToCropViewRect(RectF rectInImageSpace, int viewWidth, int viewHeight, Drawable drawable) {
+ int drawableWidth = drawable.getIntrinsicWidth();
+ int drawableHeight = drawable.getIntrinsicHeight();
+
+ double widthAspectRatio = (double) viewWidth / drawableWidth;
+ double heightAspectRatio = (double) viewHeight / drawableHeight;
+
+ return new RectF(
+ (float) (rectInImageSpace.left * widthAspectRatio),
+ (float) (rectInImageSpace.top * heightAspectRatio),
+ (float) (rectInImageSpace.right * widthAspectRatio),
+ (float) (rectInImageSpace.bottom * heightAspectRatio)
+ );
+ }
+
}
\ No newline at end of file
diff --git a/ucrop/src/main/java/com/yalantis/ucrop/view/OverlayView.java b/ucrop/src/main/java/com/yalantis/ucrop/view/OverlayView.java
index eb5397015..3ea5e9d80 100644
--- a/ucrop/src/main/java/com/yalantis/ucrop/view/OverlayView.java
+++ b/ucrop/src/main/java/com/yalantis/ucrop/view/OverlayView.java
@@ -105,6 +105,13 @@ public RectF getCropViewRect() {
return mCropViewRect;
}
+ /**
+ * Setter for mCropViewRect. Can be used to set an initial value for the mCropViewRect.
+ */
+ public void setCropViewRect(RectF rect) {
+ mCropViewRect.set(rect);
+ }
+
@Deprecated
/***
* Please use the new method {@link #getFreestyleCropMode() getFreestyleCropMode} method as we have more than 1 freestyle crop mode.
@@ -233,16 +240,18 @@ public void setTargetAspectRatio(final float targetAspectRatio) {
* {@link #mCropViewRect} is used to draw crop bounds - uses padding.
*/
public void setupCropBounds() {
- int height = (int) (mThisWidth / mTargetAspectRatio);
- if (height > mThisHeight) {
- int width = (int) (mThisHeight * mTargetAspectRatio);
- int halfDiff = (mThisWidth - width) / 2;
- mCropViewRect.set(getPaddingLeft() + halfDiff, getPaddingTop(),
- getPaddingLeft() + width + halfDiff, getPaddingTop() + mThisHeight);
- } else {
- int halfDiff = (mThisHeight - height) / 2;
- mCropViewRect.set(getPaddingLeft(), getPaddingTop() + halfDiff,
- getPaddingLeft() + mThisWidth, getPaddingTop() + height + halfDiff);
+ if (mCropViewRect.isEmpty()) {
+ int height = (int) (mThisWidth / mTargetAspectRatio);
+ if (height > mThisHeight) {
+ int width = (int) (mThisHeight * mTargetAspectRatio);
+ int halfDiff = (mThisWidth - width) / 2;
+ mCropViewRect.set(getPaddingLeft() + halfDiff, getPaddingTop(),
+ getPaddingLeft() + width + halfDiff, getPaddingTop() + mThisHeight);
+ } else {
+ int halfDiff = (mThisHeight - height) / 2;
+ mCropViewRect.set(getPaddingLeft(), getPaddingTop() + halfDiff,
+ getPaddingLeft() + mThisWidth, getPaddingTop() + height + halfDiff);
+ }
}
if (mCallback != null) {