From 32cc4dd751569721aa19218b4d947145577060d0 Mon Sep 17 00:00:00 2001 From: nicolasroard Date: Fri, 6 Sep 2013 17:21:55 -0700 Subject: [PATCH] Fix UI performances / glitches - load/process thumbnails fully in background - fix reveal slider - fix race condition when loading - better memory usage - fix loading spinner (wasn't shown!) Change-Id: Id78163556d8ee1c3ad04eae16fe1bf06f4312405 --- res/layout-land/filtershow_activity.xml | 102 ++++++++++----------- res/layout/filtershow_activity.xml | 73 ++++++++------- res/layout/filtershow_export_dialog.xml | 5 +- res/values/dimens.xml | 1 + .../gallery3d/filtershow/FilterShowActivity.java | 66 +++++++++++-- .../gallery3d/filtershow/category/Action.java | 79 +++++++++------- .../filtershow/category/CategoryAdapter.java | 9 ++ .../filtershow/category/CategorySelected.java | 14 ++- .../filtershow/category/CategoryView.java | 5 +- .../gallery3d/filtershow/category/IconView.java | 1 + .../gallery3d/filtershow/imageshow/ImageShow.java | 30 ++++++ .../filtershow/imageshow/MasterImage.java | 33 ++++++- .../filtershow/pipeline/CachingPipeline.java | 35 ++++++- .../filtershow/pipeline/RenderingRequest.java | 28 ++++++ .../filtershow/pipeline/UpdatePreviewTask.java | 2 + .../gallery3d/filtershow/tools/XmpPresets.java | 2 +- 16 files changed, 342 insertions(+), 143 deletions(-) diff --git a/res/layout-land/filtershow_activity.xml b/res/layout-land/filtershow_activity.xml index 72bbdeaf9..f4380126e 100644 --- a/res/layout-land/filtershow_activity.xml +++ b/res/layout-land/filtershow_activity.xml @@ -27,79 +27,79 @@ android:orientation="horizontal" android:animateLayoutChanges="true"> - + android:layout_weight="1"> + + + android:layout_height="match_parent" + android:layout_weight="1" + android:orientation="vertical" + > - + android:layout_width="wrap_content" + android:layout_height="0dp" + android:orientation="horizontal"> + + + + + + + + - - + android:visibility="visible"/> - - - - + - - + android:animateLayoutChanges="true"> - - - - - + android:id="@+id/main_panel_container" + android:layout_width="350dip" + android:layout_height="0dip" + android:layout_weight="1"/> diff --git a/res/layout/filtershow_activity.xml b/res/layout/filtershow_activity.xml index aabdb73e7..79c315b7b 100644 --- a/res/layout/filtershow_activity.xml +++ b/res/layout/filtershow_activity.xml @@ -26,33 +26,51 @@ android:layout_height="match_parent" android:orientation="vertical"> - + android:layout_weight="1"> - + android:layout_gravity="center" + android:indeterminate="true" + android:indeterminateOnly="true" + android:background="@null"/> - + android:orientation="horizontal"> - + - + + + + + + + + - - - - - - - diff --git a/res/layout/filtershow_export_dialog.xml b/res/layout/filtershow_export_dialog.xml index c7ce1e7c2..bfa302d79 100644 --- a/res/layout/filtershow_export_dialog.xml +++ b/res/layout/filtershow_export_dialog.xml @@ -73,8 +73,9 @@ android:layout_gravity="center" android:max="100" android:progress="100" - android:layout_width="400dp" - android:layout_columnSpan="3"/> + android:layout_width="wrap_content" + android:layout_columnSpan="3" + android:minWidth="250dp"/> 96dip 3dip 175dip + 8dp 120dp diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java index f46a0b781..59a403efc 100644 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java @@ -30,6 +30,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Matrix; +import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.ColorDrawable; @@ -164,6 +165,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL private Uri mSelectedImageUri = null; + private ArrayList mActions = new ArrayList(); private UserPresetsManager mUserPresetsManager = null; private UserPresetsAdapter mUserPresetsAdapter = null; private CategoryAdapter mCategoryLooksAdapter = null; @@ -250,7 +252,6 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL public void updateUIAfterServiceStarted() { fillCategories(); loadMainPanel(); - setDefaultPreset(); extractXMPData(); processIntent(); } @@ -384,7 +385,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL setupEditors(); mEditorPlaceHolder.hide(); - mImageShow.bindAsImageLoadListener(); + mImageShow.attach(); setupStatePanel(); } @@ -403,10 +404,27 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL } private void fillVersions() { + if (mCategoryVersionsAdapter != null) { + mCategoryVersionsAdapter.clear(); + } mCategoryVersionsAdapter = new CategoryAdapter(this); mCategoryVersionsAdapter.setShowAddButton(true); } + public void registerAction(Action action) { + if (mActions.contains(action)) { + return; + } + mActions.add(action); + } + + private void loadActions() { + for (int i = 0; i < mActions.size(); i++) { + Action action = mActions.get(i); + action.setImageFrame(new Rect(0, 0, 96, 96), 0); + } + } + public void updateVersions() { mCategoryVersionsAdapter.clear(); FilterUserPresetRepresentation originalRep = new FilterUserPresetRepresentation( @@ -455,6 +473,9 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL private void fillEffects() { FiltersManager filtersManager = FiltersManager.getManager(); ArrayList filtersRepresentations = filtersManager.getEffects(); + if (mCategoryFiltersAdapter != null) { + mCategoryFiltersAdapter.clear(); + } mCategoryFiltersAdapter = new CategoryAdapter(this); for (FilterRepresentation representation : filtersRepresentations) { if (representation.getTextId() != 0) { @@ -467,6 +488,9 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL private void fillTools() { FiltersManager filtersManager = FiltersManager.getManager(); ArrayList filtersRepresentations = filtersManager.getTools(); + if (mCategoryGeometryAdapter != null) { + mCategoryGeometryAdapter.clear(); + } mCategoryGeometryAdapter = new CategoryAdapter(this); for (FilterRepresentation representation : filtersRepresentations) { mCategoryGeometryAdapter.add(new Action(this, representation)); @@ -549,6 +573,9 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL } } + if (mCategoryBordersAdapter != null) { + mCategoryBordersAdapter.clear(); + } mCategoryBordersAdapter = new CategoryAdapter(this); for (FilterRepresentation representation : borders) { if (representation.getTextId() != 0) { @@ -713,6 +740,11 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL } } + public void stopLoadingIndicator() { + final View loading = findViewById(R.id.loading); + loading.setVisibility(View.GONE); + } + private class LoadBitmapTask extends AsyncTask { int mBitmapSize; @@ -764,14 +796,12 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL Log.v(LOGTAG,"RenderScript context destroyed during load"); return; } - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.GONE); final View imageShow = findViewById(R.id.imageShow); imageShow.setVisibility(View.VISIBLE); + Bitmap largeBitmap = MasterImage.getImage().getOriginalBitmapLarge(); mBoundService.setOriginalBitmap(largeBitmap); - MasterImage.getImage().resetGeometryImages(true); float previewScale = (float) largeBitmap.getWidth() / (float) MasterImage.getImage().getOriginalBounds().width(); @@ -785,13 +815,20 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL mCategoryFiltersAdapter.imageLoaded(); mLoadBitmapTask = null; + MasterImage.getImage().warnListeners(); + loadActions(); + if (mOriginalPreset != null) { MasterImage.getImage().setLoadedPreset(mOriginalPreset); MasterImage.getImage().setPreset(mOriginalPreset, mOriginalPreset.getLastRepresentation(), true); mOriginalPreset = null; + } else { + setDefaultPreset(); } + MasterImage.getImage().resetGeometryImages(true); + if (mAction == TINY_PLANET_ACTION) { showRepresentation(mCategoryFiltersAdapter.getTinyPlanet()); } @@ -1087,6 +1124,9 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL FiltersManager filtersManager = FiltersManager.getManager(); ArrayList filtersRepresentations = filtersManager.getLooks(); + if (mCategoryLooksAdapter != null) { + mCategoryLooksAdapter.clear(); + } mCategoryLooksAdapter = new CategoryAdapter(this); int verticalItemHeight = (int) getResources().getDimension(R.dimen.action_item_height); mCategoryLooksAdapter.setItemHeight(verticalItemHeight); @@ -1170,8 +1210,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL if (!mShowingTinyPlanet && (mLoadBitmapTask == null)) { mCategoryFiltersAdapter.removeTinyPlanet(); } - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.GONE); + stopLoadingIndicator(); } public void setupMasterImage() { @@ -1183,6 +1222,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL mMasterImage.setHistoryManager(historyManager); mMasterImage.setStateAdapter(imageStateAdapter); mMasterImage.setActivity(this); + mMasterImage.setFirstLoad(true); if (Runtime.getRuntime().maxMemory() > LIMIT_SUPPORTS_HIGHRES) { mMasterImage.setSupportsHighRes(true); @@ -1374,11 +1414,23 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL return super.dispatchTouchEvent(ev); } + public Point mHintTouchPoint = new Point(); + + public Point hintTouchPoint(View view) { + int location[] = new int[2]; + view.getLocationOnScreen(location); + int x = mHintTouchPoint.x - location[0]; + int y = mHintTouchPoint.y - location[1]; + return new Point(x, y); + } + 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); + mHintTouchPoint.x = (int) (location[0] + x); + mHintTouchPoint.y = (int) (location[1] + y); int locationHint[] = new int[2]; ((View)hint.getParent()).getLocationOnScreen(locationHint); int dx = (int) (x - (hint.getWidth())/2); diff --git a/src/com/android/gallery3d/filtershow/category/Action.java b/src/com/android/gallery3d/filtershow/category/Action.java index 7bdc8ec90..b3f35dab9 100644 --- a/src/com/android/gallery3d/filtershow/category/Action.java +++ b/src/com/android/gallery3d/filtershow/category/Action.java @@ -24,8 +24,12 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; +import android.util.Log; import android.widget.ArrayAdapter; import android.widget.ListAdapter; + +import com.android.gallery3d.R; +import com.android.gallery3d.filtershow.FilterShowActivity; import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; import com.android.gallery3d.filtershow.pipeline.RenderingRequest; import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller; @@ -48,26 +52,30 @@ public class Action implements RenderingRequestCaller { private int mType = CROP_VIEW; private Bitmap mPortraitImage; private Bitmap mOverlayBitmap; - private Context mContext; + private FilterShowActivity mContext; private boolean mCanBeRemoved = false; + private int mTextSize = 32; - public Action(Context context, FilterRepresentation representation, int type, + public Action(FilterShowActivity context, FilterRepresentation representation, int type, boolean canBeRemoved) { this(context, representation, type); mCanBeRemoved = canBeRemoved; + mTextSize = context.getResources().getDimensionPixelSize( + R.dimen.category_panel_text_size); } - public Action(Context context, FilterRepresentation representation, int type) { + public Action(FilterShowActivity context, FilterRepresentation representation, int type) { this(context, type); setRepresentation(representation); } - public Action(Context context, int type) { + public Action(FilterShowActivity context, int type) { mContext = context; setType(type); + mContext.registerAction(this); } - public Action(Context context, FilterRepresentation representation) { + public Action(FilterShowActivity context, FilterRepresentation representation) { this(context, representation, CROP_VIEW); } @@ -100,19 +108,19 @@ public class Action implements RenderingRequestCaller { if (mImageFrame != null && mImageFrame.equals(imageFrame)) { return; } - Bitmap bitmap = MasterImage.getImage().getLargeThumbnailBitmap(); + if (getType() == Action.ADD_ACTION) { + return; + } + Bitmap temp = MasterImage.getImage().getTemporaryThumbnailBitmap(); + if (temp != null) { + mImage = temp; + } + Bitmap bitmap = MasterImage.getImage().getThumbnailBitmap(); if (bitmap != null) { mImageFrame = imageFrame; int w = mImageFrame.width(); int h = mImageFrame.height(); - if (orientation == CategoryView.VERTICAL - && mType == CROP_VIEW) { - w /= 2; - } - Bitmap bitmapCrop = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - drawCenteredImage(bitmap, bitmapCrop, true); - - postNewIconRenderRequest(bitmapCrop); + postNewIconRenderRequest(w, h); } } @@ -132,40 +140,37 @@ public class Action implements RenderingRequestCaller { mType = type; } - private void postNewIconRenderRequest(Bitmap bitmap) { - if (bitmap != null && mRepresentation != null) { + private void postNewIconRenderRequest(int w, int h) { + if (mRepresentation != null) { ImagePreset preset = new ImagePreset(); preset.addFilter(mRepresentation); - RenderingRequest.post(mContext, bitmap, - preset, RenderingRequest.ICON_RENDERING, this); + RenderingRequest.postIconRequest(mContext, w, h, preset, this); } } private void drawCenteredImage(Bitmap source, Bitmap destination, boolean scale) { - RectF image = new RectF(0, 0, source.getWidth(), source.getHeight()); - int border = 0; - if (!scale) { - border = destination.getWidth() - destination.getHeight(); - if (border < 0) { - border = 0; - } - } - RectF frame = new RectF(border, 0, - destination.getWidth() - border, - destination.getHeight()); + int minSide = Math.min(destination.getWidth(), destination.getHeight()); Matrix m = new Matrix(); - m.setRectToRect(frame, image, Matrix.ScaleToFit.CENTER); - image.set(frame); - m.mapRect(image); - m.setRectToRect(image, frame, Matrix.ScaleToFit.FILL); + float scaleFactor = minSide / (float) Math.min(source.getWidth(), source.getHeight()); + + float dx = (destination.getWidth() - source.getWidth() * scaleFactor) / 2.0f; + float dy = (destination.getHeight() - source.getHeight() * scaleFactor) / 2.0f; + if (mImageFrame.height() > mImageFrame.width()) { + // if portrait + dy -= mTextSize; + } + m.setScale(scaleFactor, scaleFactor); + m.postTranslate(dx, dy); Canvas canvas = new Canvas(destination); canvas.drawBitmap(source, m, new Paint(Paint.FILTER_BITMAP_FLAG)); } @Override public void available(RenderingRequest request) { + clearBitmap(); mImage = request.getBitmap(); if (mImage == null) { + mImageFrame = null; return; } if (mRepresentation.getOverlayId() != 0 && mOverlayBitmap == null) { @@ -204,4 +209,12 @@ public class Action implements RenderingRequestCaller { public void setOverlayBitmap(Bitmap overlayBitmap) { mOverlayBitmap = overlayBitmap; } + + public void clearBitmap() { + if (mImage != null + && mImage != MasterImage.getImage().getTemporaryThumbnailBitmap()) { + MasterImage.getImage().getBitmapCache().cache(mImage); + } + mImage = null; + } } diff --git a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java index 51ae07fc2..09f02dd37 100644 --- a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java +++ b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java @@ -49,6 +49,15 @@ public class CategoryAdapter extends ArrayAdapter { this(context, 0); } + @Override + public void clear() { + for (int i = 0; i < getCount(); i++) { + Action action = getItem(i); + action.clearBitmap(); + } + super.clear(); + } + public void setItemHeight(int height) { mItemHeight = height; } diff --git a/src/com/android/gallery3d/filtershow/category/CategorySelected.java b/src/com/android/gallery3d/filtershow/category/CategorySelected.java index 1a6135bb8..42058c0db 100644 --- a/src/com/android/gallery3d/filtershow/category/CategorySelected.java +++ b/src/com/android/gallery3d/filtershow/category/CategorySelected.java @@ -7,21 +7,25 @@ import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; +import com.android.gallery3d.R; + public class CategorySelected extends View { - Paint mPaint = new Paint(); + private Paint mPaint = new Paint(); + private int mMargin = 20; public CategorySelected(Context context, AttributeSet attrs) { super(context, attrs); + mMargin = getResources().getDimensionPixelSize(R.dimen.touch_circle_size); } public void onDraw(Canvas canvas) { mPaint.reset(); - int margin = 20; - mPaint.setStrokeWidth(margin); + mPaint.setStrokeWidth(mMargin); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); - mPaint.setColor(Color.GRAY); - canvas.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2 - margin, mPaint); + mPaint.setColor(Color.argb(128, 128, 128, 128)); + canvas.drawCircle(getWidth()/2, getHeight()/2, + getWidth()/2 - mMargin, mPaint); } } diff --git a/src/com/android/gallery3d/filtershow/category/CategoryView.java b/src/com/android/gallery3d/filtershow/category/CategoryView.java index c613c2174..22c50fd96 100644 --- a/src/com/android/gallery3d/filtershow/category/CategoryView.java +++ b/src/com/android/gallery3d/filtershow/category/CategoryView.java @@ -109,9 +109,8 @@ public class CategoryView extends IconView drawSpacer(canvas); return; } - if (mAction.getImage() == null) { - mAction.setImageFrame(new Rect(0, 0, getWidth(), getHeight()), getOrientation()); - } else { + mAction.setImageFrame(new Rect(0, 0, getWidth(), getHeight()), getOrientation()); + if (mAction.getImage() != null) { setBitmap(mAction.getImage()); } } diff --git a/src/com/android/gallery3d/filtershow/category/IconView.java b/src/com/android/gallery3d/filtershow/category/IconView.java index 0443823c9..cba2d794f 100644 --- a/src/com/android/gallery3d/filtershow/category/IconView.java +++ b/src/com/android/gallery3d/filtershow/category/IconView.java @@ -193,6 +193,7 @@ public class IconView extends View { public void onDraw(Canvas canvas) { mPaint.reset(); mPaint.setAntiAlias(true); + mPaint.setFilterBitmap(true); canvas.drawColor(mBackgroundColor); computeBitmapBounds(); computeTextPosition(getText()); diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java index 77eaf4dc7..813d76172 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java +++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java @@ -30,6 +30,7 @@ import android.graphics.Rect; import android.graphics.Shader; import android.graphics.drawable.NinePatchDrawable; import android.util.AttributeSet; +import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.OnDoubleTapListener; import android.view.GestureDetector.OnGestureListener; @@ -91,6 +92,7 @@ public class ImageShow extends View implements OnGestureListener, Point mOriginalTranslation = new Point(); float mOriginalScale; float mStartFocusX, mStartFocusY; + private enum InteractionMode { NONE, SCALE, @@ -235,6 +237,19 @@ public class ImageShow extends View implements OnGestureListener, getWidth() - 2*mShadowMargin, getHeight() - 2*mShadowMargin); + MasterImage img = MasterImage.getImage(); + // Hide the loading indicator as needed + if (img.isFirstLoad() && getFilteredImage() != null) { + if ((img.getLoadedPreset() == null) + || (img.getLoadedPreset() != null + && img.getLoadedPreset().equals(img.getCurrentPreset()))) { + img.setFirstLoad(false); + mActivity.stopLoadingIndicator(); + } else if (img.getLoadedPreset() != null) { + return; + } + } + float cx = canvas.getWidth()/2.0f; float cy = canvas.getHeight()/2.0f; float scaleFactor = MasterImage.getImage().getScaleFactor(); @@ -327,6 +342,10 @@ public class ImageShow extends View implements OnGestureListener, float x = centerX - maskW * maskScale; float y = centerY - maskH * maskScale; + Point point = mActivity.hintTouchPoint(this); + x = point.x - maskW * maskScale; + y = point.y - maskH * maskScale; + // Prepare the shader mShaderMatrix.reset(); mShaderMatrix.setScale(1.0f / maskScale, 1.0f / maskScale); @@ -472,6 +491,17 @@ public class ImageShow extends View implements OnGestureListener, Rect d = new Rect(mImageBounds.left, mImageBounds.top, mImageBounds.left + px, mImageBounds.top + py); + if (mShowOriginalDirection == UNVEIL_HORIZONTAL) { + if (mTouchDown.x - mTouch.x > 0) { + d.set(mImageBounds.left + px, mImageBounds.top, + mImageBounds.right, mImageBounds.top + py); + } + } else { + if (mTouchDown.y - mTouch.y > 0) { + d.set(mImageBounds.left, mImageBounds.top + py, + mImageBounds.left + px, mImageBounds.bottom); + } + } canvas.clipRect(d); drawImage(canvas, image, false); Paint paint = new Paint(); diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java index c562e4a88..3af8c4a2a 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java +++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java @@ -19,11 +19,13 @@ package com.android.gallery3d.filtershow.imageshow; import android.animation.Animator; import android.animation.ValueAnimator; import android.graphics.Bitmap; +import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.net.Uri; +import android.util.Log; import com.android.gallery3d.exif.ExifTag; import com.android.gallery3d.filtershow.FilterShowActivity; @@ -70,6 +72,7 @@ public class MasterImage implements RenderingRequestCaller { private Bitmap mOriginalBitmapSmall = null; private Bitmap mOriginalBitmapLarge = null; private Bitmap mOriginalBitmapHighres = null; + private Bitmap mTemporaryThumbnail = null; private int mOrientation; private Rect mOriginalBounds; private final Vector mLoadListeners = new Vector(); @@ -113,6 +116,8 @@ public class MasterImage implements RenderingRequestCaller { private List mEXIF; private BitmapCache mBitmapCache = new BitmapCache(); + private boolean mFirstLoad; + private MasterImage() { } @@ -128,6 +133,14 @@ public class MasterImage implements RenderingRequestCaller { return sMasterImage; } + public void setFirstLoad(boolean firstLoad) { + mFirstLoad = firstLoad; + } + + public boolean isFirstLoad() { + return mFirstLoad; + } + public Bitmap getOriginalBitmapSmall() { return mOriginalBitmapSmall; } @@ -421,8 +434,8 @@ public class MasterImage implements RenderingRequestCaller { mPreviousPreset = getPreviewBuffer().getConsumer().getPreset(); if (newRepresentation instanceof FilterUserPresetRepresentation) { mCurrentLookAnimation = CIRCLE_ANIMATION; - mAnimator = ValueAnimator.ofFloat(0, 20); - mAnimator.setDuration(500); + mAnimator = ValueAnimator.ofFloat(0, 40); + mAnimator.setDuration(650); } if (newRepresentation instanceof FilterRotateRepresentation) { mCurrentLookAnimation = ROTATE_ANIMATION; @@ -535,6 +548,12 @@ public class MasterImage implements RenderingRequestCaller { } public void invalidatePreview() { + if (mPreset == null) { + return; + } + if (mPreset.nbFilters() == 0) { + MasterImage.getImage().setFirstLoad(false); + } mPreviewPreset.enqueuePreset(mPreset); mPreviewBuffer.invalidate(); invalidatePartialPreview(); @@ -700,6 +719,16 @@ public class MasterImage implements RenderingRequestCaller { needsUpdatePartialPreview(); } + public Bitmap getTemporaryThumbnailBitmap() { + if (mTemporaryThumbnail == null + && getOriginalBitmapSmall() != null) { + mTemporaryThumbnail = getOriginalBitmapSmall().copy(Bitmap.Config.ARGB_8888, true); + Canvas canvas = new Canvas(mTemporaryThumbnail); + canvas.drawARGB(200, 80, 80, 80); + } + return mTemporaryThumbnail; + } + public Bitmap getThumbnailBitmap() { return getOriginalBitmapSmall(); } diff --git a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java index 30f5f12fd..4370013bc 100644 --- a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java +++ b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java @@ -19,6 +19,11 @@ package com.android.gallery3d.filtershow.pipeline; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; import android.support.v8.renderscript.Allocation; import android.support.v8.renderscript.RenderScript; import android.util.Log; @@ -177,6 +182,9 @@ public class CachingPipeline implements PipelineInterface { } private synchronized boolean updateOriginalAllocation(ImagePreset preset) { + if (preset == null) { + return false; + } Bitmap originalBitmap = mOriginalBitmap; if (originalBitmap == null) { @@ -278,7 +286,8 @@ public class CachingPipeline implements PipelineInterface { if (getRenderScriptContext() == null) { return; } - if (((request.getType() != RenderingRequest.PARTIAL_RENDERING) + if ((request.getType() != RenderingRequest.PARTIAL_RENDERING + && request.getType() != RenderingRequest.ICON_RENDERING && request.getBitmap() == null) || request.getImagePreset() == null) { return; @@ -311,7 +320,7 @@ public class CachingPipeline implements PipelineInterface { updateOriginalAllocation(preset); } - if (DEBUG) { + if (DEBUG && bitmap != null) { Log.v(LOGTAG, "after update, req bitmap (" + bitmap.getWidth() + "x" + bitmap.getHeight() + " ? resizeOriginal (" + mResizedOriginalBitmap.getWidth() + "x" + mResizedOriginalBitmap.getHeight()); @@ -336,6 +345,28 @@ public class CachingPipeline implements PipelineInterface { mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); } + if (request.getType() == RenderingRequest.ICON_RENDERING) { + Rect iconBounds = request.getIconBounds(); + Bitmap source = MasterImage.getImage().getThumbnailBitmap(); + if (iconBounds.width() > source.getWidth() * 2) { + source = MasterImage.getImage().getLargeThumbnailBitmap(); + } + if (iconBounds != null) { + bitmap = mEnvironment.getBitmap(iconBounds.width(), iconBounds.height()); + Canvas canvas = new Canvas(bitmap); + Matrix m = new Matrix(); + float minSize = Math.min(source.getWidth(), source.getHeight()); + float maxSize = Math.max(iconBounds.width(), iconBounds.height()); + float scale = maxSize / minSize; + m.setScale(scale, scale); + float dx = (iconBounds.width() - (source.getWidth() * scale))/2.0f; + float dy = (iconBounds.height() - (source.getHeight() * scale))/2.0f; + m.postTranslate(dx, dy); + canvas.drawBitmap(source, m, new Paint(Paint.FILTER_BITMAP_FLAG)); + } else { + bitmap = mEnvironment.getBitmapCopy(source); + } + } Bitmap bmp = preset.apply(bitmap, mEnvironment); if (!mEnvironment.needsStop()) { request.setBitmap(bmp); diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java index 463b38d95..6498c53bf 100644 --- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java +++ b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java @@ -34,6 +34,7 @@ public class RenderingRequest { private float mScaleFactor = 1.0f; private Rect mBounds = null; private Rect mDestination = null; + private Rect mIconBounds = null; private int mType = FULL_RENDERING; public static final int FULL_RENDERING = 0; public static final int FILTERS_RENDERING = 1; @@ -90,6 +91,25 @@ public class RenderingRequest { request.post(context); } + public static void postIconRequest(Context context, int w, int h, + ImagePreset preset, + RenderingRequestCaller caller) { + if (preset == null || caller == null) { + Log.v(LOGTAG, "something null, preset: " + + preset + " or caller: " + caller); + return; + } + RenderingRequest request = new RenderingRequest(); + ImagePreset passedPreset = new ImagePreset(preset); + request.setOriginalImagePreset(preset); + request.setScaleFactor(MasterImage.getImage().getScaleFactor()); + request.setImagePreset(passedPreset); + request.setType(RenderingRequest.ICON_RENDERING); + request.setCaller(caller); + request.setIconBounds(new Rect(0, 0, w, h)); + request.post(context); + } + public void post(Context context) { if (context instanceof FilterShowActivity) { FilterShowActivity activity = (FilterShowActivity) context; @@ -166,6 +186,14 @@ public class RenderingRequest { mDestination = destination; } + public void setIconBounds(Rect bounds) { + mIconBounds = bounds; + } + + public Rect getIconBounds() { + return mIconBounds; + } + public ImagePreset getOriginalImagePreset() { return mOriginalImagePreset; } diff --git a/src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java b/src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java index 406cc9bf5..61ee8eb71 100644 --- a/src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java +++ b/src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java @@ -17,10 +17,12 @@ package com.android.gallery3d.filtershow.pipeline; import android.graphics.Bitmap; + import com.android.gallery3d.filtershow.filters.FiltersManager; import com.android.gallery3d.filtershow.imageshow.MasterImage; public class UpdatePreviewTask extends ProcessingTask { + private static final String LOGTAG = "UpdatePreviewTask"; private CachingPipeline mPreviewPipeline = null; private boolean mHasUnhandledPreviewRequest = false; private boolean mPipelineIsOn = false; diff --git a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java b/src/com/android/gallery3d/filtershow/tools/XmpPresets.java index 3995eeb85..d7c3153f2 100644 --- a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java +++ b/src/com/android/gallery3d/filtershow/tools/XmpPresets.java @@ -116,7 +116,7 @@ public class XmpPresets { Uri srcUri = Uri.parse(strSrcUri); ret.originalimage = srcUri; - ret.preset = new ImagePreset(mMasterImage.getPreset()); + ret.preset = new ImagePreset(); ret.presetString = filterString; boolean ok = ret.preset.readJsonFromString(filterString); if (!ok) { -- 2.11.0