Thumbnail.java revision 1c4edcb4f6c50997b534ac83712cc4c49531a5cb
1/* 2 * Copyright (C) 2011 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.ContentUris; 21import android.database.Cursor; 22import android.graphics.Bitmap; 23import android.graphics.BitmapFactory; 24import android.graphics.Matrix; 25import android.net.Uri; 26import android.provider.MediaStore.Images; 27import android.provider.MediaStore.Images.ImageColumns; 28import android.provider.MediaStore.MediaColumns; 29import android.provider.MediaStore.Video; 30import android.provider.MediaStore.Video.VideoColumns; 31import android.util.Log; 32 33import java.io.BufferedInputStream; 34import java.io.BufferedOutputStream; 35import java.io.DataInputStream; 36import java.io.DataOutputStream; 37import java.io.FileInputStream; 38import java.io.FileOutputStream; 39import java.io.IOException; 40 41class Thumbnail { 42 private static final String TAG = "Thumbnail"; 43 44 private static final String DIRECTORY = Storage.DCIM + "/.thumbnails/"; 45 private static final int BUFSIZE = 4096; 46 47 private Uri mUri; 48 private Bitmap mBitmap; 49 50 public Thumbnail(Uri uri, Bitmap bitmap, int orientation) { 51 mUri = uri; 52 mBitmap = rotateImage(bitmap, orientation); 53 } 54 55 public Uri getUri() { 56 return mUri; 57 } 58 59 public Bitmap getBitmap() { 60 return mBitmap; 61 } 62 63 private static Bitmap rotateImage(Bitmap bitmap, int orientation) { 64 if (orientation != 0) { 65 // We only rotate the thumbnail once even if we get OOM. 66 Matrix m = new Matrix(); 67 m.setRotate(orientation, bitmap.getWidth() * 0.5f, 68 bitmap.getHeight() * 0.5f); 69 70 try { 71 Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0, 72 bitmap.getWidth(), bitmap.getHeight(), m, true); 73 bitmap.recycle(); 74 return rotated; 75 } catch (Throwable t) { 76 Log.w(TAG, "Failed to rotate thumbnail", t); 77 } 78 } 79 return bitmap; 80 } 81 82 // Stores the bitmap to the specified file. 83 public void saveTo(String filename) { 84 String path = DIRECTORY + filename; 85 FileOutputStream f = null; 86 BufferedOutputStream b = null; 87 DataOutputStream d = null; 88 try { 89 f = new FileOutputStream(path); 90 b = new BufferedOutputStream(f, BUFSIZE); 91 d = new DataOutputStream(b); 92 d.writeUTF(mUri.toString()); 93 mBitmap.compress(Bitmap.CompressFormat.PNG, 100, d); 94 d.close(); 95 } catch (IOException e) { 96 Log.e(TAG, "Fail to store bitmap. path=" + path, e); 97 } finally { 98 Util.closeSilently(f); 99 Util.closeSilently(b); 100 Util.closeSilently(d); 101 } 102 } 103 104 105 // Loads the data from the specified file. 106 // Returns null if failure. 107 public static Thumbnail loadFrom(String filename) { 108 Uri uri = null; 109 Bitmap bitmap = null; 110 FileInputStream f = null; 111 BufferedInputStream b = null; 112 DataInputStream d = null; 113 try { 114 f = new FileInputStream(DIRECTORY + filename); 115 b = new BufferedInputStream(f, BUFSIZE); 116 d = new DataInputStream(b); 117 uri = Uri.parse(d.readUTF()); 118 bitmap = BitmapFactory.decodeStream(d); 119 d.close(); 120 } catch (IOException e) { 121 Log.i(TAG, "Fail to load bitmap. " + e); 122 return null; 123 } finally { 124 Util.closeSilently(f); 125 Util.closeSilently(b); 126 Util.closeSilently(d); 127 } 128 return new Thumbnail(uri, bitmap, 0); 129 } 130 131 public static Thumbnail getLastImageThumbnail(ContentResolver resolver) { 132 Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI; 133 134 Uri query = baseUri.buildUpon().appendQueryParameter("limit", "1").build(); 135 String[] projection = new String[] {ImageColumns._ID, ImageColumns.ORIENTATION}; 136 String selection = ImageColumns.MIME_TYPE + "='image/jpeg' AND " + 137 ImageColumns.BUCKET_ID + '=' + Storage.BUCKET_ID; 138 String order = ImageColumns.DATE_TAKEN + " DESC," + ImageColumns._ID + " DESC"; 139 140 Cursor cursor = null; 141 try { 142 cursor = resolver.query(query, projection, selection, null, order); 143 if (cursor != null && cursor.moveToFirst()) { 144 long id = cursor.getLong(0); 145 int orientation = cursor.getInt(1); 146 Bitmap bitmap = Images.Thumbnails.getThumbnail(resolver, id, 147 Images.Thumbnails.MINI_KIND, null); 148 Uri uri = ContentUris.withAppendedId(baseUri, id); 149 // Ensure there's no OOM. Ensure database and storage are in sync. 150 if (bitmap != null && Util.isUriValid(uri, resolver)) { 151 return new Thumbnail(uri, bitmap, orientation); 152 } 153 } 154 } finally { 155 if (cursor != null) { 156 cursor.close(); 157 } 158 } 159 return null; 160 } 161 162 public static Thumbnail getLastVideoThumbnail(ContentResolver resolver) { 163 Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI; 164 165 Uri query = baseUri.buildUpon().appendQueryParameter("limit", "1").build(); 166 String[] projection = new String[] {VideoColumns._ID, MediaColumns.DATA}; 167 String selection = VideoColumns.BUCKET_ID + '=' + Storage.BUCKET_ID; 168 String order = VideoColumns.DATE_TAKEN + " DESC," + VideoColumns._ID + " DESC"; 169 170 Cursor cursor = null; 171 try { 172 cursor = resolver.query(query, projection, selection, null, order); 173 if (cursor != null && cursor.moveToFirst()) { 174 Log.d(TAG, "getLastVideoThumbnail: " + cursor.getString(1)); 175 long id = cursor.getLong(0); 176 Bitmap bitmap = Video.Thumbnails.getThumbnail(resolver, id, 177 Video.Thumbnails.MINI_KIND, null); 178 Uri uri = ContentUris.withAppendedId(baseUri, id); 179 // Ensure there's no OOM. Ensure database and storage are in sync. 180 if (bitmap != null && Util.isUriValid(uri, resolver)) { 181 return new Thumbnail(uri, bitmap, 0); 182 } 183 } 184 } finally { 185 if (cursor != null) { 186 cursor.close(); 187 } 188 } 189 return null; 190 } 191 192 public static Thumbnail createThumbnail(byte[] jpeg, int orientation, int inSampleSize, 193 Uri uri) { 194 // Create the thumbnail. 195 BitmapFactory.Options options = new BitmapFactory.Options(); 196 options.inSampleSize = inSampleSize; 197 Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options); 198 if (bitmap == null) { 199 Log.e(TAG, "Failed to create thumbnail"); 200 return null; 201 } 202 return new Thumbnail(uri, bitmap, orientation); 203 } 204} 205