Skip to content

Commit

Permalink
Put crop logic to BitmapCropTask.java
Browse files Browse the repository at this point in the history
Passing to native code compress format/quality.
Refactoring.
  • Loading branch information
shliama committed May 1, 2016
1 parent dd0fed3 commit 4eff62e
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 123 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0'
classpath 'com.android.tools.build:gradle:2.1.0'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,6 @@ private UCrop advancedConfig(@NonNull UCrop uCrop) {
case R.id.radio_png:
options.setCompressionFormat(Bitmap.CompressFormat.PNG);
break;
case R.id.radio_webp:
options.setCompressionFormat(Bitmap.CompressFormat.WEBP);
break;
case R.id.radio_jpeg:
default:
options.setCompressionFormat(Bitmap.CompressFormat.JPEG);
Expand Down
8 changes: 0 additions & 8 deletions sample/src/main/res/layout/activity_sample.xml
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,6 @@
android:textAppearance="?android:textAppearanceMedium"
tools:ignore="HardcodedText"/>

<RadioButton
android:id="@+id/radio_webp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="WEBP"
android:textAppearance="?android:textAppearanceMedium"
tools:ignore="HardcodedText"/>

<TextView
android:id="@+id/text_view_quality"
android:layout_width="wrap_content"
Expand Down
13 changes: 1 addition & 12 deletions ucrop/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,10 @@ android {

resourcePrefix 'ucrop_'

// task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
// def ndkDir = android.ndkDirectory
// commandLine "$ndkDir/ndk-build",
// '-C', file('src/main/jni').absolutePath,
// '-j', Runtime.runtime.availableProcessors(),
// 'all',
// 'NDK_DEBUG=1'
// }
sourceSets.main {
// jniLibs.srcDir 'src/main/libs'
jni.srcDirs = [];
}
// tasks.withType(JavaCompile) {
// compileTask -> compileTask.dependsOn buildNative
// }

}

dependencies {
Expand Down
14 changes: 7 additions & 7 deletions ucrop/src/main/java/com/yalantis/ucrop/UCropActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,13 @@ private void setImageData(@NonNull Intent intent) {

if (mInputUri != null && mOutputUri != null) {
try {
mGestureCropImageView.setImageUri(inputUri, mOutputUri);
mGestureCropImageView.setImageUri(mInputUri, mOutputUri);
} catch (Exception e) {
setResultException(e);
setResultError(e);
finish();
}
} else {
setResultException(new NullPointerException(getString(R.string.ucrop_error_input_data_is_absent)));
setResultError(new NullPointerException(getString(R.string.ucrop_error_input_data_is_absent)));
finish();
}

Expand Down Expand Up @@ -356,7 +356,7 @@ public void onLoadComplete() {

@Override
public void onLoadFailure(@NonNull Exception e) {
setResultException(e);
setResultError(e);
finish();
}

Expand Down Expand Up @@ -587,8 +587,8 @@ public void onBitmapCropped() {
}

@Override
public void onCropFailure(@NonNull Exception bitmapCropException) {
setResultException(bitmapCropException);
public void onCropFailure(@NonNull Throwable t) {
setResultError(t);
finish();
}
});
Expand All @@ -600,7 +600,7 @@ protected void setResultUri(Uri uri, float resultAspectRatio) {
.putExtra(UCrop.EXTRA_OUTPUT_CROP_ASPECT_RATIO, resultAspectRatio));
}

protected void setResultException(Throwable throwable) {
protected void setResultError(Throwable throwable) {
setResult(UCrop.RESULT_ERROR, new Intent().putExtra(UCrop.EXTRA_ERROR, throwable));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ public interface BitmapCropCallback {

void onBitmapCropped();

void onCropFailure(@NonNull Exception bitmapCropException);
void onCropFailure(@NonNull Throwable t);

}
41 changes: 23 additions & 18 deletions ucrop/src/main/java/com/yalantis/ucrop/task/BitmapCropTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@
import android.support.annotation.Nullable;

import com.yalantis.ucrop.callback.BitmapCropCallback;
import com.yalantis.ucrop.util.BitmapLoadUtils;

import java.io.OutputStream;
import java.io.IOException;

/**
* Crops part of image that fills the crop bounds.
Expand All @@ -21,7 +20,11 @@
* Then image is rotated accordingly.
* Finally new Bitmap object is created and saved to file.
*/
public class BitmapCropTask extends AsyncTask<Void, Void, Exception> {
public class BitmapCropTask extends AsyncTask<Void, Void, Throwable> {

static {
System.loadLibrary("ucrop");
}

private final Context mContext;

Expand Down Expand Up @@ -69,7 +72,7 @@ public BitmapCropTask(@NonNull Context context, @Nullable Bitmap viewBitmap,

@Override
@Nullable
protected Exception doInBackground(Void... params) {
protected Throwable doInBackground(Void... params) {
if (mViewBitmap == null || mViewBitmap.isRecycled()) {
return new NullPointerException("ViewBitmap is null or already recycled");
}
Expand All @@ -85,19 +88,14 @@ protected Exception doInBackground(Void... params) {
rotate();
}

crop();

OutputStream outputStream = null;
try {
outputStream = mContext.getContentResolver().openOutputStream(mOutputUri);
mViewBitmap.compress(mCompressFormat, mCompressQuality, outputStream);
crop();
mViewBitmap.recycle();
mViewBitmap = null;
} catch (Exception e) {
return e;
} finally {
BitmapLoadUtils.close(outputStream);
} catch (Throwable throwable) {
return throwable;
}

return null;
}

Expand Down Expand Up @@ -135,22 +133,29 @@ private void rotate() {
mViewBitmap = rotatedBitmap;
}

private void crop() {
private boolean crop() throws IOException {
int top = Math.round((mCropRect.top - mCurrentImageRect.top) / mCurrentScale);
int left = Math.round((mCropRect.left - mCurrentImageRect.left) / mCurrentScale);
int width = Math.round(mCropRect.width() / mCurrentScale);
int height = Math.round(mCropRect.height() / mCurrentScale);

mViewBitmap = Bitmap.createBitmap(mViewBitmap, left, top, width, height);
return cropCImg(mOutputUri.getPath(), mOutputUri.getPath(),
left, top, width, height, mCurrentAngle,
mCompressFormat.ordinal(), mCompressQuality);
}

@SuppressWarnings("JniMissingFunction")
native public boolean cropCImg(String inputPath, String outputPath,
int left, int top, int width, int height, float angle,
int format, int quality) throws IOException, OutOfMemoryError;

@Override
protected void onPostExecute(@Nullable Exception result) {
protected void onPostExecute(@Nullable Throwable t) {
if (mCropCallback != null) {
if (result == null) {
if (t == null) {
mCropCallback.onBitmapCropped();
} else {
mCropCallback.onCropFailure(result);
mCropCallback.onCropFailure(t);
}
}
}
Expand Down
73 changes: 0 additions & 73 deletions ucrop/src/main/java/com/yalantis/ucrop/view/CropImageView.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
Expand All @@ -12,7 +11,6 @@
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;

import com.yalantis.ucrop.R;
import com.yalantis.ucrop.callback.BitmapCropCallback;
Expand All @@ -21,7 +19,6 @@
import com.yalantis.ucrop.util.CubicEasing;
import com.yalantis.ucrop.util.RectUtils;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Arrays;

Expand All @@ -33,10 +30,6 @@
*/
public class CropImageView extends TransformImageView {

static {
System.loadLibrary("ucrop");
}

public static final int DEFAULT_MAX_BITMAP_SIZE = 0;
public static final int DEFAULT_IMAGE_TO_CROP_BOUNDS_ANIM_DURATION = 500;
public static final float DEFAULT_MAX_SCALE_MULTIPLIER = 10.0f;
Expand Down Expand Up @@ -87,72 +80,6 @@ public void cropAndSaveImage(@NonNull Bitmap.CompressFormat compressFormat, int
outputUri, cropCallback).execute();
}

/**
* fixme
* This method crops part of image that fills the crop bounds.
* <p/>
* First image is downscaled if max size was set and if resulting image is larger that max size.
* Then image is rotated accordingly.
* Finally new Bitmap object is created and returned.
*
* @return - cropped Bitmap object or null if current Bitmap is invalid or image rectangle is empty.
*/
public boolean cropImageNative(Uri input, Uri output) throws IOException {
Bitmap viewBitmap = getViewBitmap();
if (viewBitmap == null || viewBitmap.isRecycled()) {
return false;
}

cancelAllAnimations();
setImageToWrapCropBounds(false);

RectF currentImageRect = RectUtils.trapToRect(mCurrentImageCorners);
if (currentImageRect.isEmpty()) {
return false;
}

float currentScale = getCurrentScale();
float currentAngle = getCurrentAngle();


final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(input.getPath(), options);

float scaleX = options.outWidth / viewBitmap.getWidth();
float scaleY = options.outHeight / viewBitmap.getHeight();

float resizeScale = Math.min(scaleX, scaleY);

currentScale /= resizeScale;

Log.d("WTF", "currentScale: " + currentScale + " scaleX: " + scaleX + " scaleY: " + scaleY);

int top = (int) ((mCropRect.top - currentImageRect.top) / currentScale);
int left = (int) ((mCropRect.left - currentImageRect.left) / currentScale);
int width = (int) (mCropRect.width() / currentScale);
int height = (int) (mCropRect.height() / currentScale);

/* if (mMaxResultImageSizeX > 0 && mMaxResultImageSizeY > 0) {
float cropWidth = mCropRect.width() / currentScale;
float cropHeight = mCropRect.height() / currentScale;
if (cropWidth > mMaxResultImageSizeX || cropHeight > mMaxResultImageSizeY) {*/

Log.d("WTF", String.format("java left: %s top: %s width: %s height: %s angle: %s:", left, top, width, height, currentAngle));
long startTime = System.nanoTime();
boolean result = cropCImg(input.getPath(), output.getPath(), left, top, width, height, currentAngle);

long stopTime = System.nanoTime();
Log.d("WTF", "sec: " + (stopTime - startTime) / 1000000.f);

return result;
}

@SuppressWarnings("JniMissingFunction")
native public boolean cropCImg(String inputPath, String outputPath, int left, int top, int width, int height, float angle) throws IOException, OutOfMemoryError;



/**
* @return - maximum scale value for current image and crop ratio
*/
Expand Down

0 comments on commit 4eff62e

Please sign in to comment.