/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.edx.mobile.third_party.crop;
import android.content.Context;
import android.database.Cursor;
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.media.ExifInterface;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/*
* Modified from https://github.com/jdamcd/android-crop which was itself modified from AOSP
*/
public class CropUtil {
public static int getExifOrientationFromRotation(int rotation) {
switch (rotation) {
case 90:
return ExifInterface.ORIENTATION_ROTATE_90;
case 180:
return ExifInterface.ORIENTATION_ROTATE_180;
case 270:
return ExifInterface.ORIENTATION_ROTATE_270;
default:
return ExifInterface.ORIENTATION_UNDEFINED;
}
}
public static int getRotationFromExifOrientation(int rotation) {
switch (rotation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return 90;
case ExifInterface.ORIENTATION_ROTATE_180:
return 180;
case ExifInterface.ORIENTATION_ROTATE_270:
return 270;
default:
return 0;
}
}
public static void setExifOrientation(int rotation, @NonNull File destFile) throws IOException {
ExifInterface exif = new ExifInterface(destFile.getAbsolutePath());
if (rotation != 0) {
exif.setAttribute(ExifInterface.TAG_ORIENTATION, String.valueOf(getExifOrientationFromRotation(rotation)));
exif.saveAttributes();
}
}
public static int getOrientationFromContentResolver(@NonNull Context context, @NonNull Uri photoUri) {
final Cursor cursor = context.getContentResolver().query(photoUri,
new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);
if (null == cursor) {
return 0;
}
try {
if (cursor.getCount() != 1) {
return 0;
}
cursor.moveToFirst();
return cursor.getInt(0);
} finally {
cursor.close();
}
}
public static Bitmap decodeRegionCrop(@NonNull Context context, @NonNull Uri sourceUri, Rect rect, int outWidth, int outHeight, int rotation) throws IOException, OutOfMemoryError {
Bitmap croppedImage;
final InputStream is = context.getContentResolver().openInputStream(sourceUri);
try {
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
final int width = decoder.getWidth();
final int height = decoder.getHeight();
if (rotation != 0) {
// Adjust crop area to account for image rotation
Matrix matrix = new Matrix();
matrix.setRotate(-rotation);
RectF adjusted = new RectF();
matrix.mapRect(adjusted, new RectF(rect));
// Adjust to account for origin at 0,0
adjusted.offset(adjusted.left < 0 ? width : 0, adjusted.top < 0 ? height : 0);
rect = new Rect((int) adjusted.left, (int) adjusted.top, (int) adjusted.right, (int) adjusted.bottom);
}
try {
croppedImage = decoder.decodeRegion(rect, new BitmapFactory.Options());
if (rect.width() > outWidth || rect.height() > outHeight) {
Matrix matrix = new Matrix();
matrix.postScale((float) outWidth / rect.width(), (float) outHeight / rect.height());
croppedImage = Bitmap.createBitmap(croppedImage, 0, 0, croppedImage.getWidth(), croppedImage.getHeight(), matrix, true);
}
} catch (IllegalArgumentException e) {
// Rethrow with some extra information
throw new IllegalArgumentException("Rectangle " + rect + " is outside of the image ("
+ width + "," + height + "," + rotation + ")", e);
}
} finally {
is.close();
}
return croppedImage;
}
public static void crop(@NonNull Context context, @NonNull Uri uri, @NonNull Rect cropRect, int width, int height, @NonNull File file) throws IOException {
int rotation = getOrientationFromContentResolver(context, uri);
if (0 == rotation) {
rotation = getOrientationFromUri(uri.getPath());
}
final Bitmap croppedImage = CropUtil.decodeRegionCrop(context, uri, cropRect, width, height, rotation);
try {
final OutputStream outputStream = new FileOutputStream(file);
try {
croppedImage.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
} finally {
outputStream.close();
}
} finally {
croppedImage.recycle();
}
CropUtil.setExifOrientation(
rotation,
file
);
}
public static int getOrientationFromUri(@NonNull String path) {
final ExifInterface exif;
try {
exif = new ExifInterface(path);
} catch (IOException e) {
return 0;
}
return getRotationFromExifOrientation(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED));
}
}