blob: 54183e00645f59601d826068aab9f7204f28677d [file] [log] [blame]
/*
* 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 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.PhotoView;
import com.android.gallery3d.ui.PhotoView.ImageData;
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;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
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;
public SinglePhotoDataAdapter(
GalleryActivity 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>() {
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>() {
public void onFutureDone(Future<Bitmap> future) {
mHandler.sendMessage(
mHandler.obtainMessage(MSG_UPDATE_IMAGE, future));
}
};
public boolean isEmpty() {
return false;
}
public int getImageRotation() {
return mItem.getRotation();
}
private void onDecodeLargeComplete(ImageBundle bundle) {
try {
setBackupImage(bundle.backupImage,
bundle.decoder.getWidth(), bundle.decoder.getHeight());
setRegionDecoder(bundle.decoder);
mPhotoView.notifyImageInvalidated(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) return;
setBackupImage(backup, backup.getWidth(), backup.getHeight());
mPhotoView.notifyOnNewImage();
mPhotoView.notifyImageInvalidated(0); // the current image
} catch (Throwable t) {
Log.w(TAG, "fail to decode thumb", t);
}
}
public void resume() {
if (mTask == null) {
if (mHasFullImage) {
mTask = mThreadPool.submit(
mItem.requestLargeImage(), mLargeListener);
} else {
mTask = mThreadPool.submit(
mItem.requestImage(MediaItem.TYPE_THUMBNAIL),
mThumbListener);
}
}
}
public void pause() {
Future<?> task = mTask;
task.cancel();
task.waitDone();
if (task.get() == null) {
mTask = null;
}
}
public ImageData getNextImage() {
return null;
}
public ImageData getPreviousImage() {
return null;
}
public void next() {
throw new UnsupportedOperationException();
}
public void previous() {
throw new UnsupportedOperationException();
}
public MediaItem getCurrentMediaItem() {
return mItem;
}
public int getCurrentIndex() {
return 0;
}
public void setCurrentPhoto(Path path, int indexHint) {
// ignore
}
}