Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 81 additions & 13 deletions src/com/owncloud/android/ui/preview/ImageViewCustom.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
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();
Expand All @@ -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);
}
Expand All @@ -39,18 +49,60 @@ public ImageViewCustom(Context context, AttributeSet attrs, int defStyle) {
@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);
}
}

/**
Expand All @@ -60,24 +112,40 @@ protected void onDraw(Canvas canvas) {
*/
@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");
}
}

}
9 changes: 7 additions & 2 deletions src/com/owncloud/android/ui/preview/PreviewImageFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -499,12 +499,17 @@ private void showLoadedImage(LoadImage result) {
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
}
Expand Down