package com.android.gallery3d.common;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Build;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class BitmapUtils {
private static final String TAG = "BitmapUtils";
private static final int DEFAULT_JPEG_QUALITY = 90;
public static final int UNCONSTRAINED = -1;
private BitmapUtils(){}
public static int computeSampleSize(int width, int height,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(
width, height, minSideLength, maxNumOfPixels);
return initialSize <= 8
? Utils.nextPowerOf2(initialSize)
: (initialSize + 7) / 8 * 8;
}
private static int computeInitialSampleSize(int w, int h,
int minSideLength, int maxNumOfPixels) {
if (maxNumOfPixels == UNCONSTRAINED
&& minSideLength == UNCONSTRAINED) return 1;
int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 :
(int) Math.ceil(Math.sqrt((double) (w * h) / maxNumOfPixels));
if (minSideLength == UNCONSTRAINED) {
return lowerBound;
} else {
int sampleSize = Math.min(w / minSideLength, h / minSideLength);
return Math.max(sampleSize, lowerBound);
}
}
public static int computeSampleSizeLarger(int w, int h,
int minSideLength) {
int initialSize = Math.max(w / minSideLength, h / minSideLength);
if (initialSize <= 1) return 1;
return initialSize <= 8
? Utils.prevPowerOf2(initialSize)
: initialSize / 8 * 8;
}
public static int computeSampleSizeLarger(float scale) {
int initialSize = (int) Math.floor(1 / scale);
if (initialSize <= 1) return 1;
return initialSize <= 8
? Utils.prevPowerOf2(initialSize)
: initialSize / 8 * 8;
}
public static int computeSampleSize(float scale) {
Utils.assertTrue(scale > 0);
int initialSize = Math.max(1, (int) Math.ceil(1 / scale));
return initialSize <= 8
? Utils.nextPowerOf2(initialSize)
: (initialSize + 7) / 8 * 8;
}
public static Bitmap resizeBitmapByScale(
Bitmap bitmap, float scale, boolean recycle) {
int width = Math.round(bitmap.getWidth() * scale);
int height = Math.round(bitmap.getHeight() * scale);
if (width == bitmap.getWidth()
&& height == bitmap.getHeight()) return bitmap;
Bitmap target = Bitmap.createBitmap(width, height, getConfig(bitmap));
Canvas canvas = new Canvas(target);
canvas.scale(scale, scale);
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
canvas.drawBitmap(bitmap, 0, 0, paint);
if (recycle) bitmap.recycle();
return target;
}
private static Bitmap.Config getConfig(Bitmap bitmap) {
Bitmap.Config config = bitmap.getConfig();
if (config == null) {
config = Bitmap.Config.ARGB_8888;
}
return config;
}
public static Bitmap resizeDownBySideLength(
Bitmap bitmap, int maxLength, boolean recycle) {
int srcWidth = bitmap.getWidth();
int srcHeight = bitmap.getHeight();
float scale = Math.min(
(float) maxLength / srcWidth, (float) maxLength / srcHeight);
if (scale >= 1.0f) return bitmap;
return resizeBitmapByScale(bitmap, scale, recycle);
}
public static Bitmap resizeAndCropCenter(Bitmap bitmap, int size, boolean recycle) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
if (w == size && h == size) return bitmap;
float scale = (float) size / Math.min(w, h);
Bitmap target = Bitmap.createBitmap(size, size, getConfig(bitmap));
int width = Math.round(scale * bitmap.getWidth());
int height = Math.round(scale * bitmap.getHeight());
Canvas canvas = new Canvas(target);
canvas.translate((size - width) / 2f, (size - height) / 2f);
canvas.scale(scale, scale);
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
canvas.drawBitmap(bitmap, 0, 0, paint);
if (recycle) bitmap.recycle();
return target;
}
public static void recycleSilently(Bitmap bitmap) {
if (bitmap == null) return;
try {
bitmap.recycle();
} catch (Throwable t) {
Log.w(TAG, "unable recycle bitmap", t);
}
}
public static Bitmap rotateBitmap(Bitmap source, int rotation, boolean recycle) {
if (rotation == 0) return source;
int w = source.getWidth();
int h = source.getHeight();
Matrix m = new Matrix();
m.postRotate(rotation);
Bitmap bitmap = Bitmap.createBitmap(source, 0, 0, w, h, m, true);
if (recycle) source.recycle();
return bitmap;
}
public static Bitmap createVideoThumbnail(String filePath) {
Class<?> clazz = null;
Object instance = null;
try {
clazz = Class.forName("android.media.MediaMetadataRetriever");
instance = clazz.newInstance();
Method method = clazz.getMethod("setDataSource", String.class);
method.invoke(instance, filePath);
if (Build.VERSION.SDK_INT <= 9) {
return (Bitmap) clazz.getMethod("captureFrame").invoke(instance);
} else {
byte[] data = (byte[]) clazz.getMethod("getEmbeddedPicture").invoke(instance);
if (data != null) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
if (bitmap != null) return bitmap;
}
return (Bitmap) clazz.getMethod("getFrameAtTime").invoke(instance);
}
} catch (IllegalArgumentException ex) {
} catch (RuntimeException ex) {
} catch (InstantiationException e) {
Log.e(TAG, "createVideoThumbnail", e);
} catch (InvocationTargetException e) {
Log.e(TAG, "createVideoThumbnail", e);
} catch (ClassNotFoundException e) {
Log.e(TAG, "createVideoThumbnail", e);
} catch (NoSuchMethodException e) {
Log.e(TAG, "createVideoThumbnail", e);
} catch (IllegalAccessException e) {
Log.e(TAG, "createVideoThumbnail", e);
} finally {
try {
if (instance != null) {
clazz.getMethod("release").invoke(instance);
}
} catch (Exception ignored) {
}
}
return null;
}
public static byte[] compressToBytes(Bitmap bitmap) {
return compressToBytes(bitmap, DEFAULT_JPEG_QUALITY);
}
public static byte[] compressToBytes(Bitmap bitmap, int quality) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(65536);
bitmap.compress(CompressFormat.JPEG, quality, baos);
return baos.toByteArray();
}
public static boolean isSupportedByRegionDecoder(String mimeType) {
if (mimeType == null) return false;
mimeType = mimeType.toLowerCase();
return mimeType.startsWith("image/") &&
(!mimeType.equals("image/gif") && !mimeType.endsWith("bmp"));
}
public static boolean isRotationSupported(String mimeType) {
if (mimeType == null) return false;
mimeType = mimeType.toLowerCase();
return mimeType.equals("image/jpeg");
}
}