OSDN Git Service

New UI...
[android-x86/packages-apps-Gallery2.git] / src / com / android / gallery3d / filtershow / ui / ImageCurves.java
1
2 package com.android.gallery3d.filtershow.ui;
3
4 import android.content.Context;
5 import android.graphics.Canvas;
6 import android.graphics.Paint;
7 import android.graphics.Path;
8 import android.util.AttributeSet;
9 import android.view.MenuItem;
10 import android.view.MotionEvent;
11 import android.view.View;
12 import android.widget.PopupMenu;
13 import android.widget.Toast;
14
15 import com.android.gallery3d.R;
16 import com.android.gallery3d.filtershow.filters.ImageFilterCurves;
17 import com.android.gallery3d.filtershow.imageshow.ImageSlave;
18 import com.android.gallery3d.filtershow.presets.ImagePreset;
19
20 public class ImageCurves extends ImageSlave {
21
22     private static final String LOGTAG = "ImageCurves";
23     Paint gPaint = new Paint();
24     Spline mSpline = null;
25     Path gPathSpline = new Path();
26     float[] mAppliedCurve = new float[256];
27     private boolean mDidAddPoint = false;
28     private boolean mDidDelete = false;
29     private ControlPoint mCurrentControlPoint = null;
30     private boolean mUseRed = true;
31     private boolean mUseGreen = true;
32     private boolean mUseBlue = true;
33
34     public ImageCurves(Context context) {
35         super(context);
36         resetCurve();
37     }
38
39     public ImageCurves(Context context, AttributeSet attrs) {
40         super(context, attrs);
41         resetCurve();
42     }
43
44     @Override
45     public boolean showTitle() {
46         return false;
47     }
48
49     public void setUseRed(boolean value) {
50         mUseRed = value;
51     }
52
53     public void setUseGreen(boolean value) {
54         mUseGreen = value;
55     }
56
57     public void setUseBlue(boolean value) {
58         mUseBlue = value;
59     }
60
61     public void reloadCurve() {
62         if (getMaster() != null) {
63             String filterName = getFilterName();
64             ImageFilterCurves filter = (ImageFilterCurves) getImagePreset()
65                     .getFilter(filterName);
66             if (filter == null) {
67                 resetCurve();
68                 return;
69             }
70             mSpline = new Spline(filter.getSpline());
71             applyNewCurve();
72         }
73     }
74
75     @Override
76     public void resetParameter() {
77         super.resetParameter();
78         resetCurve();
79     }
80
81     public void resetCurve() {
82         mSpline = new Spline();
83
84         mSpline.addPoint(0.0f, 1.0f);
85         mSpline.addPoint(1.0f, 0.0f);
86         if (getMaster() != null) {
87             applyNewCurve();
88         }
89     }
90
91     @Override
92     public void onDraw(Canvas canvas) {
93         super.onDraw(canvas);
94
95         gPaint.setAntiAlias(true);
96         gPaint.setFilterBitmap(true);
97         gPaint.setDither(true);
98
99         drawGrid(canvas);
100         drawSpline(canvas);
101
102         drawToast(canvas);
103     }
104
105     private void drawGrid(Canvas canvas) {
106         float w = getWidth();
107         float h = getHeight();
108
109         // Grid
110         gPaint.setARGB(128, 150, 150, 150);
111         gPaint.setStrokeWidth(1);
112
113         float stepH = h / 9;
114         float stepW = w / 9;
115
116         // central diagonal
117         gPaint.setARGB(255, 100, 100, 100);
118         gPaint.setStrokeWidth(2);
119         canvas.drawLine(0, h, w, 0, gPaint);
120
121         gPaint.setARGB(128, 200, 200, 200);
122         gPaint.setStrokeWidth(4);
123         stepH = h / 3;
124         stepW = w / 3;
125         for (int j = 1; j < 3; j++) {
126             canvas.drawLine(0, j * stepH, w, j * stepH, gPaint);
127             canvas.drawLine(j * stepW, 0, j * stepW, h, gPaint);
128         }
129     }
130
131     private void drawSpline(Canvas canvas) {
132         float w = getWidth();
133         float h = getHeight();
134
135         gPathSpline.reset();
136         for (int x = 0; x < w; x += 11) {
137             float fx = x / w;
138             ControlPoint drawPoint = mSpline.getPoint(fx);
139             float newX = drawPoint.x * w;
140             float newY = drawPoint.y * h;
141             if (x == 0) {
142                 gPathSpline.moveTo(newX, newY);
143             } else {
144                 gPathSpline.lineTo(newX, newY);
145             }
146         }
147
148         gPaint.setStrokeWidth(10);
149         gPaint.setStyle(Paint.Style.STROKE);
150         gPaint.setARGB(255, 50, 50, 50);
151         canvas.drawPath(gPathSpline, gPaint);
152         gPaint.setStrokeWidth(5);
153         gPaint.setARGB(255, 150, 150, 150);
154         canvas.drawPath(gPathSpline, gPaint);
155
156         gPaint.setARGB(255, 150, 150, 150);
157         for (int j = 1; j < mSpline.getNbPoints() - 1; j++) {
158             ControlPoint point = mSpline.getPoint(j);
159             gPaint.setStrokeWidth(10);
160             gPaint.setARGB(255, 50, 50, 100);
161             canvas.drawCircle(point.x * w, point.y * h, 30, gPaint);
162             gPaint.setStrokeWidth(5);
163             gPaint.setARGB(255, 150, 150, 200);
164             canvas.drawCircle(point.x * w, point.y * h, 30, gPaint);
165         }
166     }
167
168     private int pickControlPoint(float x, float y) {
169         int pick = 0;
170         float px = mSpline.getPoint(0).x;
171         float py = mSpline.getPoint(0).y;
172         double delta = Math.sqrt((px - x) * (px - x) + (py - y) * (py - y));
173         for (int i = 1; i < mSpline.getNbPoints(); i++) {
174             px = mSpline.getPoint(i).x;
175             py = mSpline.getPoint(i).y;
176             double currentDelta = Math.sqrt((px - x) * (px - x) + (py - y)
177                     * (py - y));
178             if (currentDelta < delta) {
179                 delta = currentDelta;
180                 pick = i;
181             }
182         }
183
184         if (!mDidAddPoint && (delta * getWidth() > 100)
185                 && (mSpline.getNbPoints() < 10)) {
186             return -1;
187         }
188
189         return pick;// mSpline.getPoint(pick);
190     }
191
192     public void showPopupMenu(View v) {
193         // TODO: sort out the popup menu UI for curves
194         final Context context = v.getContext();
195         PopupMenu popupMenu = new PopupMenu(v.getContext(), v);
196         popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_curves,
197                 popupMenu.getMenu());
198
199         popupMenu
200                 .setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
201
202                     @Override
203                     public boolean onMenuItemClick(MenuItem item) {
204                         Toast.makeText(context, item.toString(),
205                                 Toast.LENGTH_LONG).show();
206                         return true;
207                     }
208                 });
209
210         popupMenu.show();
211     }
212
213     private String getFilterName() {
214         String filterName = "Curves";
215         if (mUseRed && !mUseGreen && !mUseBlue) {
216             filterName = "CurvesRed";
217         } else if (!mUseRed && mUseGreen && !mUseBlue) {
218             filterName = "CurvesGreen";
219         } else if (!mUseRed && !mUseGreen && mUseBlue) {
220             filterName = "CurvesBlue";
221         }
222         return filterName;
223     }
224
225     @Override
226     public synchronized boolean onTouchEvent(MotionEvent e) {
227         float posX = e.getX() / getWidth();
228         float posY = e.getY() / getHeight();
229
230         /*
231          * if (true) { showPopupMenu(this); return true; }
232          */
233
234         // ControlPoint point = null;
235
236         // Log.v(LOGTAG, "onTouchEvent - " + e + " action masked : " +
237         // e.getActionMasked());
238
239         if (e.getActionMasked() == MotionEvent.ACTION_UP) {
240             applyNewCurve();
241             // Log.v(LOGTAG, "ACTION UP, mCurrentControlPoint set to null!");
242             mCurrentControlPoint = null;
243             ImagePreset copy = new ImagePreset(getImagePreset());
244
245             if (mUseRed && mUseGreen && mUseBlue) {
246                 copy.setHistoryName("Curves (RGB)");
247             } else if (mUseRed) {
248                 copy.setHistoryName("Curves (Red)");
249             } else if (mUseGreen) {
250                 copy.setHistoryName("Curves (Green)");
251             } else if (mUseBlue) {
252                 copy.setHistoryName("Curves (Blue)");
253             }
254             copy.setIsFx(false);
255             mImageLoader.getHistory().insert(copy, 0);
256
257             invalidate();
258             mDidAddPoint = false;
259             if (mDidDelete) {
260                 mDidDelete = false;
261             }
262             return true;
263         }
264
265         if (mDidDelete) {
266             return true;
267         }
268         // Log.v(LOGTAG, "ACTION DOWN, mCurrentControlPoint is " +
269         // mCurrentControlPoint);
270
271         int pick = pickControlPoint(posX, posY);
272         // Log.v(LOGTAG, "ACTION DOWN, pick is " + pick);
273         if (mCurrentControlPoint == null) {
274             if (pick == -1) {
275                 mCurrentControlPoint = new ControlPoint(posX, posY);
276                 mSpline.addPoint(mCurrentControlPoint);
277                 mDidAddPoint = true;
278                 // Log.v(LOGTAG, "ACTION DOWN - 2, added a new control point! "
279                 // + mCurrentControlPoint);
280
281             } else {
282                 mCurrentControlPoint = mSpline.getPoint(pick);
283                 // Log.v(LOGTAG, "ACTION DOWN - 2, picking up control point " +
284                 // mCurrentControlPoint + " at pick " + pick);
285             }
286         }
287         // Log.v(LOGTAG, "ACTION DOWN - 3, pick is " + pick);
288
289         if (!((mCurrentControlPoint.x == 0 && mCurrentControlPoint.y == 1) || (mCurrentControlPoint.x == 1 && mCurrentControlPoint.y == 0))) {
290             if (mSpline.isPointContained(posX, pick)) {
291                 mCurrentControlPoint.x = posX;
292                 mCurrentControlPoint.y = posY;
293                 // Log.v(LOGTAG, "ACTION DOWN - 4, move control point " +
294                 // mCurrentControlPoint);
295             } else if (pick != -1) {
296                 // Log.v(LOGTAG, "ACTION DOWN - 4, delete pick " + pick);
297                 mSpline.deletePoint(pick);
298                 mDidDelete = true;
299             }
300         }
301         // Log.v(LOGTAG, "ACTION DOWN - 5, DONE");
302         applyNewCurve();
303         invalidate();
304         return true;
305     }
306
307     public synchronized void applyNewCurve() {
308         ControlPoint[] points = new ControlPoint[256];
309         for (int i = 0; i < 256; i++) {
310             float v = i / 255.0f;
311             ControlPoint p = mSpline.getPoint(v);
312             points[i] = p;
313         }
314         for (int i = 0; i < 256; i++) {
315             mAppliedCurve[i] = -1;
316         }
317         for (int i = 0; i < 256; i++) {
318             int index = (int) (points[i].x * 255);
319             if (index >= 0 && index <= 255) {
320                 float v = 1.0f - points[i].y;
321                 if (v < 0) {
322                     v = 0;
323                 }
324                 if (v > 1.0f) {
325                     v = 1.0f;
326                 }
327                 mAppliedCurve[index] = v;
328             }
329         }
330         float prev = 0;
331         for (int i = 0; i < 256; i++) {
332             if (mAppliedCurve[i] == -1) {
333                 // need to interpolate...
334                 int j = i + 1;
335                 if (j > 255) {
336                     j = 255;
337                 }
338                 for (; j < 256; j++) {
339                     if (mAppliedCurve[j] != -1) {
340                         break;
341                     }
342                 }
343                 if (j > 255) {
344                     j = 255;
345                 }
346                 // interpolate linearly between i and j - 1
347                 float start = prev;
348                 float end = mAppliedCurve[j];
349                 float delta = (end - start) / (j - i + 1);
350                 for (int k = i; k < j; k++) {
351                     start = start + delta;
352                     mAppliedCurve[k] = start;
353                 }
354                 i = j;
355             }
356             prev = mAppliedCurve[i];
357         }
358         for (int i = 0; i < 256; i++) {
359             mAppliedCurve[i] = mAppliedCurve[i] * 255;
360         }
361         float[] appliedCurve = new float[256];
362         for (int i = 0; i < 256; i++) {
363             appliedCurve[i] = mAppliedCurve[i];
364         }
365         // update image
366         if (getImagePreset() != null) {
367             String filterName = getFilterName();
368             ImageFilterCurves filter = (ImageFilterCurves) getImagePreset()
369                     .getFilter(filterName);
370             if (filter == null) {
371                 filter = new ImageFilterCurves();
372                 filter.setName(filterName);
373                 ImagePreset copy = new ImagePreset(getImagePreset());
374                 copy.add(filter);
375                 setImagePreset(copy, false);
376             }
377
378             if (filter != null) {
379                 filter.setSpline(new Spline(mSpline));
380                 filter.setCurve(appliedCurve);
381                 filter.setUseRed(mUseRed);
382                 filter.setUseGreen(mUseGreen);
383                 filter.setUseBlue(mUseBlue);
384             }
385             mImageLoader.resetImageForPreset(getImagePreset(), this);
386             invalidate();
387         }
388     }
389
390 }