1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.app; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.BitmapUtils; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaItem; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.Path; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.PhotoView; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.PhotoView.ImageData; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.SynchronizedHandler; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.TileImageViewAdapter; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.Future; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.FutureListener; 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.ThreadPool; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap; 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.BitmapFactory; 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.BitmapRegionDecoder; 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Rect; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.Handler; 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.Message; 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class SinglePhotoDataAdapter extends TileImageViewAdapter 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin implements PhotoPage.Model { 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "SinglePhotoDataAdapter"; 425007a96dea76c9f3871b97579b51853029c115a0Owen Lin private static final int SIZE_BACKUP = 1024; 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int MSG_UPDATE_IMAGE = 1; 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private MediaItem mItem; 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mHasFullImage; 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Future<?> mTask; 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Handler mHandler; 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private PhotoView mPhotoView; 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private ThreadPool mThreadPool; 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public SinglePhotoDataAdapter( 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GalleryActivity activity, PhotoView view, MediaItem item) { 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mItem = Utils.checkNotNull(item); 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mHasFullImage = (item.getSupportedOperations() & 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaItem.SUPPORT_FULL_IMAGE) != 0; 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mPhotoView = Utils.checkNotNull(view); 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mHandler = new SynchronizedHandler(activity.getGLRoot()) { 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unchecked") 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void handleMessage(Message message) { 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Utils.assertTrue(message.what == MSG_UPDATE_IMAGE); 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mHasFullImage) { 655007a96dea76c9f3871b97579b51853029c115a0Owen Lin onDecodeLargeComplete((ImageBundle) message.obj); 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin onDecodeThumbComplete((Future<Bitmap>) message.obj); 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin }; 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mThreadPool = activity.getThreadPool(); 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 745007a96dea76c9f3871b97579b51853029c115a0Owen Lin private static class ImageBundle { 755007a96dea76c9f3871b97579b51853029c115a0Owen Lin public final BitmapRegionDecoder decoder; 765007a96dea76c9f3871b97579b51853029c115a0Owen Lin public final Bitmap backupImage; 775007a96dea76c9f3871b97579b51853029c115a0Owen Lin 785007a96dea76c9f3871b97579b51853029c115a0Owen Lin public ImageBundle(BitmapRegionDecoder decoder, Bitmap backupImage) { 795007a96dea76c9f3871b97579b51853029c115a0Owen Lin this.decoder = decoder; 805007a96dea76c9f3871b97579b51853029c115a0Owen Lin this.backupImage = backupImage; 815007a96dea76c9f3871b97579b51853029c115a0Owen Lin } 825007a96dea76c9f3871b97579b51853029c115a0Owen Lin } 835007a96dea76c9f3871b97579b51853029c115a0Owen Lin 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private FutureListener<BitmapRegionDecoder> mLargeListener = 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new FutureListener<BitmapRegionDecoder>() { 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onFutureDone(Future<BitmapRegionDecoder> future) { 875007a96dea76c9f3871b97579b51853029c115a0Owen Lin BitmapRegionDecoder decoder = future.get(); 885007a96dea76c9f3871b97579b51853029c115a0Owen Lin if (decoder == null) return; 895007a96dea76c9f3871b97579b51853029c115a0Owen Lin int width = decoder.getWidth(); 905007a96dea76c9f3871b97579b51853029c115a0Owen Lin int height = decoder.getHeight(); 915007a96dea76c9f3871b97579b51853029c115a0Owen Lin BitmapFactory.Options options = new BitmapFactory.Options(); 925007a96dea76c9f3871b97579b51853029c115a0Owen Lin options.inSampleSize = BitmapUtils.computeSampleSize( 935007a96dea76c9f3871b97579b51853029c115a0Owen Lin (float) SIZE_BACKUP / Math.max(width, height)); 945007a96dea76c9f3871b97579b51853029c115a0Owen Lin Bitmap bitmap = decoder.decodeRegion(new Rect(0, 0, width, height), options); 955007a96dea76c9f3871b97579b51853029c115a0Owen Lin mHandler.sendMessage(mHandler.obtainMessage( 965007a96dea76c9f3871b97579b51853029c115a0Owen Lin MSG_UPDATE_IMAGE, new ImageBundle(decoder, bitmap))); 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin }; 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private FutureListener<Bitmap> mThumbListener = 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new FutureListener<Bitmap>() { 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onFutureDone(Future<Bitmap> future) { 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mHandler.sendMessage( 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mHandler.obtainMessage(MSG_UPDATE_IMAGE, future)); 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin }; 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean isEmpty() { 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return false; 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getImageRotation() { 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mItem.getRotation(); 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1165007a96dea76c9f3871b97579b51853029c115a0Owen Lin private void onDecodeLargeComplete(ImageBundle bundle) { 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 1185007a96dea76c9f3871b97579b51853029c115a0Owen Lin setBackupImage(bundle.backupImage, 1195007a96dea76c9f3871b97579b51853029c115a0Owen Lin bundle.decoder.getWidth(), bundle.decoder.getHeight()); 1205007a96dea76c9f3871b97579b51853029c115a0Owen Lin setRegionDecoder(bundle.decoder); 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mPhotoView.notifyImageInvalidated(0); 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "fail to decode large", t); 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void onDecodeThumbComplete(Future<Bitmap> future) { 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 1295007a96dea76c9f3871b97579b51853029c115a0Owen Lin Bitmap backup = future.get(); 1305007a96dea76c9f3871b97579b51853029c115a0Owen Lin if (backup == null) return; 1315007a96dea76c9f3871b97579b51853029c115a0Owen Lin setBackupImage(backup, backup.getWidth(), backup.getHeight()); 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mPhotoView.notifyOnNewImage(); 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mPhotoView.notifyImageInvalidated(0); // the current image 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "fail to decode thumb", t); 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void resume() { 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mTask == null) { 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mHasFullImage) { 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mTask = mThreadPool.submit( 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mItem.requestLargeImage(), mLargeListener); 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mTask = mThreadPool.submit( 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mItem.requestImage(MediaItem.TYPE_THUMBNAIL), 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mThumbListener); 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void pause() { 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Future<?> task = mTask; 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin task.cancel(); 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin task.waitDone(); 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (task.get() == null) { 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mTask = null; 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ImageData getNextImage() { 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ImageData getPreviousImage() { 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void next() { 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new UnsupportedOperationException(); 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void previous() { 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new UnsupportedOperationException(); 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1773a54b9ae67eb7b38f19ea0bdeeef26efc0a1afa1Chih-Chung Chang public void jumpTo(int index) { 1783a54b9ae67eb7b38f19ea0bdeeef26efc0a1afa1Chih-Chung Chang throw new UnsupportedOperationException(); 1793a54b9ae67eb7b38f19ea0bdeeef26efc0a1afa1Chih-Chung Chang } 1803a54b9ae67eb7b38f19ea0bdeeef26efc0a1afa1Chih-Chung Chang 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaItem getCurrentMediaItem() { 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mItem; 183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getCurrentIndex() { 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return 0; 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void setCurrentPhoto(Path path, int indexHint) { 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // ignore 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 193