/** * Check if the corresponding thumbnail and mini-thumb have been created * for the given uri. This method creates both of them if they do not * exist yet or have been changed since last check. After thumbnails are * created, MINI_KIND thumbnail is stored in JPEG file and MICRO_KIND * thumbnail is stored in a random access file (MiniThumbFile). * * @throws IOException */ void execute() throws IOException { MiniThumbFile miniThumbFile = MiniThumbFile.instance(mUri); long magic = mMagic; if (magic != 0) { long fileMagic = miniThumbFile.getMagic(mOrigId); if (fileMagic == magic) { Cursor c = null; ParcelFileDescriptor pfd = null; try { c = mCr.query(mThumbUri, THUMB_PROJECTION, mOrigColumnName + " = " + mOrigId, null, null); if (c != null && c.moveToFirst()) { pfd = mCr.openFileDescriptor( mThumbUri.buildUpon().appendPath(c.getString(0)).build(), "r"); } } catch (IOException ex) { // MINI_THUMBNAIL not exists, ignore the exception and generate one. } finally { if (c != null) c.close(); if (pfd != null) { pfd.close(); return; } } } } // If we can't retrieve the thumbnail, first check if there is one // embedded in the EXIF data. If not, or it's not big enough, // decompress the full size image. Bitmap bitmap = null; if (mPath != null) { if (mIsVideo) { bitmap = ThumbnailUtils.createVideoThumbnail(mPath, Video.Thumbnails.MINI_KIND); } else { bitmap = ThumbnailUtils.createImageThumbnail(mPath, Images.Thumbnails.MINI_KIND); } if (bitmap == null) { Log.w(TAG, "Can't create mini thumbnail for " + mPath); return; } Uri uri = updateDatabase(bitmap); if (uri != null) { OutputStream thumbOut = mCr.openOutputStream(uri); bitmap.compress(Bitmap.CompressFormat.JPEG, 85, thumbOut); thumbOut.close(); } } bitmap = ThumbnailUtils.extractThumbnail(bitmap, ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL, ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL, ThumbnailUtils.OPTIONS_RECYCLE_INPUT); if (bitmap != null) { ByteArrayOutputStream miniOutStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 75, miniOutStream); bitmap.recycle(); byte [] data = null; try { miniOutStream.close(); data = miniOutStream.toByteArray(); } catch (java.io.IOException ex) { Log.e(TAG, "got exception ex " + ex); } // We may consider retire this proprietary format, after all it's size is only // 128 x 128 at most, which is still reasonable to be stored in database. // Gallery application can use the MINI_THUMB_MAGIC value to determine if it's // time to query and fetch by using Cursor.getBlob if (data != null) { // make a new magic number since things are out of sync do { magic = mRandom.nextLong(); } while (magic == 0); miniThumbFile.saveMiniThumbToFile(data, mOrigId, magic); ContentValues values = new ContentValues(); // both video/images table use the same column name "mini_thumb_magic" values.put(ImageColumns.MINI_THUMB_MAGIC, magic); mCr.update(mUri, values, null, null); } } else { Log.w(TAG, "can't create bitmap for thumbnail."); } }