diff options
Diffstat (limited to 'src/com/android/gallery3d/app/SinglePhotoDataAdapter.java')
-rw-r--r-- | src/com/android/gallery3d/app/SinglePhotoDataAdapter.java | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java new file mode 100644 index 000000000..00f2fe78f --- /dev/null +++ b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.app; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.BitmapRegionDecoder; +import android.graphics.Rect; +import android.os.Handler; +import android.os.Message; + +import com.android.gallery3d.common.BitmapUtils; +import com.android.gallery3d.common.Utils; +import com.android.gallery3d.data.MediaItem; +import com.android.gallery3d.data.Path; +import com.android.gallery3d.ui.BitmapScreenNail; +import com.android.gallery3d.ui.PhotoView; +import com.android.gallery3d.ui.ScreenNail; +import com.android.gallery3d.ui.SynchronizedHandler; +import com.android.gallery3d.ui.TileImageViewAdapter; +import com.android.gallery3d.util.Future; +import com.android.gallery3d.util.FutureListener; +import com.android.gallery3d.util.ThreadPool; + +public class SinglePhotoDataAdapter extends TileImageViewAdapter + implements PhotoPage.Model { + + private static final String TAG = "SinglePhotoDataAdapter"; + private static final int SIZE_BACKUP = 1024; + private static final int MSG_UPDATE_IMAGE = 1; + + private MediaItem mItem; + private boolean mHasFullImage; + private Future<?> mTask; + private Handler mHandler; + + private PhotoView mPhotoView; + private ThreadPool mThreadPool; + private int mLoadingState = LOADING_INIT; + private BitmapScreenNail mBitmapScreenNail; + + public SinglePhotoDataAdapter( + AbstractGalleryActivity activity, PhotoView view, MediaItem item) { + mItem = Utils.checkNotNull(item); + mHasFullImage = (item.getSupportedOperations() & + MediaItem.SUPPORT_FULL_IMAGE) != 0; + mPhotoView = Utils.checkNotNull(view); + mHandler = new SynchronizedHandler(activity.getGLRoot()) { + @Override + @SuppressWarnings("unchecked") + public void handleMessage(Message message) { + Utils.assertTrue(message.what == MSG_UPDATE_IMAGE); + if (mHasFullImage) { + onDecodeLargeComplete((ImageBundle) message.obj); + } else { + onDecodeThumbComplete((Future<Bitmap>) message.obj); + } + } + }; + mThreadPool = activity.getThreadPool(); + } + + private static class ImageBundle { + public final BitmapRegionDecoder decoder; + public final Bitmap backupImage; + + public ImageBundle(BitmapRegionDecoder decoder, Bitmap backupImage) { + this.decoder = decoder; + this.backupImage = backupImage; + } + } + + private FutureListener<BitmapRegionDecoder> mLargeListener = + new FutureListener<BitmapRegionDecoder>() { + @Override + public void onFutureDone(Future<BitmapRegionDecoder> future) { + BitmapRegionDecoder decoder = future.get(); + if (decoder == null) return; + int width = decoder.getWidth(); + int height = decoder.getHeight(); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = BitmapUtils.computeSampleSize( + (float) SIZE_BACKUP / Math.max(width, height)); + Bitmap bitmap = decoder.decodeRegion(new Rect(0, 0, width, height), options); + mHandler.sendMessage(mHandler.obtainMessage( + MSG_UPDATE_IMAGE, new ImageBundle(decoder, bitmap))); + } + }; + + private FutureListener<Bitmap> mThumbListener = + new FutureListener<Bitmap>() { + @Override + public void onFutureDone(Future<Bitmap> future) { + mHandler.sendMessage( + mHandler.obtainMessage(MSG_UPDATE_IMAGE, future)); + } + }; + + @Override + public boolean isEmpty() { + return false; + } + + private void setScreenNail(Bitmap bitmap, int width, int height) { + mBitmapScreenNail = new BitmapScreenNail(bitmap); + setScreenNail(mBitmapScreenNail, width, height); + } + + private void onDecodeLargeComplete(ImageBundle bundle) { + try { + setScreenNail(bundle.backupImage, + bundle.decoder.getWidth(), bundle.decoder.getHeight()); + setRegionDecoder(bundle.decoder); + mPhotoView.notifyImageChange(0); + } catch (Throwable t) { + Log.w(TAG, "fail to decode large", t); + } + } + + private void onDecodeThumbComplete(Future<Bitmap> future) { + try { + Bitmap backup = future.get(); + if (backup == null) { + mLoadingState = LOADING_FAIL; + return; + } else { + mLoadingState = LOADING_COMPLETE; + } + setScreenNail(backup, backup.getWidth(), backup.getHeight()); + mPhotoView.notifyImageChange(0); + } catch (Throwable t) { + Log.w(TAG, "fail to decode thumb", t); + } + } + + @Override + public void resume() { + if (mTask == null) { + if (mHasFullImage) { + mTask = mThreadPool.submit( + mItem.requestLargeImage(), mLargeListener); + } else { + mTask = mThreadPool.submit( + mItem.requestImage(MediaItem.TYPE_THUMBNAIL), + mThumbListener); + } + } + } + + @Override + public void pause() { + Future<?> task = mTask; + task.cancel(); + task.waitDone(); + if (task.get() == null) { + mTask = null; + } + if (mBitmapScreenNail != null) { + mBitmapScreenNail.recycle(); + mBitmapScreenNail = null; + } + } + + @Override + public void moveTo(int index) { + throw new UnsupportedOperationException(); + } + + @Override + public void getImageSize(int offset, PhotoView.Size size) { + if (offset == 0) { + size.width = mItem.getWidth(); + size.height = mItem.getHeight(); + } else { + size.width = 0; + size.height = 0; + } + } + + @Override + public int getImageRotation(int offset) { + return (offset == 0) ? mItem.getFullImageRotation() : 0; + } + + @Override + public ScreenNail getScreenNail(int offset) { + return (offset == 0) ? getScreenNail() : null; + } + + @Override + public void setNeedFullImage(boolean enabled) { + // currently not necessary. + } + + @Override + public boolean isCamera(int offset) { + return false; + } + + @Override + public boolean isPanorama(int offset) { + return false; + } + + @Override + public boolean isStaticCamera(int offset) { + return false; + } + + @Override + public boolean isVideo(int offset) { + return mItem.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO; + } + + @Override + public boolean isDeletable(int offset) { + return (mItem.getSupportedOperations() & MediaItem.SUPPORT_DELETE) != 0; + } + + @Override + public MediaItem getMediaItem(int offset) { + return offset == 0 ? mItem : null; + } + + @Override + public int getCurrentIndex() { + return 0; + } + + @Override + public void setCurrentPhoto(Path path, int indexHint) { + // ignore + } + + @Override + public void setFocusHintDirection(int direction) { + // ignore + } + + @Override + public void setFocusHintPath(Path path) { + // ignore + } + + @Override + public int getLoadingState(int offset) { + return mLoadingState; + } +} |