2 package com.android.gallery3d.filtershow.ui;
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;
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;
20 public class ImageCurves extends ImageSlave {
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;
34 public ImageCurves(Context context) {
39 public ImageCurves(Context context, AttributeSet attrs) {
40 super(context, attrs);
45 public boolean showTitle() {
49 public void setUseRed(boolean value) {
53 public void setUseGreen(boolean value) {
57 public void setUseBlue(boolean value) {
61 public void reloadCurve() {
62 if (getMaster() != null) {
63 String filterName = getFilterName();
64 ImageFilterCurves filter = (ImageFilterCurves) getImagePreset()
65 .getFilter(filterName);
70 mSpline = new Spline(filter.getSpline());
76 public void resetParameter() {
77 super.resetParameter();
81 public void resetCurve() {
82 mSpline = new Spline();
84 mSpline.addPoint(0.0f, 1.0f);
85 mSpline.addPoint(1.0f, 0.0f);
86 if (getMaster() != null) {
92 public void onDraw(Canvas canvas) {
95 gPaint.setAntiAlias(true);
96 gPaint.setFilterBitmap(true);
97 gPaint.setDither(true);
105 private void drawGrid(Canvas canvas) {
106 float w = getWidth();
107 float h = getHeight();
110 gPaint.setARGB(128, 150, 150, 150);
111 gPaint.setStrokeWidth(1);
117 gPaint.setARGB(255, 100, 100, 100);
118 gPaint.setStrokeWidth(2);
119 canvas.drawLine(0, h, w, 0, gPaint);
121 gPaint.setARGB(128, 200, 200, 200);
122 gPaint.setStrokeWidth(4);
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);
131 private void drawSpline(Canvas canvas) {
132 float w = getWidth();
133 float h = getHeight();
136 for (int x = 0; x < w; x += 11) {
138 ControlPoint drawPoint = mSpline.getPoint(fx);
139 float newX = drawPoint.x * w;
140 float newY = drawPoint.y * h;
142 gPathSpline.moveTo(newX, newY);
144 gPathSpline.lineTo(newX, newY);
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);
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);
168 private int pickControlPoint(float x, float y) {
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)
178 if (currentDelta < delta) {
179 delta = currentDelta;
184 if (!mDidAddPoint && (delta * getWidth() > 100)
185 && (mSpline.getNbPoints() < 10)) {
189 return pick;// mSpline.getPoint(pick);
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());
200 .setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
203 public boolean onMenuItemClick(MenuItem item) {
204 Toast.makeText(context, item.toString(),
205 Toast.LENGTH_LONG).show();
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";
226 public synchronized boolean onTouchEvent(MotionEvent e) {
227 float posX = e.getX() / getWidth();
228 float posY = e.getY() / getHeight();
231 * if (true) { showPopupMenu(this); return true; }
234 // ControlPoint point = null;
236 // Log.v(LOGTAG, "onTouchEvent - " + e + " action masked : " +
237 // e.getActionMasked());
239 if (e.getActionMasked() == MotionEvent.ACTION_UP) {
241 // Log.v(LOGTAG, "ACTION UP, mCurrentControlPoint set to null!");
242 mCurrentControlPoint = null;
243 ImagePreset copy = new ImagePreset(getImagePreset());
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)");
255 mImageLoader.getHistory().insert(copy, 0);
258 mDidAddPoint = false;
268 // Log.v(LOGTAG, "ACTION DOWN, mCurrentControlPoint is " +
269 // mCurrentControlPoint);
271 int pick = pickControlPoint(posX, posY);
272 // Log.v(LOGTAG, "ACTION DOWN, pick is " + pick);
273 if (mCurrentControlPoint == null) {
275 mCurrentControlPoint = new ControlPoint(posX, posY);
276 mSpline.addPoint(mCurrentControlPoint);
278 // Log.v(LOGTAG, "ACTION DOWN - 2, added a new control point! "
279 // + mCurrentControlPoint);
282 mCurrentControlPoint = mSpline.getPoint(pick);
283 // Log.v(LOGTAG, "ACTION DOWN - 2, picking up control point " +
284 // mCurrentControlPoint + " at pick " + pick);
287 // Log.v(LOGTAG, "ACTION DOWN - 3, pick is " + pick);
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);
301 // Log.v(LOGTAG, "ACTION DOWN - 5, DONE");
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);
314 for (int i = 0; i < 256; i++) {
315 mAppliedCurve[i] = -1;
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;
327 mAppliedCurve[index] = v;
331 for (int i = 0; i < 256; i++) {
332 if (mAppliedCurve[i] == -1) {
333 // need to interpolate...
338 for (; j < 256; j++) {
339 if (mAppliedCurve[j] != -1) {
346 // interpolate linearly between i and j - 1
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;
356 prev = mAppliedCurve[i];
358 for (int i = 0; i < 256; i++) {
359 mAppliedCurve[i] = mAppliedCurve[i] * 255;
361 float[] appliedCurve = new float[256];
362 for (int i = 0; i < 256; i++) {
363 appliedCurve[i] = mAppliedCurve[i];
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());
375 setImagePreset(copy, false);
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);
385 mImageLoader.resetImageForPreset(getImagePreset(), this);