diff options
| author | huiyan <huiyan@codeaurora.org> | 2016-03-21 14:55:31 +0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-03-27 23:05:40 -0700 |
| commit | cba2c073700990bea194ee14ff3eac76fc31b42b (patch) | |
| tree | 25b8ca092add9010b784372a66e47b887fc67f13 | |
| parent | 7f8e26df135b81971e409ce36c4aacce7b6cab58 (diff) | |
| download | android_packages_apps_Gallery2-cba2c073700990bea194ee14ff3eac76fc31b42b.tar.gz android_packages_apps_Gallery2-cba2c073700990bea194ee14ff3eac76fc31b42b.tar.bz2 android_packages_apps_Gallery2-cba2c073700990bea194ee14ff3eac76fc31b42b.zip | |
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
| -rw-r--r-- | AndroidManifest.xml | 12 | ||||
| -rw-r--r-- | res/layout/view_gif_image.xml | 17 | ||||
| -rwxr-xr-x | src/com/android/gallery3d/app/PhotoDataAdapter.java | 232 | ||||
| -rw-r--r-- | src/com/android/gallery3d/app/PhotoPage.java | 13 | ||||
| -rw-r--r-- | src/com/android/gallery3d/ui/PhotoView.java | 4 | ||||
| -rw-r--r-- | src/com/android/gallery3d/util/GIFView.java | 234 | ||||
| -rwxr-xr-x | src/com/android/gallery3d/util/GifDecoder.java | 22 | ||||
| -rwxr-xr-x | src/com/android/gallery3d/util/GifRequest.java | 78 | ||||
| -rwxr-xr-x | src/com/android/gallery3d/util/ViewGifImage.java | 67 |
9 files changed, 327 insertions, 352 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 08ca742e0..1eda90bf7 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 976549a6b..000000000 --- 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 aa28b5557..d65c0d1c8 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.MediaSet; 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.TileImageViewAdapter; 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { 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 class PhotoDataAdapter implements PhotoPage.Model { 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { } 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { } } + + 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { } } + + 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { } 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { // 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { 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 @@ public class PhotoDataAdapter implements PhotoPage.Model { } } + 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 class PhotoDataAdapter implements PhotoPage.Model { 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 deb3b855c..7bda6dc16 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.SelectionManager; 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 @@ public abstract class PhotoPage extends ActivityState implements // 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 @@ public abstract class PhotoPage extends ActivityState implements } } - 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 6e1c662c4..228229006 100644 --- a/src/com/android/gallery3d/ui/PhotoView.java +++ b/src/com/android/gallery3d/ui/PhotoView.java @@ -736,7 +736,7 @@ public class PhotoView extends GLView { 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 @@ public class PhotoView extends GLView { 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 6c6c49b95..000000000 --- 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 4235fc5a5..1342355e6 100755 --- a/src/com/android/gallery3d/util/GifDecoder.java +++ b/src/com/android/gallery3d/util/GifDecoder.java @@ -7,7 +7,7 @@ import android.util.Log; 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 class GifDecoder extends Thread { 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 @@ public class GifDecoder extends Thread { 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 @@ public class GifDecoder extends Thread { } } else { mStatus = STATUS_OPEN_ERROR; - mGifAction.parseOk(false, -1); + if (mGifAction != null) { + mGifAction.parseOk(false, -1); + } } return mStatus; } @@ -624,7 +632,9 @@ public class GifDecoder extends Thread { 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 000000000..ea928ad91 --- /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 cdd509280..000000000 --- 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); - } -} |
