Util.java revision 96b3c6ee6d93c136bb8270521158a989584966b1
1101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin/* 2101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Copyright (C) 2009 The Android Open Source Project 3101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * 4101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * you may not use this file except in compliance with the License. 6101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * You may obtain a copy of the License at 7101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * 8101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * http://www.apache.org/licenses/LICENSE-2.0 9101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * 10101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Unless required by applicable law or agreed to in writing, software 11101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * See the License for the specific language governing permissions and 14101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * limitations under the License. 15101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 16101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 17937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Linpackage com.android.camera; 18101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 190a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Changimport com.android.camera.gallery.IImage; 200a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang 21c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Changimport android.content.ContentResolver; 22101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.Bitmap; 23101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.BitmapFactory; 2496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Changimport android.graphics.Canvas; 25101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.Matrix; 2696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Changimport android.graphics.Rect; 27101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.media.MediaMetadataRetriever; 28c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Changimport android.net.Uri; 29101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.os.ParcelFileDescriptor; 30101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.util.Log; 31101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 32101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport java.io.ByteArrayOutputStream; 33101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport java.io.Closeable; 34c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Changimport java.io.IOException; 35c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Changimport java.io.FileDescriptor; 36101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 37101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin/** 38101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Collection of utility functions used in this package. 39101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 40101d528d59f447847d5c6b7578642132c2b76f4fOwen Linpublic class Util { 41101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin private static final boolean VERBOSE = false; 42101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin private static final String TAG = "db.Util"; 43101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 44101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin private Util() { 45101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 46101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 47101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Rotates the bitmap by the specified degree. 48101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // If a new bitmap is created, the original bitmap is recycled. 49101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap rotate(Bitmap b, int degrees) { 50101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (degrees != 0 && b != null) { 51101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Matrix m = new Matrix(); 52101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin m.setRotate(degrees, 53101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin (float) b.getWidth() / 2, (float) b.getHeight() / 2); 54101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 55101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap b2 = Bitmap.createBitmap( 56101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b, 0, 0, b.getWidth(), b.getHeight(), m, true); 57101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (b != b2) { 58101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b.recycle(); 59101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b = b2; 60101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 61101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (OutOfMemoryError ex) { 62101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // We have no memory to rotate. Return the original bitmap. 63101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 64101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 65101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return b; 66101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 67101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 68101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /* 69101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Compute the sample size as a function of the image size and the target. 70101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Scale the image down so that both the width and height are just above the 71101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * target. If this means that one of the dimension goes from above the 72101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * target to below the target (e.g. given a width of 480 and an image width 73101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * of 600 but sample size of 2 -- i.e. new width 300 -- bump the sample size 74101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * down by 1. 75101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 76101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static int computeSampleSize( 77101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin BitmapFactory.Options options, int target) { 78101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin int w = options.outWidth; 79101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin int h = options.outHeight; 80101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 81101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin int candidateW = w / target; 82101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin int candidateH = h / target; 83101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin int candidate = Math.max(candidateW, candidateH); 84101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 85101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (candidate == 0) return 1; 86101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 87101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (candidate > 1) { 88101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if ((w > target) && (w / candidate) < target) candidate -= 1; 89101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 90101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 91101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (candidate > 1) { 92101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if ((h > target) && (h / candidate) < target) candidate -= 1; 93101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 94101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 95101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return candidate; 96101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 97101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 9896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang public static Bitmap transform(Matrix scaler, 9996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap source, 10096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int targetWidth, 10196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int targetHeight, 10296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang boolean scaleUp) { 10396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int deltaX = source.getWidth() - targetWidth; 10496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int deltaY = source.getHeight() - targetHeight; 10596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (!scaleUp && (deltaX < 0 || deltaY < 0)) { 10696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang /* 10796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang * In this case the bitmap is smaller, at least in one dimension, 10896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang * than the target. Transform it by placing as much of the image 10996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang * as possible into the target and leaving the top/bottom or 11096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang * left/right (or both) black. 11196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang */ 11296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight, 11396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap.Config.ARGB_8888); 11496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Canvas c = new Canvas(b2); 11596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 11696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int deltaXHalf = Math.max(0, deltaX / 2); 11796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int deltaYHalf = Math.max(0, deltaY / 2); 11896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Rect src = new Rect( 11996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang deltaXHalf, 12096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang deltaYHalf, 12196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang deltaXHalf + Math.min(targetWidth, source.getWidth()), 12296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang deltaYHalf + Math.min(targetHeight, source.getHeight())); 12396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int dstX = (targetWidth - src.width()) / 2; 12496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int dstY = (targetHeight - src.height()) / 2; 12596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Rect dst = new Rect( 12696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang dstX, 12796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang dstY, 12896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang targetWidth - dstX, 12996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang targetHeight - dstY); 13096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang c.drawBitmap(source, src, dst, null); 13196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang return b2; 13296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 13396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float bitmapWidthF = source.getWidth(); 13496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float bitmapHeightF = source.getHeight(); 13596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 13696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float bitmapAspect = bitmapWidthF / bitmapHeightF; 13796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float viewAspect = (float) targetWidth / (float) targetHeight; 13896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 13996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (bitmapAspect > viewAspect) { 14096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float scale = targetHeight / bitmapHeightF; 14196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (scale < .9F || scale > 1F) { 14296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang scaler.setScale(scale, scale); 14396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } else { 14496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang scaler = null; 14596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 14696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } else { 14796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float scale = targetWidth / bitmapWidthF; 14896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (scale < .9F || scale > 1F) { 14996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang scaler.setScale(scale, scale); 15096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } else { 15196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang scaler = null; 15296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 15396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 15496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 15596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap b1; 15696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (scaler != null) { 15796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang // this is used for minithumb and crop, so we want to filter here. 15896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang b1 = Bitmap.createBitmap(source, 0, 0, 15996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang source.getWidth(), source.getHeight(), scaler, true); 16096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } else { 16196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang b1 = source; 16296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 16396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 16496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int dx1 = Math.max(0, b1.getWidth() - targetWidth); 16596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int dy1 = Math.max(0, b1.getHeight() - targetHeight); 16696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 16796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap b2 = Bitmap.createBitmap( 16896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang b1, 16996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang dx1 / 2, 17096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang dy1 / 2, 17196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang targetWidth, 17296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang targetHeight); 17396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 17496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (b1 != source) { 17596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang b1.recycle(); 17696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 17796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 17896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang return b2; 17996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 18096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 181101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /** 182101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Creates a centered bitmap of the desired size. Recycles the input. 183101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * @param source 184101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 185101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap extractMiniThumb( 186101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap source, int width, int height) { 187101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return Util.extractMiniThumb(source, width, height, true); 188101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 189101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 190101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap extractMiniThumb( 191101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap source, int width, int height, boolean recycle) { 192101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (source == null) { 193101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return null; 194101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 195101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 196101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin float scale; 197101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (source.getWidth() < source.getHeight()) { 198101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin scale = width / (float) source.getWidth(); 199101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } else { 200101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin scale = height / (float) source.getHeight(); 201101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 202101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Matrix matrix = new Matrix(); 203101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin matrix.setScale(scale, scale); 20496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap miniThumbnail = transform(matrix, source, width, height, false); 205101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 206101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (recycle && miniThumbnail != source) { 207101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin source.recycle(); 208101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 209101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return miniThumbnail; 210101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 211101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 212101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /** 213101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Creates a byte[] for a given bitmap of the desired size. Recycles the 214101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * input bitmap. 215101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 216101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static byte[] miniThumbData(Bitmap source) { 217101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (source == null) return null; 218101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 219101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap miniThumbnail = extractMiniThumb( 2200a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang source, IImage.MINI_THUMB_TARGET_SIZE, 2210a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang IImage.MINI_THUMB_TARGET_SIZE); 222101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 223101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin ByteArrayOutputStream miniOutStream = new ByteArrayOutputStream(); 224101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin miniThumbnail.compress(Bitmap.CompressFormat.JPEG, 75, miniOutStream); 225101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin miniThumbnail.recycle(); 226101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 227101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 228101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin miniOutStream.close(); 229101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin byte [] data = miniOutStream.toByteArray(); 230101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return data; 231101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (java.io.IOException ex) { 232101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Log.e(TAG, "got exception ex " + ex); 233101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 234101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return null; 235101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 236101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 237101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /** 238101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * @return true if the mimetype is a video mimetype. 239101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 240101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static boolean isVideoMimeType(String mimeType) { 241101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return mimeType.startsWith("video/"); 242101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 243101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 244101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /** 245101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Create a video thumbnail for a video. May return null if the video is 246101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * corrupt. 247101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * 248101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * @param filePath 249101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 250101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap createVideoThumbnail(String filePath) { 251101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap bitmap = null; 252101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 253101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 254101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); 255101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin retriever.setDataSource(filePath); 256101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin bitmap = retriever.captureFrame(); 257101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (IllegalArgumentException ex) { 258101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Assume this is a corrupt video file 259101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (RuntimeException ex) { 260101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Assume this is a corrupt video file. 261101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } finally { 262101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 263101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin retriever.release(); 264101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (RuntimeException ex) { 265101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Ignore failures while cleaning up. 266101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 267101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 268101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return bitmap; 269101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 270101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 271101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static int indexOf(String [] array, String s) { 272101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin for (int i = 0; i < array.length; i++) { 273101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (array[i].equals(s)) { 274101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return i; 275101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 276101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 277101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return -1; 278101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 279101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 280101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static void closeSiliently(Closeable c) { 281101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (c == null) return; 282101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 283101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin c.close(); 284101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (Throwable t) { 285101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // do nothing 286101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 287101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 288101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 289101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static void closeSiliently(ParcelFileDescriptor c) { 290101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (c == null) return; 291101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 292101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin c.close(); 293101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (Throwable t) { 294101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // do nothing 295101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 296101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 297101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 298c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang /** 299c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang * Make a bitmap from a given Uri. 300c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang * 301c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang * @param uri 302c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang */ 303c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang public static Bitmap makeBitmap(int targetWidthOrHeight, Uri uri, 304c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang ContentResolver cr) { 305c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang ParcelFileDescriptor input = null; 306c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang try { 307c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang input = cr.openFileDescriptor(uri, "r"); 308c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return makeBitmap(targetWidthOrHeight, uri, cr, input, null); 309c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } catch (IOException ex) { 310c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return null; 311c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } finally { 312c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang closeSiliently(input); 313c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 314c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 315c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 316c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang public static Bitmap makeBitmap(int targetWidthHeight, Uri uri, 317c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang ContentResolver cr, ParcelFileDescriptor pfd, 318c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang BitmapFactory.Options options) { 319c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang Bitmap b = null; 320c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang try { 321c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang if (pfd == null) pfd = makeInputStream(uri, cr); 322c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang if (pfd == null) return null; 323c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang if (options == null) options = new BitmapFactory.Options(); 324c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 325c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang FileDescriptor fd = pfd.getFileDescriptor(); 326c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inSampleSize = 1; 327c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang if (targetWidthHeight != -1) { 328c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inJustDecodeBounds = true; 329c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang BitmapManager.instance().decodeFileDescriptor( 330c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang fd, null, options); 331c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang if (options.mCancel || options.outWidth == -1 332c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang || options.outHeight == -1) { 333c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return null; 334c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 335c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inSampleSize = 336c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang computeSampleSize(options, targetWidthHeight); 337c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inJustDecodeBounds = false; 338c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 339c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 340c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inDither = false; 341c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inPreferredConfig = Bitmap.Config.ARGB_8888; 342c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang b = BitmapManager.instance() 343c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang .decodeFileDescriptor(fd, null, options); 344c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } catch (OutOfMemoryError ex) { 345c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang Log.e(TAG, "Got oom exception ", ex); 346c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return null; 347c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } finally { 348c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang closeSiliently(pfd); 349c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 350c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return b; 351c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 352c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 353c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang private static ParcelFileDescriptor makeInputStream( 354c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang Uri uri, ContentResolver cr) { 355c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang try { 356c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return cr.openFileDescriptor(uri, "r"); 357c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } catch (IOException ex) { 358c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return null; 359c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 360c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 361101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin} 362