summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/filtershow/imageshow
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/filtershow/imageshow')
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/GradControl.java274
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java218
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/Line.java26
3 files changed, 518 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GradControl.java b/src/com/android/gallery3d/filtershow/imageshow/GradControl.java
new file mode 100644
index 000000000..964da99e9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/GradControl.java
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.imageshow;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.DashPathEffect;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+import android.graphics.Rect;
+import android.graphics.Shader;
+
+import com.android.gallery3d.R;
+
+public class GradControl {
+ private float mPoint1X = Float.NaN; // used to flag parameters have not been set
+ private float mPoint1Y = 0;
+ private float mPoint2X = 200;
+ private float mPoint2Y = 300;
+ private int mMinTouchDist = 80;// should be a resource & in dips
+
+ private float[] handlex = new float[3];
+ private float[] handley = new float[3];
+ private int mSliderColor;
+ private int mCenterDotSize;
+ private float mDownX;
+ private float mDownY;
+ private float mDownPoint1X;
+ private float mDownPoint1Y;
+ private float mDownPoint2X;
+ private float mDownPoint2Y;
+ Rect mImageBounds;
+ int mImageHeight;
+ private Matrix mScrToImg;
+ Paint mPaint = new Paint();
+ DashPathEffect mDash = new DashPathEffect(new float[]{30, 30}, 0);
+ private boolean mShowReshapeHandles = true;
+ public final static int HAN_CENTER = 0;
+ public final static int HAN_NORTH = 2;
+ public final static int HAN_SOUTH = 1;
+ private int[] mPointColorPatern;
+ private int[] mGrayPointColorPatern;
+ private float[] mPointRadialPos = new float[]{0, .3f, .31f, 1};
+ private int mLineColor;
+ private int mlineShadowColor;
+
+ public GradControl(Context context) {
+
+ Resources res = context.getResources();
+ mCenterDotSize = (int) res.getDimension(R.dimen.gradcontrol_dot_size);
+ mMinTouchDist = (int) res.getDimension(R.dimen.gradcontrol_min_touch_dist);
+ int grayPointCenterColor = res.getColor(R.color.gradcontrol_graypoint_center);
+ int grayPointEdgeColor = res.getColor(R.color.gradcontrol_graypoint_edge);
+ int pointCenterColor = res.getColor(R.color.gradcontrol_point_center);
+ int pointEdgeColor = res.getColor(R.color.gradcontrol_point_edge);
+ int pointShadowStartColor = res.getColor(R.color.gradcontrol_point_shadow_start);
+ int pointShadowEndColor = res.getColor(R.color.gradcontrol_point_shadow_end);
+ mPointColorPatern = new int[]{
+ pointCenterColor, pointEdgeColor, pointShadowStartColor, pointShadowEndColor};
+ mGrayPointColorPatern = new int[]{
+ grayPointCenterColor, grayPointEdgeColor, pointShadowStartColor, pointShadowEndColor};
+ mSliderColor = Color.WHITE;
+ mLineColor = res.getColor(R.color.gradcontrol_line_color);
+ mlineShadowColor = res.getColor(R.color.gradcontrol_line_shadow);
+ }
+
+ public void setPoint2(float x, float y) {
+ mPoint2X = x;
+ mPoint2Y = y;
+ }
+
+ public void setPoint1(float x, float y) {
+ mPoint1X = x;
+ mPoint1Y = y;
+ }
+
+ public int getCloseHandle(float x, float y) {
+ float min = Float.MAX_VALUE;
+ int handle = -1;
+ for (int i = 0; i < handlex.length; i++) {
+ float dx = handlex[i] - x;
+ float dy = handley[i] - y;
+ float dist = dx * dx + dy * dy;
+ if (dist < min) {
+ min = dist;
+ handle = i;
+ }
+ }
+
+ if (min < mMinTouchDist * mMinTouchDist) {
+ return handle;
+ }
+ for (int i = 0; i < handlex.length; i++) {
+ float dx = handlex[i] - x;
+ float dy = handley[i] - y;
+ float dist = (float) Math.sqrt(dx * dx + dy * dy);
+ }
+
+ return -1;
+ }
+
+ public void setScrImageInfo(Matrix scrToImg, Rect imageBounds) {
+ mScrToImg = scrToImg;
+ mImageBounds = new Rect(imageBounds);
+ }
+
+ private boolean centerIsOutside(float x1, float y1, float x2, float y2) {
+ return (!mImageBounds.contains((int) ((x1 + x2) / 2), (int) ((y1 + y2) / 2)));
+ }
+
+ public void actionDown(float x, float y, Line line) {
+ float[] point = new float[]{
+ x, y};
+ mScrToImg.mapPoints(point);
+ mDownX = point[0];
+ mDownY = point[1];
+ mDownPoint1X = line.getPoint1X();
+ mDownPoint1Y = line.getPoint1Y();
+ mDownPoint2X = line.getPoint2X();
+ mDownPoint2Y = line.getPoint2Y();
+ }
+
+ public void actionMove(int handle, float x, float y, Line line) {
+ float[] point = new float[]{
+ x, y};
+ mScrToImg.mapPoints(point);
+ x = point[0];
+ y = point[1];
+
+ // Test if the matrix is swapping x and y
+ point[0] = 0;
+ point[1] = 1;
+ mScrToImg.mapVectors(point);
+ boolean swapxy = (point[0] > 0.0f);
+
+ int sign = 1;
+
+ float dx = x - mDownX;
+ float dy = y - mDownY;
+ switch (handle) {
+ case HAN_CENTER:
+ if (centerIsOutside(mDownPoint1X + dx, mDownPoint1Y + dy,
+ mDownPoint2X + dx, mDownPoint2Y + dy)) {
+ break;
+ }
+ line.setPoint1(mDownPoint1X + dx, mDownPoint1Y + dy);
+ line.setPoint2(mDownPoint2X + dx, mDownPoint2Y + dy);
+ break;
+ case HAN_SOUTH:
+ if (centerIsOutside(mDownPoint1X + dx, mDownPoint1Y + dy,
+ mDownPoint2X, mDownPoint2Y)) {
+ break;
+ }
+ line.setPoint1(mDownPoint1X + dx, mDownPoint1Y + dy);
+ break;
+ case HAN_NORTH:
+ if (centerIsOutside(mDownPoint1X, mDownPoint1Y,
+ mDownPoint2X + dx, mDownPoint2Y + dy)) {
+ break;
+ }
+ line.setPoint2(mDownPoint2X + dx, mDownPoint2Y + dy);
+ break;
+ }
+ }
+
+ public void paintGrayPoint(Canvas canvas, float x, float y) {
+ if (isUndefined()) {
+ return;
+ }
+
+ Paint paint = new Paint();
+ paint.setStyle(Paint.Style.FILL);
+ RadialGradient g = new RadialGradient(x, y, mCenterDotSize, mGrayPointColorPatern,
+ mPointRadialPos, Shader.TileMode.CLAMP);
+ paint.setShader(g);
+ canvas.drawCircle(x, y, mCenterDotSize, paint);
+ }
+
+ public void paintPoint(Canvas canvas, float x, float y) {
+ if (isUndefined()) {
+ return;
+ }
+
+ Paint paint = new Paint();
+ paint.setStyle(Paint.Style.FILL);
+ RadialGradient g = new RadialGradient(x, y, mCenterDotSize, mPointColorPatern,
+ mPointRadialPos, Shader.TileMode.CLAMP);
+ paint.setShader(g);
+ canvas.drawCircle(x, y, mCenterDotSize, paint);
+ }
+
+ void paintLines(Canvas canvas, float p1x, float p1y, float p2x, float p2y) {
+ if (isUndefined()) {
+ return;
+ }
+
+ mPaint.setAntiAlias(true);
+ mPaint.setStyle(Paint.Style.STROKE);
+
+ mPaint.setStrokeWidth(6);
+ mPaint.setColor(mlineShadowColor);
+ mPaint.setPathEffect(mDash);
+ paintOvallines(canvas, mPaint, p1x, p1y, p2x, p2y);
+
+ mPaint.setStrokeWidth(3);
+ mPaint.setColor(mLineColor);
+ mPaint.setPathEffect(mDash);
+ paintOvallines(canvas, mPaint, p1x, p1y, p2x, p2y);
+ }
+
+ public void paintOvallines(
+ Canvas canvas, Paint paint, float p1x, float p1y, float p2x, float p2y) {
+
+
+
+ canvas.drawLine(p1x, p1y, p2x, p2y, paint);
+
+ float cx = (p1x + p2x) / 2;
+ float cy = (p1y + p2y) / 2;
+ float dx = p1x - p2x;
+ float dy = p1y - p2y;
+ float len = (float) Math.sqrt(dx * dx + dy * dy);
+ dx *= 2048 / len;
+ dy *= 2048 / len;
+
+ canvas.drawLine(p1x + dy, p1y - dx, p1x - dy, p1y + dx, paint);
+ canvas.drawLine(p2x + dy, p2y - dx, p2x - dy, p2y + dx, paint);
+ }
+
+ public void fillHandles(Canvas canvas, float p1x, float p1y, float p2x, float p2y) {
+ float cx = (p1x + p2x) / 2;
+ float cy = (p1y + p2y) / 2;
+ handlex[0] = cx;
+ handley[0] = cy;
+ handlex[1] = p1x;
+ handley[1] = p1y;
+ handlex[2] = p2x;
+ handley[2] = p2y;
+
+ }
+
+ public void draw(Canvas canvas) {
+ paintLines(canvas, mPoint1X, mPoint1Y, mPoint2X, mPoint2Y);
+ fillHandles(canvas, mPoint1X, mPoint1Y, mPoint2X, mPoint2Y);
+ paintPoint(canvas, mPoint2X, mPoint2Y);
+ paintPoint(canvas, mPoint1X, mPoint1Y);
+ paintPoint(canvas, (mPoint1X + mPoint2X) / 2, (mPoint1Y + mPoint2Y) / 2);
+ }
+
+ public boolean isUndefined() {
+ return Float.isNaN(mPoint1X);
+ }
+
+ public void setShowReshapeHandles(boolean showReshapeHandles) {
+ this.mShowReshapeHandles = showReshapeHandles;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java b/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java
new file mode 100644
index 000000000..ef72e8a6e
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java
@@ -0,0 +1,218 @@
+package com.android.gallery3d.filtershow.imageshow;
+/*
+ * Copyright (C) 2013 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.
+ */
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorGrad;
+import com.android.gallery3d.filtershow.filters.FilterGradRepresentation;
+
+public class ImageGrad extends ImageShow {
+ private static final String LOGTAG = "ImageGrad";
+ private FilterGradRepresentation mGradRep;
+ private EditorGrad mEditorGrad;
+ private int mMinTouchDist;
+ private int mActiveHandle = -1;
+ private GradControl mEllipse;
+
+ Matrix mToScr = new Matrix();
+ float[] mPointsX = new float[FilterGradRepresentation.MAX_POINTS];
+ float[] mPointsY = new float[FilterGradRepresentation.MAX_POINTS];
+
+ public ImageGrad(Context context) {
+ super(context);
+ Resources res = context.getResources();
+ mMinTouchDist = res.getDimensionPixelSize(R.dimen.gradcontrol_min_touch_dist);
+ mEllipse = new GradControl(context);
+ mEllipse.setShowReshapeHandles(false);
+ }
+
+ public ImageGrad(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mEllipse = new GradControl(context);
+ mEllipse.setShowReshapeHandles(false);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ int mask = event.getActionMasked();
+
+ if (mask == MotionEvent.ACTION_DOWN || mask == MotionEvent.ACTION_UP) {
+ mGradRep.setInking(MotionEvent.ACTION_DOWN == mask);
+ }
+
+ if (mActiveHandle == -1) {
+ if (MotionEvent.ACTION_DOWN != mask) {
+ return super.onTouchEvent(event);
+ }
+ if (event.getPointerCount() == 1) {
+ mActiveHandle = mEllipse.getCloseHandle(event.getX(), event.getY());
+ if (mActiveHandle == -1) {
+ float x = event.getX();
+ float y = event.getY();
+ float min_d = Float.MAX_VALUE;
+ int pos = -1;
+ for (int i = 0; i < mPointsX.length; i++) {
+ if (mPointsX[i] == -1) {
+ continue;
+ }
+ float d = (float) Math.hypot(x - mPointsX[i], y - mPointsY[i]);
+ if ( min_d > d) {
+ min_d = d;
+ pos = i;
+ }
+ }
+ if (min_d > mMinTouchDist){
+ pos = -1;
+ }
+
+ if (pos != -1) {
+ mGradRep.setSelectedPoint(pos);
+ mGradRep.setInking(true);
+ resetImageCaches(this);
+ mEditorGrad.updateSeekBar(mGradRep);
+ mEditorGrad.commitLocalRepresentation();
+ invalidate();
+ }
+ }
+ }
+ if (mActiveHandle == -1) {
+ return super.onTouchEvent(event);
+ }
+ } else {
+ switch (mask) {
+ case MotionEvent.ACTION_UP: {
+
+ mActiveHandle = -1;
+ break;
+ }
+ case MotionEvent.ACTION_DOWN: {
+ break;
+ }
+ }
+ }
+ float x = event.getX();
+ float y = event.getY();
+
+ mEllipse.setScrImageInfo(getScreenToImageMatrix(true),
+ MasterImage.getImage().getOriginalBounds());
+
+ switch (mask) {
+ case (MotionEvent.ACTION_DOWN): {
+ mEllipse.actionDown(x, y, mGradRep);
+ break;
+ }
+ case (MotionEvent.ACTION_UP):
+ case (MotionEvent.ACTION_MOVE): {
+ mEllipse.actionMove(mActiveHandle, x, y, mGradRep);
+ setRepresentation(mGradRep);
+ break;
+ }
+ }
+ invalidate();
+ mEditorGrad.commitLocalRepresentation();
+ return true;
+ }
+
+ public void setRepresentation(FilterGradRepresentation pointRep) {
+ mGradRep = pointRep;
+ Matrix toImg = getScreenToImageMatrix(false);
+
+ toImg.invert(mToScr);
+
+ float[] c1 = new float[] { mGradRep.getPoint1X(), mGradRep.getPoint1Y() };
+ float[] c2 = new float[] { mGradRep.getPoint2X(), mGradRep.getPoint2Y() };
+
+ if (c1[0] == -1) {
+ float cx = MasterImage.getImage().getOriginalBounds().width() / 2;
+ float cy = MasterImage.getImage().getOriginalBounds().height() / 2;
+ float rx = Math.min(cx, cy) * .4f;
+
+ mGradRep.setPoint1(cx, cy-rx);
+ mGradRep.setPoint2(cx, cy+rx);
+ c1[0] = cx;
+ c1[1] = cy-rx;
+ mToScr.mapPoints(c1);
+ if (getWidth() != 0) {
+ mEllipse.setPoint1(c1[0], c1[1]);
+ c2[0] = cx;
+ c2[1] = cy+rx;
+ mToScr.mapPoints(c2);
+ mEllipse.setPoint2(c2[0], c2[1]);
+ }
+ mEditorGrad.commitLocalRepresentation();
+ } else {
+ mToScr.mapPoints(c1);
+ mToScr.mapPoints(c2);
+ mEllipse.setPoint1(c1[0], c1[1]);
+ mEllipse.setPoint2(c2[0], c2[1]);
+ }
+ }
+
+ public void drawOtherPoints(Canvas canvas) {
+ computCenterLocations();
+ for (int i = 0; i < mPointsX.length; i++) {
+ if (mPointsX[i] != -1) {
+ mEllipse.paintGrayPoint(canvas, mPointsX[i], mPointsY[i]);
+ }
+ }
+ }
+
+ public void computCenterLocations() {
+ int x1[] = mGradRep.getXPos1();
+ int y1[] = mGradRep.getYPos1();
+ int x2[] = mGradRep.getXPos2();
+ int y2[] = mGradRep.getYPos2();
+ int selected = mGradRep.getSelectedPoint();
+ boolean m[] = mGradRep.getMask();
+ float[] c = new float[2];
+ for (int i = 0; i < m.length; i++) {
+ if (selected == i || !m[i]) {
+ mPointsX[i] = -1;
+ continue;
+ }
+
+ c[0] = (x1[i]+x2[i])/2;
+ c[1] = (y1[i]+y2[i])/2;
+ mToScr.mapPoints(c);
+
+ mPointsX[i] = c[0];
+ mPointsY[i] = c[1];
+ }
+ }
+
+ public void setEditor(EditorGrad editorGrad) {
+ mEditorGrad = editorGrad;
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (mGradRep == null) {
+ return;
+ }
+ setRepresentation(mGradRep);
+ mEllipse.draw(canvas);
+ drawOtherPoints(canvas);
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/Line.java b/src/com/android/gallery3d/filtershow/imageshow/Line.java
new file mode 100644
index 000000000..a767bd809
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/Line.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.imageshow;
+
+public interface Line {
+ void setPoint1(float x, float y);
+ void setPoint2(float x, float y);
+ float getPoint1X();
+ float getPoint1Y();
+ float getPoint2X();
+ float getPoint2Y();
+}