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