summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/filtershow
diff options
context:
space:
mode:
authornicolasroard <nicolasroard@google.com>2013-08-23 00:10:01 -0700
committernicolasroard <nicolasroard@google.com>2013-08-27 00:47:43 -0700
commit9f452e09889199a28a86d9bd8f8fdaa8508ca0c1 (patch)
treed2dc35313a9467fc23e7db308da67be07985aba9 /src/com/android/gallery3d/filtershow
parent0594bd40959aaa55ec4f4204fbe3d12240f51480 (diff)
downloadandroid_packages_apps_Gallery2-9f452e09889199a28a86d9bd8f8fdaa8508ca0c1.tar.gz
android_packages_apps_Gallery2-9f452e09889199a28a86d9bd8f8fdaa8508ca0c1.tar.bz2
android_packages_apps_Gallery2-9f452e09889199a28a86d9bd8f8fdaa8508ca0c1.zip
Improves UI / size
- improves overdraw - filter change anim - better borders - remove unused images bug:9470514 bug:8658176 Change-Id: I764879be415acbfba5a36f239d1905ec54e2d3cb
Diffstat (limited to 'src/com/android/gallery3d/filtershow')
-rw-r--r--src/com/android/gallery3d/filtershow/EditorPlaceHolder.java2
-rw-r--r--src/com/android/gallery3d/filtershow/FilterShowActivity.java38
-rw-r--r--src/com/android/gallery3d/filtershow/cache/BitmapCache.java2
-rw-r--r--src/com/android/gallery3d/filtershow/category/CategorySelected.java27
-rw-r--r--src/com/android/gallery3d/filtershow/category/CategoryView.java6
-rw-r--r--src/com/android/gallery3d/filtershow/editors/Editor.java3
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java26
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java26
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageShow.java203
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/MasterImage.java125
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java4
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java62
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java3
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java36
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java10
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java8
16 files changed, 512 insertions, 69 deletions
diff --git a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java b/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
index 95abce114..95fc56d4f 100644
--- a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
+++ b/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
@@ -45,7 +45,7 @@ public class EditorPlaceHolder {
}
editor.createEditor(mActivity, mContainer);
- editor.getImageShow().bindAsImageLoadListener();
+ editor.getImageShow().attach();
mContainer.setVisibility(View.VISIBLE);
mContainer.removeAllViews();
View eview = editor.getTopLevelView();
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index c3a5e15ff..c7e9cc68d 100644
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -32,6 +32,7 @@ import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
@@ -66,6 +67,7 @@ import com.android.gallery3d.data.LocalAlbum;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.category.Action;
import com.android.gallery3d.filtershow.category.CategoryAdapter;
+import com.android.gallery3d.filtershow.category.CategorySelected;
import com.android.gallery3d.filtershow.category.CategoryView;
import com.android.gallery3d.filtershow.category.MainPanel;
import com.android.gallery3d.filtershow.category.SwipableView;
@@ -136,6 +138,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
private View mSaveButton = null;
private EditorPlaceHolder mEditorPlaceHolder = new EditorPlaceHolder(this);
+ private Editor mCurrentEditor = null;
private static final int SELECT_PICTURE = 1;
private static final String LOGTAG = "FilterShowActivity";
@@ -364,6 +367,8 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
ActionBar actionBar = getActionBar();
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
actionBar.setCustomView(R.layout.filtershow_actionbar);
+ actionBar.setBackgroundDrawable(new ColorDrawable(
+ getResources().getColor(R.color.background_screen)));
mSaveButton = actionBar.getCustomView();
mSaveButton.setOnClickListener(new OnClickListener() {
@@ -600,6 +605,11 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
&& MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) {
return;
}
+ if (filterRepresentation instanceof FilterUserPresetRepresentation
+ || filterRepresentation instanceof FilterRotateRepresentation
+ || filterRepresentation instanceof FilterMirrorRepresentation) {
+ MasterImage.getImage().onNewLook(filterRepresentation);
+ }
ImagePreset oldPreset = MasterImage.getImage().getPreset();
ImagePreset copy = new ImagePreset(oldPreset);
FilterRepresentation representation = copy.getRepresentation(filterRepresentation);
@@ -639,7 +649,10 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
useFilterRepresentation(representation);
// show representation
- Editor mCurrentEditor = mEditorPlaceHolder.showEditor(representation.getEditorId());
+ if (mCurrentEditor != null) {
+ mCurrentEditor.detach();
+ }
+ mCurrentEditor = mEditorPlaceHolder.showEditor(representation.getEditorId());
loadEditorPanel(representation, mCurrentEditor);
hideInformationPanel();
}
@@ -1358,4 +1371,27 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
}
return super.dispatchTouchEvent(ev);
}
+
+ public void startTouchAnimation(View target, float x, float y) {
+ final CategorySelected hint =
+ (CategorySelected) findViewById(R.id.categorySelectedIndicator);
+ int location[] = new int[2];
+ target.getLocationOnScreen(location);
+ int locationHint[] = new int[2];
+ ((View)hint.getParent()).getLocationOnScreen(locationHint);
+ int dx = (int) (x - (hint.getWidth())/2);
+ int dy = (int) (y - (hint.getHeight())/2);
+ hint.setTranslationX(location[0] - locationHint[0] + dx);
+ hint.setTranslationY(location[1] - locationHint[1] + dy);
+ hint.setVisibility(View.VISIBLE);
+ hint.animate().scaleX(2).scaleY(2).alpha(0).withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ hint.setVisibility(View.INVISIBLE);
+ hint.setScaleX(1);
+ hint.setScaleY(1);
+ hint.setAlpha(1);
+ }
+ });
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/cache/BitmapCache.java b/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
index 26998783d..339ddf07d 100644
--- a/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
+++ b/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
@@ -75,7 +75,7 @@ public class BitmapCache {
public synchronized Bitmap getBitmap(int w, int h) {
Long key = calcKey(w, h);
- WeakReference<Bitmap> ref = null; //mBitmapCache.remove(key);
+ WeakReference<Bitmap> ref = null;
ArrayList<WeakReference<Bitmap>> list = mBitmapCache.get(key);
if (list != null && list.size() > 0) {
ref = list.remove(0);
diff --git a/src/com/android/gallery3d/filtershow/category/CategorySelected.java b/src/com/android/gallery3d/filtershow/category/CategorySelected.java
new file mode 100644
index 000000000..1a6135bb8
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/CategorySelected.java
@@ -0,0 +1,27 @@
+package com.android.gallery3d.filtershow.category;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class CategorySelected extends View {
+ Paint mPaint = new Paint();
+
+ public CategorySelected(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void onDraw(Canvas canvas) {
+ mPaint.reset();
+ int margin = 20;
+ mPaint.setStrokeWidth(margin);
+ mPaint.setAntiAlias(true);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(Color.GRAY);
+ canvas.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2 - margin, mPaint);
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryView.java b/src/com/android/gallery3d/filtershow/category/CategoryView.java
index 3a9d47355..c613c2174 100644
--- a/src/com/android/gallery3d/filtershow/category/CategoryView.java
+++ b/src/com/android/gallery3d/filtershow/category/CategoryView.java
@@ -154,6 +154,11 @@ public class CategoryView extends IconView
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean ret = super.onTouchEvent(event);
+ FilterShowActivity activity = (FilterShowActivity) getContext();
+
+ if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+ activity.startTouchAnimation(this, event.getX(), event.getY());
+ }
if (!canBeRemoved()) {
return ret;
}
@@ -171,7 +176,6 @@ public class CategoryView extends IconView
delta = event.getX() - mStartTouchX;
}
if (Math.abs(delta) > mDeleteSlope) {
- FilterShowActivity activity = (FilterShowActivity) getContext();
activity.setHandlesSwipeForView(this, mStartTouchX, mStartTouchY);
}
}
diff --git a/src/com/android/gallery3d/filtershow/editors/Editor.java b/src/com/android/gallery3d/filtershow/editors/Editor.java
index fb04fb35c..5f8e8f6f6 100644
--- a/src/com/android/gallery3d/filtershow/editors/Editor.java
+++ b/src/com/android/gallery3d/filtershow/editors/Editor.java
@@ -323,5 +323,8 @@ public class Editor implements OnSeekBarChangeListener, SwapButton.SwapButtonLis
}
public void detach() {
+ if (mImageShow != null) {
+ mImageShow.detach();
+ }
}
}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java
index 765796ea5..84caa9e75 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java
@@ -23,8 +23,12 @@ import android.util.Log;
import com.android.gallery3d.R;
import com.android.gallery3d.filtershow.editors.EditorMirror;
import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
import java.io.IOException;
+import java.util.ArrayList;
public class FilterMirrorRepresentation extends FilterRepresentation {
public static final String SERIALIZATION_NAME = "MIRROR";
@@ -108,18 +112,34 @@ public class FilterMirrorRepresentation extends FilterRepresentation {
mMirror = mirror;
}
+ public boolean isHorizontal() {
+ if (mMirror == Mirror.BOTH
+ || mMirror == Mirror.HORIZONTAL) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isVertical() {
+ if (mMirror == Mirror.BOTH
+ || mMirror == Mirror.VERTICAL) {
+ return true;
+ }
+ return false;
+ }
+
public void cycle() {
switch (mMirror) {
case NONE:
mMirror = Mirror.HORIZONTAL;
break;
case HORIZONTAL:
- mMirror = Mirror.VERTICAL;
- break;
- case VERTICAL:
mMirror = Mirror.BOTH;
break;
case BOTH:
+ mMirror = Mirror.VERTICAL;
+ break;
+ case VERTICAL:
mMirror = Mirror.NONE;
break;
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
index 1cefe085e..e3cd56db7 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
@@ -23,6 +23,7 @@ import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
+import com.android.gallery3d.filtershow.cache.BitmapCache;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
@@ -209,7 +210,19 @@ public final class GeometryMathUtils {
return q;
}
- private static void concatMirrorMatrix(Matrix m, Mirror type) {
+ private static void concatMirrorMatrix(Matrix m, GeometryHolder holder) {
+ Mirror type = holder.mirror;
+ if (type == Mirror.HORIZONTAL) {
+ if (holder.rotation.value() == 90
+ || holder.rotation.value() == 270) {
+ type = Mirror.VERTICAL;
+ }
+ } else if (type == Mirror.VERTICAL) {
+ if (holder.rotation.value() == 90
+ || holder.rotation.value() == 270) {
+ type = Mirror.HORIZONTAL;
+ }
+ }
if (type == Mirror.HORIZONTAL) {
m.postScale(-1, 1);
} else if (type == Mirror.VERTICAL) {
@@ -299,7 +312,8 @@ public final class GeometryMathUtils {
crop.roundOut(frame);
Matrix m = getCropSelectionToScreenMatrix(null, holder, width, height, frame.width(),
frame.height());
- Bitmap temp = Bitmap.createBitmap(frame.width(), frame.height(), Bitmap.Config.ARGB_8888);
+ BitmapCache bitmapCache = MasterImage.getImage().getBitmapCache();
+ Bitmap temp = bitmapCache.getBitmap(frame.width(), frame.height());
Canvas canvas = new Canvas(temp);
Paint paint = new Paint();
paint.setAntiAlias(true);
@@ -345,7 +359,7 @@ public final class GeometryMathUtils {
compensation.postRotate(angle, cx, cy);
compensation.postRotate(rotation, cx, cy);
compensation.postTranslate(-cx, -cy);
- concatMirrorMatrix(compensation, holder.mirror);
+ concatMirrorMatrix(compensation, holder);
compensation.postTranslate(cx, cy);
return compensation;
}
@@ -371,6 +385,10 @@ public final class GeometryMathUtils {
// If there are geometry changes, apply them to the image
if (!holder.isNil()) {
bmap = applyFullGeometryMatrix(bmap, holder);
+ if (bmap != image) {
+ BitmapCache cache = MasterImage.getImage().getBitmapCache();
+ cache.cache(image);
+ }
}
return bmap;
}
@@ -410,7 +428,7 @@ public final class GeometryMathUtils {
Matrix m = new Matrix();
m.setTranslate(-centerX, -centerY);
m.postRotate(holder.straighten + holder.rotation.value());
- concatMirrorMatrix(m, holder.mirror);
+ concatMirrorMatrix(m, holder);
return m;
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
index 2bb269e29..ad4568723 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
@@ -19,13 +19,15 @@ package com.android.gallery3d.filtershow.imageshow;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.RectF;
+import android.graphics.Shader;
import android.graphics.drawable.NinePatchDrawable;
import android.util.AttributeSet;
import android.view.GestureDetector;
@@ -38,12 +40,14 @@ import android.widget.LinearLayout;
import com.android.gallery3d.R;
import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.ImageFilter;
import com.android.gallery3d.filtershow.pipeline.ImagePreset;
import com.android.gallery3d.filtershow.tools.SaveImage;
import java.io.File;
+import java.util.ArrayList;
import java.util.Collection;
public class ImageShow extends View implements OnGestureListener,
@@ -74,6 +78,7 @@ public class ImageShow extends View implements OnGestureListener,
private NinePatchDrawable mShadow = null;
private Rect mShadowBounds = new Rect();
private int mShadowMargin = 15; // not scaled, fixed in the asset
+ private boolean mShadowDrawn = false;
private Point mTouchDown = new Point();
private Point mTouch = new Point();
@@ -93,6 +98,21 @@ public class ImageShow extends View implements OnGestureListener,
}
InteractionMode mInteractionMode = InteractionMode.NONE;
+ private static Bitmap sMask;
+ private Paint mMaskPaint = new Paint();
+ private Matrix mShaderMatrix = new Matrix();
+
+ private static Bitmap convertToAlphaMask(Bitmap b) {
+ Bitmap a = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ALPHA_8);
+ Canvas c = new Canvas(a);
+ c.drawBitmap(b, 0.0f, 0.0f, null);
+ return a;
+ }
+
+ private static Shader createShader(Bitmap b) {
+ return new BitmapShader(b, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
+ }
+
private FilterShowActivity mActivity = null;
public FilterShowActivity getActivity() {
@@ -138,7 +158,20 @@ public class ImageShow extends View implements OnGestureListener,
mShadow = (NinePatchDrawable) res.getDrawable(R.drawable.geometry_shadow);
setupGestureDetector(context);
mActivity = (FilterShowActivity) context;
+ if (sMask == null) {
+ Bitmap mask = BitmapFactory.decodeResource(res, R.drawable.spot_mask);
+ sMask = convertToAlphaMask(mask);
+ }
+ }
+
+ public void attach() {
MasterImage.getImage().addObserver(this);
+ bindAsImageLoadListener();
+ }
+
+ public void detach() {
+ MasterImage.getImage().removeObserver(this);
+ mMaskPaint.reset();
}
public void setupGestureDetector(Context context) {
@@ -206,36 +239,27 @@ public class ImageShow extends View implements OnGestureListener,
float scaleFactor = MasterImage.getImage().getScaleFactor();
Point translation = MasterImage.getImage().getTranslation();
- Matrix scalingMatrix = new Matrix();
- scalingMatrix.postScale(scaleFactor, scaleFactor, cx, cy);
- scalingMatrix.preTranslate(translation.x, translation.y);
-
- RectF unscaledClipRect = new RectF(mImageBounds);
- scalingMatrix.mapRect(unscaledClipRect, unscaledClipRect);
-
canvas.save();
- boolean enablePartialRendering = false;
-
- // For now, partial rendering is disabled for all filters,
- // so no need to clip.
- if (enablePartialRendering && !unscaledClipRect.isEmpty()) {
- canvas.clipRect(unscaledClipRect);
- }
+ mShadowDrawn = false;
canvas.save();
// TODO: center scale on gesture
canvas.scale(scaleFactor, scaleFactor, cx, cy);
canvas.translate(translation.x, translation.y);
- drawImage(canvas, getFilteredImage(), true);
Bitmap highresPreview = MasterImage.getImage().getHighresImage();
- if (highresPreview != null) {
+
+ boolean isDoingNewLookAnimation = MasterImage.getImage().onGoingNewLookAnimation();
+
+ if (!isDoingNewLookAnimation && highresPreview != null) {
drawImage(canvas, highresPreview, true);
+ } else {
+ drawImage(canvas, getFilteredImage(), true);
}
canvas.restore();
Bitmap partialPreview = MasterImage.getImage().getPartialImage();
- if (partialPreview != null) {
+ if (!isDoingNewLookAnimation && partialPreview != null) {
canvas.save();
Rect originalBounds = MasterImage.getImage().getOriginalBounds();
Collection<FilterRepresentation> geo = MasterImage.getImage().getPreset()
@@ -274,30 +298,135 @@ public class ImageShow extends View implements OnGestureListener,
}
public void drawImage(Canvas canvas, Bitmap image, boolean updateBounds) {
- if (image != null) {
- Rect s = new Rect(0, 0, image.getWidth(),
- image.getHeight());
-
- float scale = GeometryMathUtils.scale(image.getWidth(), image.getHeight(), getWidth(),
- getHeight());
-
- float w = image.getWidth() * scale;
- float h = image.getHeight() * scale;
- float ty = (getHeight() - h) / 2.0f;
- float tx = (getWidth() - w) / 2.0f;
-
- Rect d = new Rect((int) tx + mShadowMargin,
- (int) ty + mShadowMargin,
- (int) (w + tx) - mShadowMargin,
- (int) (h + ty) - mShadowMargin);
- if (updateBounds) {
- mImageBounds = d;
+ if (image == null) {
+ return;
+ }
+
+ Rect d = computeImageBounds(image);
+
+ if (updateBounds) {
+ mImageBounds = d;
+ }
+
+ float centerX = mShadowMargin + (getWidth() - 2 * mShadowMargin) / 2;
+ float centerY = mShadowMargin + (getHeight() - 2 * mShadowMargin) / 2;
+
+ MasterImage master = MasterImage.getImage();
+ canvas.save();
+ if (master.onGoingNewLookAnimation()) {
+ if (master.getCurrentLookAnimation()
+ == MasterImage.CIRCLE_ANIMATION
+ && MasterImage.getImage().getPreviousImage() != null) {
+ float maskScale = MasterImage.getImage().getMaskScale();
+ if (maskScale > 1.0f) {
+ float maskW = sMask.getWidth() / 2.0f;
+ float maskH = sMask.getHeight() / 2.0f;
+ float x = centerX - maskW * maskScale;
+ float y = centerY - maskH * maskScale;
+
+ // Prepare the shader
+ mShaderMatrix.reset();
+ mShaderMatrix.setScale(1.0f / maskScale, 1.0f / maskScale);
+ mShaderMatrix.preTranslate(-x + d.left, -y + d.top);
+ float scaleImageX = d.width() / (float) image.getWidth();
+ float scaleImageY = d.height() / (float) image.getHeight();
+ mShaderMatrix.preScale(scaleImageX, scaleImageY);
+ mMaskPaint.reset();
+ mMaskPaint.setShader(createShader(image));
+ mMaskPaint.getShader().setLocalMatrix(mShaderMatrix);
+
+ drawImage(canvas, MasterImage.getImage().getPreviousImage());
+ canvas.translate(x, y);
+ canvas.scale(maskScale, maskScale);
+ canvas.drawBitmap(sMask, 0, 0, mMaskPaint);
+ } else {
+ drawImage(canvas, image);
+ }
+ } else if (master.getCurrentLookAnimation()
+ == MasterImage.ROTATE_ANIMATION) {
+ Rect d2 = computeImageBounds(master.getPreviousImage());
+ float finalScale = d.width() / (float) d2.height();
+ finalScale = (1.0f * (1.0f - master.getAnimFraction()))
+ + (finalScale * master.getAnimFraction());
+ canvas.rotate(master.getAnimRotationValue(), centerX, centerY);
+ canvas.scale(finalScale, finalScale, centerX, centerY);
+ drawImage(canvas, master.getPreviousImage());
+ } else if (master.getCurrentLookAnimation()
+ == MasterImage.MIRROR_ANIMATION) {
+ if (master.getCurrentFilterRepresentation()
+ instanceof FilterMirrorRepresentation) {
+ FilterMirrorRepresentation rep =
+ (FilterMirrorRepresentation) master.getCurrentFilterRepresentation();
+
+ ImagePreset preset = master.getPreset();
+ ArrayList<FilterRepresentation> geometry =
+ (ArrayList<FilterRepresentation>) preset.getGeometryFilters();
+ GeometryMathUtils.GeometryHolder holder = null;
+ holder = GeometryMathUtils.unpackGeometry(geometry);
+
+ if (holder.rotation.value() == 90 || holder.rotation.value() == 270) {
+ if (rep.isHorizontal() && !rep.isVertical()) {
+ canvas.scale(1, master.getAnimRotationValue(), centerX, centerY);
+ } else if (rep.isVertical() && !rep.isHorizontal()) {
+ canvas.scale(1, master.getAnimRotationValue(), centerX, centerY);
+ } else if (rep.isHorizontal() && rep.isVertical()) {
+ canvas.scale(master.getAnimRotationValue(), 1, centerX, centerY);
+ } else {
+ canvas.scale(master.getAnimRotationValue(), 1, centerX, centerY);
+ }
+ } else {
+ if (rep.isHorizontal() && !rep.isVertical()) {
+ canvas.scale(master.getAnimRotationValue(), 1, centerX, centerY);
+ } else if (rep.isVertical() && !rep.isHorizontal()) {
+ canvas.scale(master.getAnimRotationValue(), 1, centerX, centerY);
+ } else if (rep.isHorizontal() && rep.isVertical()) {
+ canvas.scale(1, master.getAnimRotationValue(), centerX, centerY);
+ } else {
+ canvas.scale(1, master.getAnimRotationValue(), centerX, centerY);
+ }
+ }
+ }
+ drawImage(canvas, master.getPreviousImage());
}
+ } else {
+ drawImage(canvas, image);
+ }
+ canvas.restore();
+ }
+
+ private void drawImage(Canvas canvas, Bitmap image) {
+ Rect d = computeImageBounds(image);
+ float scaleImageX = d.width() / (float) image.getWidth();
+ float scaleImageY = d.height() / (float) image.getHeight();
+ Matrix imageMatrix = new Matrix();
+ imageMatrix.postScale(scaleImageX, scaleImageY);
+ imageMatrix.postTranslate(d.left, d.top);
+ drawShadow(canvas, d);
+ canvas.clipRect(d);
+ canvas.drawBitmap(image, imageMatrix, mPaint);
+ }
+
+ private Rect computeImageBounds(Bitmap image) {
+ float scale = GeometryMathUtils.scale(image.getWidth(), image.getHeight(),
+ getWidth(), getHeight());
+
+ float w = image.getWidth() * scale;
+ float h = image.getHeight() * scale;
+ float ty = (getHeight() - h) / 2.0f;
+ float tx = (getWidth() - w) / 2.0f;
+ return new Rect((int) tx + mShadowMargin,
+ (int) ty + mShadowMargin,
+ (int) (w + tx) - mShadowMargin,
+ (int) (h + ty) - mShadowMargin);
+ }
+
+ private void drawShadow(Canvas canvas, Rect d) {
+ if (!mShadowDrawn) {
mShadowBounds.set(d.left - mShadowMargin, d.top - mShadowMargin,
d.right + mShadowMargin, d.bottom + mShadowMargin);
mShadow.setBounds(mShadowBounds);
mShadow.draw(canvas);
- canvas.drawBitmap(image, s, d, mPaint);
+ mShadowDrawn = true;
}
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
index fabc7b3dc..525b45801 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
@@ -16,6 +16,8 @@
package com.android.gallery3d.filtershow.imageshow;
+import android.animation.Animator;
+import android.animation.ValueAnimator;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Point;
@@ -24,12 +26,16 @@ import android.graphics.RectF;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
+import android.util.Log;
import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.cache.BitmapCache;
import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
import com.android.gallery3d.filtershow.filters.ImageFilter;
import com.android.gallery3d.filtershow.history.HistoryItem;
import com.android.gallery3d.filtershow.history.HistoryManager;
@@ -77,6 +83,16 @@ public class MasterImage implements RenderingRequestCaller {
private Bitmap mFiltersOnlyBitmap = null;
private Bitmap mPartialBitmap = null;
private Bitmap mHighresBitmap = null;
+ private Bitmap mPreviousImage = null;
+
+ private float mMaskScale = 1;
+ private boolean mOnGoingNewLookAnimation = false;
+ private float mAnimRotationValue = 0;
+ private float mAnimFraction = 0;
+ private int mCurrentLookAnimation = 0;
+ public static final int CIRCLE_ANIMATION = 1;
+ public static final int ROTATE_ANIMATION = 2;
+ public static final int MIRROR_ANIMATION = 3;
private HistoryManager mHistory = null;
private StateAdapter mState = null;
@@ -205,6 +221,10 @@ public class MasterImage implements RenderingRequestCaller {
mObservers.add(observer);
}
+ public void removeObserver(ImageShow observer) {
+ mObservers.remove(observer);
+ }
+
public void setActivity(FilterShowActivity activity) {
mActivity = activity;
}
@@ -328,6 +348,103 @@ public class MasterImage implements RenderingRequestCaller {
return mHighresBitmap;
}
+ public Bitmap getPreviousImage() {
+ return mPreviousImage;
+ }
+
+ public float getMaskScale() {
+ return mMaskScale;
+ }
+
+ public void setMaskScale(float scale) {
+ mMaskScale = scale;
+ notifyObservers();
+ }
+
+ public float getAnimRotationValue() {
+ return mAnimRotationValue;
+ }
+
+ public void setAnimRotation(float rotation) {
+ mAnimRotationValue = rotation;
+ notifyObservers();
+ }
+
+ public void setAnimFraction(float fraction) {
+ mAnimFraction = fraction;
+ }
+
+ public float getAnimFraction() {
+ return mAnimFraction;
+ }
+
+ public boolean onGoingNewLookAnimation() {
+ return mOnGoingNewLookAnimation;
+ }
+
+ public int getCurrentLookAnimation() {
+ return mCurrentLookAnimation;
+ }
+
+ public void onNewLook(FilterRepresentation newRepresentation) {
+ getBitmapCache().cache(mPreviousImage);
+ mPreviousImage = getBitmapCache().getBitmapCopy(getFilteredImage());
+ ValueAnimator animator = null;
+ if (newRepresentation instanceof FilterUserPresetRepresentation) {
+ mCurrentLookAnimation = CIRCLE_ANIMATION;
+ animator = ValueAnimator.ofFloat(1, 20);
+ }
+ if (newRepresentation instanceof FilterRotateRepresentation) {
+ mCurrentLookAnimation = ROTATE_ANIMATION;
+ animator = ValueAnimator.ofFloat(0, 90);
+ }
+ if (newRepresentation instanceof FilterMirrorRepresentation) {
+ mCurrentLookAnimation = MIRROR_ANIMATION;
+ animator = ValueAnimator.ofFloat(1, 0, -1);
+ }
+ animator.setDuration(400);
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ if (mCurrentLookAnimation == CIRCLE_ANIMATION) {
+ Log.v(LOGTAG, "circle animation " + animation.getAnimatedValue());
+ setMaskScale((Float) animation.getAnimatedValue());
+ } else if (mCurrentLookAnimation == ROTATE_ANIMATION
+ || mCurrentLookAnimation == MIRROR_ANIMATION) {
+ setAnimRotation((Float) animation.getAnimatedValue());
+ setAnimFraction(animation.getAnimatedFraction());
+ }
+ }
+ });
+ animator.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mOnGoingNewLookAnimation = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mBitmapCache.cache(mPreviousImage);
+ mPreviousImage = null;
+ mOnGoingNewLookAnimation = false;
+ setMaskScale(1);
+ setAnimRotation(0);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+ });
+ animator.start();
+ notifyObservers();
+ }
+
public void notifyObservers() {
for (ImageShow observer : mObservers) {
observer.invalidate();
@@ -339,9 +456,9 @@ public class MasterImage implements RenderingRequestCaller {
newPresetGeometryOnly.setDoApplyFilters(false);
newPresetGeometryOnly.setDoApplyGeometry(true);
if (force || mGeometryOnlyPreset == null
- || !newPresetGeometryOnly.same(mGeometryOnlyPreset)) {
+ || !newPresetGeometryOnly.equals(mGeometryOnlyPreset)) {
mGeometryOnlyPreset = newPresetGeometryOnly;
- RenderingRequest.post(mActivity, getOriginalBitmapLarge(),
+ RenderingRequest.post(mActivity, null,
mGeometryOnlyPreset, RenderingRequest.GEOMETRY_RENDERING, this);
}
ImagePreset newPresetFiltersOnly = new ImagePreset(mPreset);
@@ -350,7 +467,7 @@ public class MasterImage implements RenderingRequestCaller {
if (force || mFiltersOnlyPreset == null
|| !newPresetFiltersOnly.same(mFiltersOnlyPreset)) {
mFiltersOnlyPreset = newPresetFiltersOnly;
- RenderingRequest.post(mActivity, MasterImage.getImage().getOriginalBitmapLarge(),
+ RenderingRequest.post(mActivity, null,
mFiltersOnlyPreset, RenderingRequest.FILTERS_RENDERING, this);
}
}
@@ -474,10 +591,12 @@ public class MasterImage implements RenderingRequestCaller {
boolean needsCheckModification = false;
if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
+ mBitmapCache.cache(mGeometryOnlyBitmap);
mGeometryOnlyBitmap = request.getBitmap();
needsCheckModification = true;
}
if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
+ mBitmapCache.cache(mFiltersOnlyBitmap);
mFiltersOnlyBitmap = request.getBitmap();
notifyObservers();
needsCheckModification = true;
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java b/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
index 8f6eda261..2a8321908 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
@@ -170,9 +170,11 @@ public class CacheProcessing {
+ mSteps.size() + " cacheBitmap: " + cacheBitmap);
}
+ Bitmap originalCopy = null;
for (int i = findBaseImageIndex; i < mSteps.size(); i++) {
if (i == -1 || cacheBitmap == null) {
cacheBitmap = environment.getBitmapCopy(originalBitmap);
+ originalCopy = cacheBitmap;
if (DEBUG) {
Log.v(LOGTAG, "i: " + i + " cacheBitmap: " + cacheBitmap + " w: "
+ cacheBitmap.getWidth() + " h: " + cacheBitmap.getHeight()
@@ -189,12 +191,12 @@ public class CacheProcessing {
Log.v(LOGTAG, "i: " + i + " get new copy for cacheBitmap "
+ cacheBitmap + " apply...");
}
- environment.cache(step.cache);
cacheBitmap = environment.getBitmapCopy(cacheBitmap);
cacheBitmap = step.apply(environment, cacheBitmap);
step.cache = cacheBitmap;
}
}
+ environment.cache(originalCopy);
if (DEBUG) {
Log.v(LOGTAG, "now let's cleanup the cache...");
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
index 0ff8bfbad..823da642a 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
@@ -221,18 +221,64 @@ public class CachingPipeline implements PipelineInterface {
Bitmap bmp = preset.apply(bitmap, mEnvironment);
if (!mEnvironment.needsStop()) {
request.setBitmap(bmp);
+ } else {
+ mEnvironment.cache(bmp);
+ }
+ mFiltersManager.freeFilterResources(preset);
+ }
+ }
+
+ public void renderGeometry(RenderingRequest request) {
+ synchronized (CachingPipeline.class) {
+ if (getRenderScriptContext() == null) {
+ return;
+ }
+ ImagePreset preset = request.getImagePreset();
+ setupEnvironment(preset, false);
+ Bitmap bitmap = MasterImage.getImage().getOriginalBitmapHighres();
+ if (bitmap == null) {
+ return;
+ }
+ bitmap = mEnvironment.getBitmapCopy(bitmap);
+ bitmap = preset.applyGeometry(bitmap, mEnvironment);
+ if (!mEnvironment.needsStop()) {
+ request.setBitmap(bitmap);
+ } else {
+ mEnvironment.cache(bitmap);
+ }
+ mFiltersManager.freeFilterResources(preset);
+ }
+ }
+
+ public void renderFilters(RenderingRequest request) {
+ synchronized (CachingPipeline.class) {
+ if (getRenderScriptContext() == null) {
+ return;
+ }
+ ImagePreset preset = request.getImagePreset();
+ setupEnvironment(preset, false);
+ Bitmap bitmap = MasterImage.getImage().getOriginalBitmapHighres();
+ if (bitmap == null) {
+ return;
+ }
+ bitmap = mEnvironment.getBitmapCopy(bitmap);
+ bitmap = preset.apply(bitmap, mEnvironment);
+ if (!mEnvironment.needsStop()) {
+ request.setBitmap(bitmap);
+ } else {
+ mEnvironment.cache(bitmap);
}
mFiltersManager.freeFilterResources(preset);
}
}
public synchronized void render(RenderingRequest request) {
+ // TODO: cleanup/remove GEOMETRY / FILTERS paths
synchronized (CachingPipeline.class) {
if (getRenderScriptContext() == null) {
return;
}
- if (((request.getType() != RenderingRequest.PARTIAL_RENDERING
- && request.getType() != RenderingRequest.HIGHRES_RENDERING)
+ if (((request.getType() != RenderingRequest.PARTIAL_RENDERING)
&& request.getBitmap() == null)
|| request.getImagePreset() == null) {
return;
@@ -244,8 +290,7 @@ public class CachingPipeline implements PipelineInterface {
Bitmap bitmap = request.getBitmap();
ImagePreset preset = request.getImagePreset();
- setupEnvironment(preset,
- request.getType() != RenderingRequest.HIGHRES_RENDERING);
+ setupEnvironment(preset, true);
mFiltersManager.freeFilterResources(preset);
if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
@@ -260,13 +305,6 @@ public class CachingPipeline implements PipelineInterface {
}
}
- if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
- bitmap = MasterImage.getImage().getOriginalBitmapHighres();
- if (bitmap != null) {
- bitmap = preset.applyGeometry(bitmap, mEnvironment);
- }
- }
-
if (request.getType() == RenderingRequest.FULL_RENDERING
|| request.getType() == RenderingRequest.GEOMETRY_RENDERING
|| request.getType() == RenderingRequest.FILTERS_RENDERING) {
@@ -290,7 +328,6 @@ public class CachingPipeline implements PipelineInterface {
|| request.getType() == RenderingRequest.FILTERS_RENDERING
|| request.getType() == RenderingRequest.ICON_RENDERING
|| request.getType() == RenderingRequest.PARTIAL_RENDERING
- || request.getType() == RenderingRequest.HIGHRES_RENDERING
|| request.getType() == RenderingRequest.STYLE_ICON_RENDERING) {
if (request.getType() == RenderingRequest.ICON_RENDERING) {
@@ -351,6 +388,7 @@ public class CachingPipeline implements PipelineInterface {
Vector<FilterRepresentation> filters = preset.getFilters();
Bitmap result = mCachedProcessing.process(mOriginalBitmap, filters, mEnvironment);
buffer.setProducer(result);
+ mEnvironment.cache(result);
}
public synchronized void computeOld(SharedBuffer buffer, ImagePreset preset, int type) {
diff --git a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
index b34537668..72c02f32f 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
@@ -133,6 +133,9 @@ public class FilterEnvironment {
filter.useRepresentation(representation);
filter.setEnvironment(this);
Bitmap ret = filter.apply(bitmap, mScaleFactor, mQuality);
+ if (bitmap != ret) {
+ cache(bitmap);
+ }
filter.setGeneralParameters();
filter.setEnvironment(null);
return ret;
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
index 88e8d42e8..3f71547dd 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
@@ -24,6 +24,7 @@ import android.util.JsonWriter;
import android.util.Log;
import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.cache.BitmapCache;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
@@ -235,6 +236,37 @@ public class ImagePreset {
return true;
}
+ public boolean equals(ImagePreset preset) {
+ if (preset == null) {
+ return false;
+ }
+
+ if (preset.mFilters.size() != mFilters.size()) {
+ return false;
+ }
+
+ if (mDoApplyGeometry != preset.mDoApplyGeometry) {
+ return false;
+ }
+
+ if (mDoApplyFilters != preset.mDoApplyFilters) {
+ if (mFilters.size() > 0 || preset.mFilters.size() > 0) {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < preset.mFilters.size(); i++) {
+ FilterRepresentation a = preset.mFilters.elementAt(i);
+ FilterRepresentation b = mFilters.elementAt(i);
+
+ if (!a.equals(b)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
public int similarUpTo(ImagePreset preset) {
for (int i = 0; i < preset.mFilters.size(); i++) {
FilterRepresentation a = preset.mFilters.elementAt(i);
@@ -476,7 +508,11 @@ public class ImagePreset {
// TODO: might be worth getting rid of applyBorder.
continue;
}
+ Bitmap tmp = bitmap;
bitmap = environment.applyRepresentation(representation, bitmap);
+ if (tmp != bitmap) {
+ environment.cache(tmp);
+ }
if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) {
UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
"SaveFilter", representation.getSerializationName(), 1);
diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
index ef4bb9bc0..463b38d95 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
@@ -52,7 +52,8 @@ public class RenderingRequest {
public static void post(Context context, Bitmap source, ImagePreset preset, int type,
RenderingRequestCaller caller, Rect bounds, Rect destination) {
- if (((type != PARTIAL_RENDERING && type != HIGHRES_RENDERING) && source == null)
+ if (((type != PARTIAL_RENDERING && type != HIGHRES_RENDERING
+ && type != GEOMETRY_RENDERING && type != FILTERS_RENDERING) && source == null)
|| preset == null || caller == null) {
Log.v(LOGTAG, "something null: source: " + source
+ " or preset: " + preset + " or caller: " + caller);
@@ -61,14 +62,15 @@ public class RenderingRequest {
RenderingRequest request = new RenderingRequest();
Bitmap bitmap = null;
if (type == FULL_RENDERING
- || type == GEOMETRY_RENDERING
|| type == ICON_RENDERING
|| type == STYLE_ICON_RENDERING) {
CachingPipeline pipeline = new CachingPipeline(
FiltersManager.getManager(), "Icon");
bitmap = pipeline.renderGeometryIcon(source, preset);
- } else if (type != PARTIAL_RENDERING && type != HIGHRES_RENDERING) {
- bitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), mConfig);
+ } else if (type != PARTIAL_RENDERING && type != HIGHRES_RENDERING
+ && type != GEOMETRY_RENDERING && type != FILTERS_RENDERING) {
+ bitmap = MasterImage.getImage().getBitmapCache().getBitmap(
+ source.getWidth(), source.getHeight());
}
request.setBitmap(bitmap);
diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java
index 7a83f7072..c8bc57d38 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java
@@ -63,7 +63,13 @@ public class RenderingRequestTask extends ProcessingTask {
public Result doInBackground(Request message) {
RenderingRequest request = ((Render) message).request;
RenderResult result = null;
- mPreviewPipeline.render(request);
+ if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
+ mPreviewPipeline.renderGeometry(request);
+ } else if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
+ mPreviewPipeline.renderFilters(request);
+ } else {
+ mPreviewPipeline.render(request);
+ }
result = new RenderResult();
result.request = request;
return result;