Преглед изворни кода

Merge pull request #9 from nextcloud/animatedGif

Support animated GiF-Images
Tobias Kaminsky пре 8 година
родитељ
комит
704ffb4bac

+ 81 - 13
src/com/owncloud/android/ui/preview/ImageViewCustom.java

@@ -4,13 +4,18 @@ import android.annotation.SuppressLint;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Movie;
 import android.os.Build;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.ImageView;
 
+import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.common.utils.Log_OC;
 
+import java.io.FileInputStream;
+import java.io.InputStream;
+
 public class ImageViewCustom extends ImageView {
 
     private static final String TAG = ImageViewCustom.class.getSimpleName();
@@ -23,7 +28,12 @@ public class ImageViewCustom extends ImageView {
     private int mBitmapHeight;
     private int mBitmapWidth;
 
-    
+    private Movie mGifMovie;
+    private int mMovieWidth, mMovieHeight;
+    private long mMovieDuration;
+    private long mMovieRunDuration;
+    private long mLastTick;
+
     public ImageViewCustom(Context context) {
         super(context);
     }
@@ -39,18 +49,60 @@ public class ImageViewCustom extends ImageView {
     @SuppressLint("NewApi")
 	@Override
     protected void onDraw(Canvas canvas) {
-
         if(IS_ICS_OR_HIGHER && checkIfMaximumBitmapExceed(canvas) || IS_VERSION_BUGGY_ON_RECYCLES ) {
             // Software type is set with two targets:
             // 1. prevent that bitmaps larger than maximum textures allowed are shown as black views in devices
             //  with LAYER_TYPE_HARDWARE enabled by default;
-            // 2. grant that bitmaps are correctly dellocated from memory in versions suffering the bug fixed in
+            // 2. grant that bitmaps are correctly de-allocated from memory in versions suffering the bug fixed in
             //  https://android.googlesource.com/platform/frameworks/base/+/034de6b1ec561797a2422314e6ef03e3cd3e08e0;
             //
             setLayerType(View.LAYER_TYPE_SOFTWARE, null);
         }
 
-        super.onDraw(canvas);
+        if(mGifMovie != null) {
+            long nowTick = android.os.SystemClock.uptimeMillis();
+            if (mLastTick == 0) {
+                mMovieRunDuration = 0;
+            } else {
+                mMovieRunDuration += nowTick - mLastTick;
+                if(mMovieRunDuration > mMovieDuration) {
+                        mMovieRunDuration = 0;
+                }
+            }
+
+            mGifMovie.setTime((int) mMovieRunDuration);
+
+            float scale = getScaleToViewFactor(mGifMovie, canvas);
+
+            canvas.scale(scale, scale);
+            canvas.translate(((float) getWidth() / scale - (float) mGifMovie.width()) / 2f,
+                    ((float) getHeight() / scale - (float) mGifMovie.height()) /2f);
+
+            mGifMovie.draw(canvas, 0, 0);
+
+            mLastTick = nowTick;
+            invalidate();
+        } else {
+            super.onDraw(canvas);
+        }
+    }
+
+    private float getScaleToViewFactor(Movie movie, Canvas canvas) {
+        if (movie.height() > getHeight() || movie.width() > getWidth()) {
+            float offset = 0.25f;
+            return (1f / Math.min(canvas.getHeight() / movie.height(), canvas.getWidth() / movie.width())) + offset;
+        }
+
+        return Math.min(canvas.getHeight() / movie.height(), canvas.getWidth() / movie.width());
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (mGifMovie == null) {
+            setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
+        } else {
+            setMeasuredDimension(mMovieWidth, mMovieHeight);
+        }
     }
 
     /**
@@ -60,24 +112,40 @@ public class ImageViewCustom extends ImageView {
      */
     @SuppressLint("NewApi")
 	private boolean checkIfMaximumBitmapExceed(Canvas canvas) {
-        Log_OC.v(TAG, "Canvas maximum: " + canvas.getMaximumBitmapWidth() + " - " + canvas.getMaximumBitmapHeight());
-        if (mBitmapWidth > canvas.getMaximumBitmapWidth()
-                || mBitmapHeight > canvas.getMaximumBitmapHeight()) {
-            return true;
-        }
-        
-        return false;
+        return mBitmapWidth > canvas.getMaximumBitmapWidth()
+                || mBitmapHeight > canvas.getMaximumBitmapHeight();
+
     }
     
     @Override
     /**
-     * Keeps the size of the bitmap cached in member variables for faster access in {@link #onDraw(Canvas)} ,
+     * Keeps the size of the bitmap cached in member variables for faster access in {@link #onDraw(Canvas)},
      * but without keeping another reference to the {@link Bitmap}
      */
-    public void setImageBitmap (Bitmap bm) {
+    public void setImageBitmap(Bitmap bm) {
         mBitmapWidth = bm.getWidth();
         mBitmapHeight = bm.getHeight();
         super.setImageBitmap(bm);
     }
 
+    /**
+     * sets the GIF image of the given storage path.
+     *
+     * @param storagePath the storage path of the GIF image
+     */
+    public void setGIFImageFromStoragePath(String storagePath) {
+        try {
+            InputStream gifInputStream = new FileInputStream(storagePath);
+            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+            setFocusable(true);
+
+            mGifMovie = Movie.decodeStream(gifInputStream);
+            mMovieWidth = mGifMovie.width();
+            mMovieHeight = mGifMovie.height();
+            mMovieDuration = mGifMovie.duration();
+        } catch (Exception e) {
+            Log_OC.e(TAG, "Failed to set GIF image");
+        }
+    }
+
 }

+ 7 - 2
src/com/owncloud/android/ui/preview/PreviewImageFragment.java

@@ -499,12 +499,17 @@ public class PreviewImageFragment extends FileFragment {
                 Log_OC.d(TAG, "Showing image with resolution " + bitmap.getWidth() + "x" +
                         bitmap.getHeight());
 
-                if (result.ocFile.getMimetype().equalsIgnoreCase("image/png")){
+                if (result.ocFile.getMimetype().equalsIgnoreCase("image/png")) {
                     Drawable backrepeat = getResources().getDrawable(R.drawable.backrepeat);
                     imageView.setBackground(backrepeat);
                 }
 
-                imageView.setImageBitmap(bitmap);
+                if (result.ocFile.getMimetype().equalsIgnoreCase("image/gif")) {
+                    imageView.setGIFImageFromStoragePath(result.ocFile.getStoragePath());
+                } else {
+                    imageView.setImageBitmap(bitmap);
+                }
+
                 imageView.setVisibility(View.VISIBLE);
                 mBitmap  = bitmap;  // needs to be kept for recycling when not useful
             }