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 5ab08c4..006e301 100644 --- a/lib/src/main/java/com/soundcloud/android/crop/CropImageActivity.java +++ b/lib/src/main/java/com/soundcloud/android/crop/CropImageActivity.java @@ -17,9 +17,7 @@ package com.soundcloud.android.crop; import android.annotation.TargetApi; -import android.content.ContentResolver; import android.content.Intent; -import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; @@ -27,18 +25,15 @@ import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.RectF; -import android.media.ExifInterface; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.provider.MediaStore; -import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.Window; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -49,7 +44,6 @@ import java.util.concurrent.CountDownLatch; */ public class CropImageActivity extends MonitoredActivity { - private static final String TAG = CropImageActivity.class.getSimpleName(); private static final boolean IN_MEMORY_CROP = Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD_MR1; private final Handler mHandler = new Handler(); @@ -75,10 +69,19 @@ public class CropImageActivity extends MonitoredActivity { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); - requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_crop); + initViews(); + setupFromIntent(); + if (mRotateBitmap == null) { + finish(); + return; + } + startCrop(); + } + + private void initViews() { mImageView = (CropImageView) findViewById(R.id.crop_image); mImageView.mContext = this; mImageView.setRecycler(new ImageViewTouchBase.Recycler() { @@ -89,6 +92,21 @@ public class CropImageActivity extends MonitoredActivity { } }); + findViewById(R.id.btn_cancel).setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + setResult(RESULT_CANCELED); + finish(); + } + }); + + findViewById(R.id.btn_done).setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + onSaveClicked(); + } + }); + } + + private void setupFromIntent() { Intent intent = getIntent(); Bundle extras = intent.getExtras(); @@ -102,43 +120,22 @@ public class CropImageActivity extends MonitoredActivity { mSourceUri = intent.getData(); if (mSourceUri != null) { - mExifRotation = getExifRotation(getFromMediaUri(getContentResolver(), mSourceUri)); + mExifRotation = Util.getExifRotation(Util.getFromMediaUri(getContentResolver(), mSourceUri)); InputStream is = null; try { is = getContentResolver().openInputStream(mSourceUri); mRotateBitmap = new RotateBitmap(BitmapFactory.decodeStream(is), mExifRotation); } catch (IOException e) { - Log.e(TAG, "error reading picture: " + e.getMessage(), e); + Log.e(Util.TAG, "Error reading picture: " + e.getMessage(), e); setResultByUriWithException(mSourceUri, e); } catch (OutOfMemoryError e) { - Log.e(TAG, "OOM while reading picture: " + e.getMessage(), e); + Log.e(Util.TAG, "OOM while reading picture: " + e.getMessage(), e); setResultByUri(mSourceUri); } finally{ Util.closeSilently(is); } } - - if (mRotateBitmap == null) { - finish(); - return; - } - - findViewById(R.id.btn_cancel).setOnClickListener( - new View.OnClickListener() { - public void onClick(View v) { - setResult(RESULT_CANCELED); - finish(); - } - }); - - findViewById(R.id.btn_done).setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - onSaveClicked(); - } - }); - - startCrop(); } private void startCrop() { @@ -146,8 +143,7 @@ public class CropImageActivity extends MonitoredActivity { return; } mImageView.setImageRotateBitmapResetBase(mRotateBitmap, true); - Util.startBackgroundJob(this, null, - getResources().getString(R.string.wait), + Util.startBackgroundJob(this, null, getResources().getString(R.string.wait), new Runnable() { public void run() { final CountDownLatch latch = new CountDownLatch(1); @@ -169,7 +165,6 @@ public class CropImageActivity extends MonitoredActivity { }, mHandler); } - private class Cropper { private void makeDefault() { @@ -183,7 +178,7 @@ public class CropImageActivity extends MonitoredActivity { // Make the default size about 4/5 of the width or height int cropWidth = Math.min(width, height) * 4 / 5; - // Noinspection SuspiciousNameCombination + @SuppressWarnings("SuspiciousNameCombination") int cropHeight = cropWidth; if (mAspectX != 0 && mAspectY != 0) { @@ -198,8 +193,7 @@ public class CropImageActivity extends MonitoredActivity { int y = (height - cropHeight) / 2; RectF cropRect = new RectF(x, y, x + cropWidth, y + cropHeight); - hv.setup(mImageView.getUnrotatedMatrix(), imageRect, cropRect, - mAspectX != 0 && mAspectY != 0); + hv.setup(mImageView.getUnrotatedMatrix(), imageRect, cropRect, mAspectX != 0 && mAspectY != 0); mImageView.add(hv); } @@ -276,8 +270,7 @@ public class CropImageActivity extends MonitoredActivity { if (croppedImage != null) { extras.putParcelable("data", croppedImage); } - setResult(RESULT_OK, - (new Intent()).setAction("inline-data").putExtras(extras)); + setResult(RESULT_OK, (new Intent()).setAction("inline-data").putExtras(extras)); finish(); } else { if (croppedImage != null){ @@ -332,7 +325,7 @@ public class CropImageActivity extends MonitoredActivity { } } catch (IOException e) { - Log.e(TAG, "error cropping picture: " + e.getMessage(), e); + Log.e(Util.TAG, "Error cropping picture: " + e.getMessage(), e); finish(); } finally { Util.closeSilently(is); @@ -340,9 +333,7 @@ public class CropImageActivity extends MonitoredActivity { return croppedImage; } - private Bitmap inMemoryCrop(RotateBitmap rotateBitmap, - Bitmap croppedImage, - Rect r, + private Bitmap inMemoryCrop(RotateBitmap rotateBitmap, Bitmap croppedImage, Rect r, int width, int height, int outWidth, int outHeight) { // In-memory crop, potential OOM errors, // but we have no choice as we can't selectively decode a bitmap with this sdk @@ -360,7 +351,7 @@ public class CropImageActivity extends MonitoredActivity { canvas.drawBitmap(rotateBitmap.getBitmap(), m, null); } catch (OutOfMemoryError e){ - Log.e(TAG, "error cropping picture: " + e.getMessage(), e); + Log.e(Util.TAG, "Error cropping picture: " + e.getMessage(), e); System.gc(); } @@ -388,16 +379,16 @@ public class CropImageActivity extends MonitoredActivity { } catch (IOException ex) { // TODO: report error to caller - Log.e(TAG, "Cannot open file: " + mSaveUri, ex); + Log.e(Util.TAG, "Cannot open file: " + mSaveUri, ex); } finally { Util.closeSilently(outputStream); } if (!IN_MEMORY_CROP){ // In-memory crop negates the rotation - copyExifRotation( - getFromMediaUri(getContentResolver(), mSourceUri), - getFromMediaUri(getContentResolver(), mSaveUri) + Util.copyExifRotation( + Util.getFromMediaUri(getContentResolver(), mSourceUri), + Util.getFromMediaUri(getContentResolver(), mSaveUri) ); } @@ -440,71 +431,5 @@ public class CropImageActivity extends MonitoredActivity { setResult(RESULT_OK, new Intent().putExtra(MediaStore.EXTRA_OUTPUT, uri).putExtra(Crop.Extra.ERROR, exception)); } - public static int getExifRotation(File imageFile) { - if (imageFile == null) { - return ExifInterface.ORIENTATION_UNDEFINED; - } - try { - ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath()); - // We only recognize a subset of orientation tag values - switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)) { - case ExifInterface.ORIENTATION_ROTATE_90: - return 90; - case ExifInterface.ORIENTATION_ROTATE_180: - return 180; - case ExifInterface.ORIENTATION_ROTATE_270: - return 270; - default: - return ExifInterface.ORIENTATION_UNDEFINED; - } - } catch (IOException e) { - Log.e(TAG, "error", e); - return ExifInterface.ORIENTATION_UNDEFINED; - } - } - - public static boolean copyExifRotation(File sourceFile, File destFile) { - if (sourceFile == null || destFile == null) return false; - try { - ExifInterface exifSource = new ExifInterface(sourceFile.getAbsolutePath()); - ExifInterface exifDest = new ExifInterface(destFile.getAbsolutePath()); - exifDest.setAttribute(ExifInterface.TAG_ORIENTATION, exifSource.getAttribute(ExifInterface.TAG_ORIENTATION)); - exifDest.saveAttributes(); - return true; - } catch (IOException e) { - Log.e(TAG, "error", e); - return false; - } - } - - public static File getFromMediaUri(ContentResolver resolver, Uri uri) { - if (uri == null) return null; - - if ("file".equals(uri.getScheme())) { - return new File(uri.getPath()); - } else if ("content".equals(uri.getScheme())) { - final String[] filePathColumn = {MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DISPLAY_NAME}; - Cursor cursor = null; - try { - cursor = resolver.query(uri, filePathColumn, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - final int columnIndex = (uri.toString().startsWith("content://com.google.android.gallery3d")) ? - cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME) : - cursor.getColumnIndex(MediaStore.MediaColumns.DATA); // if it is a picasa image on newer devices with OS 3.0 and up - if (columnIndex != -1) { - String filePath = cursor.getString(columnIndex); - if (!TextUtils.isEmpty(filePath)) { - return new File(filePath); - } - } - } - } catch (SecurityException ignored) { - // Nothing we can do - } finally { - if (cursor != null) cursor.close(); - } - } - return null; - } } diff --git a/lib/src/main/java/com/soundcloud/android/crop/Util.java b/lib/src/main/java/com/soundcloud/android/crop/Util.java index 98aca1e..b38e711 100644 --- a/lib/src/main/java/com/soundcloud/android/crop/Util.java +++ b/lib/src/main/java/com/soundcloud/android/crop/Util.java @@ -17,15 +17,26 @@ package com.soundcloud.android.crop; import android.app.ProgressDialog; +import android.content.ContentResolver; +import android.database.Cursor; +import android.media.ExifInterface; +import android.net.Uri; import android.os.Handler; +import android.provider.MediaStore; +import android.text.TextUtils; +import android.util.Log; import java.io.Closeable; +import java.io.File; +import java.io.IOException; /* * Modified from original in AOSP. */ public class Util { + public static final String TAG = "android-crop"; + public static void closeSilently(Closeable c) { if (c == null) return; try { @@ -35,6 +46,72 @@ public class Util { } } + public static int getExifRotation(File imageFile) { + if (imageFile == null) return 0; + try { + ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath()); + // We only recognize a subset of orientation tag values + switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)) { + case ExifInterface.ORIENTATION_ROTATE_90: + return 90; + case ExifInterface.ORIENTATION_ROTATE_180: + return 180; + case ExifInterface.ORIENTATION_ROTATE_270: + return 270; + default: + return ExifInterface.ORIENTATION_UNDEFINED; + } + } catch (IOException e) { + Log.e(TAG, "Error getting Exif data", e); + return 0; + } + } + + public static boolean copyExifRotation(File sourceFile, File destFile) { + if (sourceFile == null || destFile == null) return false; + try { + ExifInterface exifSource = new ExifInterface(sourceFile.getAbsolutePath()); + ExifInterface exifDest = new ExifInterface(destFile.getAbsolutePath()); + exifDest.setAttribute(ExifInterface.TAG_ORIENTATION, exifSource.getAttribute(ExifInterface.TAG_ORIENTATION)); + exifDest.saveAttributes(); + return true; + } catch (IOException e) { + Log.e(TAG, "Error copying Exif data", e); + return false; + } + } + + public static File getFromMediaUri(ContentResolver resolver, Uri uri) { + if (uri == null) return null; + + if ("file".equals(uri.getScheme())) { + return new File(uri.getPath()); + } else if ("content".equals(uri.getScheme())) { + final String[] filePathColumn = { MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DISPLAY_NAME }; + Cursor cursor = null; + try { + cursor = resolver.query(uri, filePathColumn, null, null, null); + if (cursor != null && cursor.moveToFirst()) { + final int columnIndex = (uri.toString().startsWith("content://com.google.android.gallery3d")) ? + cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME) : + cursor.getColumnIndex(MediaStore.MediaColumns.DATA); + // Picasa image on newer devices with Honeycomb and up + if (columnIndex != -1) { + String filePath = cursor.getString(columnIndex); + if (!TextUtils.isEmpty(filePath)) { + return new File(filePath); + } + } + } + } catch (SecurityException ignored) { + // Nothing we can do + } finally { + if (cursor != null) cursor.close(); + } + } + return null; + } + public static void startBackgroundJob(MonitoredActivity activity, String title, String message, Runnable job, Handler handler) { // Make the progress dialog uncancelable, so that we can gurantee @@ -93,4 +170,5 @@ public class Util { mDialog.show(); } } + }