• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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