Util.java revision 341ad98e59d92769e1cc8ba68fa86c72dce0543b
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 21601ce56b034f111b2875e7636776f2f359f6a156Owen Linimport android.app.ProgressDialog; 22c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Changimport android.content.ContentResolver; 23601ce56b034f111b2875e7636776f2f359f6a156Owen Linimport android.content.Context; 24101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.Bitmap; 25101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.BitmapFactory; 2696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Changimport android.graphics.Canvas; 27101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.Matrix; 2896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Changimport android.graphics.Rect; 29101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.media.MediaMetadataRetriever; 30c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Changimport android.net.Uri; 31101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.os.ParcelFileDescriptor; 32101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.util.Log; 33601ce56b034f111b2875e7636776f2f359f6a156Owen Linimport android.view.View; 34601ce56b034f111b2875e7636776f2f359f6a156Owen Linimport android.view.View.OnClickListener; 35101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 36101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport java.io.ByteArrayOutputStream; 37101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport java.io.Closeable; 38c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Changimport java.io.FileDescriptor; 39d30b5877fbdedcebc0af5cccffddccfe9b11cb0bOwen Linimport java.io.IOException; 40101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 41101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin/** 42101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Collection of utility functions used in this package. 43101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 44101d528d59f447847d5c6b7578642132c2b76f4fOwen Linpublic class Util { 45101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin private static final String TAG = "db.Util"; 46101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 47601ce56b034f111b2875e7636776f2f359f6a156Owen Lin private static OnClickListener sNullOnClickListener; 48601ce56b034f111b2875e7636776f2f359f6a156Owen Lin 49101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin private Util() { 50101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 51101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 52101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Rotates the bitmap by the specified degree. 53101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // If a new bitmap is created, the original bitmap is recycled. 54101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap rotate(Bitmap b, int degrees) { 55101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (degrees != 0 && b != null) { 56101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Matrix m = new Matrix(); 57101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin m.setRotate(degrees, 58101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin (float) b.getWidth() / 2, (float) b.getHeight() / 2); 59101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 60101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap b2 = Bitmap.createBitmap( 61101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b, 0, 0, b.getWidth(), b.getHeight(), m, true); 62101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (b != b2) { 63101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b.recycle(); 64101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b = b2; 65101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 66101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (OutOfMemoryError ex) { 67101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // We have no memory to rotate. Return the original bitmap. 68101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 69101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 70101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return b; 71101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 72101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 73101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /* 74101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Compute the sample size as a function of the image size and the target. 75101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Scale the image down so that both the width and height are just above the 76101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * target. If this means that one of the dimension goes from above the 77101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * target to below the target (e.g. given a width of 480 and an image width 78101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * of 600 but sample size of 2 -- i.e. new width 300 -- bump the sample size 79101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * down by 1. 80101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 81101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static int computeSampleSize( 82101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin BitmapFactory.Options options, int target) { 83101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin int w = options.outWidth; 84101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin int h = options.outHeight; 85101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 86101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin int candidateW = w / target; 87101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin int candidateH = h / target; 88101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin int candidate = Math.max(candidateW, candidateH); 89101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 90101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (candidate == 0) return 1; 91101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 92101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (candidate > 1) { 93101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if ((w > target) && (w / candidate) < target) candidate -= 1; 94101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 95101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 96101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (candidate > 1) { 97101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if ((h > target) && (h / candidate) < target) candidate -= 1; 98101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 99101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 100101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return candidate; 101101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 102101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 10396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang public static Bitmap transform(Matrix scaler, 10496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap source, 10596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int targetWidth, 10696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int targetHeight, 10796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang boolean scaleUp) { 10896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int deltaX = source.getWidth() - targetWidth; 10996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int deltaY = source.getHeight() - targetHeight; 11096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (!scaleUp && (deltaX < 0 || deltaY < 0)) { 11196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang /* 11296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang * In this case the bitmap is smaller, at least in one dimension, 11396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang * than the target. Transform it by placing as much of the image 11496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang * as possible into the target and leaving the top/bottom or 11596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang * left/right (or both) black. 11696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang */ 11796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight, 11896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap.Config.ARGB_8888); 11996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Canvas c = new Canvas(b2); 12096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 12196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int deltaXHalf = Math.max(0, deltaX / 2); 12296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int deltaYHalf = Math.max(0, deltaY / 2); 12396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Rect src = new Rect( 12496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang deltaXHalf, 12596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang deltaYHalf, 12696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang deltaXHalf + Math.min(targetWidth, source.getWidth()), 12796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang deltaYHalf + Math.min(targetHeight, source.getHeight())); 12896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int dstX = (targetWidth - src.width()) / 2; 12996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int dstY = (targetHeight - src.height()) / 2; 13096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Rect dst = new Rect( 13196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang dstX, 13296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang dstY, 13396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang targetWidth - dstX, 13496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang targetHeight - dstY); 13596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang c.drawBitmap(source, src, dst, null); 13696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang return b2; 13796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 13896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float bitmapWidthF = source.getWidth(); 13996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float bitmapHeightF = source.getHeight(); 14096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 14196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float bitmapAspect = bitmapWidthF / bitmapHeightF; 14258e94eddd371a9bb7c04936dbeb99615fd1a0c2cChih-Chung Chang float viewAspect = (float) targetWidth / targetHeight; 14396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 14496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (bitmapAspect > viewAspect) { 14596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float scale = targetHeight / bitmapHeightF; 14696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (scale < .9F || scale > 1F) { 14796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang scaler.setScale(scale, scale); 14896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } else { 14996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang scaler = null; 15096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 15196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } else { 15296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang float scale = targetWidth / bitmapWidthF; 15396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (scale < .9F || scale > 1F) { 15496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang scaler.setScale(scale, scale); 15596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } else { 15696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang scaler = null; 15796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 15896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 15996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 16096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap b1; 16196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (scaler != null) { 16296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang // this is used for minithumb and crop, so we want to filter here. 16396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang b1 = Bitmap.createBitmap(source, 0, 0, 16496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang source.getWidth(), source.getHeight(), scaler, true); 16596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } else { 16696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang b1 = source; 16796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 16896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 16996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int dx1 = Math.max(0, b1.getWidth() - targetWidth); 17096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang int dy1 = Math.max(0, b1.getHeight() - targetHeight); 17196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 17296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap b2 = Bitmap.createBitmap( 17396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang b1, 17496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang dx1 / 2, 17596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang dy1 / 2, 17696b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang targetWidth, 17796b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang targetHeight); 17896b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 17996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang if (b1 != source) { 18096b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang b1.recycle(); 18196b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 18296b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 18396b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang return b2; 18496b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang } 18596b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang 186101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /** 187101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Creates a centered bitmap of the desired size. Recycles the input. 188101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * @param source 189101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 190101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap extractMiniThumb( 191101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap source, int width, int height) { 192101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return Util.extractMiniThumb(source, width, height, true); 193101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 194101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 195101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap extractMiniThumb( 196101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap source, int width, int height, boolean recycle) { 197101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (source == null) { 198101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return null; 199101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 200101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 201101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin float scale; 202101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (source.getWidth() < source.getHeight()) { 203101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin scale = width / (float) source.getWidth(); 204101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } else { 205101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin scale = height / (float) source.getHeight(); 206101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 207101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Matrix matrix = new Matrix(); 208101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin matrix.setScale(scale, scale); 20996b3c6ee6d93c136bb8270521158a989584966b1Chih-Chung Chang Bitmap miniThumbnail = transform(matrix, source, width, height, false); 210101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 211101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (recycle && miniThumbnail != source) { 212101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin source.recycle(); 213101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 214101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return miniThumbnail; 215101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 216101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 217101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /** 218101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Creates a byte[] for a given bitmap of the desired size. Recycles the 219101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * input bitmap. 220101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 221101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static byte[] miniThumbData(Bitmap source) { 222101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (source == null) return null; 223101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 224101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap miniThumbnail = extractMiniThumb( 2250a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang source, IImage.MINI_THUMB_TARGET_SIZE, 2260a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang IImage.MINI_THUMB_TARGET_SIZE); 227101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 228101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin ByteArrayOutputStream miniOutStream = new ByteArrayOutputStream(); 229101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin miniThumbnail.compress(Bitmap.CompressFormat.JPEG, 75, miniOutStream); 230101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin miniThumbnail.recycle(); 231101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 232101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 233101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin miniOutStream.close(); 234101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin byte [] data = miniOutStream.toByteArray(); 235101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return data; 236101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (java.io.IOException ex) { 237101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Log.e(TAG, "got exception ex " + ex); 238101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 239101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return null; 240101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 241101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 242101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /** 243101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * @return true if the mimetype is a video mimetype. 244101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 245101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static boolean isVideoMimeType(String mimeType) { 246101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return mimeType.startsWith("video/"); 247101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 248101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 249101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /** 250101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Create a video thumbnail for a video. May return null if the video is 251101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * corrupt. 252101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * 253101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * @param filePath 254101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 255101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap createVideoThumbnail(String filePath) { 256101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap bitmap = null; 257101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 258101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 259101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); 260101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin retriever.setDataSource(filePath); 261101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin bitmap = retriever.captureFrame(); 262101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (IllegalArgumentException ex) { 263101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Assume this is a corrupt video file 264101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (RuntimeException ex) { 265101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Assume this is a corrupt video file. 266101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } finally { 267101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 268101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin retriever.release(); 269101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (RuntimeException ex) { 270101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Ignore failures while cleaning up. 271101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 272101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 273101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return bitmap; 274101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 275101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 276101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static int indexOf(String [] array, String s) { 277101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin for (int i = 0; i < array.length; i++) { 278101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (array[i].equals(s)) { 279101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return i; 280101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 281101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 282101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return -1; 283101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 284101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 285101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static void closeSiliently(Closeable c) { 286101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (c == null) return; 287101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 288101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin c.close(); 289101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (Throwable t) { 290101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // do nothing 291101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 292101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 293101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 294101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static void closeSiliently(ParcelFileDescriptor c) { 295101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (c == null) return; 296101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 297101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin c.close(); 298101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (Throwable t) { 299101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // do nothing 300101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 301101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 302101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 303c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang /** 304c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang * Make a bitmap from a given Uri. 305c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang * 306c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang * @param uri 307c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang */ 308c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang public static Bitmap makeBitmap(int targetWidthOrHeight, Uri uri, 309c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang ContentResolver cr) { 310c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang ParcelFileDescriptor input = null; 311c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang try { 312c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang input = cr.openFileDescriptor(uri, "r"); 313c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return makeBitmap(targetWidthOrHeight, uri, cr, input, null); 314c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } catch (IOException ex) { 315c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return null; 316c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } finally { 317c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang closeSiliently(input); 318c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 319c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 320c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 321c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang public static Bitmap makeBitmap(int targetWidthHeight, Uri uri, 322c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang ContentResolver cr, ParcelFileDescriptor pfd, 323c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang BitmapFactory.Options options) { 324c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang Bitmap b = null; 325c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang try { 326c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang if (pfd == null) pfd = makeInputStream(uri, cr); 327c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang if (pfd == null) return null; 328c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang if (options == null) options = new BitmapFactory.Options(); 329c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 330c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang FileDescriptor fd = pfd.getFileDescriptor(); 331c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inSampleSize = 1; 332c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang if (targetWidthHeight != -1) { 333c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inJustDecodeBounds = true; 334d30b5877fbdedcebc0af5cccffddccfe9b11cb0bOwen Lin BitmapManager.instance().decodeFileDescriptor(fd, options); 335c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang if (options.mCancel || options.outWidth == -1 336c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang || options.outHeight == -1) { 337c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return null; 338c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 339c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inSampleSize = 340c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang computeSampleSize(options, targetWidthHeight); 341c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inJustDecodeBounds = false; 342c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 343c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 344c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inDither = false; 345c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang options.inPreferredConfig = Bitmap.Config.ARGB_8888; 346d30b5877fbdedcebc0af5cccffddccfe9b11cb0bOwen Lin b = BitmapManager.instance().decodeFileDescriptor(fd, options); 347c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } catch (OutOfMemoryError ex) { 348c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang Log.e(TAG, "Got oom exception ", ex); 349c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return null; 350c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } finally { 351c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang closeSiliently(pfd); 352c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 353c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return b; 354c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 355c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 356c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang private static ParcelFileDescriptor makeInputStream( 357c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang Uri uri, ContentResolver cr) { 358c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang try { 359c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return cr.openFileDescriptor(uri, "r"); 360c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } catch (IOException ex) { 361c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang return null; 362c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 363c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 364fa021af9397011cf180003139e80a88902c4b70aChih-Chung Chang 365fa021af9397011cf180003139e80a88902c4b70aChih-Chung Chang public static void debugWhere(String tag, String msg) { 36674c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin Log.d(tag, msg + " --- stack trace begins: "); 36774c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin StackTraceElement elements[] = Thread.currentThread().getStackTrace(); 36874c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin // skip first 3 element, they are not related to the caller 36974c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin for (int i = 3, n = elements.length; i < n; ++i) { 37074c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin StackTraceElement st = elements[i]; 37174c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin String message = String.format(" at %s.%s(%s:%s)", 37274c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin st.getClassName(), st.getMethodName(), st.getFileName(), 37374c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin st.getLineNumber()); 37474c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin Log.d(tag, message); 37574c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin } 37674c3bd38d4155c694bbb575f389597ee60aec7d3Owen Lin Log.d(tag, msg + " --- stack trace ends."); 377fa021af9397011cf180003139e80a88902c4b70aChih-Chung Chang } 378601ce56b034f111b2875e7636776f2f359f6a156Owen Lin 379601ce56b034f111b2875e7636776f2f359f6a156Owen Lin public static <T> void showProgressDialog(final Context context, 380601ce56b034f111b2875e7636776f2f359f6a156Owen Lin String title, String message, PriorityTask<T> task) { 381601ce56b034f111b2875e7636776f2f359f6a156Owen Lin final ProgressDialog dialog = 382601ce56b034f111b2875e7636776f2f359f6a156Owen Lin ProgressDialog.show(context, title, message); 383601ce56b034f111b2875e7636776f2f359f6a156Owen Lin 384601ce56b034f111b2875e7636776f2f359f6a156Owen Lin task.addCallback(new PriorityTask.Callback<T>() { 385601ce56b034f111b2875e7636776f2f359f6a156Owen Lin 386601ce56b034f111b2875e7636776f2f359f6a156Owen Lin public void onCanceled(PriorityTask<T> t) { 387601ce56b034f111b2875e7636776f2f359f6a156Owen Lin dialog.dismiss(); 388601ce56b034f111b2875e7636776f2f359f6a156Owen Lin } 389601ce56b034f111b2875e7636776f2f359f6a156Owen Lin 390601ce56b034f111b2875e7636776f2f359f6a156Owen Lin public void onFail(PriorityTask<T> t, Throwable error) { 391601ce56b034f111b2875e7636776f2f359f6a156Owen Lin dialog.dismiss(); 392601ce56b034f111b2875e7636776f2f359f6a156Owen Lin } 393601ce56b034f111b2875e7636776f2f359f6a156Owen Lin 394601ce56b034f111b2875e7636776f2f359f6a156Owen Lin public void onResultAvailable(PriorityTask<T> t, T result) { 395601ce56b034f111b2875e7636776f2f359f6a156Owen Lin dialog.dismiss(); 396601ce56b034f111b2875e7636776f2f359f6a156Owen Lin } 397601ce56b034f111b2875e7636776f2f359f6a156Owen Lin }); 398601ce56b034f111b2875e7636776f2f359f6a156Owen Lin } 399601ce56b034f111b2875e7636776f2f359f6a156Owen Lin 400601ce56b034f111b2875e7636776f2f359f6a156Owen Lin public synchronized static OnClickListener getNullOnClickListener() { 401601ce56b034f111b2875e7636776f2f359f6a156Owen Lin if (sNullOnClickListener == null) { 402601ce56b034f111b2875e7636776f2f359f6a156Owen Lin sNullOnClickListener = new OnClickListener() { 403601ce56b034f111b2875e7636776f2f359f6a156Owen Lin public void onClick(View v) { 404601ce56b034f111b2875e7636776f2f359f6a156Owen Lin } 405601ce56b034f111b2875e7636776f2f359f6a156Owen Lin }; 406601ce56b034f111b2875e7636776f2f359f6a156Owen Lin } 407601ce56b034f111b2875e7636776f2f359f6a156Owen Lin return sNullOnClickListener; 408601ce56b034f111b2875e7636776f2f359f6a156Owen Lin } 409341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang 410341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang public static void Assert(boolean cond) { 411341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang if (!cond) { 412341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang throw new AssertionError(); 413341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang } 414341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang } 415101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin} 416