diff --git a/.travis.yml b/.travis.yml
index 8a555561..b1406f5c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,7 @@ sudo: false
android:
components:
- - build-tools-23.0.1
+ - build-tools-23.0.3
- android-23
- extra-android-support
- extra-android-m2repository
diff --git a/build.gradle b/build.gradle
index 9eb04bf7..49c948aa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,9 +1,10 @@
buildscript {
repositories {
- mavenCentral()
+ google()
+ jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.1.0'
+ classpath 'com.android.tools.build:gradle:3.1.2'
}
}
@@ -13,5 +14,6 @@ allprojects {
repositories {
mavenCentral()
+ google()
}
}
diff --git a/example/build.gradle b/example/build.gradle
index 33f163f5..5b9decd1 100644
--- a/example/build.gradle
+++ b/example/build.gradle
@@ -3,17 +3,16 @@ apply plugin: 'com.android.application'
archivesBaseName = 'android-crop-example'
android {
- compileSdkVersion 23
- buildToolsVersion '23.0.1'
+ compileSdkVersion 27
defaultConfig {
- minSdkVersion 10
- targetSdkVersion 22
+ minSdkVersion 14
+ targetSdkVersion 27
versionCode Integer.parseInt(project.VERSION_CODE)
versionName project.VERSION
}
}
dependencies {
- compile project(':lib')
+ implementation project(':lib')
}
diff --git a/example/src/main/java/com/soundcloud/android/crop/example/MainActivity.java b/example/src/main/java/com/soundcloud/android/crop/example/MainActivity.java
index 079775aa..ef28dacf 100644
--- a/example/src/main/java/com/soundcloud/android/crop/example/MainActivity.java
+++ b/example/src/main/java/com/soundcloud/android/crop/example/MainActivity.java
@@ -1,7 +1,5 @@
package com.soundcloud.android.crop.example;
-import com.soundcloud.android.crop.Crop;
-
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
@@ -11,6 +9,8 @@
import android.widget.ImageView;
import android.widget.Toast;
+import com.soundcloud.android.crop.Crop;
+
import java.io.File;
public class MainActivity extends Activity {
@@ -51,7 +51,8 @@ protected void onActivityResult(int requestCode, int resultCode, Intent result)
private void beginCrop(Uri source) {
Uri destination = Uri.fromFile(new File(getCacheDir(), "cropped"));
- Crop.of(source, destination).asSquare().start(this);
+
+ Crop.of(source, destination).withMinSize(512, (512 / 16)).start(this);
}
private void handleCrop(int resultCode, Intent result) {
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 7d0eb9b2..84b3274a 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
diff --git a/lib/build.gradle b/lib/build.gradle
index 20e1a767..014d9c71 100644
--- a/lib/build.gradle
+++ b/lib/build.gradle
@@ -6,25 +6,29 @@ apply plugin: 'signing'
archivesBaseName = 'android-crop'
android {
- compileSdkVersion 23
- buildToolsVersion '23.0.1'
+ compileSdkVersion 27
defaultConfig {
- minSdkVersion 10
- targetSdkVersion 22
+ minSdkVersion 14
+ targetSdkVersion 27
+ versionCode 1
+ versionName "1.0.1"
testApplicationId 'com.soundcloud.android.crop.test'
testInstrumentationRunner 'android.test.InstrumentationTestRunner'
}
+ lintOptions {
+ disable 'Registered', 'IconDensities'
+ }
}
dependencies {
- compile 'com.android.support:support-annotations:23.0.1'
- compile 'com.android.support:support-v4:23.0.1'
- androidTestCompile 'com.squareup:fest-android:1.0.7'
- androidTestCompile 'com.android.support:support-v4:23.0.1'
- androidTestCompile 'org.mockito:mockito-core:1.9.5'
- androidTestCompile 'com.google.dexmaker:dexmaker:1.0'
- androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.0'
+ implementation 'com.android.support:support-annotations:27.1.1'
+ implementation 'com.android.support:support-v4:27.1.1'
+ androidTestImplementation 'com.squareup:fest-android:1.0.7'
+ androidTestImplementation 'com.android.support:support-v4:27.1.1'
+ androidTestImplementation 'org.mockito:mockito-core:1.9.5'
+ androidTestImplementation 'com.google.dexmaker:dexmaker:1.0'
+ androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.0'
}
diff --git a/lib/src/main/AndroidManifest.xml b/lib/src/main/AndroidManifest.xml
index 0cb62bb6..760b435c 100644
--- a/lib/src/main/AndroidManifest.xml
+++ b/lib/src/main/AndroidManifest.xml
@@ -1 +1 @@
-
+
\ No newline at end of file
diff --git a/lib/src/main/java/com/soundcloud/android/crop/Crop.java b/lib/src/main/java/com/soundcloud/android/crop/Crop.java
index 3ce06d61..a4baa881 100644
--- a/lib/src/main/java/com/soundcloud/android/crop/Crop.java
+++ b/lib/src/main/java/com/soundcloud/android/crop/Crop.java
@@ -23,10 +23,19 @@ public class Crop {
interface Extra {
String ASPECT_X = "aspect_x";
String ASPECT_Y = "aspect_y";
+
+ String MIN_ASPECT_X = "min_aspect_x";
+ String MIN_ASPECT_Y = "min_aspect_y";
+ String MAX_ASPECT_X = "max_aspect_x";
+ String MAX_ASPECT_Y = "max_aspect_y";
+
String MAX_X = "max_x";
String MAX_Y = "max_y";
+ String MIN_X = "min_x";
+ String MIN_Y = "min_y";
String AS_PNG = "as_png";
String ERROR = "error";
+ String LAYOUT_ID = "layout_id";
}
private Intent cropIntent;
@@ -47,6 +56,11 @@ private Crop(Uri source, Uri destination) {
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, destination);
}
+// public Crop withLayout(int layoutId) {
+// cropIntent.putExtra(Extra.LAYOUT_ID, layoutId);
+// return this;
+// }
+
/**
* Set fixed aspect ratio for crop area
*
@@ -59,6 +73,16 @@ public Crop withAspect(int x, int y) {
return this;
}
+// public Crop withAspectRange(int minX, int minY, int maxX, int maxY) {
+// cropIntent.putExtra(Extra.MIN_ASPECT_X, minX);
+// cropIntent.putExtra(Extra.MIN_ASPECT_Y, minY);
+// cropIntent.putExtra(Extra.MAX_ASPECT_X, maxX);
+// cropIntent.putExtra(Extra.MAX_ASPECT_Y, maxY);
+// cropIntent.putExtra(Extra.ASPECT_X, maxX);
+// cropIntent.putExtra(Extra.ASPECT_Y, maxY);
+// return this;
+// }
+
/**
* Crop area with fixed 1:1 aspect ratio
*/
@@ -80,8 +104,21 @@ public Crop withMaxSize(int width, int height) {
return this;
}
+ /**
+ * Set minimum crop size
+ *
+ * @param width Min width
+ * @param height Min height
+ */
+ public Crop withMinSize(int width, int height) {
+ cropIntent.putExtra(Extra.MIN_X, width);
+ cropIntent.putExtra(Extra.MIN_Y, height);
+ return this;
+ }
+
/**
* Set whether to save the result as a PNG or not. Helpful to preserve alpha.
+ *
* @param asPng whether to save the result as a PNG or not
*/
public Crop asPng(boolean asPng) {
diff --git a/lib/src/main/java/com/soundcloud/android/crop/CropImageActivity.java b/lib/src/main/java/com/soundcloud/android/crop/CropImageActivity.java
index 1cb31d04..9834fcbf 100644
--- a/lib/src/main/java/com/soundcloud/android/crop/CropImageActivity.java
+++ b/lib/src/main/java/com/soundcloud/android/crop/CropImageActivity.java
@@ -34,6 +34,7 @@
import android.view.Window;
import android.view.WindowManager;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -52,7 +53,14 @@ public class CropImageActivity extends MonitoredActivity {
private int aspectX;
private int aspectY;
+ private int minAspectX;
+ private int minAspectY;
+ private int maxAspectX;
+ private int maxAspectY;
+
// Output image
+ private int minX;
+ private int minY;
private int maxX;
private int maxY;
private int exifRotation;
@@ -91,7 +99,14 @@ private void setupWindowFlags() {
}
private void setupViews() {
- setContentView(R.layout.crop__activity_crop);
+ Intent intent = getIntent();
+ Bundle extras = intent.getExtras();
+
+ int layoutId = R.layout.crop__activity_crop;
+ if (extras != null) {
+ layoutId = extras.getInt(Crop.Extra.LAYOUT_ID, R.layout.crop__activity_crop);
+ }
+ setContentView(layoutId);
imageView = (CropImageView) findViewById(R.id.crop_image);
imageView.context = this;
@@ -124,10 +139,19 @@ private void loadInput() {
if (extras != null) {
aspectX = extras.getInt(Crop.Extra.ASPECT_X);
aspectY = extras.getInt(Crop.Extra.ASPECT_Y);
+
+ minAspectX = extras.getInt(Crop.Extra.MIN_ASPECT_X);
+ minAspectY = extras.getInt(Crop.Extra.MIN_ASPECT_Y);
+ maxAspectX = extras.getInt(Crop.Extra.MAX_ASPECT_X);
+ maxAspectX = extras.getInt(Crop.Extra.MAX_ASPECT_Y);
+
maxX = extras.getInt(Crop.Extra.MAX_X);
maxY = extras.getInt(Crop.Extra.MAX_Y);
saveAsPng = extras.getBoolean(Crop.Extra.AS_PNG, false);
saveUri = extras.getParcelable(MediaStore.EXTRA_OUTPUT);
+
+ minX = extras.getInt(Crop.Extra.MIN_X, 0);
+ minY = extras.getInt(Crop.Extra.MIN_Y, 0);
}
sourceUri = intent.getData();
@@ -141,6 +165,19 @@ private void loadInput() {
BitmapFactory.Options option = new BitmapFactory.Options();
option.inSampleSize = sampleSize;
rotateBitmap = new RotateBitmap(BitmapFactory.decodeStream(is, null, option), exifRotation);
+
+ option.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(new File(sourceUri.getPath()).getAbsolutePath(), option);
+ int imageHeight = option.outHeight;
+ int imageWidth = option.outWidth;
+
+ if (minX > imageHeight || minY > imageWidth) {
+ Intent intentError = new Intent();
+ intentError.putExtra(Crop.Extra.ERROR, new Throwable("Image is less then minimum size specified.\nRequired size:" + minX + "x" + minY));
+ setResult(Crop.RESULT_ERROR, intentError);
+ finish();
+ }
+
} catch (IOException e) {
Log.e("Error reading image: " + e.getMessage(), e);
setResultException(e);
@@ -246,7 +283,10 @@ private void makeDefault() {
int y = (height - cropHeight) / 2;
RectF cropRect = new RectF(x, y, x + cropWidth, y + cropHeight);
- hv.setup(imageView.getUnrotatedMatrix(), imageRect, cropRect, aspectX != 0 && aspectY != 0);
+
+ boolean maintainAspectRatio = !(minAspectX != 0 && minAspectY != 0 && maxAspectX != 0 && maxAspectY != 0) && (aspectX != 0 && aspectY != 0);
+
+ hv.setup(imageView.getUnrotatedMatrix(), imageRect, cropRect, maintainAspectRatio, minX, minY);
imageView.add(hv);
}
@@ -290,6 +330,12 @@ private void onSaveClicked() {
try {
croppedImage = decodeRegionCrop(r, outWidth, outHeight);
+
+ if (exifRotation != 0) {
+ Matrix m = new Matrix();
+ m.postRotate(exifRotation);
+ croppedImage = Bitmap.createBitmap(croppedImage, 0, 0, croppedImage.getWidth(), croppedImage.getHeight(), m, true);
+ }
} catch (IllegalArgumentException e) {
setResultException(e);
finish();
@@ -297,7 +343,7 @@ private void onSaveClicked() {
}
if (croppedImage != null) {
- imageView.setImageRotateBitmapResetBase(new RotateBitmap(croppedImage, exifRotation), true);
+// imageView.setImageRotateBitmapResetBase(new RotateBitmap(croppedImage, exifRotation), true);
imageView.center();
imageView.highlightViews.clear();
}
@@ -394,11 +440,6 @@ private void saveOutput(Bitmap croppedImage) {
CropUtil.closeSilently(outputStream);
}
- CropUtil.copyExifRotation(
- CropUtil.getFromMediaUri(this, getContentResolver(), sourceUri),
- CropUtil.getFromMediaUri(this, getContentResolver(), saveUri)
- );
-
setResultUri(saveUri);
}
diff --git a/lib/src/main/java/com/soundcloud/android/crop/HighlightView.java b/lib/src/main/java/com/soundcloud/android/crop/HighlightView.java
index 27cc10da..92e85b09 100644
--- a/lib/src/main/java/com/soundcloud/android/crop/HighlightView.java
+++ b/lib/src/main/java/com/soundcloud/android/crop/HighlightView.java
@@ -77,6 +77,9 @@ enum HandleMode { Changing, Always, Never }
private float outlineWidth;
private boolean isFocused;
+ private float minWidth = 0f;
+ private float minHeight = 0f;
+
public HighlightView(View context) {
viewContext = context;
initStyles(context.getContext());
@@ -97,6 +100,13 @@ private void initStyles(Context context) {
}
}
+ public void setup(Matrix m, Rect imageRect, RectF cropRect, boolean maintainAspectRatio, int minWidth, int minHeight)
+ {
+ this.minWidth = minWidth;
+ this.minHeight = minHeight;
+ setup(m, imageRect, cropRect, maintainAspectRatio);
+ }
+
public void setup(Matrix m, Rect imageRect, RectF cropRect, boolean maintainAspectRatio) {
matrix = new Matrix(m);
@@ -209,10 +219,8 @@ private void drawThirds(Canvas canvas) {
drawRect.left + xThird, drawRect.bottom, outlinePaint);
canvas.drawLine(drawRect.left + xThird * 2, drawRect.top,
drawRect.left + xThird * 2, drawRect.bottom, outlinePaint);
- canvas.drawLine(drawRect.left, drawRect.top + yThird,
- drawRect.right, drawRect.top + yThird, outlinePaint);
- canvas.drawLine(drawRect.left, drawRect.top + yThird * 2,
- drawRect.right, drawRect.top + yThird * 2, outlinePaint);
+ canvas.drawLine(drawRect.left, drawRect.top + yThird, drawRect.right, drawRect.top + yThird, outlinePaint);
+ canvas.drawLine(drawRect.left, drawRect.top + yThird * 2, drawRect.right, drawRect.top + yThird * 2, outlinePaint);
}
private void drawCircle(Canvas canvas) {
@@ -348,6 +356,14 @@ void growBy(float dx, float dy) {
r.inset(0F, -(heightCap - r.height()) / 2F);
}
+ // Limits the size of the image to the given minimum amount
+ if (minWidth > 0f || minHeight > 0f)
+ {
+ float widthDiff = (Math.abs((r.right-r.left)) < minWidth) ? minWidth - Math.abs((r.right-r.left)) : 0f;
+ float heightDiff = (Math.abs((r.bottom-r.top)) < minHeight) ? minHeight - Math.abs((r.bottom-r.top)) : 0f;
+ r.inset((widthDiff/2)*-1, (heightDiff / 2) * -1);
+ }
+
// Put the cropping rectangle inside the image rectangle
if (r.left < imageRect.left) {
r.offset(imageRect.left - r.left, 0F);
diff --git a/lib/src/main/res/drawable-hdpi/crop__tile.png b/lib/src/main/res/drawable-hdpi/crop__tile.png
new file mode 100644
index 00000000..2f2569f5
Binary files /dev/null and b/lib/src/main/res/drawable-hdpi/crop__tile.png differ
diff --git a/lib/src/main/res/drawable-mdpi/crop__divider.9.png b/lib/src/main/res/drawable-mdpi/crop__divider.9.png
deleted file mode 100644
index 0279e17a..00000000
Binary files a/lib/src/main/res/drawable-mdpi/crop__divider.9.png and /dev/null differ
diff --git a/lib/src/main/res/drawable-mdpi/crop__tile.png b/lib/src/main/res/drawable-mdpi/crop__tile.png
new file mode 100644
index 00000000..77a325cd
Binary files /dev/null and b/lib/src/main/res/drawable-mdpi/crop__tile.png differ
diff --git a/lib/src/main/res/drawable/crop__selectable_background.xml b/lib/src/main/res/drawable-v10/crop__selectable_background.xml
similarity index 86%
rename from lib/src/main/res/drawable/crop__selectable_background.xml
rename to lib/src/main/res/drawable-v10/crop__selectable_background.xml
index 83c4a7de..b92a29a2 100644
--- a/lib/src/main/res/drawable/crop__selectable_background.xml
+++ b/lib/src/main/res/drawable-v10/crop__selectable_background.xml
@@ -1,7 +1,6 @@
-
+
-
diff --git a/lib/src/main/res/drawable-v11/crop__selectable_background.xml b/lib/src/main/res/drawable-v11/crop__selectable_background.xml
new file mode 100644
index 00000000..9469b59a
--- /dev/null
+++ b/lib/src/main/res/drawable-v11/crop__selectable_background.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
-
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/src/main/res/drawable-xhdpi/crop__divider.9.png b/lib/src/main/res/drawable-xhdpi/crop__divider.9.png
index 65061c0f..809f1307 100644
Binary files a/lib/src/main/res/drawable-xhdpi/crop__divider.9.png and b/lib/src/main/res/drawable-xhdpi/crop__divider.9.png differ
diff --git a/lib/src/main/res/drawable-xhdpi/crop__tile.png b/lib/src/main/res/drawable-xhdpi/crop__tile.png
index b0b00440..43739d28 100644
Binary files a/lib/src/main/res/drawable-xhdpi/crop__tile.png and b/lib/src/main/res/drawable-xhdpi/crop__tile.png differ
diff --git a/lib/src/main/res/drawable-xxhdpi/crop__divider.9.png b/lib/src/main/res/drawable-xxhdpi/crop__divider.9.png
new file mode 100644
index 00000000..ea71af02
Binary files /dev/null and b/lib/src/main/res/drawable-xxhdpi/crop__divider.9.png differ
diff --git a/lib/src/main/res/drawable-xxhdpi/crop__tile.png b/lib/src/main/res/drawable-xxhdpi/crop__tile.png
new file mode 100644
index 00000000..7f757d90
Binary files /dev/null and b/lib/src/main/res/drawable-xxhdpi/crop__tile.png differ
diff --git a/lib/src/main/res/drawable-xxxhdpi/crop__divider.9.png b/lib/src/main/res/drawable-xxxhdpi/crop__divider.9.png
new file mode 100644
index 00000000..d505ff90
Binary files /dev/null and b/lib/src/main/res/drawable-xxxhdpi/crop__divider.9.png differ
diff --git a/lib/src/main/res/drawable-xxxhdpi/crop__tile.png b/lib/src/main/res/drawable-xxxhdpi/crop__tile.png
new file mode 100644
index 00000000..0833b970
Binary files /dev/null and b/lib/src/main/res/drawable-xxxhdpi/crop__tile.png differ
diff --git a/lib/src/main/res/values-fa/strings.xml b/lib/src/main/res/values-fa/strings.xml
index a4f3d6cf..962f2f81 100644
--- a/lib/src/main/res/values-fa/strings.xml
+++ b/lib/src/main/res/values-fa/strings.xml
@@ -1,7 +1,7 @@
در حال ذخیره سازی
- لطفاً صبر کنید ...
+ لطفاً صبر کنید …
تصویری در دسترس نیست
تأیید