177 lines
4.8 KiB
Java
177 lines
4.8 KiB
Java
// "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
|
|
}
|