summaryrefslogtreecommitdiffstats
path: root/cropper/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'cropper/src/main/java/com')
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapCroppingWorkerTask.java354
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapLoadingWorkerTask.java176
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapUtils.java923
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/CropImage.java1048
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/CropImageActivity.java367
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/CropImageAnimation.java123
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/CropImageOptions.java541
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/CropImageView.java2296
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/CropOverlayView.java1118
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/CropWindowHandler.java405
-rw-r--r--cropper/src/main/java/com/theartofdev/edmodo/cropper/CropWindowMoveHandler.java786
11 files changed, 0 insertions, 8137 deletions
diff --git a/cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapCroppingWorkerTask.java b/cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapCroppingWorkerTask.java
deleted file mode 100644
index 54d33df4e..000000000
--- a/cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapCroppingWorkerTask.java
+++ /dev/null
@@ -1,354 +0,0 @@
-// "Therefore those skilled at the unorthodox
-// are infinite as heaven and earth,
-// inexhaustible as the great rivers.
-// When they come to an end,
-// they begin again,
-// like the days and months;
-// they die and are reborn,
-// like the four seasons."
-//
-// - Sun Tsu,
-// "The Art of War"
-
-package com.theartofdev.edmodo.cropper;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.AsyncTask;
-
-import java.lang.ref.WeakReference;
-
-/**
- * Task to crop bitmap asynchronously from the UI thread.
- */
-final class BitmapCroppingWorkerTask
- extends AsyncTask<Void, Void, BitmapCroppingWorkerTask.Result> {
-
- // region: Fields and Consts
-
- /**
- * Use a WeakReference to ensure the ImageView can be garbage collected
- */
- private final WeakReference<CropImageView> mCropImageViewReference;
-
- /**
- * the bitmap to crop
- */
- private final Bitmap mBitmap;
-
- /**
- * The Android URI of the image to load
- */
- private final Uri mUri;
-
- /**
- * The context of the crop image view widget used for loading of bitmap by Android URI
- */
- private final Context mContext;
-
- /**
- * Required cropping 4 points (x0,y0,x1,y1,x2,y2,x3,y3)
- */
- private final float[] mCropPoints;
-
- /**
- * Degrees the image was rotated after loading
- */
- private final int mDegreesRotated;
-
- /**
- * the original width of the image to be cropped (for image loaded from URI)
- */
- private final int mOrgWidth;
-
- /**
- * the original height of the image to be cropped (for image loaded from URI)
- */
- private final int mOrgHeight;
-
- /**
- * is there is fixed aspect ratio for the crop rectangle
- */
- private final boolean mFixAspectRatio;
-
- /**
- * the X aspect ration of the crop rectangle
- */
- private final int mAspectRatioX;
-
- /**
- * the Y aspect ration of the crop rectangle
- */
- private final int mAspectRatioY;
-
- /**
- * required width of the cropping image
- */
- private final int mReqWidth;
-
- /**
- * required height of the cropping image
- */
- private final int mReqHeight;
-
- /**
- * is the image flipped horizontally
- */
- private final boolean mFlipHorizontally;
-
- /**
- * is the image flipped vertically
- */
- private final boolean mFlipVertically;
-
- /**
- * The option to handle requested width/height
- */
- private final CropImageView.RequestSizeOptions mReqSizeOptions;
-
- /**
- * the Android Uri to save the cropped image to
- */
- private final Uri mSaveUri;
-
- /**
- * the compression format to use when writing the image
- */
- private final Bitmap.CompressFormat mSaveCompressFormat;
-
- /**
- * the quality (if applicable) to use when writing the image (0 - 100)
- */
- private final int mSaveCompressQuality;
- // endregion
-
- BitmapCroppingWorkerTask(
- CropImageView cropImageView,
- Bitmap bitmap,
- float[] cropPoints,
- int degreesRotated,
- boolean fixAspectRatio,
- int aspectRatioX,
- int aspectRatioY,
- int reqWidth,
- int reqHeight,
- boolean flipHorizontally,
- boolean flipVertically,
- CropImageView.RequestSizeOptions options,
- Uri saveUri,
- Bitmap.CompressFormat saveCompressFormat,
- int saveCompressQuality) {
-
- mCropImageViewReference = new WeakReference<>(cropImageView);
- mContext = cropImageView.getContext();
- mBitmap = bitmap;
- mCropPoints = cropPoints;
- mUri = null;
- mDegreesRotated = degreesRotated;
- mFixAspectRatio = fixAspectRatio;
- mAspectRatioX = aspectRatioX;
- mAspectRatioY = aspectRatioY;
- mReqWidth = reqWidth;
- mReqHeight = reqHeight;
- mFlipHorizontally = flipHorizontally;
- mFlipVertically = flipVertically;
- mReqSizeOptions = options;
- mSaveUri = saveUri;
- mSaveCompressFormat = saveCompressFormat;
- mSaveCompressQuality = saveCompressQuality;
- mOrgWidth = 0;
- mOrgHeight = 0;
- }
-
- BitmapCroppingWorkerTask(
- CropImageView cropImageView,
- Uri uri,
- float[] cropPoints,
- int degreesRotated,
- int orgWidth,
- int orgHeight,
- boolean fixAspectRatio,
- int aspectRatioX,
- int aspectRatioY,
- int reqWidth,
- int reqHeight,
- boolean flipHorizontally,
- boolean flipVertically,
- CropImageView.RequestSizeOptions options,
- Uri saveUri,
- Bitmap.CompressFormat saveCompressFormat,
- int saveCompressQuality) {
-
- mCropImageViewReference = new WeakReference<>(cropImageView);
- mContext = cropImageView.getContext();
- mUri = uri;
- mCropPoints = cropPoints;
- mDegreesRotated = degreesRotated;
- mFixAspectRatio = fixAspectRatio;
- mAspectRatioX = aspectRatioX;
- mAspectRatioY = aspectRatioY;
- mOrgWidth = orgWidth;
- mOrgHeight = orgHeight;
- mReqWidth = reqWidth;
- mReqHeight = reqHeight;
- mFlipHorizontally = flipHorizontally;
- mFlipVertically = flipVertically;
- mReqSizeOptions = options;
- mSaveUri = saveUri;
- mSaveCompressFormat = saveCompressFormat;
- mSaveCompressQuality = saveCompressQuality;
- mBitmap = null;
- }
-
- /**
- * The Android URI that this task is currently loading.
- */
- public Uri getUri() {
- return mUri;
- }
-
- /**
- * Crop image in background.
- *
- * @param params ignored
- * @return the decoded bitmap data
- */
- @Override
- protected BitmapCroppingWorkerTask.Result doInBackground(Void... params) {
- try {
- if (!isCancelled()) {
-
- BitmapUtils.BitmapSampled bitmapSampled;
- if (mUri != null) {
- bitmapSampled =
- BitmapUtils.cropBitmap(
- mContext,
- mUri,
- mCropPoints,
- mDegreesRotated,
- mOrgWidth,
- mOrgHeight,
- mFixAspectRatio,
- mAspectRatioX,
- mAspectRatioY,
- mReqWidth,
- mReqHeight,
- mFlipHorizontally,
- mFlipVertically);
- } else if (mBitmap != null) {
- bitmapSampled =
- BitmapUtils.cropBitmapObjectHandleOOM(
- mBitmap,
- mCropPoints,
- mDegreesRotated,
- mFixAspectRatio,
- mAspectRatioX,
- mAspectRatioY,
- mFlipHorizontally,
- mFlipVertically);
- } else {
- return new Result((Bitmap) null, 1);
- }
-
- Bitmap bitmap =
- BitmapUtils.resizeBitmap(bitmapSampled.bitmap, mReqWidth, mReqHeight, mReqSizeOptions);
-
- if (mSaveUri == null) {
- return new Result(bitmap, bitmapSampled.sampleSize);
- } else {
- BitmapUtils.writeBitmapToUri(
- mContext, bitmap, mSaveUri, mSaveCompressFormat, mSaveCompressQuality);
- if (bitmap != null) {
- bitmap.recycle();
- }
- return new Result(mSaveUri, bitmapSampled.sampleSize);
- }
- }
- return null;
- } catch (Exception e) {
- return new Result(e, mSaveUri != null);
- }
- }
-
- /**
- * Once complete, see if ImageView is still around and set bitmap.
- *
- * @param result the result of bitmap cropping
- */
- @Override
- protected void onPostExecute(Result result) {
- if (result != null) {
- boolean completeCalled = false;
- if (!isCancelled()) {
- CropImageView cropImageView = mCropImageViewReference.get();
- if (cropImageView != null) {
- completeCalled = true;
- cropImageView.onImageCroppingAsyncComplete(result);
- }
- }
- if (!completeCalled && result.bitmap != null) {
- // fast release of unused bitmap
- result.bitmap.recycle();
- }
- }
- }
-
- // region: Inner class: Result
-
- /**
- * The result of BitmapCroppingWorkerTask async loading.
- */
- static final class Result {
-
- /**
- * The cropped bitmap
- */
- public final Bitmap bitmap;
-
- /**
- * The saved cropped bitmap uri
- */
- public final Uri uri;
-
- /**
- * The error that occurred during async bitmap cropping.
- */
- final Exception error;
-
- /**
- * is the cropping request was to get a bitmap or to save it to uri
- */
- final boolean isSave;
-
- /**
- * sample size used creating the crop bitmap to lower its size
- */
- final int sampleSize;
-
- Result(Bitmap bitmap, int sampleSize) {
- this.bitmap = bitmap;
- this.uri = null;
- this.error = null;
- this.isSave = false;
- this.sampleSize = sampleSize;
- }
-
- Result(Uri uri, int sampleSize) {
- this.bitmap = null;
- this.uri = uri;
- this.error = null;
- this.isSave = true;
- this.sampleSize = sampleSize;
- }
-
- Result(Exception error, boolean isSave) {
- this.bitmap = null;
- this.uri = null;
- this.error = error;
- this.isSave = isSave;
- this.sampleSize = 1;
- }
- }
- // endregion
-}
diff --git a/cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapLoadingWorkerTask.java b/cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapLoadingWorkerTask.java
deleted file mode 100644
index a6ecf9396..000000000
--- a/cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapLoadingWorkerTask.java
+++ /dev/null
@@ -1,176 +0,0 @@
-// "Therefore those skilled at the unorthodox
-// are infinite as heaven and earth,
-// inexhaustible as the great rivers.
-// When they come to an end,
-// they begin again,
-// like the days and months;
-// they die and are reborn,
-// like the four seasons."
-//
-// - Sun Tsu,
-// "The Art of War"
-
-package com.theartofdev.edmodo.cropper;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.util.DisplayMetrics;
-
-import java.lang.ref.WeakReference;
-
-/**
- * Task to load bitmap asynchronously from the UI thread.
- */
-final class BitmapLoadingWorkerTask extends AsyncTask<Void, Void, BitmapLoadingWorkerTask.Result> {
-
- // region: Fields and Consts
-
- /**
- * Use a WeakReference to ensure the ImageView can be garbage collected
- */
- private final WeakReference<CropImageView> mCropImageViewReference;
-
- /**
- * The Android URI of the image to load
- */
- private final Uri mUri;
-
- /**
- * The context of the crop image view widget used for loading of bitmap by Android URI
- */
- private final Context mContext;
-
- /**
- * required width of the cropping image after density adjustment
- */
- private final int mWidth;
-
- /**
- * required height of the cropping image after density adjustment
- */
- private final int mHeight;
- // endregion
-
- public BitmapLoadingWorkerTask(CropImageView cropImageView, Uri uri) {
- mUri = uri;
- mCropImageViewReference = new WeakReference<>(cropImageView);
-
- mContext = cropImageView.getContext();
-
- DisplayMetrics metrics = cropImageView.getResources().getDisplayMetrics();
- double densityAdj = metrics.density > 1 ? 1 / metrics.density : 1;
- mWidth = (int) (metrics.widthPixels * densityAdj);
- mHeight = (int) (metrics.heightPixels * densityAdj);
- }
-
- /**
- * The Android URI that this task is currently loading.
- */
- public Uri getUri() {
- return mUri;
- }
-
- /**
- * Decode image in background.
- *
- * @param params ignored
- * @return the decoded bitmap data
- */
- @Override
- protected Result doInBackground(Void... params) {
- try {
- if (!isCancelled()) {
-
- BitmapUtils.BitmapSampled decodeResult =
- BitmapUtils.decodeSampledBitmap(mContext, mUri, mWidth, mHeight);
-
- if (!isCancelled()) {
-
- BitmapUtils.RotateBitmapResult rotateResult =
- BitmapUtils.rotateBitmapByExif(decodeResult.bitmap, mContext, mUri);
-
- return new Result(
- mUri, rotateResult.bitmap, decodeResult.sampleSize, rotateResult.degrees);
- }
- }
- return null;
- } catch (Exception e) {
- return new Result(mUri, e);
- }
- }
-
- /**
- * Once complete, see if ImageView is still around and set bitmap.
- *
- * @param result the result of bitmap loading
- */
- @Override
- protected void onPostExecute(Result result) {
- if (result != null) {
- boolean completeCalled = false;
- if (!isCancelled()) {
- CropImageView cropImageView = mCropImageViewReference.get();
- if (cropImageView != null) {
- completeCalled = true;
- cropImageView.onSetImageUriAsyncComplete(result);
- }
- }
- if (!completeCalled && result.bitmap != null) {
- // fast release of unused bitmap
- result.bitmap.recycle();
- }
- }
- }
-
- // region: Inner class: Result
-
- /**
- * The result of BitmapLoadingWorkerTask async loading.
- */
- public static final class Result {
-
- /**
- * The Android URI of the image to load
- */
- public final Uri uri;
-
- /**
- * The loaded bitmap
- */
- public final Bitmap bitmap;
-
- /**
- * The sample size used to load the given bitmap
- */
- public final int loadSampleSize;
-
- /**
- * The degrees the image was rotated
- */
- public final int degreesRotated;
-
- /**
- * The error that occurred during async bitmap loading.
- */
- public final Exception error;
-
- Result(Uri uri, Bitmap bitmap, int loadSampleSize, int degreesRotated) {
- this.uri = uri;
- this.bitmap = bitmap;
- this.loadSampleSize = loadSampleSize;
- this.degreesRotated = degreesRotated;
- this.error = null;
- }
-
- Result(Uri uri, Exception error) {
- this.uri = uri;
- this.bitmap = null;
- this.loadSampleSize = 0;
- this.degreesRotated = 0;
- this.error = error;
- }
- }
- // endregion
-}
diff --git a/cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapUtils.java b/cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapUtils.java
deleted file mode 100644
index 7190bd429..000000000
--- a/cropper/src/main/java/com/theartofdev/edmodo/cropper/BitmapUtils.java
+++ /dev/null
@@ -1,923 +0,0 @@
-// "Therefore those skilled at the unorthodox
-// are infinite as heaven and earth,
-// inexhaustible as the great rivers.
-// When they come to an end,
-// they begin again,
-// like the days and months;
-// they die and are reborn,
-// like the four seasons."
-//
-// - Sun Tsu,
-// "The Art of War"
-
-package com.theartofdev.edmodo.cropper;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.net.Uri;
-import android.util.Log;
-import android.util.Pair;
-
-import androidx.exifinterface.media.ExifInterface;
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.ref.WeakReference;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-
-/**
- * Utility class that deals with operations with an ImageView.
- */
-final class BitmapUtils {
-
- static final Rect EMPTY_RECT = new Rect();
-
- static final RectF EMPTY_RECT_F = new RectF();
-
- /**
- * Reusable rectangle for general internal usage
- */
- static final RectF RECT = new RectF();
-
- /**
- * Reusable point for general internal usage
- */
- static final float[] POINTS = new float[6];
-
- /**
- * Reusable point for general internal usage
- */
- static final float[] POINTS2 = new float[6];
- /**
- * used to save bitmaps during state save and restore so not to reload them.
- */
- static Pair<String, WeakReference<Bitmap>> mStateBitmap;
- /**
- * Used to know the max texture size allowed to be rendered
- */
- private static int mMaxTextureSize;
-
- /**
- * Rotate the given image by reading the Exif value of the image (uri).<br>
- * If no rotation is required the image will not be rotated.<br>
- * New bitmap is created and the old one is recycled.
- */
- static RotateBitmapResult rotateBitmapByExif(Bitmap bitmap, Context context, Uri uri) {
- ExifInterface ei = null;
- try {
- InputStream is = context.getContentResolver().openInputStream(uri);
- if (is != null) {
- ei = new ExifInterface(is);
- is.close();
- }
- } catch (Exception ignored) {
- }
- return ei != null ? rotateBitmapByExif(bitmap, ei) : new RotateBitmapResult(bitmap, 0);
- }
-
- /**
- * Rotate the given image by given Exif value.<br>
- * If no rotation is required the image will not be rotated.<br>
- * New bitmap is created and the old one is recycled.
- */
- static RotateBitmapResult rotateBitmapByExif(Bitmap bitmap, ExifInterface exif) {
- int degrees;
- int orientation =
- exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
- switch (orientation) {
- case ExifInterface.ORIENTATION_ROTATE_90:
- degrees = 90;
- break;
- case ExifInterface.ORIENTATION_ROTATE_180:
- degrees = 180;
- break;
- case ExifInterface.ORIENTATION_ROTATE_270:
- degrees = 270;
- break;
- default:
- degrees = 0;
- break;
- }
- return new RotateBitmapResult(bitmap, degrees);
- }
-
- /**
- * Decode bitmap from stream using sampling to get bitmap with the requested limit.
- */
- static BitmapSampled decodeSampledBitmap(Context context, Uri uri, int reqWidth, int reqHeight) {
-
- try {
- ContentResolver resolver = context.getContentResolver();
-
- // First decode with inJustDecodeBounds=true to check dimensions
- BitmapFactory.Options options = decodeImageForOption(resolver, uri);
-
- if (options.outWidth == -1 && options.outHeight == -1)
- throw new RuntimeException("File is not a picture");
-
- // Calculate inSampleSize
- options.inSampleSize =
- Math.max(
- calculateInSampleSizeByReqestedSize(
- options.outWidth, options.outHeight, reqWidth, reqHeight),
- calculateInSampleSizeByMaxTextureSize(options.outWidth, options.outHeight));
-
- // Decode bitmap with inSampleSize set
- Bitmap bitmap = decodeImage(resolver, uri, options);
-
- return new BitmapSampled(bitmap, options.inSampleSize);
-
- } catch (Exception e) {
- throw new RuntimeException(
- "Failed to load sampled bitmap: " + uri + "\r\n" + e.getMessage(), e);
- }
- }
-
- /**
- * Crop image bitmap from given bitmap using the given points in the original bitmap and the given
- * rotation.<br>
- * if the rotation is not 0,90,180 or 270 degrees then we must first crop a larger area of the
- * image that contains the requires rectangle, rotate and then crop again a sub rectangle.<br>
- * If crop fails due to OOM we scale the cropping image by 0.5 every time it fails until it is
- * small enough.
- */
- static BitmapSampled cropBitmapObjectHandleOOM(
- Bitmap bitmap,
- float[] points,
- int degreesRotated,
- boolean fixAspectRatio,
- int aspectRatioX,
- int aspectRatioY,
- boolean flipHorizontally,
- boolean flipVertically) {
- int scale = 1;
- while (true) {
- try {
- Bitmap cropBitmap =
- cropBitmapObjectWithScale(
- bitmap,
- points,
- degreesRotated,
- fixAspectRatio,
- aspectRatioX,
- aspectRatioY,
- 1 / (float) scale,
- flipHorizontally,
- flipVertically);
- return new BitmapSampled(cropBitmap, scale);
- } catch (OutOfMemoryError e) {
- scale *= 2;
- if (scale > 8) {
- throw e;
- }
- }
- }
- }
-
- /**
- * Crop image bitmap from given bitmap using the given points in the original bitmap and the given
- * rotation.<br>
- * if the rotation is not 0,90,180 or 270 degrees then we must first crop a larger area of the
- * image that contains the requires rectangle, rotate and then crop again a sub rectangle.
- *
- * @param scale how much to scale the cropped image part, use 0.5 to lower the image by half (OOM
- * handling)
- */
- private static Bitmap cropBitmapObjectWithScale(
- Bitmap bitmap,
- float[] points,
- int degreesRotated,
- boolean fixAspectRatio,
- int aspectRatioX,
- int aspectRatioY,
- float scale,
- boolean flipHorizontally,
- boolean flipVertically) {
-
- // get the rectangle in original image that contains the required cropped area (larger for non
- // rectangular crop)
- Rect rect =
- getRectFromPoints(
- points,
- bitmap.getWidth(),
- bitmap.getHeight(),
- fixAspectRatio,
- aspectRatioX,
- aspectRatioY);
-
- // crop and rotate the cropped image in one operation
- Matrix matrix = new Matrix();
- matrix.setRotate(degreesRotated, bitmap.getWidth() / 2, bitmap.getHeight() / 2);
- matrix.postScale(flipHorizontally ? -scale : scale, flipVertically ? -scale : scale);
- Bitmap result =
- Bitmap.createBitmap(bitmap, rect.left, rect.top, rect.width(), rect.height(), matrix, true);
-
- if (result == bitmap) {
- // corner case when all bitmap is selected, no worth optimizing for it
- result = bitmap.copy(bitmap.getConfig(), false);
- }
-
- // rotating by 0, 90, 180 or 270 degrees doesn't require extra cropping
- if (degreesRotated % 90 != 0) {
-
- // extra crop because non rectangular crop cannot be done directly on the image without
- // rotating first
- result =
- cropForRotatedImage(
- result, points, rect, degreesRotated, fixAspectRatio, aspectRatioX, aspectRatioY);
- }
-
- return result;
- }
-
- /**
- * Crop image bitmap from URI by decoding it with specific width and height to down-sample if
- * required.<br>
- * Additionally if OOM is thrown try to increase the sampling (2,4,8).
- */
- static BitmapSampled cropBitmap(
- Context context,
- Uri loadedImageUri,
- float[] points,
- int degreesRotated,
- int orgWidth,
- int orgHeight,
- boolean fixAspectRatio,
- int aspectRatioX,
- int aspectRatioY,
- int reqWidth,
- int reqHeight,
- boolean flipHorizontally,
- boolean flipVertically) {
- int sampleMulti = 1;
- while (true) {
- try {
- // if successful, just return the resulting bitmap
- return cropBitmap(
- context,
- loadedImageUri,
- points,
- degreesRotated,
- orgWidth,
- orgHeight,
- fixAspectRatio,
- aspectRatioX,
- aspectRatioY,
- reqWidth,
- reqHeight,
- flipHorizontally,
- flipVertically,
- sampleMulti);
- } catch (OutOfMemoryError e) {
- // if OOM try to increase the sampling to lower the memory usage
- sampleMulti *= 2;
- if (sampleMulti > 16) {
- throw new RuntimeException(
- "Failed to handle OOM by sampling ("
- + sampleMulti
- + "): "
- + loadedImageUri
- + "\r\n"
- + e.getMessage(),
- e);
- }
- }
- }
- }
-
- /**
- * Get left value of the bounding rectangle of the given points.
- */
- static float getRectLeft(float[] points) {
- return Math.min(Math.min(Math.min(points[0], points[2]), points[4]), points[6]);
- }
-
- /**
- * Get top value of the bounding rectangle of the given points.
- */
- static float getRectTop(float[] points) {
- return Math.min(Math.min(Math.min(points[1], points[3]), points[5]), points[7]);
- }
-
- /**
- * Get right value of the bounding rectangle of the given points.
- */
- static float getRectRight(float[] points) {
- return Math.max(Math.max(Math.max(points[0], points[2]), points[4]), points[6]);
- }
-
- /**
- * Get bottom value of the bounding rectangle of the given points.
- */
- static float getRectBottom(float[] points) {
- return Math.max(Math.max(Math.max(points[1], points[3]), points[5]), points[7]);
- }
-
- /**
- * Get width of the bounding rectangle of the given points.
- */
- static float getRectWidth(float[] points) {
- return getRectRight(points) - getRectLeft(points);
- }
-
- /**
- * Get height of the bounding rectangle of the given points.
- */
- static float getRectHeight(float[] points) {
- return getRectBottom(points) - getRectTop(points);
- }
-
- /**
- * Get horizontal center value of the bounding rectangle of the given points.
- */
- static float getRectCenterX(float[] points) {
- return (getRectRight(points) + getRectLeft(points)) / 2f;
- }
-
- /**
- * Get vertical center value of the bounding rectangle of the given points.
- */
- static float getRectCenterY(float[] points) {
- return (getRectBottom(points) + getRectTop(points)) / 2f;
- }
-
- /**
- * Get a rectangle for the given 4 points (x0,y0,x1,y1,x2,y2,x3,y3) by finding the min/max 2
- * points that contains the given 4 points and is a straight rectangle.
- */
- static Rect getRectFromPoints(
- float[] points,
- int imageWidth,
- int imageHeight,
- boolean fixAspectRatio,
- int aspectRatioX,
- int aspectRatioY) {
- int left = Math.round(Math.max(0, getRectLeft(points)));
- int top = Math.round(Math.max(0, getRectTop(points)));
- int right = Math.round(Math.min(imageWidth, getRectRight(points)));
- int bottom = Math.round(Math.min(imageHeight, getRectBottom(points)));
-
- Rect rect = new Rect(left, top, right, bottom);
- if (fixAspectRatio) {
- fixRectForAspectRatio(rect, aspectRatioX, aspectRatioY);
- }
-
- return rect;
- }
-
- /**
- * Fix the given rectangle if it doesn't confirm to aspect ration rule.<br>
- * Make sure that width and height are equal if 1:1 fixed aspect ratio is requested.
- */
- private static void fixRectForAspectRatio(Rect rect, int aspectRatioX, int aspectRatioY) {
- if (aspectRatioX == aspectRatioY && rect.width() != rect.height()) {
- if (rect.height() > rect.width()) {
- rect.bottom -= rect.height() - rect.width();
- } else {
- rect.right -= rect.width() - rect.height();
- }
- }
- }
-
- /**
- * Write given bitmap to a temp file. If file already exists no-op as we already saved the file in
- * this session. Uses JPEG 95% compression.
- *
- * @param uri the uri to write the bitmap to, if null
- * @return the uri where the image was saved in, either the given uri or new pointing to temp
- * file.
- */
- static Uri writeTempStateStoreBitmap(Context context, Bitmap bitmap, Uri uri) {
- try {
- boolean needSave = true;
- if (uri == null) {
- uri =
- Uri.fromFile(
- File.createTempFile("aic_state_store_temp", ".jpg", context.getCacheDir()));
- } else if (new File(uri.getPath()).exists()) {
- needSave = false;
- }
- if (needSave) {
- writeBitmapToUri(context, bitmap, uri, Bitmap.CompressFormat.JPEG, 95);
- }
- return uri;
- } catch (Exception e) {
- Log.w("AIC", "Failed to write bitmap to temp file for image-cropper save instance state", e);
- return null;
- }
- }
-
- /**
- * Write the given bitmap to the given uri using the given compression.
- */
- static void writeBitmapToUri(
- Context context,
- Bitmap bitmap,
- Uri uri,
- Bitmap.CompressFormat compressFormat,
- int compressQuality)
- throws FileNotFoundException {
- OutputStream outputStream = null;
- try {
- outputStream = context.getContentResolver().openOutputStream(uri);
- bitmap.compress(compressFormat, compressQuality, outputStream);<