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