1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.gallery3d.filtershow.filters;
17 
18 import android.graphics.Rect;
19 import android.util.JsonReader;
20 import android.util.JsonWriter;
21 
22 import com.android.gallery3d.R;
23 import com.android.gallery3d.filtershow.editors.EditorGrad;
24 import com.android.gallery3d.filtershow.imageshow.MasterImage;
25 import com.android.gallery3d.filtershow.imageshow.Line;
26 
27 import java.io.IOException;
28 import java.util.Vector;
29 
30 public class FilterGradRepresentation extends FilterRepresentation
31         implements Line {
32     private static final String LOGTAG = "FilterGradRepresentation";
33     public static final int MAX_POINTS = 16;
34     public static final int PARAM_BRIGHTNESS = 0;
35     public static final int PARAM_SATURATION = 1;
36     public static final int PARAM_CONTRAST = 2;
37     private static final double ADD_MIN_DIST = .05;
38     private static String LINE_NAME = "Point";
39     private static final  String SERIALIZATION_NAME = "grad";
40 
FilterGradRepresentation()41     public FilterGradRepresentation() {
42         super("Grad");
43         setSerializationName(SERIALIZATION_NAME);
44         creatExample();
45         setOverlayId(R.drawable.filtershow_button_grad);
46         setFilterClass(ImageFilterGrad.class);
47         setTextId(R.string.grad);
48         setEditorId(EditorGrad.ID);
49     }
50 
trimVector()51     public void trimVector(){
52         int n = mBands.size();
53         for (int i = n; i < MAX_POINTS; i++) {
54             mBands.add(new Band());
55         }
56         for (int i = MAX_POINTS; i <  n; i++) {
57             mBands.remove(i);
58         }
59     }
60 
61     Vector<Band> mBands = new Vector<Band>();
62     Band mCurrentBand;
63 
64     static class Band {
65         private boolean mask = true;
66 
67         private int xPos1 = -1;
68         private int yPos1 = 100;
69         private int xPos2 = -1;
70         private int yPos2 = 100;
71         private int brightness = -40;
72         private int contrast = 0;
73         private int saturation = 0;
74 
75 
Band()76         public Band() {
77         }
78 
Band(int x, int y)79         public Band(int x, int y) {
80             xPos1 = x;
81             yPos1 = y+30;
82             xPos2 = x;
83             yPos2 = y-30;
84         }
85 
Band(Band copy)86         public Band(Band copy) {
87             mask = copy.mask;
88             xPos1 = copy.xPos1;
89             yPos1 = copy.yPos1;
90             xPos2 = copy.xPos2;
91             yPos2 = copy.yPos2;
92             brightness = copy.brightness;
93             contrast = copy.contrast;
94             saturation = copy.saturation;
95         }
96 
97     }
98 
99     @Override
toString()100     public String toString() {
101         int count = 0;
102         for (Band point : mBands) {
103             if (!point.mask) {
104                 count++;
105             }
106         }
107         return "c=" + mBands.indexOf(mBands) + "[" + mBands.size() + "]" + count;
108     }
109 
creatExample()110     private void creatExample() {
111         Band p = new Band();
112         p.mask = false;
113         p.xPos1 = -1;
114         p.yPos1 = 100;
115         p.xPos2 = -1;
116         p.yPos2 = 100;
117         p.brightness = -50;
118         p.contrast = 0;
119         p.saturation = 0;
120         mBands.add(0, p);
121         mCurrentBand = p;
122         trimVector();
123     }
124 
125     @Override
useParametersFrom(FilterRepresentation a)126     public void useParametersFrom(FilterRepresentation a) {
127             FilterGradRepresentation rep = (FilterGradRepresentation) a;
128             Vector<Band> tmpBands = new Vector<Band>();
129             int n = (rep.mCurrentBand == null) ? 0 : rep.mBands.indexOf(rep.mCurrentBand);
130             for (Band band : rep.mBands) {
131                 tmpBands.add(new Band(band));
132             }
133             mCurrentBand = null;
134             mBands = tmpBands;
135             mCurrentBand = mBands.elementAt(n);
136     }
137 
138     @Override
copy()139     public FilterRepresentation copy() {
140         FilterGradRepresentation representation = new FilterGradRepresentation();
141         copyAllParameters(representation);
142         return representation;
143     }
144 
145     @Override
copyAllParameters(FilterRepresentation representation)146     protected void copyAllParameters(FilterRepresentation representation) {
147         super.copyAllParameters(representation);
148         representation.useParametersFrom(this);
149     }
150 
151     @Override
equals(FilterRepresentation representation)152     public boolean equals(FilterRepresentation representation) {
153         if (representation instanceof FilterGradRepresentation) {
154             FilterGradRepresentation rep = (FilterGradRepresentation) representation;
155             int n = getNumberOfBands();
156             if (rep.getNumberOfBands() != n) {
157                 return false;
158             }
159             for (int i = 0; i < mBands.size(); i++) {
160                 Band b1 = mBands.get(i);
161                 Band b2 = rep.mBands.get(i);
162                 if (b1.mask != b2.mask
163                         || b1.brightness != b2.brightness
164                         || b1.contrast != b2.contrast
165                         || b1.saturation != b2.saturation
166                         || b1.xPos1 != b2.xPos1
167                         || b1.xPos2 != b2.xPos2
168                         || b1.yPos1 != b2.yPos1
169                         || b1.yPos2 != b2.yPos2) {
170                     return false;
171                 }
172             }
173             return true;
174         }
175         return false;
176     }
177 
getNumberOfBands()178     public int getNumberOfBands() {
179         int count = 0;
180         for (Band point : mBands) {
181             if (!point.mask) {
182                 count++;
183             }
184         }
185         return count;
186     }
187 
addBand(Rect rect)188     public int addBand(Rect rect) {
189         mBands.add(0, mCurrentBand = new Band(rect.centerX(), rect.centerY()));
190         mCurrentBand.mask = false;
191         int x = (mCurrentBand.xPos1 + mCurrentBand.xPos2)/2;
192         int y = (mCurrentBand.yPos1 + mCurrentBand.yPos2)/2;
193         double addDelta = ADD_MIN_DIST * Math.max(rect.width(), rect.height());
194         boolean moved = true;
195         int count = 0;
196         int toMove =  mBands.indexOf(mCurrentBand);
197 
198         while (moved) {
199             moved = false;
200             count++;
201             if (count > 14) {
202                 break;
203             }
204 
205             for (Band point : mBands) {
206                 if (point.mask) {
207                     break;
208                 }
209             }
210 
211             for (Band point : mBands) {
212                 if (point.mask) {
213                     break;
214                 }
215                 int index = mBands.indexOf(point);
216 
217                 if (toMove != index) {
218                     double dist = Math.hypot(point.xPos1 - x, point.yPos1 - y);
219                     if (dist < addDelta) {
220                         moved = true;
221                         mCurrentBand.xPos1 += addDelta;
222                         mCurrentBand.yPos1 += addDelta;
223                         mCurrentBand.xPos2 += addDelta;
224                         mCurrentBand.yPos2 += addDelta;
225                         x = (mCurrentBand.xPos1 + mCurrentBand.xPos2)/2;
226                         y = (mCurrentBand.yPos1 + mCurrentBand.yPos2)/2;
227 
228                         if (mCurrentBand.yPos1 > rect.bottom) {
229                             mCurrentBand.yPos1 = (int) (rect.top + addDelta);
230                         }
231                         if (mCurrentBand.xPos1 > rect.right) {
232                             mCurrentBand.xPos1 = (int) (rect.left + addDelta);
233                         }
234                     }
235                 }
236             }
237         }
238         trimVector();
239         return 0;
240     }
241 
deleteCurrentBand()242     public void deleteCurrentBand() {
243         int index = mBands.indexOf(mCurrentBand);
244         mBands.remove(mCurrentBand);
245         trimVector();
246         if (getNumberOfBands() == 0) {
247             addBand(MasterImage.getImage().getOriginalBounds());
248         }
249         mCurrentBand = mBands.get(0);
250     }
251 
nextPoint()252     public void  nextPoint(){
253         int index = mBands.indexOf(mCurrentBand);
254         int tmp = index;
255         Band point;
256         int k = 0;
257         do  {
258             index =   (index+1)% mBands.size();
259             point = mBands.get(index);
260             if (k++ >= mBands.size()) {
261                 break;
262             }
263         }
264         while (point.mask == true);
265         mCurrentBand = mBands.get(index);
266     }
267 
setSelectedPoint(int pos)268     public void setSelectedPoint(int pos) {
269         mCurrentBand = mBands.get(pos);
270     }
271 
getSelectedPoint()272     public int getSelectedPoint() {
273         return mBands.indexOf(mCurrentBand);
274     }
275 
getMask()276     public boolean[] getMask() {
277         boolean[] ret = new boolean[mBands.size()];
278         int i = 0;
279         for (Band point : mBands) {
280             ret[i++] = !point.mask;
281         }
282         return ret;
283     }
284 
getXPos1()285     public int[] getXPos1() {
286         int[] ret = new int[mBands.size()];
287         int i = 0;
288         for (Band point : mBands) {
289             ret[i++] = point.xPos1;
290         }
291         return ret;
292     }
293 
getYPos1()294     public int[] getYPos1() {
295         int[] ret = new int[mBands.size()];
296         int i = 0;
297         for (Band point : mBands) {
298             ret[i++] = point.yPos1;
299         }
300         return ret;
301     }
302 
getXPos2()303     public int[] getXPos2() {
304         int[] ret = new int[mBands.size()];
305         int i = 0;
306         for (Band point : mBands) {
307             ret[i++] = point.xPos2;
308         }
309         return ret;
310     }
311 
getYPos2()312     public int[] getYPos2() {
313         int[] ret = new int[mBands.size()];
314         int i = 0;
315         for (Band point : mBands) {
316             ret[i++] = point.yPos2;
317         }
318         return ret;
319     }
320 
getBrightness()321     public int[] getBrightness() {
322         int[] ret = new int[mBands.size()];
323         int i = 0;
324         for (Band point : mBands) {
325             ret[i++] = point.brightness;
326         }
327         return ret;
328     }
329 
getContrast()330     public int[] getContrast() {
331         int[] ret = new int[mBands.size()];
332         int i = 0;
333         for (Band point : mBands) {
334             ret[i++] = point.contrast;
335         }
336         return ret;
337     }
338 
getSaturation()339     public int[] getSaturation() {
340         int[] ret = new int[mBands.size()];
341         int i = 0;
342         for (Band point : mBands) {
343             ret[i++] = point.saturation;
344         }
345         return ret;
346     }
347 
getParameter(int type)348     public int getParameter(int type) {
349         switch (type){
350             case PARAM_BRIGHTNESS:
351                 return mCurrentBand.brightness;
352             case PARAM_SATURATION:
353                 return mCurrentBand.saturation;
354             case PARAM_CONTRAST:
355                 return mCurrentBand.contrast;
356         }
357         throw new IllegalArgumentException("no such type " + type);
358     }
359 
getParameterMax(int type)360     public int getParameterMax(int type) {
361         switch (type) {
362             case PARAM_BRIGHTNESS:
363                 return 100;
364             case PARAM_SATURATION:
365                 return 100;
366             case PARAM_CONTRAST:
367                 return 100;
368         }
369         throw new IllegalArgumentException("no such type " + type);
370     }
371 
getParameterMin(int type)372     public int getParameterMin(int type) {
373         switch (type) {
374             case PARAM_BRIGHTNESS:
375                 return -100;
376             case PARAM_SATURATION:
377                 return -100;
378             case PARAM_CONTRAST:
379                 return -100;
380         }
381         throw new IllegalArgumentException("no such type " + type);
382     }
383 
setParameter(int type, int value)384     public void setParameter(int type, int value) {
385         mCurrentBand.mask = false;
386         switch (type) {
387             case PARAM_BRIGHTNESS:
388                 mCurrentBand.brightness = value;
389                 break;
390             case PARAM_SATURATION:
391                 mCurrentBand.saturation = value;
392                 break;
393             case PARAM_CONTRAST:
394                 mCurrentBand.contrast = value;
395                 break;
396             default:
397                 throw new IllegalArgumentException("no such type " + type);
398         }
399     }
400 
401     @Override
setPoint1(float x, float y)402     public void setPoint1(float x, float y) {
403         mCurrentBand.xPos1 = (int)x;
404         mCurrentBand.yPos1 = (int)y;
405     }
406 
407     @Override
setPoint2(float x, float y)408     public void setPoint2(float x, float y) {
409         mCurrentBand.xPos2 = (int)x;
410         mCurrentBand.yPos2 = (int)y;
411     }
412 
413     @Override
getPoint1X()414     public float getPoint1X() {
415         return mCurrentBand.xPos1;
416     }
417 
418     @Override
getPoint1Y()419     public float getPoint1Y() {
420         return mCurrentBand.yPos1;
421     }
422     @Override
getPoint2X()423     public float getPoint2X() {
424         return mCurrentBand.xPos2;
425     }
426 
427     @Override
getPoint2Y()428     public float getPoint2Y() {
429         return mCurrentBand.yPos2;
430     }
431 
432     @Override
serializeRepresentation(JsonWriter writer)433     public void serializeRepresentation(JsonWriter writer) throws IOException {
434         writer.beginObject();
435         int len = mBands.size();
436         int count = 0;
437 
438         for (int i = 0; i < len; i++) {
439             Band point = mBands.get(i);
440             if (point.mask) {
441                 continue;
442             }
443             writer.name(LINE_NAME + count);
444             count++;
445             writer.beginArray();
446             writer.value(point.xPos1);
447             writer.value(point.yPos1);
448             writer.value(point.xPos2);
449             writer.value(point.yPos2);
450             writer.value(point.brightness);
451             writer.value(point.contrast);
452             writer.value(point.saturation);
453             writer.endArray();
454         }
455         writer.endObject();
456     }
457 
458     @Override
deSerializeRepresentation(JsonReader sreader)459     public void deSerializeRepresentation(JsonReader sreader) throws IOException {
460         sreader.beginObject();
461         Vector<Band> points = new Vector<Band>();
462 
463         while (sreader.hasNext()) {
464             String name = sreader.nextName();
465             if (name.startsWith(LINE_NAME)) {
466                 int pointNo = Integer.parseInt(name.substring(LINE_NAME.length()));
467                 sreader.beginArray();
468                 Band p = new Band();
469                 p.mask = false;
470                 sreader.hasNext();
471                 p.xPos1 = sreader.nextInt();
472                 sreader.hasNext();
473                 p.yPos1 = sreader.nextInt();
474                 sreader.hasNext();
475                 p.xPos2 = sreader.nextInt();
476                 sreader.hasNext();
477                 p.yPos2 = sreader.nextInt();
478                 sreader.hasNext();
479                 p.brightness = sreader.nextInt();
480                 sreader.hasNext();
481                 p.contrast = sreader.nextInt();
482                 sreader.hasNext();
483                 p.saturation = sreader.nextInt();
484                 sreader.hasNext();
485                 sreader.endArray();
486                 points.add(p);
487 
488             } else {
489                 sreader.skipValue();
490             }
491         }
492         mBands = points;
493         trimVector();
494         mCurrentBand = mBands.get(0);
495         sreader.endObject();
496     }
497 }
498