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 17 package com.android.camera; 18 19 20 import android.content.ContentResolver; 21 import android.graphics.Bitmap; 22 import android.graphics.BitmapFactory; 23 import android.graphics.drawable.BitmapDrawable; 24 import android.graphics.drawable.Drawable; 25 import android.graphics.drawable.TransitionDrawable; 26 import android.net.Uri; 27 import android.os.ParcelFileDescriptor; 28 import android.util.Log; 29 import android.view.View; 30 import android.view.ViewGroup.LayoutParams; 31 import android.view.animation.AlphaAnimation; 32 import android.view.animation.Animation; 33 import android.widget.ImageView; 34 35 import java.io.BufferedInputStream; 36 import java.io.BufferedOutputStream; 37 import java.io.DataInputStream; 38 import java.io.DataOutputStream; 39 import java.io.FileInputStream; 40 import java.io.FileOutputStream; 41 import java.io.IOException; 42 43 /** A controller shows thumbnail picture on a button. The thumbnail picture 44 * corresponds to a URI of the original picture/video. The thumbnail bitmap 45 * and the URI can be saved to a file (and later loaded from it). 46 * <pre> 47 * public ThumbnailController(ImageView button) 48 * public void setData(Uri uri, Bitmap original) 49 * public void updateDisplayIfNeeded() 50 * public Uri getUri() 51 * public Bitmap getThumb() 52 * public boolean storeData(String filePath) 53 * public boolean loadData(String filePath) 54 * </pre> 55 */ 56 public class ThumbnailController { 57 58 @SuppressWarnings("unused") 59 private static final String TAG = "ThumbnailController"; 60 private final ContentResolver mContentResolver; 61 private Uri mUri; 62 private Bitmap mThumb; 63 private final ImageView mButton; 64 private Drawable[] mThumbs; 65 private TransitionDrawable mThumbTransition; 66 private boolean mShouldAnimateThumb; 67 private final Animation mShowButtonAnimation = new AlphaAnimation(0F, 1F); 68 private boolean mShouldAnimateButton; 69 70 // The "frame" is a drawable we want to put on top of the thumbnail. ThumbnailController( ImageView button, ContentResolver contentResolver)71 public ThumbnailController( 72 ImageView button, ContentResolver contentResolver) { 73 mButton = button; 74 mContentResolver = contentResolver; 75 mShowButtonAnimation.setDuration(500); 76 } 77 setData(Uri uri, Bitmap original)78 public void setData(Uri uri, Bitmap original) { 79 // Make sure uri and original are consistently both null or both 80 // non-null. 81 if (uri == null || original == null) { 82 uri = null; 83 original = null; 84 } 85 mUri = uri; 86 updateThumb(original); 87 } 88 getUri()89 public Uri getUri() { 90 return mUri; 91 } 92 getThumb()93 public Bitmap getThumb() { 94 return mThumb; 95 } 96 97 private static final int BUFSIZE = 4096; 98 99 // Stores the data from the specified file. 100 // Returns true for success. storeData(String filePath)101 public boolean storeData(String filePath) { 102 if (mUri == null) { 103 return false; 104 } 105 106 FileOutputStream f = null; 107 BufferedOutputStream b = null; 108 DataOutputStream d = null; 109 try { 110 f = new FileOutputStream(filePath); 111 b = new BufferedOutputStream(f, BUFSIZE); 112 d = new DataOutputStream(b); 113 d.writeUTF(mUri.toString()); 114 mThumb.compress(Bitmap.CompressFormat.PNG, 100, d); 115 d.close(); 116 } catch (IOException e) { 117 return false; 118 } finally { 119 MenuHelper.closeSilently(f); 120 MenuHelper.closeSilently(b); 121 MenuHelper.closeSilently(d); 122 } 123 return true; 124 } 125 126 // Loads the data from the specified file. 127 // Returns true for success. loadData(String filePath)128 public boolean loadData(String filePath) { 129 FileInputStream f = null; 130 BufferedInputStream b = null; 131 DataInputStream d = null; 132 try { 133 f = new FileInputStream(filePath); 134 b = new BufferedInputStream(f, BUFSIZE); 135 d = new DataInputStream(b); 136 Uri uri = Uri.parse(d.readUTF()); 137 Bitmap thumb = BitmapFactory.decodeStream(d); 138 setData(uri, thumb); 139 d.close(); 140 } catch (IOException e) { 141 return false; 142 } finally { 143 MenuHelper.closeSilently(f); 144 MenuHelper.closeSilently(b); 145 MenuHelper.closeSilently(d); 146 } 147 return true; 148 } 149 updateDisplayIfNeeded()150 public void updateDisplayIfNeeded() { 151 if (mUri == null) { 152 mButton.setVisibility(View.INVISIBLE); 153 return; 154 } 155 156 if (mShouldAnimateButton) { 157 mButton.setVisibility(View.VISIBLE); 158 mButton.startAnimation(mShowButtonAnimation); 159 mShouldAnimateButton = false; 160 } 161 162 if (mShouldAnimateThumb) { 163 mThumbTransition.startTransition(500); 164 mShouldAnimateThumb = false; 165 } 166 } 167 updateThumb(Bitmap original)168 private void updateThumb(Bitmap original) { 169 if (original == null) { 170 mThumb = null; 171 mThumbs = null; 172 return; 173 } 174 175 // Make the mini-thumb size smaller than the button size so that the 176 // image corners don't peek out from the rounded corners of the 177 // frame_thumb graphic: 178 final int PADDING_WIDTH = 2; 179 final int PADDING_HEIGHT = 2; 180 LayoutParams param = mButton.getLayoutParams(); 181 final int miniThumbWidth = param.width - 2 * PADDING_WIDTH; 182 final int miniThumbHeight = param.height - 2 * PADDING_HEIGHT; 183 mThumb = Util.extractMiniThumb( 184 original, miniThumbWidth, miniThumbHeight, false); 185 Drawable drawable; 186 if (mThumbs == null) { 187 mThumbs = new Drawable[2]; 188 mThumbs[1] = new BitmapDrawable(mThumb); 189 drawable = mThumbs[1]; 190 mShouldAnimateThumb = false; 191 } else { 192 mThumbs[0] = mThumbs[1]; 193 mThumbs[1] = new BitmapDrawable(mThumb); 194 mThumbTransition = new TransitionDrawable(mThumbs); 195 drawable = mThumbTransition; 196 mShouldAnimateThumb = true; 197 } 198 mButton.setImageDrawable(drawable); 199 200 if (mButton.getVisibility() != View.VISIBLE) { 201 mShouldAnimateButton = true; 202 } 203 } 204 isUriValid()205 public boolean isUriValid() { 206 if (mUri == null) { 207 return false; 208 } 209 try { 210 ParcelFileDescriptor pfd = 211 mContentResolver.openFileDescriptor(mUri, "r"); 212 if (pfd == null) { 213 Log.e(TAG, "Fail to open URI."); 214 return false; 215 } 216 pfd.close(); 217 } catch (IOException ex) { 218 return false; 219 } 220 return true; 221 } 222 } 223