1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.common; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap.CompressFormat; 218cdfc6a0cd6b32f4c2baa64dbaddb8f496dced6dOwen Linimport android.graphics.BitmapFactory; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Canvas; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Matrix; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Paint; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.Build; 26fd91413ab46e2960803a33652025aebe3e05f2d9Chih-Chung Changimport android.util.FloatMath; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.util.Log; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.ByteArrayOutputStream; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.lang.reflect.InvocationTargetException; 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.lang.reflect.Method; 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class BitmapUtils { 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "BitmapUtils"; 354bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin private static final int DEFAULT_JPEG_QUALITY = 90; 3604a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen public static final int UNCONSTRAINED = -1; 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private BitmapUtils(){} 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin /* 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Compute the sample size as a function of minSideLength 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * and maxNumOfPixels. 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * minSideLength is used to specify that minimal width or height of a 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * bitmap. 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * maxNumOfPixels is used to specify the maximal size in pixels that is 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * tolerable in terms of memory usage. 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * The function returns a sample size based on the constraints. 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Both size and minSideLength can be passed in as UNCONSTRAINED, 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * which indicates no care of the corresponding constraint. 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * The functions prefers returning a sample size that 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * generates a smaller bitmap, unless minSideLength = UNCONSTRAINED. 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Also, the function rounds up the sample size to a power of 2 or multiple 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * of 8 because BitmapFactory only honors sample size this way. 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * For example, BitmapFactory downsamples an image by 2 even though the 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * request is 3. So we round up the sample size to avoid OOM. 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int computeSampleSize(int width, int height, 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int minSideLength, int maxNumOfPixels) { 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int initialSize = computeInitialSampleSize( 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin width, height, minSideLength, maxNumOfPixels); 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return initialSize <= 8 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ? Utils.nextPowerOf2(initialSize) 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin : (initialSize + 7) / 8 * 8; 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static int computeInitialSampleSize(int w, int h, 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int minSideLength, int maxNumOfPixels) { 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (maxNumOfPixels == UNCONSTRAINED 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin && minSideLength == UNCONSTRAINED) return 1; 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 : 75fd91413ab46e2960803a33652025aebe3e05f2d9Chih-Chung Chang (int) FloatMath.ceil(FloatMath.sqrt((float) (w * h) / maxNumOfPixels)); 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (minSideLength == UNCONSTRAINED) { 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return lowerBound; 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int sampleSize = Math.min(w / minSideLength, h / minSideLength); 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return Math.max(sampleSize, lowerBound); 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // This computes a sample size which makes the longer side at least 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // minSideLength long. If that's not possible, return 1. 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int computeSampleSizeLarger(int w, int h, 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int minSideLength) { 895da31f8fd85d7c1e33133473bd1fbc5e3a240f2dOwen Lin int initialSize = Math.max(w / minSideLength, h / minSideLength); 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (initialSize <= 1) return 1; 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return initialSize <= 8 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ? Utils.prevPowerOf2(initialSize) 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin : initialSize / 8 * 8; 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 974bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // Find the min x that 1 / x >= scale 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int computeSampleSizeLarger(float scale) { 99fd91413ab46e2960803a33652025aebe3e05f2d9Chih-Chung Chang int initialSize = (int) FloatMath.floor(1f / scale); 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (initialSize <= 1) return 1; 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return initialSize <= 8 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ? Utils.prevPowerOf2(initialSize) 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin : initialSize / 8 * 8; 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1074bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // Find the max x that 1 / x <= scale. 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int computeSampleSize(float scale) { 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Utils.assertTrue(scale > 0); 110fd91413ab46e2960803a33652025aebe3e05f2d9Chih-Chung Chang int initialSize = Math.max(1, (int) FloatMath.ceil(1 / scale)); 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return initialSize <= 8 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ? Utils.nextPowerOf2(initialSize) 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin : (initialSize + 7) / 8 * 8; 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static Bitmap resizeBitmapByScale( 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap bitmap, float scale, boolean recycle) { 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int width = Math.round(bitmap.getWidth() * scale); 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int height = Math.round(bitmap.getHeight() * scale); 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (width == bitmap.getWidth() 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin && height == bitmap.getHeight()) return bitmap; 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap target = Bitmap.createBitmap(width, height, getConfig(bitmap)); 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Canvas canvas = new Canvas(target); 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin canvas.scale(scale, scale); 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG); 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin canvas.drawBitmap(bitmap, 0, 0, paint); 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (recycle) bitmap.recycle(); 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return target; 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static Bitmap.Config getConfig(Bitmap bitmap) { 132ea0feffc18ed2d0086d5fc4c57353f9e81154099Owen Lin Bitmap.Config config = bitmap.getConfig(); 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (config == null) { 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin config = Bitmap.Config.ARGB_8888; 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return config; 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static Bitmap resizeDownBySideLength( 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap bitmap, int maxLength, boolean recycle) { 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int srcWidth = bitmap.getWidth(); 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int srcHeight = bitmap.getHeight(); 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float scale = Math.min( 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin (float) maxLength / srcWidth, (float) maxLength / srcHeight); 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (scale >= 1.0f) return bitmap; 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return resizeBitmapByScale(bitmap, scale, recycle); 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1494bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap resizeAndCropCenter(Bitmap bitmap, int size, boolean recycle) { 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int w = bitmap.getWidth(); 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int h = bitmap.getHeight(); 1524bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin if (w == size && h == size) return bitmap; 1534bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 1544bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // scale the image so that the shorter side equals to the target; 1554bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // the longer side will be center-cropped. 1564bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin float scale = (float) size / Math.min(w, h); 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap target = Bitmap.createBitmap(size, size, getConfig(bitmap)); 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int width = Math.round(scale * bitmap.getWidth()); 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int height = Math.round(scale * bitmap.getHeight()); 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Canvas canvas = new Canvas(target); 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin canvas.translate((size - width) / 2f, (size - height) / 2f); 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin canvas.scale(scale, scale); 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG); 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin canvas.drawBitmap(bitmap, 0, 0, paint); 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (recycle) bitmap.recycle(); 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return target; 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static void recycleSilently(Bitmap bitmap) { 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (bitmap == null) return; 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin bitmap.recycle(); 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "unable recycle bitmap", t); 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static Bitmap rotateBitmap(Bitmap source, int rotation, boolean recycle) { 18022493b29c32142f2588c623f5c78e9167352dddcOwen Lin if (rotation == 0) return source; 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int w = source.getWidth(); 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int h = source.getHeight(); 183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Matrix m = new Matrix(); 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin m.postRotate(rotation); 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap bitmap = Bitmap.createBitmap(source, 0, 0, w, h, m, true); 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (recycle) source.recycle(); 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return bitmap; 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static Bitmap createVideoThumbnail(String filePath) { 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // MediaMetadataRetriever is available on API Level 8 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // but is hidden until API Level 10 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Class<?> clazz = null; 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Object instance = null; 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin clazz = Class.forName("android.media.MediaMetadataRetriever"); 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin instance = clazz.newInstance(); 198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Method method = clazz.getMethod("setDataSource", String.class); 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin method.invoke(instance, filePath); 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The method name changes between API Level 9 and 10. 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (Build.VERSION.SDK_INT <= 9) { 204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return (Bitmap) clazz.getMethod("captureFrame").invoke(instance); 205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 2068cdfc6a0cd6b32f4c2baa64dbaddb8f496dced6dOwen Lin byte[] data = (byte[]) clazz.getMethod("getEmbeddedPicture").invoke(instance); 2078cdfc6a0cd6b32f4c2baa64dbaddb8f496dced6dOwen Lin if (data != null) { 2088cdfc6a0cd6b32f4c2baa64dbaddb8f496dced6dOwen Lin Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); 2098cdfc6a0cd6b32f4c2baa64dbaddb8f496dced6dOwen Lin if (bitmap != null) return bitmap; 2108cdfc6a0cd6b32f4c2baa64dbaddb8f496dced6dOwen Lin } 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return (Bitmap) clazz.getMethod("getFrameAtTime").invoke(instance); 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (IllegalArgumentException ex) { 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Assume this is a corrupt video file 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (RuntimeException ex) { 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Assume this is a corrupt video file. 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (InstantiationException e) { 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.e(TAG, "createVideoThumbnail", e); 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (InvocationTargetException e) { 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.e(TAG, "createVideoThumbnail", e); 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (ClassNotFoundException e) { 222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.e(TAG, "createVideoThumbnail", e); 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (NoSuchMethodException e) { 224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.e(TAG, "createVideoThumbnail", e); 225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (IllegalAccessException e) { 226f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.e(TAG, "createVideoThumbnail", e); 227f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (instance != null) { 230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin clazz.getMethod("release").invoke(instance); 231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Exception ignored) { 233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 235f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 236f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 237f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2384bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static byte[] compressToBytes(Bitmap bitmap) { 2394bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin return compressToBytes(bitmap, DEFAULT_JPEG_QUALITY); 2404bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin } 2414bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 2424bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static byte[] compressToBytes(Bitmap bitmap, int quality) { 2434bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin ByteArrayOutputStream baos = new ByteArrayOutputStream(65536); 2444bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin bitmap.compress(CompressFormat.JPEG, quality, baos); 2454bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin return baos.toByteArray(); 246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 248f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static boolean isSupportedByRegionDecoder(String mimeType) { 249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mimeType == null) return false; 250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mimeType = mimeType.toLowerCase(); 251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mimeType.startsWith("image/") && 252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin (!mimeType.equals("image/gif") && !mimeType.endsWith("bmp")); 253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 254f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 255f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static boolean isRotationSupported(String mimeType) { 256f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mimeType == null) return false; 257f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mimeType = mimeType.toLowerCase(); 258f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mimeType.equals("image/jpeg"); 259f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 261