summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
diff options
context:
space:
mode:
authornicolasroard <nicolasroard@google.com>2012-09-25 14:27:56 -0700
committernicolasroard <nicolasroard@google.com>2012-09-26 16:13:45 -0700
commit5728a84cf5fa2733b09af06b9016957a9a566624 (patch)
treed6d95a724fa12a61dc03460865758c9392e59217 /src/com/android/gallery3d/filtershow/ui/ImageCurves.java
parent4994b8649de154c59de47cb1a2e14acca1a17096 (diff)
downloadandroid_packages_apps_Snap-5728a84cf5fa2733b09af06b9016957a9a566624.tar.gz
android_packages_apps_Snap-5728a84cf5fa2733b09af06b9016957a9a566624.tar.bz2
android_packages_apps_Snap-5728a84cf5fa2733b09af06b9016957a9a566624.zip
Initial import of the new image editor
bug:7165910 Change-Id: I756d6594f5bddd233772c979410362ca22e232a3
Diffstat (limited to 'src/com/android/gallery3d/filtershow/ui/ImageCurves.java')
-rw-r--r--src/com/android/gallery3d/filtershow/ui/ImageCurves.java408
1 files changed, 408 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/ui/ImageCurves.java b/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
new file mode 100644
index 000000000..8091c1e7b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
@@ -0,0 +1,408 @@
+
+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.presets.ImagePreset;
+import com.android.gallery3d.filtershow.ui.ControlPoint;
+import com.android.gallery3d.filtershow.ui.Spline;
+import com.android.gallery3d.R;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.PopupMenu;
+import android.widget.Toast;
+
+public class ImageCurves extends ImageShow {
+
+ private static final String LOGTAG = "ImageCurves";
+ Paint gPaint = new Paint();
+ Spline mSpline = null;
+ Path gPathSpline = new Path();
+ 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;
+ private boolean mUseBlue = true;
+
+ public ImageCurves(Context context) {
+ super(context);
+ resetCurve();
+ }
+
+ public ImageCurves(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ resetCurve();
+ }
+
+ public void setMaster(ImageShow master) {
+ mMasterImageShow = master;
+ }
+
+ public boolean showTitle() {
+ return false;
+ }
+
+ public void setUseRed(boolean value) {
+ mUseRed = value;
+ }
+
+ public void setUseGreen(boolean value) {
+ mUseGreen = value;
+ }
+
+ public void setUseBlue(boolean value) {
+ mUseBlue = value;
+ }
+
+ public void reloadCurve() {
+ if (mMasterImageShow != null) {
+ String filterName = getFilterName();
+ ImageFilterCurves filter = (ImageFilterCurves) getImagePreset()
+ .getFilter(filterName);
+ if (filter == null) {
+ resetCurve();
+ return;
+ }
+ mSpline = new Spline(filter.getSpline());
+ applyNewCurve();
+ }
+ }
+
+ public void resetCurve() {
+ mSpline = new Spline();
+
+ mSpline.addPoint(0.0f, 1.0f);
+ mSpline.addPoint(1.0f, 0.0f);
+ if (mMasterImageShow != 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);
+
+ gPaint.setAntiAlias(true);
+ gPaint.setFilterBitmap(true);
+ gPaint.setDither(true);
+
+ drawGrid(canvas);
+ drawSpline(canvas);
+
+ drawToast(canvas);
+ }
+
+ private void drawGrid(Canvas canvas) {
+ float w = getWidth();
+ float h = getHeight();
+
+ // Grid
+ gPaint.setARGB(128, 150, 150, 150);
+ gPaint.setStrokeWidth(1);
+
+ float stepH = h / 9;
+ float stepW = w / 9;
+
+ // central diagonal
+ gPaint.setARGB(255, 100, 100, 100);
+ gPaint.setStrokeWidth(2);
+ canvas.drawLine(0, h, w, 0, gPaint);
+
+ gPaint.setARGB(128, 200, 200, 200);
+ gPaint.setStrokeWidth(4);
+ stepH = h / 3;
+ stepW = w / 3;
+ for (int j = 1; j < 3; j++) {
+ canvas.drawLine(0, j * stepH, w, j * stepH, gPaint);
+ canvas.drawLine(j * stepW, 0, j * stepW, h, gPaint);
+ }
+ }
+
+ private void drawSpline(Canvas canvas) {
+ float w = getWidth();
+ float h = getHeight();
+
+ gPathSpline.reset();
+ for (int x = 0; x < w; x += 11) {
+ float fx = x / w;
+ ControlPoint drawPoint = mSpline.getPoint(fx);
+ float newX = drawPoint.x * w;
+ float newY = drawPoint.y * h;
+ if (x == 0) {
+ gPathSpline.moveTo(newX, newY);
+ } else {
+ gPathSpline.lineTo(newX, newY);
+ }
+ }
+
+ gPaint.setStrokeWidth(10);
+ gPaint.setStyle(Paint.Style.STROKE);
+ gPaint.setARGB(255, 50, 50, 50);
+ canvas.drawPath(gPathSpline, gPaint);
+ gPaint.setStrokeWidth(5);
+ gPaint.setARGB(255, 150, 150, 150);
+ canvas.drawPath(gPathSpline, gPaint);
+
+ gPaint.setARGB(255, 150, 150, 150);
+ for (int j = 1; j < mSpline.getNbPoints() - 1; j++) {
+ ControlPoint point = mSpline.getPoint(j);
+ gPaint.setStrokeWidth(10);
+ gPaint.setARGB(255, 50, 50, 100);
+ canvas.drawCircle(point.x * w, point.y * h, 30, gPaint);
+ gPaint.setStrokeWidth(5);
+ gPaint.setARGB(255, 150, 150, 200);
+ canvas.drawCircle(point.x * w, point.y * h, 30, gPaint);
+ }
+ }
+
+ private int pickControlPoint(float x, float y) {
+ int pick = 0;
+ float px = mSpline.getPoint(0).x;
+ float py = mSpline.getPoint(0).y;
+ double delta = Math.sqrt((px - x) * (px - x) + (py - y) * (py - y));
+ for (int i = 1; i < mSpline.getNbPoints(); i++) {
+ px = mSpline.getPoint(i).x;
+ py = mSpline.getPoint(i).y;
+ double currentDelta = Math.sqrt((px - x) * (px - x) + (py - y)
+ * (py - y));
+ if (currentDelta < delta) {
+ delta = currentDelta;
+ pick = i;
+ }
+ }
+
+ if (!mDidAddPoint && (delta * getWidth() > 100)
+ && (mSpline.getNbPoints() < 10)) {
+ return -1;
+ }
+
+ return pick;// mSpline.getPoint(pick);
+ }
+
+ public void showPopupMenu(View v) {
+ // TODO: sort out the popup menu UI for curves
+ final Context context = v.getContext();
+ PopupMenu popupMenu = new PopupMenu(v.getContext(), v);
+ popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_curves,
+ popupMenu.getMenu());
+
+ popupMenu
+ .setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ Toast.makeText(context, item.toString(),
+ Toast.LENGTH_LONG).show();
+ return true;
+ }
+ });
+
+ popupMenu.show();
+ }
+
+ private String getFilterName() {
+ String filterName = "Curves";
+ if (mUseRed && !mUseGreen && !mUseBlue) {
+ filterName = "CurvesRed";
+ } else if (!mUseRed && mUseGreen && !mUseBlue) {
+ filterName = "CurvesGreen";
+ } else if (!mUseRed && !mUseGreen && mUseBlue) {
+ filterName = "CurvesBlue";
+ }
+ return filterName;
+ }
+
+ @Override
+ public synchronized boolean onTouchEvent(MotionEvent e) {
+ float posX = e.getX() / getWidth();
+ float posY = e.getY() / getHeight();
+
+ /*
+ * if (true) { showPopupMenu(this); return true; }
+ */
+
+ // ControlPoint point = null;
+
+ // Log.v(LOGTAG, "onTouchEvent - " + e + " action masked : " +
+ // e.getActionMasked());
+
+ if (e.getActionMasked() == MotionEvent.ACTION_UP) {
+ applyNewCurve();
+ // Log.v(LOGTAG, "ACTION UP, mCurrentControlPoint set to null!");
+ mCurrentControlPoint = null;
+ ImagePreset copy = new ImagePreset(getImagePreset());
+
+ if (mUseRed && mUseGreen && mUseBlue) {
+ copy.setHistoryName("Curves (RGB)");
+ } else if (mUseRed) {
+ copy.setHistoryName("Curves (Red)");
+ } else if (mUseGreen) {
+ copy.setHistoryName("Curves (Green)");
+ } else if (mUseBlue) {
+ copy.setHistoryName("Curves (Blue)");
+ }
+ copy.setIsFx(false);
+ mImageLoader.getHistory().insert(copy, 0);
+
+ invalidate();
+ mDidAddPoint = false;
+ if (mDidDelete) {
+ mDidDelete = false;
+ }
+ return true;
+ }
+
+ if (mDidDelete) {
+ return true;
+ }
+ // Log.v(LOGTAG, "ACTION DOWN, mCurrentControlPoint is " +
+ // mCurrentControlPoint);
+
+ int pick = pickControlPoint(posX, posY);
+ // Log.v(LOGTAG, "ACTION DOWN, pick is " + pick);
+ if (mCurrentControlPoint == null) {
+ if (pick == -1) {
+ mCurrentControlPoint = new ControlPoint(posX, posY);
+ mSpline.addPoint(mCurrentControlPoint);
+ mDidAddPoint = true;
+ // Log.v(LOGTAG, "ACTION DOWN - 2, added a new control point! "
+ // + mCurrentControlPoint);
+
+ } else {
+ mCurrentControlPoint = mSpline.getPoint(pick);
+ // Log.v(LOGTAG, "ACTION DOWN - 2, picking up control point " +
+ // mCurrentControlPoint + " at pick " + pick);
+ }
+ }
+ // Log.v(LOGTAG, "ACTION DOWN - 3, pick is " + pick);
+
+ if (!((mCurrentControlPoint.x == 0 && mCurrentControlPoint.y == 1) || (mCurrentControlPoint.x == 1 && mCurrentControlPoint.y == 0))) {
+ if (mSpline.isPointContained(posX, pick)) {
+ mCurrentControlPoint.x = posX;
+ mCurrentControlPoint.y = posY;
+ // Log.v(LOGTAG, "ACTION DOWN - 4, move control point " +
+ // mCurrentControlPoint);
+ } else if (pick != -1) {
+ // Log.v(LOGTAG, "ACTION DOWN - 4, delete pick " + pick);
+ mSpline.deletePoint(pick);
+ mDidDelete = true;
+ }
+ }
+ // Log.v(LOGTAG, "ACTION DOWN - 5, DONE");
+ applyNewCurve();
+ invalidate();
+ return true;
+ }
+
+ public synchronized void applyNewCurve() {
+ ControlPoint[] points = new ControlPoint[256];
+ for (int i = 0; i < 256; i++) {
+ float v = i / 255.0f;
+ ControlPoint p = mSpline.getPoint(v);
+ points[i] = p;
+ }
+ for (int i = 0; i < 256; i++) {
+ mAppliedCurve[i] = -1;
+ }
+ for (int i = 0; i < 256; i++) {
+ int index = (int) (points[i].x * 255);
+ if (index >= 0 && index <= 255) {
+ float v = 1.0f - points[i].y;
+ if (v < 0) {
+ v = 0;
+ }
+ if (v > 1.0f) {
+ v = 1.0f;
+ }
+ mAppliedCurve[index] = v;
+ }
+ }
+ float prev = 0;
+ for (int i = 0; i < 256; i++) {
+ if (mAppliedCurve[i] == -1) {
+ // need to interpolate...
+ int j = i + 1;
+ if (j > 255) {
+ j = 255;
+ }
+ for (; j < 256; j++) {
+ if (mAppliedCurve[j] != -1) {
+ break;
+ }
+ }
+ if (j > 255) {
+ j = 255;
+ }
+ // interpolate linearly between i and j - 1
+ float start = prev;
+ float end = mAppliedCurve[j];
+ float delta = (end - start) / (j - i + 1);
+ for (int k = i; k < j; k++) {
+ start = start + delta;
+ mAppliedCurve[k] = start;
+ }
+ i = j;
+ }
+ prev = mAppliedCurve[i];
+ }
+ for (int i = 0; i < 256; i++) {
+ mAppliedCurve[i] = mAppliedCurve[i] * 255;
+ }
+ float[] appliedCurve = new float[256];
+ for (int i = 0; i < 256; i++) {
+ appliedCurve[i] = mAppliedCurve[i];
+ }
+ // update image
+ if (getImagePreset() != null) {
+ String filterName = getFilterName();
+ ImageFilterCurves filter = (ImageFilterCurves) getImagePreset()
+ .getFilter(filterName);
+ if (filter == null) {
+ filter = new ImageFilterCurves();
+ filter.setName(filterName);
+ ImagePreset copy = new ImagePreset(getImagePreset());
+ copy.add(filter);
+ setImagePreset(copy, false);
+ }
+
+ if (filter != null) {
+ filter.setSpline(new Spline(mSpline));
+ filter.setCurve(appliedCurve);
+ filter.setUseRed(mUseRed);
+ filter.setUseGreen(mUseGreen);
+ filter.setUseBlue(mUseBlue);
+ }
+ mImageLoader.resetImageForPreset(getImagePreset(), this);
+ invalidate();
+ }
+ }
+
+}