diff options
Diffstat (limited to 'WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java')
-rw-r--r-- | WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java | 253 |
1 files changed, 37 insertions, 216 deletions
diff --git a/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java b/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java index a671ed2b9..9ac5c1bf7 100644 --- a/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java +++ b/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java @@ -16,87 +16,24 @@ 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.FloatMath; +import android.content.Context; +import android.content.res.Resources; +import android.net.Uri; import android.util.Log; -import java.io.ByteArrayOutputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import com.android.gallery3d.exif.ExifInterface; -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(){} - - /* - * Compute the sample size as a function of minSideLength - * and maxNumOfPixels. - * minSideLength is used to specify that minimal width or height of a - * bitmap. - * maxNumOfPixels is used to specify the maximal size in pixels that is - * tolerable in terms of memory usage. - * - * The function returns a sample size based on the constraints. - * Both size and minSideLength can be passed in as UNCONSTRAINED, - * which indicates no care of the corresponding constraint. - * The functions prefers returning a sample size that - * generates a smaller bitmap, unless minSideLength = UNCONSTRAINED. - * - * Also, the function rounds up the sample size to a power of 2 or multiple - * of 8 because BitmapFactory only honors sample size this way. - * For example, BitmapFactory downsamples an image by 2 even though the - * request is 3. So we round up the sample size to avoid OOM. - */ - 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) FloatMath.ceil(FloatMath.sqrt((float) (w * h) / maxNumOfPixels)); - - if (minSideLength == UNCONSTRAINED) { - return lowerBound; - } else { - int sampleSize = Math.min(w / minSideLength, h / minSideLength); - return Math.max(sampleSize, lowerBound); - } - } +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; - // This computes a sample size which makes the longer side at least - // minSideLength long. If that's not possible, return 1. - public static int computeSampleSizeLarger(int w, int h, - int minSideLength) { - int initialSize = Math.max(w / minSideLength, h / minSideLength); - if (initialSize <= 1) return 1; +public class BitmapUtils { - return initialSize <= 8 - ? Utils.prevPowerOf2(initialSize) - : initialSize / 8 * 8; - } + private static final String TAG = "BitmapUtils"; // Find the min x that 1 / x >= scale public static int computeSampleSizeLarger(float scale) { - int initialSize = (int) FloatMath.floor(1f / scale); + int initialSize = (int) Math.floor(1f / scale); if (initialSize <= 1) return 1; return initialSize <= 8 @@ -104,157 +41,41 @@ public class BitmapUtils { : initialSize / 8 * 8; } - // Find the max x that 1 / x <= scale. - public static int computeSampleSize(float scale) { - Utils.assertTrue(scale > 0); - int initialSize = Math.max(1, (int) FloatMath.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; + public static int getRotationFromExif(Context context, Uri uri) { + return BitmapUtils.getRotationFromExifHelper(null, 0, context, uri); } - private static Bitmap.Config getConfig(Bitmap bitmap) { - Bitmap.Config config = bitmap.getConfig(); - if (config == null) { - config = Bitmap.Config.ARGB_8888; - } - return config; + public static int getRotationFromExif(Resources res, int resId) { + return BitmapUtils.getRotationFromExifHelper(res, resId, null, null); } - 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; - - // scale the image so that the shorter side equals to the target; - // the longer side will be center-cropped. - 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) { - // MediaMetadataRetriever is available on API Level 8 - // but is hidden until API Level 10 - Class<?> clazz = null; - Object instance = null; + private static int getRotationFromExifHelper(Resources res, int resId, Context context, Uri uri) { + ExifInterface ei = new ExifInterface(); + InputStream is = null; + BufferedInputStream bis = null; try { - clazz = Class.forName("android.media.MediaMetadataRetriever"); - instance = clazz.newInstance(); - - Method method = clazz.getMethod("setDataSource", String.class); - method.invoke(instance, filePath); - - // The method name changes between API Level 9 and 10. - if (Build.VERSION.SDK_INT <= 9) { - return (Bitmap) clazz.getMethod("captureFrame").invoke(instance); + if (uri != null) { + is = context.getContentResolver().openInputStream(uri); + bis = new BufferedInputStream(is); + ei.readExif(bis); } 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); + is = res.openRawResource(resId); + bis = new BufferedInputStream(is); + ei.readExif(bis); } - } catch (IllegalArgumentException ex) { - // Assume this is a corrupt video file - } catch (RuntimeException ex) { - // Assume this is a corrupt video file. - } 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) { + Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION); + if (ori != null) { + return ExifInterface.getRotationForOrientationValue(ori.shortValue()); } + } catch (IOException e) { + Log.w(TAG, "Getting exif data failed", e); + } catch (NullPointerException e) { + // Sometimes the ExifInterface has an internal NPE if Exif data isn't valid + Log.w(TAG, "Getting exif data failed", e); + } finally { + Utils.closeSilently(bis); + Utils.closeSilently(is); } - 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"); + return 0; } } |