Util.java revision c1c20e9ce386c1f660059acaede591d2d718995a
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.camera; 18 19import android.content.ContentResolver; 20import android.content.Context; 21import android.graphics.Bitmap; 22import android.graphics.BitmapFactory; 23import android.graphics.Matrix; 24import android.media.MediaMetadataRetriever; 25import android.net.Uri; 26import android.os.ParcelFileDescriptor; 27import android.util.Log; 28 29import java.io.ByteArrayOutputStream; 30import java.io.Closeable; 31import java.io.IOException; 32import java.io.FileDescriptor; 33 34/** 35 * Collection of utility functions used in this package. 36 */ 37public class Util { 38 private static final boolean VERBOSE = false; 39 private static final String TAG = "db.Util"; 40 41 private Util() { 42 } 43 44 // Rotates the bitmap by the specified degree. 45 // If a new bitmap is created, the original bitmap is recycled. 46 public static Bitmap rotate(Bitmap b, int degrees) { 47 if (degrees != 0 && b != null) { 48 Matrix m = new Matrix(); 49 m.setRotate(degrees, 50 (float) b.getWidth() / 2, (float) b.getHeight() / 2); 51 try { 52 Bitmap b2 = Bitmap.createBitmap( 53 b, 0, 0, b.getWidth(), b.getHeight(), m, true); 54 if (b != b2) { 55 b.recycle(); 56 b = b2; 57 } 58 } catch (OutOfMemoryError ex) { 59 // We have no memory to rotate. Return the original bitmap. 60 } 61 } 62 return b; 63 } 64 65 /* 66 * Compute the sample size as a function of the image size and the target. 67 * Scale the image down so that both the width and height are just above the 68 * target. If this means that one of the dimension goes from above the 69 * target to below the target (e.g. given a width of 480 and an image width 70 * of 600 but sample size of 2 -- i.e. new width 300 -- bump the sample size 71 * down by 1. 72 */ 73 public static int computeSampleSize( 74 BitmapFactory.Options options, int target) { 75 int w = options.outWidth; 76 int h = options.outHeight; 77 78 int candidateW = w / target; 79 int candidateH = h / target; 80 int candidate = Math.max(candidateW, candidateH); 81 82 if (candidate == 0) return 1; 83 84 if (candidate > 1) { 85 if ((w > target) && (w / candidate) < target) candidate -= 1; 86 } 87 88 if (candidate > 1) { 89 if ((h > target) && (h / candidate) < target) candidate -= 1; 90 } 91 92 return candidate; 93 } 94 95 /** 96 * Creates a centered bitmap of the desired size. Recycles the input. 97 * @param source 98 */ 99 public static Bitmap extractMiniThumb( 100 Bitmap source, int width, int height) { 101 return Util.extractMiniThumb(source, width, height, true); 102 } 103 104 public static Bitmap extractMiniThumb( 105 Bitmap source, int width, int height, boolean recycle) { 106 if (source == null) { 107 return null; 108 } 109 110 float scale; 111 if (source.getWidth() < source.getHeight()) { 112 scale = width / (float) source.getWidth(); 113 } else { 114 scale = height / (float) source.getHeight(); 115 } 116 Matrix matrix = new Matrix(); 117 matrix.setScale(scale, scale); 118 Bitmap miniThumbnail = ImageLoader.transform(matrix, source, 119 width, height, false); 120 121 if (recycle && miniThumbnail != source) { 122 source.recycle(); 123 } 124 return miniThumbnail; 125 } 126 127 /** 128 * Creates a byte[] for a given bitmap of the desired size. Recycles the 129 * input bitmap. 130 */ 131 public static byte[] miniThumbData(Bitmap source) { 132 if (source == null) return null; 133 134 Bitmap miniThumbnail = extractMiniThumb( 135 source, ImageManager.MINI_THUMB_TARGET_SIZE, 136 ImageManager.MINI_THUMB_TARGET_SIZE); 137 138 ByteArrayOutputStream miniOutStream = new ByteArrayOutputStream(); 139 miniThumbnail.compress(Bitmap.CompressFormat.JPEG, 75, miniOutStream); 140 miniThumbnail.recycle(); 141 142 try { 143 miniOutStream.close(); 144 byte [] data = miniOutStream.toByteArray(); 145 return data; 146 } catch (java.io.IOException ex) { 147 Log.e(TAG, "got exception ex " + ex); 148 } 149 return null; 150 } 151 152 /** 153 * @return true if the mimetype is a video mimetype. 154 */ 155 public static boolean isVideoMimeType(String mimeType) { 156 return mimeType.startsWith("video/"); 157 } 158 159 /** 160 * Create a video thumbnail for a video. May return null if the video is 161 * corrupt. 162 * 163 * @param filePath 164 */ 165 public static Bitmap createVideoThumbnail(String filePath) { 166 Bitmap bitmap = null; 167 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 168 try { 169 retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); 170 retriever.setDataSource(filePath); 171 bitmap = retriever.captureFrame(); 172 } catch (IllegalArgumentException ex) { 173 // Assume this is a corrupt video file 174 } catch (RuntimeException ex) { 175 // Assume this is a corrupt video file. 176 } finally { 177 try { 178 retriever.release(); 179 } catch (RuntimeException ex) { 180 // Ignore failures while cleaning up. 181 } 182 } 183 return bitmap; 184 } 185 186 public static int indexOf(String [] array, String s) { 187 for (int i = 0; i < array.length; i++) { 188 if (array[i].equals(s)) { 189 return i; 190 } 191 } 192 return -1; 193 } 194 195 public static void closeSiliently(Closeable c) { 196 if (c == null) return; 197 try { 198 c.close(); 199 } catch (Throwable t) { 200 // do nothing 201 } 202 } 203 204 public static void closeSiliently(ParcelFileDescriptor c) { 205 if (c == null) return; 206 try { 207 c.close(); 208 } catch (Throwable t) { 209 // do nothing 210 } 211 } 212 213 /** 214 * Make a bitmap from a given Uri. 215 * 216 * @param uri 217 */ 218 public static Bitmap makeBitmap(int targetWidthOrHeight, Uri uri, 219 ContentResolver cr) { 220 ParcelFileDescriptor input = null; 221 try { 222 input = cr.openFileDescriptor(uri, "r"); 223 return makeBitmap(targetWidthOrHeight, uri, cr, input, null); 224 } catch (IOException ex) { 225 return null; 226 } finally { 227 closeSiliently(input); 228 } 229 } 230 231 public static Bitmap makeBitmap(int targetWidthHeight, Uri uri, 232 ContentResolver cr, ParcelFileDescriptor pfd, 233 BitmapFactory.Options options) { 234 Bitmap b = null; 235 try { 236 if (pfd == null) pfd = makeInputStream(uri, cr); 237 if (pfd == null) return null; 238 if (options == null) options = new BitmapFactory.Options(); 239 240 FileDescriptor fd = pfd.getFileDescriptor(); 241 options.inSampleSize = 1; 242 if (targetWidthHeight != -1) { 243 options.inJustDecodeBounds = true; 244 BitmapManager.instance().decodeFileDescriptor( 245 fd, null, options); 246 if (options.mCancel || options.outWidth == -1 247 || options.outHeight == -1) { 248 return null; 249 } 250 options.inSampleSize = 251 computeSampleSize(options, targetWidthHeight); 252 options.inJustDecodeBounds = false; 253 } 254 255 options.inDither = false; 256 options.inPreferredConfig = Bitmap.Config.ARGB_8888; 257 b = BitmapManager.instance() 258 .decodeFileDescriptor(fd, null, options); 259 } catch (OutOfMemoryError ex) { 260 Log.e(TAG, "Got oom exception ", ex); 261 return null; 262 } finally { 263 closeSiliently(pfd); 264 } 265 return b; 266 } 267 268 private static ParcelFileDescriptor makeInputStream( 269 Uri uri, ContentResolver cr) { 270 try { 271 return cr.openFileDescriptor(uri, "r"); 272 } catch (IOException ex) { 273 return null; 274 } 275 } 276} 277