package com.yalantis.ucrop.util;
|
|
import android.content.Context;
|
import android.graphics.Bitmap;
|
import android.graphics.BitmapFactory;
|
import android.graphics.Canvas;
|
import android.graphics.Matrix;
|
import android.graphics.Point;
|
import android.media.ExifInterface;
|
import android.net.Uri;
|
import android.os.Build;
|
import android.util.Log;
|
import android.view.Display;
|
import android.view.WindowManager;
|
|
import androidx.annotation.NonNull;
|
import androidx.annotation.Nullable;
|
|
import com.yalantis.ucrop.callback.BitmapLoadCallback;
|
import com.yalantis.ucrop.callback.BitmapLoadShowCallback;
|
import com.yalantis.ucrop.task.BitmapLoadShowTask;
|
import com.yalantis.ucrop.task.BitmapLoadTask;
|
|
import java.io.Closeable;
|
import java.io.IOException;
|
import java.io.InputStream;
|
|
/**
|
* Created by Oleksii Shliama (https://github.com/shliama).
|
*/
|
public class BitmapLoadUtils {
|
|
private static final String TAG = "BitmapLoadUtils";
|
|
public static void decodeBitmapInBackground(@NonNull Context context,
|
@NonNull Uri uri, @Nullable Uri outputUri,
|
int requiredWidth, int requiredHeight,
|
BitmapLoadCallback loadCallback) {
|
|
new BitmapLoadTask(context, uri, outputUri, requiredWidth, requiredHeight, loadCallback).execute();
|
}
|
|
public static void decodeBitmapInBackground(@NonNull Context context,
|
@NonNull Uri uri,
|
@Nullable Uri outputUri,
|
int requiredWidth,
|
int requiredHeight,
|
BitmapLoadShowCallback loadCallback) {
|
|
new BitmapLoadShowTask(context, uri, outputUri, requiredWidth, requiredHeight, loadCallback).execute();
|
}
|
|
public static Bitmap transformBitmap(@NonNull Bitmap bitmap, @NonNull Matrix transformMatrix) {
|
try {
|
Bitmap converted = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), transformMatrix, true);
|
if (!bitmap.sameAs(converted)) {
|
bitmap = converted;
|
}
|
} catch (OutOfMemoryError error) {
|
Log.e(TAG, "transformBitmap: ", error);
|
}
|
return bitmap;
|
}
|
|
public static int calculateInSampleSize(@NonNull BitmapFactory.Options options, int reqWidth, int reqHeight) {
|
// Raw height and width of image
|
final int height = options.outHeight;
|
final int width = options.outWidth;
|
int inSampleSize = 1;
|
|
if (height > reqHeight || width > reqWidth) {
|
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
|
// height and width lower or equal to the requested height and width.
|
while ((height / inSampleSize) > reqHeight || (width / inSampleSize) > reqWidth) {
|
inSampleSize *= 2;
|
}
|
}
|
return inSampleSize;
|
}
|
|
public static int getExifOrientation(@NonNull Context context, @NonNull Uri imageUri) {
|
int orientation = ExifInterface.ORIENTATION_UNDEFINED;
|
try {
|
InputStream stream = context.getContentResolver().openInputStream(imageUri);
|
if (stream == null) {
|
return orientation;
|
}
|
orientation = new ImageHeaderParser(stream).getOrientation();
|
close(stream);
|
} catch (IOException e) {
|
Log.e(TAG, "getExifOrientation: " + imageUri.toString(), e);
|
}
|
return orientation;
|
}
|
|
public static int exifToDegrees(int exifOrientation) {
|
int rotation;
|
switch (exifOrientation) {
|
case ExifInterface.ORIENTATION_ROTATE_90:
|
case ExifInterface.ORIENTATION_TRANSPOSE:
|
rotation = 90;
|
break;
|
case ExifInterface.ORIENTATION_ROTATE_180:
|
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
|
rotation = 180;
|
break;
|
case ExifInterface.ORIENTATION_ROTATE_270:
|
case ExifInterface.ORIENTATION_TRANSVERSE:
|
rotation = 270;
|
break;
|
default:
|
rotation = 0;
|
}
|
return rotation;
|
}
|
|
public static int exifToTranslation(int exifOrientation) {
|
int translation;
|
switch (exifOrientation) {
|
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
|
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
|
case ExifInterface.ORIENTATION_TRANSPOSE:
|
case ExifInterface.ORIENTATION_TRANSVERSE:
|
translation = -1;
|
break;
|
default:
|
translation = 1;
|
}
|
return translation;
|
}
|
|
/**
|
* This method calculates maximum size of both width and height of bitmap.
|
* It is twice the device screen diagonal for default implementation (extra quality to zoom image).
|
* Size cannot exceed max texture size.
|
*
|
* @return - max bitmap size in pixels.
|
*/
|
@SuppressWarnings({"SuspiciousNameCombination", "deprecation"})
|
public static int calculateMaxBitmapSize(@NonNull Context context) {
|
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
Display display = wm.getDefaultDisplay();
|
|
Point size = new Point();
|
int width, height;
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
|
display.getSize(size);
|
width = size.x;
|
height = size.y;
|
} else {
|
width = display.getWidth();
|
height = display.getHeight();
|
}
|
|
// Twice the device screen diagonal as default
|
int maxBitmapSize = (int) Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
|
|
// Check for max texture size via Canvas
|
Canvas canvas = new Canvas();
|
final int maxCanvasSize = Math.min(canvas.getMaximumBitmapWidth(), canvas.getMaximumBitmapHeight());
|
if (maxCanvasSize > 0) {
|
maxBitmapSize = Math.min(maxBitmapSize, maxCanvasSize);
|
}
|
|
// Check for max texture size via GL
|
final int maxTextureSize = EglUtils.getMaxTextureSize();
|
if (maxTextureSize > 0) {
|
maxBitmapSize = Math.min(maxBitmapSize, maxTextureSize);
|
}
|
|
Log.d(TAG, "maxBitmapSize: " + maxBitmapSize);
|
return maxBitmapSize;
|
}
|
|
@SuppressWarnings("ConstantConditions")
|
public static void close(@Nullable Closeable c) {
|
if (c != null && c instanceof Closeable) { // java.lang.IncompatibleClassChangeError: interface not implemented
|
try {
|
c.close();
|
} catch (IOException e) {
|
// silence
|
}
|
}
|
}
|
|
}
|