• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.gallery3d.app;
18 
19 import com.android.gallery3d.common.BitmapUtils;
20 import com.android.gallery3d.common.Utils;
21 import com.android.gallery3d.data.MediaItem;
22 import com.android.gallery3d.data.Path;
23 import com.android.gallery3d.ui.PhotoView;
24 import com.android.gallery3d.ui.PhotoView.ImageData;
25 import com.android.gallery3d.ui.SynchronizedHandler;
26 import com.android.gallery3d.ui.TileImageViewAdapter;
27 import com.android.gallery3d.util.Future;
28 import com.android.gallery3d.util.FutureListener;
29 import com.android.gallery3d.util.ThreadPool;
30 
31 import android.graphics.Bitmap;
32 import android.graphics.BitmapFactory;
33 import android.graphics.BitmapRegionDecoder;
34 import android.graphics.Rect;
35 import android.os.Handler;
36 import android.os.Message;
37 
38 public class SinglePhotoDataAdapter extends TileImageViewAdapter
39         implements PhotoPage.Model {
40 
41     private static final String TAG = "SinglePhotoDataAdapter";
42     private static final int SIZE_BACKUP = 1024;
43     private static final int MSG_UPDATE_IMAGE = 1;
44 
45     private MediaItem mItem;
46     private boolean mHasFullImage;
47     private Future<?> mTask;
48     private Handler mHandler;
49 
50     private PhotoView mPhotoView;
51     private ThreadPool mThreadPool;
52 
SinglePhotoDataAdapter( GalleryActivity activity, PhotoView view, MediaItem item)53     public SinglePhotoDataAdapter(
54             GalleryActivity activity, PhotoView view, MediaItem item) {
55         mItem = Utils.checkNotNull(item);
56         mHasFullImage = (item.getSupportedOperations() &
57                 MediaItem.SUPPORT_FULL_IMAGE) != 0;
58         mPhotoView = Utils.checkNotNull(view);
59         mHandler = new SynchronizedHandler(activity.getGLRoot()) {
60             @Override
61             @SuppressWarnings("unchecked")
62             public void handleMessage(Message message) {
63                 Utils.assertTrue(message.what == MSG_UPDATE_IMAGE);
64                 if (mHasFullImage) {
65                     onDecodeLargeComplete((ImageBundle) message.obj);
66                 } else {
67                     onDecodeThumbComplete((Future<Bitmap>) message.obj);
68                 }
69             }
70         };
71         mThreadPool = activity.getThreadPool();
72     }
73 
74     private static class ImageBundle {
75         public final BitmapRegionDecoder decoder;
76         public final Bitmap backupImage;
77 
ImageBundle(BitmapRegionDecoder decoder, Bitmap backupImage)78         public ImageBundle(BitmapRegionDecoder decoder, Bitmap backupImage) {
79             this.decoder = decoder;
80             this.backupImage = backupImage;
81         }
82     }
83 
84     private FutureListener<BitmapRegionDecoder> mLargeListener =
85             new FutureListener<BitmapRegionDecoder>() {
86         public void onFutureDone(Future<BitmapRegionDecoder> future) {
87             BitmapRegionDecoder decoder = future.get();
88             if (decoder == null) return;
89             int width = decoder.getWidth();
90             int height = decoder.getHeight();
91             BitmapFactory.Options options = new BitmapFactory.Options();
92             options.inSampleSize = BitmapUtils.computeSampleSize(
93                     (float) SIZE_BACKUP / Math.max(width, height));
94             Bitmap bitmap = decoder.decodeRegion(new Rect(0, 0, width, height), options);
95             mHandler.sendMessage(mHandler.obtainMessage(
96                     MSG_UPDATE_IMAGE, new ImageBundle(decoder, bitmap)));
97         }
98     };
99 
100     private FutureListener<Bitmap> mThumbListener =
101             new FutureListener<Bitmap>() {
102         public void onFutureDone(Future<Bitmap> future) {
103             mHandler.sendMessage(
104                     mHandler.obtainMessage(MSG_UPDATE_IMAGE, future));
105         }
106     };
107 
isEmpty()108     public boolean isEmpty() {
109         return false;
110     }
111 
getImageRotation()112     public int getImageRotation() {
113         return mItem.getRotation();
114     }
115 
onDecodeLargeComplete(ImageBundle bundle)116     private void onDecodeLargeComplete(ImageBundle bundle) {
117         try {
118             setBackupImage(bundle.backupImage,
119                     bundle.decoder.getWidth(), bundle.decoder.getHeight());
120             setRegionDecoder(bundle.decoder);
121             mPhotoView.notifyImageInvalidated(0);
122         } catch (Throwable t) {
123             Log.w(TAG, "fail to decode large", t);
124         }
125     }
126 
onDecodeThumbComplete(Future<Bitmap> future)127     private void onDecodeThumbComplete(Future<Bitmap> future) {
128         try {
129             Bitmap backup = future.get();
130             if (backup == null) return;
131             setBackupImage(backup, backup.getWidth(), backup.getHeight());
132             mPhotoView.notifyOnNewImage();
133             mPhotoView.notifyImageInvalidated(0); // the current image
134         } catch (Throwable t) {
135             Log.w(TAG, "fail to decode thumb", t);
136         }
137     }
138 
resume()139     public void resume() {
140         if (mTask == null) {
141             if (mHasFullImage) {
142                 mTask = mThreadPool.submit(
143                         mItem.requestLargeImage(), mLargeListener);
144             } else {
145                 mTask = mThreadPool.submit(
146                         mItem.requestImage(MediaItem.TYPE_THUMBNAIL),
147                         mThumbListener);
148             }
149         }
150     }
151 
pause()152     public void pause() {
153         Future<?> task = mTask;
154         task.cancel();
155         task.waitDone();
156         if (task.get() == null) {
157             mTask = null;
158         }
159     }
160 
getNextImage()161     public ImageData getNextImage() {
162         return null;
163     }
164 
getPreviousImage()165     public ImageData getPreviousImage() {
166         return null;
167     }
168 
next()169     public void next() {
170         throw new UnsupportedOperationException();
171     }
172 
previous()173     public void previous() {
174         throw new UnsupportedOperationException();
175     }
176 
jumpTo(int index)177     public void jumpTo(int index) {
178         throw new UnsupportedOperationException();
179     }
180 
getCurrentMediaItem()181     public MediaItem getCurrentMediaItem() {
182         return mItem;
183     }
184 
getCurrentIndex()185     public int getCurrentIndex() {
186         return 0;
187     }
188 
setCurrentPhoto(Path path, int indexHint)189     public void setCurrentPhoto(Path path, int indexHint) {
190         // ignore
191     }
192 }
193