Gallery2: Play gif photo directly in photopage
Implement new feature: Remove play icon and play the gif photo directly
Change-Id: I95f82ca8ab912a98a5120ce2c01fe2fe33c9a875
CRs-Fixed: 987942
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 08ca742..1eda90b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+<!-- Copyright (c) 2010-2014, 2016, The Linux Foundation. All rights reserved.
Not a Contribution.
Copyright (C) 2007 The Android Open Source Project
@@ -328,16 +328,6 @@
android:theme="@style/Theme.Gallery"
android:configChanges="orientation|keyboardHidden|screenSize" />
- <activity android:name="com.android.gallery3d.util.ViewGifImage"
- android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
- android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation">
- <intent-filter>
- <action android:name="com.android.gallery3d.VIEW_GIF" />
- <data android:mimeType="image/gif" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
<provider android:name="com.android.gallery3d.provider.GalleryProvider"
android:syncable="false"
android:grantUriPermissions="true"
diff --git a/res/layout/view_gif_image.xml b/res/layout/view_gif_image.xml
deleted file mode 100644
index 976549a..0000000
--- a/res/layout/view_gif_image.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:id="@+id/image_absoluteLayout"
- android:layout_height="match_parent"
- android:layout_width="match_parent">
- <ImageView android:id="@+id/image_display_area"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:clickable="true">
- </ImageView>
- </LinearLayout>
-
-</RelativeLayout>
diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java
index aa28b55..d65c0d1 100755
--- a/src/com/android/gallery3d/app/PhotoDataAdapter.java
+++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java
@@ -34,6 +34,7 @@
import com.android.gallery3d.data.Path;
import com.android.gallery3d.data.SnailItem;
import com.android.gallery3d.glrenderer.TiledTexture;
+import com.android.gallery3d.ui.BitmapScreenNail;
import com.android.gallery3d.ui.PhotoView;
import com.android.gallery3d.ui.ScreenNail;
import com.android.gallery3d.ui.SynchronizedHandler;
@@ -41,11 +42,14 @@
import com.android.gallery3d.ui.TiledScreenNail;
import com.android.gallery3d.util.Future;
import com.android.gallery3d.util.FutureListener;
+import com.android.gallery3d.util.GifDecoder;
+import com.android.gallery3d.util.GifRequest;
import com.android.gallery3d.util.MediaSetUtils;
import com.android.gallery3d.util.ThreadPool;
import com.android.gallery3d.util.ThreadPool.Job;
import com.android.gallery3d.util.ThreadPool.JobContext;
+import java.lang.Exception;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -71,6 +75,7 @@
private static final int BIT_SCREEN_NAIL = 1;
private static final int BIT_FULL_IMAGE = 2;
+ private static final int BIT_GIF_ANIMATION = 3;
private static final long NOTIFY_DIRTY_WAIT_TIME = 10;
// sImageFetchSeq is the fetching sequence for images.
@@ -91,7 +96,7 @@
static {
int k = 0;
- sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 3];
+ sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 4];
sImageFetchSeq[k++] = new ImageFetch(0, BIT_SCREEN_NAIL);
for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) {
@@ -102,6 +107,7 @@
sImageFetchSeq[k++] = new ImageFetch(0, BIT_FULL_IMAGE);
sImageFetchSeq[k++] = new ImageFetch(1, BIT_FULL_IMAGE);
sImageFetchSeq[k++] = new ImageFetch(-1, BIT_FULL_IMAGE);
+ sImageFetchSeq[k++] = new ImageFetch(0, BIT_GIF_ANIMATION);
}
private final TileImageViewAdapter mTileProvider = new TileImageViewAdapter();
@@ -160,6 +166,7 @@
private boolean mNeedFullImage;
private int mFocusHintDirection = FOCUS_HINT_NEXT;
private Path mFocusHintPath = null;
+ private AbstractGalleryActivity mActivity;
// If Bundle is from widget, it's true, otherwise it's false.
private boolean mIsFromWidget = false;
@@ -181,6 +188,7 @@
public PhotoDataAdapter(AbstractGalleryActivity activity, PhotoView view,
MediaSet mediaSet, Path itemPath, int indexHint, int cameraIndex,
boolean isPanorama, boolean isStaticCamera) {
+ mActivity = activity;
mSource = Utils.checkNotNull(mediaSet);
mPhotoView = Utils.checkNotNull(view);
mItemPath = Utils.checkNotNull(itemPath);
@@ -470,6 +478,8 @@
ImageEntry entry = mImageCache.get(item.getPath());
if (entry == null) return null;
+ ScreenNail targetScreenNail = getTargetScreenNail(entry);
+ if (targetScreenNail != null) return targetScreenNail;
// Create a default ScreenNail if the real one is not available yet,
// except for camera that a black screen is better than a gray tile.
if (entry.screenNail == null && !isCamera(offset)) {
@@ -631,7 +641,7 @@
}
private void updateTileProvider(ImageEntry entry) {
- ScreenNail screenNail = entry.screenNail;
+ ScreenNail screenNail = getTargetScreenNail(entry);
BitmapRegionDecoder fullImage = entry.fullImage;
if (screenNail != null) {
if (fullImage != null) {
@@ -648,6 +658,15 @@
}
}
+
+ private ScreenNail getTargetScreenNail(ImageEntry entry) {
+ if (null == entry) return null;
+ if (null != entry.currentGifFrame){
+ return entry.currentGifFrame;
+ }
+ return entry.screenNail;
+ }
+
private void updateSlidingWindow() {
// 1. Update the image window
int start = Utils.clamp(mCurrentIndex - IMAGE_CACHE_SIZE / 2,
@@ -733,6 +752,12 @@
entry.fullImageTask = null;
entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION;
}
+
+ if (entry.gifDecoderTask != null && entry.gifDecoderTask != task) {
+ entry.gifDecoderTask.cancel();
+ entry.gifDecoderTask = null;
+ entry.requestedGif = MediaObject.INVALID_DATA_VERSION;
+ }
}
}
@@ -782,6 +807,23 @@
}
}
+
+ private class GifDecoderJob implements Job<GifDecoder> {
+ private MediaItem mItem;
+
+ public GifDecoderJob(MediaItem item) {
+ mItem = item;
+ }
+
+ @Override
+ public GifDecoder run(JobContext jc) {
+ if (isTemporaryItem(mItem)) {
+ return null;
+ }
+ return new GifRequest(mItem.getContentUri(), mActivity).run(jc);
+ }
+ }
+
// Returns true if we think this is a temporary item created by Camera. A
// temporary item is an image or a video whose data is still being
// processed, but an incomplete entry is created first in MediaProvider, so
@@ -830,6 +872,9 @@
} else if (which == BIT_FULL_IMAGE && entry.fullImageTask != null
&& entry.requestedFullImage == version) {
return entry.fullImageTask;
+ } else if (which == BIT_GIF_ANIMATION && entry.gifDecoderTask != null
+ && entry.requestedGif == version) {
+ return entry.gifDecoderTask;
}
if (which == BIT_SCREEN_NAIL && entry.requestedScreenNail != version) {
@@ -850,6 +895,18 @@
// request full image
return entry.fullImageTask;
}
+
+ if (which == BIT_GIF_ANIMATION
+ && (entry.requestedGif != version)
+ && isGif(0)) {
+ entry.requestedGif = version;
+ entry.gifDecoderTask = mThreadPool.submit(
+ new GifDecoderJob(item),
+ new GifDecoderListener(item.getPath()));
+ // request gif decoder
+ return entry.gifDecoderTask;
+ }
+
return null;
}
@@ -879,6 +936,20 @@
item.getWidth(), item.getHeight());
}
}
+
+ if (Math.abs(i - mCurrentIndex) > 0) {
+ if (entry.gifDecoderTask != null) {
+ entry.gifDecoderTask.cancel();
+ entry.gifDecoderTask = null;
+ }
+ entry.gifDecoder = null;
+ entry.requestedGif = MediaItem.INVALID_DATA_VERSION;
+ if (null != entry.currentGifFrame) {
+ //recycle cached gif frame
+ entry.currentGifFrame.recycle();
+ entry.currentGifFrame = null;
+ }
+ }
} else {
entry = new ImageEntry();
mImageCache.put(path, entry);
@@ -940,6 +1011,158 @@
}
}
+ private class GifDecoderListener
+ implements Runnable, FutureListener<GifDecoder> {
+ private final Path mPath;
+ private Future<GifDecoder> mFuture;
+
+ public GifDecoderListener(Path path) {
+ mPath = path;
+ }
+
+ @Override
+ public void onFutureDone(Future<GifDecoder> future) {
+ mFuture = future;
+ if (null != mFuture.get()) {
+ mMainHandler.sendMessage(
+ mMainHandler.obtainMessage(MSG_RUN_OBJECT, this));
+ }
+ }
+
+ @Override
+ public void run() {
+ updateGifDecoder(mPath, mFuture);
+ }
+ }
+
+ private void updateGifDecoder(Path path,
+ Future<GifDecoder> future) {
+
+ ImageEntry entry = mImageCache.get(path);
+ if (entry == null || entry.gifDecoderTask != future) {
+ return;
+ }
+
+ entry.gifDecoderTask = null;
+ entry.gifDecoder = future.get();
+
+ playGif(path);
+ updateImageRequests();
+
+ }
+
+ private void playGif(Path path) {
+ ImageEntry entry = mImageCache.get(path);
+ if (null == entry) return;
+ if (entry.gifDecoder != null && entry.gifDecoder.getFrameCount() != 0) {
+ if (entry.gifDecoder.mWidth <= 0 || entry.gifDecoder.mHeight <= 0) {
+ return;
+ }
+
+ int currentIndex = mCurrentIndex;
+ if (path == getPath(currentIndex)) {
+ GifEntry gifEntry = new GifEntry();
+ gifEntry.gifDecoder = entry.gifDecoder;
+ gifEntry.animatedIndex = currentIndex;
+ gifEntry.entry = entry;
+
+ mMainHandler.sendMessage(
+ mMainHandler.obtainMessage(MSG_RUN_OBJECT,
+ new GifRunnable(path, gifEntry)));
+ }
+ }
+ }
+
+ private class GifRunnable implements Runnable {
+
+ private GifEntry mGifEntry;
+ private Path mPath;
+
+ private void free() {
+ if (null != mGifEntry.gifDecoder) {
+ mGifEntry.gifDecoder.free();
+ mGifEntry.gifDecoder = null;
+ }
+
+ if (null != mGifEntry) {
+ mGifEntry = null;
+ }
+ }
+
+ public GifRunnable(Path path, GifEntry gifEntry) {
+ mPath = path;
+ mGifEntry = gifEntry;
+ if (null == mGifEntry || null == mGifEntry.gifDecoder) {
+ free();
+ return;
+ }
+ boolean imageChanged = mGifEntry.animatedIndex != mCurrentIndex;
+ MediaItem item = getMediaItem(0);
+ Path currentPath = (item != null ? item.getPath() : null);
+ imageChanged |= path != currentPath;
+ if (imageChanged) {
+ free();
+ return;
+ }
+ mGifEntry.currentFrame = 0;
+ mGifEntry.totalFrameCount = mGifEntry.gifDecoder.getFrameCount();
+ if (mGifEntry.totalFrameCount <= 1) {
+ free();
+ return;
+ }
+ }
+
+ @Override
+ public void run() {
+ if (!mIsActive) {
+ free();
+ return;
+ }
+
+ if (null == mGifEntry || null == mGifEntry.gifDecoder) {
+ free();
+ return;
+ }
+
+ boolean imageChanged = mGifEntry.animatedIndex != mCurrentIndex;
+ MediaItem item = getMediaItem(0);
+ Path currentPath = (item != null ? item.getPath() : null);
+ imageChanged |= mPath != currentPath;
+ if (imageChanged) {
+ free();
+ return;
+ }
+
+ Bitmap frameBitmap = mGifEntry.gifDecoder.getFrameImage(mGifEntry.currentFrame);
+ if (null == frameBitmap) {
+ free();
+ return;
+ }
+ long delay = (long) mGifEntry.gifDecoder.getDelay(mGifEntry.currentFrame);
+ mGifEntry.currentFrame = (mGifEntry.currentFrame + 1) % mGifEntry.totalFrameCount;
+
+ ScreenNail gifFrame = new BitmapScreenNail(frameBitmap);
+ if (mGifEntry.entry.currentGifFrame != null) {
+ mGifEntry.entry.currentGifFrame.recycle();
+ mGifEntry.entry.currentGifFrame = null;
+ }
+ mGifEntry.entry.currentGifFrame = gifFrame;
+ updateTileProvider(mGifEntry.entry);
+ mPhotoView.notifyImageChange(0);
+ mMainHandler.sendMessageDelayed(
+ mMainHandler.obtainMessage(MSG_RUN_OBJECT, this), delay);
+ }
+ }
+
+
+ private static class GifEntry {
+ public ImageEntry entry;
+ public GifDecoder gifDecoder;
+ public int animatedIndex;
+ public int currentFrame;
+ public int totalFrameCount;
+ }
+
private static class ImageEntry {
public BitmapRegionDecoder fullImage;
public ScreenNail screenNail;
@@ -948,6 +1171,11 @@
public long requestedScreenNail = MediaObject.INVALID_DATA_VERSION;
public long requestedFullImage = MediaObject.INVALID_DATA_VERSION;
public boolean failToLoad = false;
+
+ public GifDecoder gifDecoder;
+ public Future<GifDecoder> gifDecoderTask;
+ public ScreenNail currentGifFrame;
+ public long requestedGif = MediaObject.INVALID_DATA_VERSION;
}
private class SourceListener implements ContentListener {
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
index deb3b85..7bda6dc 100644
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ b/src/com/android/gallery3d/app/PhotoPage.java
@@ -78,7 +78,6 @@
import com.android.gallery3d.ui.SynchronizedHandler;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.UsageStatistics;
-import com.android.gallery3d.util.ViewGifImage;
import java.util.ArrayList;
import java.util.Locale;
@@ -1275,10 +1274,6 @@
// item is not ready or it is camera preview, ignore
return;
}
- if (item.getMimeType().equals(MediaItem.MIME_TYPE_GIF)) {
- viewAnimateGif((Activity) mActivity, item.getContentUri());
- return;
- }
int supported = item.getSupportedOperations();
boolean playVideo = ((supported & MediaItem.SUPPORT_PLAY) != 0);
@@ -1738,12 +1733,4 @@
}
}
- private static void viewAnimateGif(Activity activity, Uri uri) {
- Intent intent = new Intent(ViewGifImage.VIEW_GIF_ACTION, uri);
- String scheme = uri.getScheme();
- if ("file".equals(scheme)) {
- intent.setDataAndType(uri, "image/gif");
- }
- activity.startActivity(intent);
- }
}
diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java
index 6e1c662..2282290 100644
--- a/src/com/android/gallery3d/ui/PhotoView.java
+++ b/src/com/android/gallery3d/ui/PhotoView.java
@@ -736,7 +736,7 @@
canvas.translate((int) (cx + 0.5f), (int) (cy + 0.5f));
int s = (int) (scale * Math.min(r.width(), r.height()) + 0.5f);
//Full pic locates at index 0 of the array in PhotoDataAdapter
- if (mModel.isVideo(0) || mModel.isGif(0)) {
+ if (mModel.isVideo(0)) {
drawVideoPlayIcon(canvas, s);
}
if (mLoadingState == Model.LOADING_FAIL ) {
@@ -866,7 +866,7 @@
invalidate();
}
int s = Math.min(drawW, drawH);
- if (mModel.isVideo(mIndex) || mModel.isGif(mIndex)) {
+ if (mModel.isVideo(mIndex)) {
drawVideoPlayIcon(canvas, s);
}
diff --git a/src/com/android/gallery3d/util/GIFView.java b/src/com/android/gallery3d/util/GIFView.java
deleted file mode 100644
index 6c6c49b..0000000
--- a/src/com/android/gallery3d/util/GIFView.java
+++ /dev/null
@@ -1,234 +0,0 @@
-package com.android.gallery3d.util;
-
-import com.android.gallery3d.R;
-
-import android.content.Context;
-import android.content.ContentResolver;
-import android.content.res.AssetManager;
-import android.database.Cursor;
-//import android.drm.DrmHelper;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-import android.widget.ImageView;
-import android.widget.Toast;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.IOException;
-
-public class GIFView extends ImageView implements GifAction {
-
- private static final String TAG = "GIFView";
- private static final float SCALE_LIMIT = 4;
- private static final long FRAME_DELAY = 200; //milliseconds
-
- private GifDecoder mGifDecoder = null;
- private Bitmap mCurrentImage = null;
- private DrawThread mDrawThread = null;
-
- private Uri mUri;
- private Context mContext;
-
- public GIFView(Context context) {
- super(context);
- mContext = context;
- }
-
- public boolean setDrawable(Uri uri) {
- if (null == uri) {
- return false;
- }
- mUri = uri;
-
- // Let decode the GIF image from byte stream instead of file stream
-// String filepath = DrmHelper.getFilePath(mContext, mUri);
-// if (DrmHelper.isDrmFile(filepath)) {
-// byte[] bytes = DrmHelper.getDrmImageBytes(filepath);
-// DrmHelper.manageDrmLicense(mContext, this.getHandler(), filepath,
-// "image/gif");
-// if (bytes == null) {
-// return false;
-// }
-// startDecode(bytes);
-// return true;
-// }
-
- InputStream is = getInputStream(uri);
- if (is == null || (getFileSize (is) == 0)) {
- return false;
- }
- startDecode(is);
- return true;
- }
-
- private int getFileSize (InputStream is) {
- if(is == null) return 0;
-
- int size = 0;
- try {
- if (is instanceof FileInputStream) {
- FileInputStream f = (FileInputStream) is;
- size = (int) f.getChannel().size();
- } else {
- while (-1 != is.read()) {
- size++;
- }
- }
-
- } catch (IOException e) {
- Log.e(TAG, "catch exception:" + e);
- }
-
- return size;
-
- }
-
- private InputStream getInputStream (Uri uri) {
- ContentResolver cr = mContext.getContentResolver();
- InputStream input = null;
- try {
- input = cr.openInputStream(uri);
- } catch (IOException e) {
- Log.e(TAG, "catch exception:" + e);
- }
- return input;
- }
-
- private void startDecode(InputStream is) {
- freeGifDecoder();
- mGifDecoder = new GifDecoder(is, this);
- mGifDecoder.start();
- }
-
- private void startDecode(byte[] bytes) {
- freeGifDecoder();
- mGifDecoder = new GifDecoder(bytes, this);
- mGifDecoder.start();
- }
-
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mGifDecoder == null) {
- return;
- }
-
- if (mCurrentImage == null) {
- mCurrentImage = mGifDecoder.getImage();
- }
- if (mCurrentImage == null) {
- // if this gif can not be displayed, just try to show it as jpg by parsing mUri
- setImageURI(mUri);
- return;
- }
- setImageURI(null);
- int saveCount = canvas.getSaveCount();
- canvas.save();
- canvas.translate(getPaddingLeft(), getPaddingTop());
- Rect sRect = null;
- Rect dRect = null;
-
- int imageHeight = mCurrentImage.getHeight();
- int imageWidth = mCurrentImage.getWidth();
-
- int displayHeight = ViewGifImage.mDM.heightPixels;
- int displayWidth = ViewGifImage.mDM.widthPixels;
-
- int width, height;
- if (imageWidth >= displayWidth || imageHeight >= displayHeight) {
- // scale-down the image
- if (imageWidth * displayHeight > displayWidth * imageHeight) {
- width = displayWidth;
- height = (imageHeight * width) / imageWidth;
- } else {
- height = displayHeight;
- width = (imageWidth * height) / imageHeight;
- }
- } else {
- // scale-up the image
- float scale = Math.min(SCALE_LIMIT, Math.min(displayWidth / (float) imageWidth,
- displayHeight / (float) imageHeight));
- width = (int) (imageWidth * scale);
- height = (int) (imageHeight * scale);
- }
- dRect = new Rect((displayWidth - width) / 2, (displayHeight - height) / 2,
- (displayWidth + width) / 2, (displayHeight + height) / 2);
- canvas.drawBitmap(mCurrentImage, sRect, dRect, null);
- canvas.restoreToCount(saveCount);
- }
-
- public void parseOk(boolean parseStatus, int frameIndex) {
- if (parseStatus) {
- //indicates the start of a new GIF
- if (mGifDecoder != null && frameIndex == -1
- && mGifDecoder.getFrameCount() > 1) {
- if (mDrawThread != null) {
- mDrawThread = null;
- }
- mDrawThread = new DrawThread();
- mDrawThread.start();
- }
- } else {
- Log.e(TAG, "parse error");
- }
- }
-
- private Handler mRedrawHandler = new Handler() {
- public void handleMessage(Message msg) {
- invalidate();
- }
- };
-
- private class DrawThread extends Thread {
- public void run() {
- if (mGifDecoder == null) {
- return;
- }
-
- while (true) {
- if (!isShown() || mRedrawHandler == null) {
- break;
- }
- if (mGifDecoder == null) {
- return;
- }
- GifFrame frame = mGifDecoder.next();
- mCurrentImage = frame.mImage;
-
- Message msg = mRedrawHandler.obtainMessage();
- mRedrawHandler.sendMessage(msg);
- try {
- Thread.sleep(getDelay(frame));
- } catch (InterruptedException e) {
- Log.e(TAG, "catch exception:" + e);
- }
- }
- }
-
- }
-
- private long getDelay (GifFrame frame) {
- //in milliseconds
- return frame.mDelayInMs == 0 ? FRAME_DELAY : frame.mDelayInMs;
- }
-
- private void freeGifDecoder () {
- if (mGifDecoder != null) {
- mGifDecoder.free();
- mGifDecoder = null;
- }
-
- }
-
- public void freeMemory() {
- if (mDrawThread != null) {
- mDrawThread = null;
- }
- freeGifDecoder();
- }
-}
diff --git a/src/com/android/gallery3d/util/GifDecoder.java b/src/com/android/gallery3d/util/GifDecoder.java
index 4235fc5..1342355 100755
--- a/src/com/android/gallery3d/util/GifDecoder.java
+++ b/src/com/android/gallery3d/util/GifDecoder.java
@@ -7,7 +7,7 @@
import java.io.ByteArrayInputStream;
import java.io.InputStream;
-public class GifDecoder extends Thread {
+public class GifDecoder {
public static final int STATUS_PARSING = 0;
public static final int STATUS_FORMAT_ERROR = 1;
@@ -71,14 +71,16 @@
public GifDecoder(byte[] data, GifAction act) {
mGifData = data;
mGifAction = act;
+ startDecoder();
}
public GifDecoder(InputStream is, GifAction act) {
mIS = is;
mGifAction = act;
+ startDecoder();
}
- public void run() {
+ public void startDecoder() {
if (mIS != null) {
readStream();
} else if (mGifData != null) {
@@ -295,10 +297,14 @@
readContents();
if (mFrameCount < 0) {
mStatus = STATUS_FORMAT_ERROR;
- mGifAction.parseOk(false, -1);
+ if (mGifAction != null) {
+ mGifAction.parseOk(false, -1);
+ }
} else {
mStatus = STATUS_FINISH;
- mGifAction.parseOk(true, -1);
+ if (mGifAction != null) {
+ mGifAction.parseOk(true, -1);
+ }
}
}
try {
@@ -308,7 +314,9 @@
}
} else {
mStatus = STATUS_OPEN_ERROR;
- mGifAction.parseOk(false, -1);
+ if (mGifAction != null) {
+ mGifAction.parseOk(false, -1);
+ }
}
return mStatus;
}
@@ -624,7 +632,9 @@
mAct[mTransIndex] = save;
}
resetFrame();
- mGifAction.parseOk(true, mFrameCount);
+ if (mGifAction != null) {
+ mGifAction.parseOk(true, mFrameCount);
+ }
} catch (OutOfMemoryError e) {
Log.e("GifDecoder", ">>> log : " + e.toString());
e.printStackTrace();
diff --git a/src/com/android/gallery3d/util/GifRequest.java b/src/com/android/gallery3d/util/GifRequest.java
new file mode 100755
index 0000000..ea928ad
--- /dev/null
+++ b/src/com/android/gallery3d/util/GifRequest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.util;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.gallery3d.util.ThreadPool.Job;
+import com.android.gallery3d.util.ThreadPool.JobContext;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+
+public class GifRequest implements Job<GifDecoder> {
+
+ private static final String TAG = "GifRequest";
+ Uri itemUri;
+ Context mContext;
+
+ public GifRequest(Uri uri, Context context) {
+ itemUri = uri;
+ mContext = context;
+ }
+
+ private InputStream getInputStream(Uri uri) {
+ ContentResolver cr = mContext.getContentResolver();
+ InputStream input = null;
+ try {
+ input = cr.openInputStream(uri);
+ } catch (IOException e) {
+ Log.e(TAG, "catch exception:" + e);
+ }
+ return input;
+ }
+
+ @Override
+ public GifDecoder run(JobContext jc) {
+ InputStream input = getInputStream(itemUri);
+ if (input != null) {
+ return new GifDecoder(getInputStream(itemUri), null);
+ } else {
+ return null;
+ }
+ }
+
+
+}
+
diff --git a/src/com/android/gallery3d/util/ViewGifImage.java b/src/com/android/gallery3d/util/ViewGifImage.java
deleted file mode 100755
index cdd5092..0000000
--- a/src/com/android/gallery3d/util/ViewGifImage.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.android.gallery3d.util;
-
-import com.android.gallery3d.R;
-
-import android.app.Activity;
-import android.content.res.Configuration;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.util.DisplayMetrics;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-public class ViewGifImage extends Activity {
- private static final String TAG = "ViewGifImage";
- public static final String VIEW_GIF_ACTION = "com.android.gallery3d.VIEW_GIF";
-
- public static DisplayMetrics mDM;
-
- private ImageView mGifView;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.view_gif_image);
- mDM = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(mDM);
- if (getIntent().getAction() != null
- && getIntent().getAction().equals(VIEW_GIF_ACTION)) {
- Uri gifUri = getIntent().getData();
- showGifPicture(gifUri);
- }
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- finish();
- }
-
- @Override
- protected void onDestroy() {
- if (mGifView != null && mGifView instanceof GIFView) {
- ((GIFView) mGifView).freeMemory();
- mGifView = null;
- }
- super.onDestroy();
- }
-
- private void showGifPicture(Uri uri) {
- mGifView = new GIFView(this);
- ((LinearLayout) findViewById(R.id.image_absoluteLayout)).addView(mGifView,
- new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- if (((GIFView) mGifView).setDrawable(uri)) return;
-
- finish();
-
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- getWindowManager().getDefaultDisplay().getMetrics(mDM);
- super.onConfigurationChanged(newConfig);
- }
-}