Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ final class BitmapCroppingWorkerTask extends AsyncTask<Void, Void, BitmapCroppin
*/
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
*/
Expand All @@ -114,7 +124,7 @@ final class BitmapCroppingWorkerTask extends AsyncTask<Void, Void, BitmapCroppin

BitmapCroppingWorkerTask(CropImageView cropImageView, Bitmap bitmap, float[] cropPoints,
int degreesRotated, boolean fixAspectRatio, int aspectRatioX, int aspectRatioY,
int reqWidth, int reqHeight, CropImageView.RequestSizeOptions options,
int reqWidth, int reqHeight, boolean flipHorizontally, boolean flipVertically, CropImageView.RequestSizeOptions options,
Uri saveUri, Bitmap.CompressFormat saveCompressFormat, int saveCompressQuality) {

mCropImageViewReference = new WeakReference<>(cropImageView);
Expand All @@ -128,6 +138,8 @@ final class BitmapCroppingWorkerTask extends AsyncTask<Void, Void, BitmapCroppin
mAspectRatioY = aspectRatioY;
mReqWidth = reqWidth;
mReqHeight = reqHeight;
mFlipHorizontally = flipHorizontally;
mFlipVertically = flipVertically;
mReqSizeOptions = options;
mSaveUri = saveUri;
mSaveCompressFormat = saveCompressFormat;
Expand All @@ -138,8 +150,8 @@ final class BitmapCroppingWorkerTask extends AsyncTask<Void, Void, BitmapCroppin

BitmapCroppingWorkerTask(CropImageView cropImageView, Uri uri, float[] cropPoints,
int degreesRotated, int orgWidth, int orgHeight,
boolean fixAspectRatio, int aspectRatioX, int aspectRatioY,
int reqWidth, int reqHeight, CropImageView.RequestSizeOptions options,
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);
Expand All @@ -154,6 +166,8 @@ final class BitmapCroppingWorkerTask extends AsyncTask<Void, Void, BitmapCroppin
mOrgHeight = orgHeight;
mReqWidth = reqWidth;
mReqHeight = reqHeight;
mFlipHorizontally = flipHorizontally;
mFlipVertically = flipVertically;
mReqSizeOptions = options;
mSaveUri = saveUri;
mSaveCompressFormat = saveCompressFormat;
Expand Down Expand Up @@ -182,9 +196,10 @@ protected BitmapCroppingWorkerTask.Result doInBackground(Void... params) {
BitmapUtils.BitmapSampled bitmapSampled;
if (mUri != null) {
bitmapSampled = BitmapUtils.cropBitmap(mContext, mUri, mCropPoints, mDegreesRotated, mOrgWidth, mOrgHeight,
mFixAspectRatio, mAspectRatioX, mAspectRatioY, mReqWidth, mReqHeight);
mFixAspectRatio, mAspectRatioX, mAspectRatioY, mReqWidth, mReqHeight, mFlipHorizontally, mFlipVertically);
} else if (mBitmap != null) {
bitmapSampled = BitmapUtils.cropBitmapObjectHandleOOM(mBitmap, mCropPoints, mDegreesRotated, mFixAspectRatio, mAspectRatioX, mAspectRatioY);
bitmapSampled = BitmapUtils.cropBitmapObjectHandleOOM(mBitmap, mCropPoints, mDegreesRotated, mFixAspectRatio,
mAspectRatioX, mAspectRatioY, mFlipHorizontally, mFlipVertically);
} else {
return new Result((Bitmap) null, 1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,13 @@ static BitmapSampled decodeSampledBitmap(Context context, Uri uri, int reqWidth,
* 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 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);
Bitmap cropBitmap = cropBitmapObjectWithScale(bitmap, points, degreesRotated, fixAspectRatio, aspectRatioX, aspectRatioY,
1 / (float) scale, flipHorizontally, flipVertically);
return new BitmapSampled(cropBitmap, scale);
} catch (OutOfMemoryError e) {
scale *= 2;
Expand All @@ -172,14 +174,26 @@ static BitmapSampled cropBitmapObjectHandleOOM(Bitmap bitmap, float[] points, in
* @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 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);

if (degreesRotated == 90 || degreesRotated == 270) {
if (flipHorizontally != flipVertically) {
boolean temp = flipHorizontally;
flipHorizontally = flipVertically;
flipVertically = temp;
}
}

// crop and rotate the cropped image in one operation
float scaleX = flipHorizontally ? -scale : scale;
float scaleY = flipVertically ? -scale : scale;

Matrix matrix = new Matrix();
matrix.setScale(scale, scale);
matrix.setScale(scaleX, scaleY);
matrix.postRotate(degreesRotated, bitmap.getWidth() / 2, bitmap.getHeight() / 2);
Bitmap result = Bitmap.createBitmap(bitmap, rect.left, rect.top, rect.width(), rect.height(), matrix, true);

Expand All @@ -204,15 +218,16 @@ private static Bitmap cropBitmapObjectWithScale(Bitmap bitmap, float[] points, i
*/
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) {
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,
sampleMulti);
flipHorizontally, flipVertically, sampleMulti);
} catch (OutOfMemoryError e) {
// if OOM try to increase the sampling to lower the memory usage
sampleMulti *= 2;
Expand Down Expand Up @@ -366,9 +381,9 @@ static Bitmap resizeBitmap(Bitmap bitmap, int reqWidth, int reqHeight, CropImage
* @param orgHeight used to get rectangle from points (handle edge cases to limit rectangle)
* @param sampleMulti used to increase the sampling of the image to handle memory issues.
*/
private 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, int sampleMulti) {
private 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) {

// get the rectangle in original image that contains the required cropped area (larger for non rectangular crop)
Rect rect = getRectFromPoints(points, orgWidth, orgHeight, fixAspectRatio, aspectRatioX, aspectRatioY);
Expand Down Expand Up @@ -406,7 +421,8 @@ private static BitmapSampled cropBitmap(Context context, Uri loadedImageUri, flo
return new BitmapSampled(result, sampleSize);
} else {
// failed to decode region, may be skia issue, try full decode and then crop
return cropBitmap(context, loadedImageUri, points, degreesRotated, fixAspectRatio, aspectRatioX, aspectRatioY, sampleMulti, rect, width, height);
return cropBitmap(context, loadedImageUri, points, degreesRotated, fixAspectRatio, aspectRatioX, aspectRatioY, sampleMulti,
rect, width, height, flipHorizontally, flipVertically);
}
}

Expand All @@ -415,7 +431,7 @@ private static BitmapSampled cropBitmap(Context context, Uri loadedImageUri, flo
*/
private static BitmapSampled cropBitmap(Context context, Uri loadedImageUri, float[] points,
int degreesRotated, boolean fixAspectRatio, int aspectRatioX, int aspectRatioY,
int sampleMulti, Rect rect, int width, int height) {
int sampleMulti, Rect rect, int width, int height, boolean flipHorizontally, boolean flipVertically) {
Bitmap result = null;
int sampleSize;
try {
Expand All @@ -432,7 +448,8 @@ private static BitmapSampled cropBitmap(Context context, Uri loadedImageUri, flo
points2[i] = points2[i] / options.inSampleSize;
}

result = cropBitmapObjectWithScale(fullBitmap, points2, degreesRotated, fixAspectRatio, aspectRatioX, aspectRatioY, 1);
result = cropBitmapObjectWithScale(fullBitmap, points2, degreesRotated, fixAspectRatio, aspectRatioX, aspectRatioY, 1,
flipHorizontally, flipVertically);
} finally {
if (result != fullBitmap) {
fullBitmap.recycle();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,16 @@ public CropImageOptions[] newArray(int size) {
*/
public int rotationDegrees;

/**
* whether the image should be flipped horizontally
*/
public boolean flipHorizontally;

/**
* whether the image should be flipped vertically
*/
public boolean flipVertically;

/**
* Init options with defaults.
*/
Expand Down Expand Up @@ -320,6 +330,8 @@ public CropImageOptions() {
allowRotation = true;
allowCounterRotation = false;
rotationDegrees = 90;
flipHorizontally = false;
flipVertically = false;
}

/**
Expand Down Expand Up @@ -369,6 +381,8 @@ protected CropImageOptions(Parcel in) {
allowRotation = in.readByte() != 0;
allowCounterRotation = in.readByte() != 0;
rotationDegrees = in.readInt();
flipHorizontally = in.readByte() != 0;
flipVertically = in.readByte() != 0;
}

@Override
Expand Down Expand Up @@ -416,6 +430,8 @@ public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (allowRotation ? 1 : 0));
dest.writeByte((byte) (allowCounterRotation ? 1 : 0));
dest.writeInt(rotationDegrees);
dest.writeByte((byte) (flipHorizontally ? 1 : 0));
dest.writeByte((byte) (flipVertically ? 1 : 0));
}

@Override
Expand Down
Loading