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