diff options
Diffstat (limited to 'src/com/android/gallery3d/util/GIFView.java')
-rwxr-xr-x | src/com/android/gallery3d/util/GIFView.java | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/util/GIFView.java b/src/com/android/gallery3d/util/GIFView.java new file mode 100755 index 000000000..7bcc52d1b --- /dev/null +++ b/src/com/android/gallery3d/util/GIFView.java @@ -0,0 +1,207 @@ +package com.android.gallery3d.util; + +import org.codeaurora.gallery.R; + +import android.content.Context; +import android.content.ContentResolver; +import android.content.res.AssetManager; +import android.database.Cursor; +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; + + 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(); + } + + 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() { + while (true) { + if (mGifDecoder == null || !isShown() || mRedrawHandler == null) { + break; + } + 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(); + } +} |