summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicolasroard <nicolasroard@google.com>2012-10-02 21:57:22 -0700
committernicolasroard <nicolasroard@google.com>2012-10-04 17:11:52 -0700
commit5448bf8095483574649afcc2add7f153670c7450 (patch)
tree13b3e7532f79cfcce29325914642389b9933e8cc
parent94805da05624e939ff402a9586cddacaf622a716 (diff)
downloadandroid_packages_apps_Gallery2-5448bf8095483574649afcc2add7f153670c7450.tar.gz
android_packages_apps_Gallery2-5448bf8095483574649afcc2add7f153670c7450.tar.bz2
android_packages_apps_Gallery2-5448bf8095483574649afcc2add7f153670c7450.zip
Implement sharpen
bug:7279964 bug:7247494 bug:7234321 - add a sharpen filter - add infrastructure to use RenderScript - some refactoring (add an ImageSlave class) - add new zoom UI Change-Id: Id94dc94d32866c7107b6818adf4db35d0c6c0b01
-rw-r--r--Android.mk2
-rw-r--r--res/layout/filtershow_activity.xml6
-rw-r--r--src/com/android/gallery3d/filtershow/FilterShowActivity.java27
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ImageLoader.java47
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ZoomCache.java39
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilter.java2
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java59
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java52
-rw-r--r--src/com/android/gallery3d/filtershow/filters/convolve3x3.rs67
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageBorder.java15
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageShow.java100
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageSlave.java65
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java25
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageZoom.java134
-rw-r--r--src/com/android/gallery3d/filtershow/ui/ImageCurves.java28
-rw-r--r--src/com/android/gallery3d/filtershow/ui/SliderController.java6
-rw-r--r--src/com/android/gallery3d/filtershow/ui/SliderListener.java2
17 files changed, 576 insertions, 100 deletions
diff --git a/Android.mk b/Android.mk
index 1e4430bee..e2914bb3a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -8,7 +8,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13
LOCAL_STATIC_JAVA_LIBRARIES += com.android.gallery3d.common2
LOCAL_STATIC_JAVA_LIBRARIES += mp4parser
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
LOCAL_SRC_FILES += $(call all-java-files-under, src_pd)
LOCAL_SRC_FILES += $(call all-java-files-under, ../Camera/src)
diff --git a/res/layout/filtershow_activity.xml b/res/layout/filtershow_activity.xml
index 0dead607f..1449f16e9 100644
--- a/res/layout/filtershow_activity.xml
+++ b/res/layout/filtershow_activity.xml
@@ -125,6 +125,12 @@
android:layout_height="wrap_content"
android:visibility="gone" />
+ <com.android.gallery3d.filtershow.imageshow.ImageZoom
+ android:id="@+id/imageZoom"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone" />
+
<ImageButton
android:id="@+id/showOriginalButton"
android:layout_width="64dip"
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index 694f51290..389973e50 100644
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -11,6 +11,7 @@ import com.android.gallery3d.filtershow.imageshow.ImageBorder;
import com.android.gallery3d.filtershow.imageshow.ImageShow;
import com.android.gallery3d.filtershow.imageshow.ImageSmallFilter;
import com.android.gallery3d.filtershow.imageshow.ImageStraighten;
+import com.android.gallery3d.filtershow.imageshow.ImageZoom;
import com.android.gallery3d.filtershow.presets.*;
import com.android.gallery3d.filtershow.provider.SharedImageProvider;
import com.android.gallery3d.filtershow.tools.SaveCopyTask;
@@ -19,6 +20,7 @@ import com.android.gallery3d.R;
import android.net.Uri;
import android.os.Bundle;
+import android.renderscript.RenderScript;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
@@ -57,6 +59,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
private ImageCurves mImageCurves = null;
private ImageBorder mImageBorders = null;
private ImageStraighten mImageStraighten = null;
+ private ImageZoom mImageZoom = null;
private View mListFx = null;
private View mListBorders = null;
@@ -100,6 +103,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ ImageFilterRS.setRenderScriptContext(this);
+
setContentView(R.layout.filtershow_activity);
ActionBar actionBar = getActionBar();
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
@@ -121,11 +126,13 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mImageCurves = (ImageCurves) findViewById(R.id.imageCurves);
mImageBorders = (ImageBorder) findViewById(R.id.imageBorder);
mImageStraighten = (ImageStraighten) findViewById(R.id.imageStraighten);
+ mImageZoom = (ImageZoom) findViewById(R.id.imageZoom);
mImageViews.add(mImageShow);
mImageViews.add(mImageCurves);
mImageViews.add(mImageBorders);
mImageViews.add(mImageStraighten);
+ mImageViews.add(mImageZoom);
mListFx = findViewById(R.id.fxList);
mListBorders = findViewById(R.id.bordersList);
@@ -211,6 +218,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mImageBorders.setMaster(mImageShow);
mImageStraighten.setImageLoader(mImageLoader);
mImageStraighten.setMaster(mImageShow);
+ mImageZoom.setImageLoader(mImageLoader);
+ mImageZoom.setMaster(mImageShow);
Intent intent = getIntent();
String data = intent.getDataString();
@@ -688,11 +697,23 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
@Override
public void onClick(View v) {
hideImageViews();
- mImageShow.setVisibility(View.VISIBLE);
+ mImageZoom.setVisibility(View.VISIBLE);
+ mImageZoom.setShowControls(true);
+ ImagePreset preset = mImageZoom.getImagePreset();
+ ImageFilter filter = preset.getFilter("Sharpen");
+ if (filter == null) {
+ ImageFilterSharpen sharpen = new ImageFilterSharpen();
+ ImagePreset copy = new ImagePreset(preset);
+ copy.add(sharpen);
+ copy.setHistoryName(sharpen.getName());
+ copy.setIsFx(false);
+ filter = copy.getFilter("Sharpen");
+ mImageZoom.setImagePreset(copy);
+ }
+ mImageZoom.setCurrentFilter(filter);
unselectPanelButtons(mColorsPanelButtons);
mSharpenButton.setSelected(true);
- mImageShow.showToast("Sharpen", true);
- mImageShow.setCurrentFilter(null);
+ invalidateViews();
}
};
}
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
index ac16c13cd..9944f5fce 100644
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
@@ -8,7 +8,9 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
import android.graphics.Matrix;
+import android.graphics.Rect;
import android.media.ExifInterface;
import android.net.Uri;
import android.provider.MediaStore;
@@ -42,6 +44,7 @@ public class ImageLoader {
private Cache mCache = new DelayedPresetCache(30);
private Cache mHiresCache = new DelayedPresetCache(2);
+ private ZoomCache mZoomCache = new ZoomCache();
private int mOrientation = 0;
private HistoryAdapter mAdapter = null;
@@ -50,6 +53,8 @@ public class ImageLoader {
private Context mContext = null;
private Uri mUri = null;
+ private Rect mOriginalBounds = null;
+
public ImageLoader(Context context) {
mContext = context;
}
@@ -66,6 +71,10 @@ public class ImageLoader {
return mUri;
}
+ public Rect getOriginalBounds() {
+ return mOriginalBounds;
+ }
+
private int getOrientation(Uri uri) {
if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
return getOrientationFromPath(uri.getPath());
@@ -125,6 +134,22 @@ public class ImageLoader {
}
}
+ private Bitmap loadRegionBitmap(Uri uri, Rect bounds) {
+ InputStream is = null;
+ try {
+ is = mContext.getContentResolver().openInputStream(uri);
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
+ return decoder.decodeRegion(bounds, null);
+ } catch (FileNotFoundException e) {
+ Log.e(LOGTAG, "FileNotFoundException: " + uri);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ closeStream(is);
+ }
+ return null;
+ }
+
private Bitmap loadScaledBitmap(Uri uri, int size) {
InputStream is = null;
try {
@@ -137,6 +162,9 @@ public class ImageLoader {
int width_tmp = o.outWidth;
int height_tmp = o.outHeight;
+
+ mOriginalBounds = new Rect(0, 0, width_tmp, height_tmp);
+
int scale = 1;
while (true) {
if (width_tmp / 2 < size || height_tmp / 2 < size)
@@ -192,6 +220,24 @@ public class ImageLoader {
}
}
+ // TODO: this currently does the loading + filtering on the UI thread -- need to
+ // move this to a background thread.
+ public Bitmap getScaleOneImageForPreset(ImageShow caller, ImagePreset imagePreset, Rect bounds,
+ boolean force) {
+ Bitmap bmp = mZoomCache.getImage(imagePreset, bounds);
+ if (force || bmp == null) {
+ bmp = loadRegionBitmap(mUri, bounds);
+ if (bmp != null) {
+ // TODO: this workaround for RS might not be needed ultimately
+ Bitmap bmp2 = bmp.copy(Bitmap.Config.ARGB_8888, true);
+ imagePreset.apply(bmp2);
+ mZoomCache.setImage(imagePreset, bounds, bmp2);
+ return bmp2;
+ }
+ }
+ return bmp;
+ }
+
// Caching method
public Bitmap getImageForPreset(ImageShow caller, ImagePreset imagePreset,
boolean hiRes) {
@@ -223,6 +269,7 @@ public class ImageLoader {
public void resetImageForPreset(ImagePreset imagePreset, ImageShow caller) {
mHiresCache.reset(imagePreset);
mCache.reset(imagePreset);
+ mZoomCache.reset(imagePreset);
}
public Uri saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity,
diff --git a/src/com/android/gallery3d/filtershow/cache/ZoomCache.java b/src/com/android/gallery3d/filtershow/cache/ZoomCache.java
new file mode 100644
index 000000000..e6e7f14ce
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/cache/ZoomCache.java
@@ -0,0 +1,39 @@
+package com.android.gallery3d.filtershow.cache;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+
+import com.android.gallery3d.filtershow.presets.ImagePreset;
+
+public class ZoomCache {
+
+ private ImagePreset mImagePreset = null;
+ private Bitmap mBitmap = null;
+ private Rect mBounds = null;
+
+ // TODO: move the processing to a background thread...
+ public Bitmap getImage(ImagePreset preset, Rect bounds) {
+ if (mBounds != bounds) {
+ return null;
+ }
+ if (mImagePreset == null) {
+ return null;
+ }
+ if (!mImagePreset.same(preset)) {
+ return null;
+ }
+ return mBitmap;
+ }
+
+ public void setImage(ImagePreset preset, Rect bounds, Bitmap bitmap) {
+ mBitmap = bitmap;
+ mBounds = bounds;
+ mImagePreset = preset;
+ }
+
+ public void reset(ImagePreset imagePreset) {
+ if (imagePreset == mImagePreset) {
+ mBitmap = null;
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
index c2bd952f8..c039fce47 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
@@ -2,11 +2,13 @@
package com.android.gallery3d.filtershow.filters;
import android.graphics.Bitmap;
+import android.util.Log;
public class ImageFilter implements Cloneable {
protected int mParameter = 0;
protected String mName = "Original";
+ private final String LOGTAG = "ImageFilter";
@Override
public ImageFilter clone() throws CloneNotSupportedException {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
new file mode 100644
index 000000000..ab2d304a4
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
@@ -0,0 +1,59 @@
+package com.android.gallery3d.filtershow.filters;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.util.Log;
+
+public class ImageFilterRS extends ImageFilter {
+ private final String LOGTAG = "ImageFilterRS";
+
+ private static RenderScript mRS = null;
+ protected static Allocation mInPixelsAllocation;
+ protected static Allocation mOutPixelsAllocation;
+ private static android.content.res.Resources mResources = null;
+
+ public void prepare(Bitmap bitmap) {
+ mInPixelsAllocation = Allocation.createFromBitmap(mRS, bitmap,
+ Allocation.MipmapControl.MIPMAP_NONE,
+ Allocation.USAGE_SCRIPT);
+ mOutPixelsAllocation = Allocation.createTyped(mRS, mInPixelsAllocation.getType());
+ }
+
+ public void createFilter(android.content.res.Resources res) {
+ }
+
+ public void runFilter() {
+ }
+
+ public void update(Bitmap bitmap) {
+ mOutPixelsAllocation.copyTo(bitmap);
+ }
+
+ public void apply(Bitmap bitmap) {
+ if (bitmap == null) {
+ return;
+ }
+ try {
+ prepare(bitmap);
+ createFilter(mResources);
+ runFilter();
+ update(bitmap);
+ } catch (android.renderscript.RSIllegalArgumentException e) {
+ Log.e(LOGTAG, "Illegal argument? " + e);
+ } catch (android.renderscript.RSRuntimeException e) {
+ Log.e(LOGTAG, "RS runtime exception ? " + e);
+ }
+ }
+
+ public static RenderScript getRenderScriptContext() {
+ return mRS;
+ }
+
+ public static void setRenderScriptContext(Activity context) {
+ mRS = RenderScript.create(context);
+ mResources = context.getResources();
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
new file mode 100644
index 000000000..3ec7b5f70
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
@@ -0,0 +1,52 @@
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+import android.util.Log;
+import android.renderscript.Element;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+
+import com.android.gallery3d.R;
+
+public class ImageFilterSharpen extends ImageFilterRS {
+
+ private static final String LOGTAG = "ImageFilterSharpen";
+ private ScriptC_convolve3x3 mScript;
+
+ public ImageFilterSharpen() {
+ mName = "Sharpen";
+ }
+
+ public void createFilter(android.content.res.Resources res) {
+ int w = mInPixelsAllocation.getType().getX();
+ int h = mInPixelsAllocation.getType().getY();
+
+ float p1 = mParameter;
+ float value = p1 / 100.0f;
+ float f[] = new float[9];
+ float p = value;
+ f[0] = -p;
+ f[1] = -p;
+ f[2] = -p;
+ f[3] = -p;
+ f[4] = 8 * p + 1;
+ f[5] = -p;
+ f[6] = -p;
+ f[7] = -p;
+ f[8] = -p;
+ if (mScript == null) {
+ mScript = new ScriptC_convolve3x3(getRenderScriptContext(), res, R.raw.convolve3x3);
+ }
+ mScript.set_gCoeffs(f);
+ mScript.set_gWidth(w);
+ mScript.set_gHeight(h);
+ }
+
+ public void runFilter() {
+ mScript.set_gIn(mInPixelsAllocation);
+ mScript.bind_gPixels(mInPixelsAllocation);
+ mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs b/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs
new file mode 100644
index 000000000..2acffab06
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+const uchar4 *gPixels;
+rs_allocation gIn;
+
+float gCoeffs[9];
+
+void root(const uchar4 *in, uchar4 *out, const void *usrData, uint32_t x, uint32_t y) {
+ uint32_t x1 = min((int32_t)x+1, gWidth-1);
+ uint32_t x2 = max((int32_t)x-1, 0);
+ uint32_t y1 = min((int32_t)y+1, gHeight-1);
+ uint32_t y2 = max((int32_t)y-1, 0);
+
+ float4 p00 = rsUnpackColor8888(gPixels[x1 + gWidth * y1]);
+ float4 p01 = rsUnpackColor8888(gPixels[x + gWidth * y1]);
+ float4 p02 = rsUnpackColor8888(gPixels[x2 + gWidth * y1]);
+ float4 p10 = rsUnpackColor8888(gPixels[x1 + gWidth * y]);
+ float4 p11 = rsUnpackColor8888(gPixels[x + gWidth * y]);
+ float4 p12 = rsUnpackColor8888(gPixels[x2 + gWidth * y]);
+ float4 p20 = rsUnpackColor8888(gPixels[x1 + gWidth * y2]);
+ float4 p21 = rsUnpackColor8888(gPixels[x + gWidth * y2]);
+ float4 p22 = rsUnpackColor8888(gPixels[x2 + gWidth * y2]);
+
+ p00 *= gCoeffs[0];
+ p01 *= gCoeffs[1];
+ p02 *= gCoeffs[2];
+ p10 *= gCoeffs[3];
+ p11 *= gCoeffs[4];
+ p12 *= gCoeffs[5];
+ p20 *= gCoeffs[6];
+ p21 *= gCoeffs[7];
+ p22 *= gCoeffs[8];
+
+ p00 += p01;
+ p02 += p10;
+ p11 += p12;
+ p20 += p21;
+
+ p22 += p00;
+ p02 += p11;
+
+ p20 += p22;
+ p20 += p02;
+
+ p20 = clamp(p20, 0.f, 1.f);
+ *out = rsPackColorTo8888(p20.r, p20.g, p20.b);
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageBorder.java b/src/com/android/gallery3d/filtershow/imageshow/ImageBorder.java
index 00be8267d..f8c0142ae 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageBorder.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageBorder.java
@@ -13,9 +13,8 @@ import android.graphics.Rect;
import android.graphics.drawable.NinePatchDrawable;
import android.util.AttributeSet;
-public class ImageBorder extends ImageShow {
+public class ImageBorder extends ImageSlave {
Paint gPaint = new Paint();
- private ImageShow mMasterImageShow = null;
public ImageBorder(Context context) {
super(context);
@@ -25,18 +24,6 @@ public class ImageBorder extends ImageShow {
super(context, attrs);
}
- public void setMaster(ImageShow master) {
- mMasterImageShow = master;
- }
-
- public ImagePreset getImagePreset() {
- return mMasterImageShow.getImagePreset();
- }
-
- public void setImagePreset(ImagePreset preset, boolean addToHistory) {
- mMasterImageShow.setImagePreset(preset, addToHistory);
- }
-
public boolean showTitle() {
return false;
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
index 2caa2d578..2a660d40f 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
@@ -61,19 +61,31 @@ public class ImageShow extends View implements SliderListener {
private boolean mShowToast = false;
private boolean mImportantToast = false;
+ protected float mTouchX = 0;
+ protected float mTouchY = 0;
+
private Handler mHandler = new Handler();
public void onNewValue(int value) {
- if (mCurrentFilter != null) {
- mCurrentFilter.setParameter(value);
+ if (getCurrentFilter() != null) {
+ getCurrentFilter().setParameter(value);
}
- if (mImagePreset != null) {
- mImageLoader.resetImageForPreset(mImagePreset, this);
- mImagePreset.fillImageStateAdapter(mImageStateAdapter);
+ if (getImagePreset() != null) {
+ mImageLoader.resetImageForPreset(getImagePreset(), this);
+ getImagePreset().fillImageStateAdapter(mImageStateAdapter);
}
invalidate();
}
+ public void onTouchDown(float x, float y) {
+ mTouchX = x;
+ mTouchY = y;
+ invalidate();
+ }
+
+ public void onTouchUp() {
+ }
+
public ImageShow(Context context, AttributeSet attrs) {
super(context, attrs);
mSliderController.setListener(this);
@@ -102,6 +114,10 @@ public class ImageShow extends View implements SliderListener {
mCurrentFilter = filter;
}
+ public ImageFilter getCurrentFilter() {
+ return mCurrentFilter;
+ }
+
public void setAdapter(HistoryAdapter adapter) {
mHistoryAdapter = adapter;
}
@@ -125,6 +141,10 @@ public class ImageShow extends View implements SliderListener {
}, 400);
}
+ public Rect getImageBounds() {
+ return mImageBounds;
+ }
+
public ImagePreset getImagePreset() {
return mImagePreset;
}
@@ -161,16 +181,32 @@ public class ImageShow extends View implements SliderListener {
}
public void onDraw(Canvas canvas) {
- if (mBackgroundImage == null) {
- mBackgroundImage = mImageLoader.getBackgroundBitmap(getResources());
+ drawBackground(canvas);
+ getFilteredImage();
+ drawImage(canvas, mFilteredImage);
+
+ if (showTitle() && getImagePreset() != null) {
+ mPaint.setARGB(200, 0, 0, 0);
+ mPaint.setTextSize(mTextSize);
+
+ Rect textRect = new Rect(0, 0, getWidth(), mTextSize + mTextPadding);
+ canvas.drawRect(textRect, mPaint);
+ mPaint.setARGB(255, 200, 200, 200);
+ canvas.drawText(getImagePreset().name(), mTextPadding,
+ 10 + mTextPadding, mPaint);
}
- if (mBackgroundImage != null) {
- Rect s = new Rect(0, 0, mBackgroundImage.getWidth(),
- mBackgroundImage.getHeight());
- Rect d = new Rect(0, 0, getWidth(), getHeight());
- canvas.drawBitmap(mBackgroundImage, s, d, mPaint);
+ mPaint.setARGB(255, 150, 150, 150);
+ mPaint.setStrokeWidth(4);
+ canvas.drawLine(0, 0, getWidth(), 0, mPaint);
+
+ if (showControls()) {
+ mSliderController.onDraw(canvas);
}
+ drawToast(canvas);
+ }
+
+ public void getFilteredImage() {
Bitmap filteredImage = null;
if (mImageLoader != null) {
filteredImage = mImageLoader.getImageForPreset(this,
@@ -187,12 +223,14 @@ public class ImageShow extends View implements SliderListener {
if (mShowOriginal || mFilteredImage == null) {
mFilteredImage = mForegroundImage;
}
+ }
- if (mFilteredImage != null) {
- Rect s = new Rect(0, 0, mFilteredImage.getWidth(),
- mFilteredImage.getHeight());
- float ratio = mFilteredImage.getWidth()
- / (float) mFilteredImage.getHeight();
+ public void drawImage(Canvas canvas, Bitmap image) {
+ if (image != null) {
+ Rect s = new Rect(0, 0, image.getWidth(),
+ image.getHeight());
+ float ratio = image.getWidth()
+ / (float) image.getHeight();
float w = getWidth();
float h = w / ratio;
float ty = (getHeight() - h) / 2.0f;
@@ -208,28 +246,20 @@ public class ImageShow extends View implements SliderListener {
(int) (h + ty));
mImageBounds = d;
- canvas.drawBitmap(mFilteredImage, s, d, mPaint);
+ canvas.drawBitmap(image, s, d, mPaint);
}
+ }
- if (showTitle() && getImagePreset() != null) {
- mPaint.setARGB(200, 0, 0, 0);
- mPaint.setTextSize(mTextSize);
-
- Rect textRect = new Rect(0, 0, getWidth(), mTextSize + mTextPadding);
- canvas.drawRect(textRect, mPaint);
- mPaint.setARGB(255, 200, 200, 200);
- canvas.drawText(getImagePreset().name(), mTextPadding,
- 10 + mTextPadding, mPaint);
+ public void drawBackground(Canvas canvas) {
+ if (mBackgroundImage == null) {
+ mBackgroundImage = mImageLoader.getBackgroundBitmap(getResources());
}
- mPaint.setARGB(255, 150, 150, 150);
- mPaint.setStrokeWidth(4);
- canvas.drawLine(0, 0, getWidth(), 0, mPaint);
-
- if (showControls()) {
- mSliderController.onDraw(canvas);
+ if (mBackgroundImage != null) {
+ Rect s = new Rect(0, 0, mBackgroundImage.getWidth(),
+ mBackgroundImage.getHeight());
+ Rect d = new Rect(0, 0, getWidth(), getHeight());
+ canvas.drawBitmap(mBackgroundImage, s, d, mPaint);
}
-
- drawToast(canvas);
}
public void setShowControls(boolean value) {
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageSlave.java b/src/com/android/gallery3d/filtershow/imageshow/ImageSlave.java
new file mode 100644
index 000000000..debaec708
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageSlave.java
@@ -0,0 +1,65 @@
+package com.android.gallery3d.filtershow.imageshow;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+
+import com.android.gallery3d.filtershow.filters.ImageFilter;
+import com.android.gallery3d.filtershow.presets.ImagePreset;
+
+public class ImageSlave extends ImageShow {
+ private ImageShow mMasterImageShow = null;
+
+ public ImageSlave(Context context) {
+ super(context);
+ }
+
+ public ImageSlave(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ImageShow getMaster() {
+ return mMasterImageShow;
+ }
+
+ public void setMaster(ImageShow master) {
+ mMasterImageShow = master;
+ }
+
+ public ImagePreset getImagePreset() {
+ return mMasterImageShow.getImagePreset();
+ }
+
+ public void setImagePreset(ImagePreset preset, boolean addToHistory) {
+ mMasterImageShow.setImagePreset(preset, addToHistory);
+ }
+
+ public void setCurrentFilter(ImageFilter filter) {
+ mMasterImageShow.setCurrentFilter(filter);
+ }
+
+ public ImageFilter getCurrentFilter() {
+ return mMasterImageShow.getCurrentFilter();
+ }
+
+ public void updateAngle() {
+ mMasterImageShow.setImageRotation(mImageRotation, mImageRotationZoomFactor);
+ }
+
+ public boolean showTitle() {
+ return false;
+ }
+
+ public float getImageRotation() {
+ return mMasterImageShow.getImageRotation();
+ }
+
+ public float getImageRotationZoomFactor() {
+ return mMasterImageShow.getImageRotationZoomFactor();
+ }
+
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java b/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
index c4f0456cb..eb034bf10 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
@@ -15,8 +15,7 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
-public class ImageStraighten extends ImageShow {
- private ImageShow mMasterImageShow = null;
+public class ImageStraighten extends ImageSlave {
private float mImageRotation = 0;
private float mImageRotationZoomFactor = 0;
@@ -48,26 +47,6 @@ public class ImageStraighten extends ImageShow {
super(context, attrs);
}
- public void updateAngle() {
- mMasterImageShow.setImageRotation(mImageRotation, mImageRotationZoomFactor);
- }
-
- public void setMaster(ImageShow master) {
- mMasterImageShow = master;
- }
-
- public boolean showTitle() {
- return false;
- }
-
- public ImagePreset getImagePreset() {
- return mMasterImageShow.getImagePreset();
- }
-
- public void setImagePreset(ImagePreset preset, boolean addToHistory) {
- mMasterImageShow.setImagePreset(preset, addToHistory);
- }
-
// ///////////////////////////////////////////////////////////////////////////
// touch event handler
@@ -168,7 +147,7 @@ public class ImageStraighten extends ImageShow {
// so that we can fake the rotation, etc.
Bitmap image = null; // mMasterImageShow.mFilteredImage;
if (image == null) {
- image = mMasterImageShow.mForegroundImage;
+ image = getMaster().mForegroundImage;
}
if (image == null) {
return;
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageZoom.java b/src/com/android/gallery3d/filtershow/imageshow/ImageZoom.java
new file mode 100644
index 000000000..1c5a9b50e
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageZoom.java
@@ -0,0 +1,134 @@
+package com.android.gallery3d.filtershow.imageshow;
+
+import com.android.gallery3d.filtershow.presets.ImagePreset;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.GestureDetector;
+import android.view.GestureDetector.OnDoubleTapListener;
+import android.view.GestureDetector.OnGestureListener;
+import android.view.MotionEvent;
+
+public class ImageZoom extends ImageSlave implements OnGestureListener, OnDoubleTapListener {
+ private boolean mTouchDown = false;
+ private boolean mZoomedIn = false;
+ private Rect mZoomBounds = null;
+ private GestureDetector mGestureDetector = null;
+
+ public ImageZoom(Context context) {
+ super(context);
+ setupGestureDetector(context);
+ }
+
+ public ImageZoom(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setupGestureDetector(context);
+ }
+
+ public void setupGestureDetector(Context context) {
+ mGestureDetector = new GestureDetector(context, this);
+ }
+
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean ret = mGestureDetector.onTouchEvent(event);
+ ret = super.onTouchEvent(event);
+ return ret;
+ }
+
+ public void onTouchDown(float x, float y) {
+ super.onTouchDown(x, y);
+ if (mZoomedIn || mTouchDown) {
+ return;
+ }
+ mTouchDown = true;
+ Rect originalBounds = mImageLoader.getOriginalBounds();
+ Rect imageBounds = getImageBounds();
+ float touchX = x - imageBounds.left;
+ float touchY = y - imageBounds.top;
+
+ float w = originalBounds.width();
+ float h = originalBounds.height();
+ float ratio = w / h;
+ int mw = getWidth() / 2;
+ int mh = getHeight() / 2;
+ int cx = (int) (w / 2);
+ int cy = (int) (h / 2);
+ cx = (int) (touchX / imageBounds.width() * w);
+ cy = (int) (touchY / imageBounds.height() * h);
+ int left = cx - mw;
+ int top = cy - mh;
+ mZoomBounds = new Rect(left, top, left + mw * 2, top + mh * 2);
+ }
+
+ public void onTouchUp() {
+ mTouchDown = false;
+ }
+
+ public void onDraw(Canvas canvas) {
+ drawBackground(canvas);
+ Bitmap filteredImage = null;
+ if ((mZoomedIn ||mTouchDown) && mImageLoader != null) {
+ filteredImage = mImageLoader.getScaleOneImageForPreset(this, getImagePreset(), mZoomBounds, false);
+ } else {
+ getFilteredImage();
+ filteredImage = mFilteredImage;
+ }
+ drawImage(canvas, filteredImage);
+ if (showControls()) {
+ mSliderController.onDraw(canvas);
+ }
+
+ drawToast(canvas);
+ }
+
+ // TODO: move back some of that touch handling to a superclass / refactor
+ // SlideController into a more generic gesture detector
+ @Override
+ public boolean onDown(MotionEvent arg0) {
+ return false;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
+ return false;
+ }
+
+ @Override
+ public void onLongPress(MotionEvent arg0) {
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
+ return false;
+ }
+
+ @Override
+ public void onShowPress(MotionEvent arg0) {
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent arg0) {
+ return false;
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent arg0) {
+ return false;
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent arg0) {
+ mZoomedIn = !mZoomedIn;
+ invalidate();
+ return false;
+ }
+
+ @Override
+ public boolean onDoubleTapEvent(MotionEvent arg0) {
+ return false;
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/ui/ImageCurves.java b/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
index 8091c1e7b..3da058bc7 100644
--- a/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
+++ b/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
@@ -4,6 +4,7 @@ package com.android.gallery3d.filtershow.ui;
import com.android.gallery3d.filtershow.filters.ImageFilter;
import com.android.gallery3d.filtershow.filters.ImageFilterCurves;
import com.android.gallery3d.filtershow.imageshow.ImageShow;
+import com.android.gallery3d.filtershow.imageshow.ImageSlave;
import com.android.gallery3d.filtershow.presets.ImagePreset;
import com.android.gallery3d.filtershow.ui.ControlPoint;
import com.android.gallery3d.filtershow.ui.Spline;
@@ -22,7 +23,7 @@ import android.view.View;
import android.widget.PopupMenu;
import android.widget.Toast;
-public class ImageCurves extends ImageShow {
+public class ImageCurves extends ImageSlave {
private static final String LOGTAG = "ImageCurves";
Paint gPaint = new Paint();
@@ -31,7 +32,6 @@ public class ImageCurves extends ImageShow {
float[] mAppliedCurve = new float[256];
private boolean mDidAddPoint = false;
private boolean mDidDelete = false;
- private ImageShow mMasterImageShow = null;
private ControlPoint mCurrentControlPoint = null;
private boolean mUseRed = true;
private boolean mUseGreen = true;
@@ -47,10 +47,6 @@ public class ImageCurves extends ImageShow {
resetCurve();
}
- public void setMaster(ImageShow master) {
- mMasterImageShow = master;
- }
-
public boolean showTitle() {
return false;
}
@@ -68,7 +64,7 @@ public class ImageCurves extends ImageShow {
}
public void reloadCurve() {
- if (mMasterImageShow != null) {
+ if (getMaster() != null) {
String filterName = getFilterName();
ImageFilterCurves filter = (ImageFilterCurves) getImagePreset()
.getFilter(filterName);
@@ -86,27 +82,11 @@ public class ImageCurves extends ImageShow {
mSpline.addPoint(0.0f, 1.0f);
mSpline.addPoint(1.0f, 0.0f);
- if (mMasterImageShow != null) {
+ if (getMaster() != null) {
applyNewCurve();
}
}
- public ImagePreset getImagePreset() {
- return mMasterImageShow.getImagePreset();
- }
-
- public void setImagePreset(ImagePreset preset, boolean addToHistory) {
- mMasterImageShow.setImagePreset(preset, addToHistory);
- }
-
- public float getImageRotation() {
- return mMasterImageShow.getImageRotation();
- }
-
- public float getImageRotationZoomFactor() {
- return mMasterImageShow.getImageRotationZoomFactor();
- }
-
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
diff --git a/src/com/android/gallery3d/filtershow/ui/SliderController.java b/src/com/android/gallery3d/filtershow/ui/SliderController.java
index b5b9c81ec..f2f0df30b 100644
--- a/src/com/android/gallery3d/filtershow/ui/SliderController.java
+++ b/src/com/android/gallery3d/filtershow/ui/SliderController.java
@@ -116,6 +116,9 @@ public class SliderController {
mCurrentX = x;
mCurrentY = y;
mMode = MODES.DOWN;
+ if (mListener != null) {
+ mListener.onTouchDown(x, y);
+ }
}
public void setActionMove(float x, float y) {
@@ -131,6 +134,9 @@ public class SliderController {
public void setActionUp() {
mMode = MODES.UP;
mOriginalValue = computeValue();
+ if (mListener != null) {
+ mListener.onTouchUp();
+ }
}
public void setNoAction() {
diff --git a/src/com/android/gallery3d/filtershow/ui/SliderListener.java b/src/com/android/gallery3d/filtershow/ui/SliderListener.java
index 67e28de0e..b11966ece 100644
--- a/src/com/android/gallery3d/filtershow/ui/SliderListener.java
+++ b/src/com/android/gallery3d/filtershow/ui/SliderListener.java
@@ -3,4 +3,6 @@ package com.android.gallery3d.filtershow.ui;
public interface SliderListener {
public void onNewValue(int value);
+ public void onTouchDown(float x, float y);
+ public void onTouchUp();
}