1 /*
2  * Copyright (C) 2012 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 
17 package com.android.gallery3d.filtershow.pipeline;
18 
19 import android.graphics.Bitmap;
20 import android.graphics.Rect;
21 import android.support.v8.renderscript.Allocation;
22 import android.util.JsonReader;
23 import android.util.JsonWriter;
24 import android.util.Log;
25 
26 import com.android.gallery3d.R;
27 import com.android.gallery3d.filtershow.cache.BitmapCache;
28 import com.android.gallery3d.filtershow.cache.ImageLoader;
29 import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
30 import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
31 import com.android.gallery3d.filtershow.filters.FilterFxRepresentation;
32 import com.android.gallery3d.filtershow.filters.FilterImageBorderRepresentation;
33 import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
34 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
35 import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
36 import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
37 import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
38 import com.android.gallery3d.filtershow.filters.FiltersManager;
39 import com.android.gallery3d.filtershow.filters.ImageFilter;
40 import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
41 import com.android.gallery3d.filtershow.imageshow.MasterImage;
42 import com.android.gallery3d.filtershow.state.State;
43 import com.android.gallery3d.filtershow.state.StateAdapter;
44 
45 import java.io.IOException;
46 import java.io.StringReader;
47 import java.io.StringWriter;
48 import java.util.ArrayList;
49 import java.util.Collection;
50 import java.util.Vector;
51 
52 public class ImagePreset {
53 
54     private static final String LOGTAG = "ImagePreset";
55     public static final String JASON_SAVED = "Saved";
56 
57     private Vector<FilterRepresentation> mFilters = new Vector<FilterRepresentation>();
58 
59     private boolean mDoApplyGeometry = true;
60     private boolean mDoApplyFilters = true;
61 
62     private boolean mPartialRendering = false;
63     private Rect mPartialRenderingBounds;
64     private static final boolean DEBUG = false;
65 
ImagePreset()66     public ImagePreset() {
67     }
68 
ImagePreset(ImagePreset source)69     public ImagePreset(ImagePreset source) {
70         for (int i = 0; i < source.mFilters.size(); i++) {
71             FilterRepresentation sourceRepresentation = source.mFilters.elementAt(i);
72             mFilters.add(sourceRepresentation.copy());
73         }
74     }
75 
getFilters()76     public Vector<FilterRepresentation> getFilters() {
77         return mFilters;
78     }
79 
getFilterRepresentation(int position)80     public FilterRepresentation getFilterRepresentation(int position) {
81         FilterRepresentation representation = null;
82 
83         representation = mFilters.elementAt(position).copy();
84 
85         return representation;
86     }
87 
sameSerializationName(String a, String b)88     private static boolean sameSerializationName(String a, String b) {
89         if (a != null && b != null) {
90             return a.equals(b);
91         } else {
92             return a == null && b == null;
93         }
94     }
95 
sameSerializationName(FilterRepresentation a, FilterRepresentation b)96     public static boolean sameSerializationName(FilterRepresentation a, FilterRepresentation b) {
97         if (a == null || b == null) {
98             return false;
99         }
100         return sameSerializationName(a.getSerializationName(), b.getSerializationName());
101     }
102 
getPositionForRepresentation(FilterRepresentation representation)103     public int getPositionForRepresentation(FilterRepresentation representation) {
104         for (int i = 0; i < mFilters.size(); i++) {
105             if (sameSerializationName(mFilters.elementAt(i), representation)) {
106                 return i;
107             }
108         }
109         return -1;
110     }
111 
getFilterRepresentationForType(int type)112     private FilterRepresentation getFilterRepresentationForType(int type) {
113         for (int i = 0; i < mFilters.size(); i++) {
114             if (mFilters.elementAt(i).getFilterType() == type) {
115                 return mFilters.elementAt(i);
116             }
117         }
118         return null;
119     }
120 
getPositionForType(int type)121     public int getPositionForType(int type) {
122         for (int i = 0; i < mFilters.size(); i++) {
123             if (mFilters.elementAt(i).getFilterType() == type) {
124                 return i;
125             }
126         }
127         return -1;
128     }
129 
getFilterRepresentationCopyFrom( FilterRepresentation filterRepresentation)130     public FilterRepresentation getFilterRepresentationCopyFrom(
131             FilterRepresentation filterRepresentation) {
132         // TODO: add concept of position in the filters (to allow multiple instances)
133         if (filterRepresentation == null) {
134             return null;
135         }
136         int position = getPositionForRepresentation(filterRepresentation);
137         if (position == -1) {
138             return null;
139         }
140         FilterRepresentation representation = mFilters.elementAt(position);
141         if (representation != null) {
142             representation = representation.copy();
143         }
144         return representation;
145     }
146 
updateFilterRepresentations(Collection<FilterRepresentation> reps)147     public void updateFilterRepresentations(Collection<FilterRepresentation> reps) {
148         for (FilterRepresentation r : reps) {
149             updateOrAddFilterRepresentation(r);
150         }
151     }
152 
updateOrAddFilterRepresentation(FilterRepresentation rep)153     public void updateOrAddFilterRepresentation(FilterRepresentation rep) {
154         int pos = getPositionForRepresentation(rep);
155         if (pos != -1) {
156             mFilters.elementAt(pos).useParametersFrom(rep);
157         } else {
158             addFilter(rep.copy());
159         }
160     }
161 
setDoApplyGeometry(boolean value)162     public void setDoApplyGeometry(boolean value) {
163         mDoApplyGeometry = value;
164     }
165 
setDoApplyFilters(boolean value)166     public void setDoApplyFilters(boolean value) {
167         mDoApplyFilters = value;
168     }
169 
getDoApplyFilters()170     public boolean getDoApplyFilters() {
171         return mDoApplyFilters;
172     }
173 
hasModifications()174     public boolean hasModifications() {
175         for (int i = 0; i < mFilters.size(); i++) {
176             FilterRepresentation filter = mFilters.elementAt(i);
177             if (!filter.isNil()) {
178                 return true;
179             }
180         }
181         return false;
182     }
183 
contains(byte type)184     public boolean contains(byte type) {
185         for (FilterRepresentation representation : mFilters) {
186             if (representation.getFilterType() == type
187                     && !representation.isNil()) {
188                 return true;
189             }
190         }
191         return false;
192     }
193 
isPanoramaSafe()194     public boolean isPanoramaSafe() {
195         for (FilterRepresentation representation : mFilters) {
196             if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY
197                     && !representation.isNil()) {
198                 return false;
199             }
200             if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER
201                     && !representation.isNil()) {
202                 return false;
203             }
204             if (representation.getFilterType() == FilterRepresentation.TYPE_VIGNETTE
205                     && !representation.isNil()) {
206                 return false;
207             }
208             if (representation.getFilterType() == FilterRepresentation.TYPE_TINYPLANET
209                     && !representation.isNil()) {
210                 return false;
211             }
212         }
213         return true;
214     }
215 
same(ImagePreset preset)216     public boolean same(ImagePreset preset) {
217         if (preset == null) {
218             return false;
219         }
220 
221         if (preset.mFilters.size() != mFilters.size()) {
222             return false;
223         }
224 
225         if (mDoApplyGeometry != preset.mDoApplyGeometry) {
226             return false;
227         }
228 
229         if (mDoApplyFilters != preset.mDoApplyFilters) {
230             if (mFilters.size() > 0 || preset.mFilters.size() > 0) {
231                 return false;
232             }
233         }
234 
235         if (mDoApplyFilters && preset.mDoApplyFilters) {
236             for (int i = 0; i < preset.mFilters.size(); i++) {
237                 FilterRepresentation a = preset.mFilters.elementAt(i);
238                 FilterRepresentation b = mFilters.elementAt(i);
239 
240                 if (!a.same(b)) {
241                     return false;
242                 }
243             }
244         }
245 
246         return true;
247     }
248 
equals(ImagePreset preset)249     public boolean equals(ImagePreset preset) {
250         if (preset == null) {
251             return false;
252         }
253 
254         if (preset.mFilters.size() != mFilters.size()) {
255             return false;
256         }
257 
258         if (mDoApplyGeometry != preset.mDoApplyGeometry) {
259             return false;
260         }
261 
262         if (mDoApplyFilters != preset.mDoApplyFilters) {
263             if (mFilters.size() > 0 || preset.mFilters.size() > 0) {
264                 return false;
265             }
266         }
267 
268         for (int i = 0; i < preset.mFilters.size(); i++) {
269             FilterRepresentation a = preset.mFilters.elementAt(i);
270             FilterRepresentation b = mFilters.elementAt(i);
271             boolean isGeometry = false;
272             if (a instanceof FilterRotateRepresentation
273                     || a instanceof FilterMirrorRepresentation
274                     || a instanceof FilterCropRepresentation
275                     || a instanceof FilterStraightenRepresentation) {
276                 isGeometry = true;
277             }
278             boolean evaluate = true;
279             if (!isGeometry && mDoApplyGeometry && !mDoApplyFilters) {
280                 evaluate = false;
281             } else if (isGeometry && !mDoApplyGeometry && mDoApplyFilters) {
282                 evaluate = false;
283             }
284             if (evaluate && !a.equals(b)) {
285                 return false;
286             }
287         }
288 
289         return true;
290     }
291 
similarUpTo(ImagePreset preset)292     public int similarUpTo(ImagePreset preset) {
293         for (int i = 0; i < preset.mFilters.size(); i++) {
294             FilterRepresentation a = preset.mFilters.elementAt(i);
295             if (i < mFilters.size()) {
296                 FilterRepresentation b = mFilters.elementAt(i);
297                 if (!a.same(b)) {
298                     return i;
299                 }
300                 if (!a.equals(b)) {
301                     return i;
302                 }
303             } else {
304                 return i;
305             }
306         }
307         return preset.mFilters.size();
308     }
309 
showFilters()310     public void showFilters() {
311         Log.v(LOGTAG, "\\\\\\ showFilters -- " + mFilters.size() + " filters");
312         int n = 0;
313         for (FilterRepresentation representation : mFilters) {
314             Log.v(LOGTAG, " filter " + n + " : " + representation.toString());
315             n++;
316         }
317         Log.v(LOGTAG, "/// showFilters -- " + mFilters.size() + " filters");
318     }
319 
getLastRepresentation()320     public FilterRepresentation getLastRepresentation() {
321         if (mFilters.size() > 0) {
322             return mFilters.lastElement();
323         }
324         return null;
325     }
326 
removeFilter(FilterRepresentation filterRepresentation)327     public void removeFilter(FilterRepresentation filterRepresentation) {
328         if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
329             for (int i = 0; i < mFilters.size(); i++) {
330                 if (mFilters.elementAt(i).getFilterType()
331                 == filterRepresentation.getFilterType()) {
332                     mFilters.remove(i);
333                     break;
334                 }
335             }
336         } else {
337             for (int i = 0; i < mFilters.size(); i++) {
338                 if (sameSerializationName(mFilters.elementAt(i), filterRepresentation)) {
339                     mFilters.remove(i);
340                     break;
341                 }
342             }
343         }
344     }
345 
346     // If the filter is an "None" effect or border, then just don't add this filter.
addFilter(FilterRepresentation representation)347     public void addFilter(FilterRepresentation representation) {
348         if (representation instanceof FilterUserPresetRepresentation) {
349             ImagePreset preset = ((FilterUserPresetRepresentation) representation).getImagePreset();
350             if (preset.nbFilters() == 1
351                 && preset.contains(FilterRepresentation.TYPE_FX)) {
352                 FilterRepresentation rep = preset.getFilterRepresentationForType(
353                         FilterRepresentation.TYPE_FX);
354                 addFilter(rep);
355             } else {
356                 // user preset replaces everything
357                 mFilters.clear();
358                 for (int i = 0; i < preset.nbFilters(); i++) {
359                     addFilter(preset.getFilterRepresentation(i));
360                 }
361             }
362         } else if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) {
363             // Add geometry filter, removing duplicates and do-nothing operations.
364             for (int i = 0; i < mFilters.size(); i++) {
365                 if (sameSerializationName(representation, mFilters.elementAt(i))) {
366                     mFilters.remove(i);
367                 }
368             }
369             int index = 0;
370             for (; index < mFilters.size(); index++) {
371                 FilterRepresentation rep = mFilters.elementAt(index);
372                 if (rep.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
373                     break;
374                 }
375             }
376             if (!representation.isNil()) {
377                 mFilters.insertElementAt(representation, index);
378             }
379         } else if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
380             removeFilter(representation);
381             if (!isNoneBorderFilter(representation)) {
382                 mFilters.add(representation);
383             }
384         } else if (representation.getFilterType() == FilterRepresentation.TYPE_FX) {
385             boolean replaced = false;
386             for (int i = 0; i < mFilters.size(); i++) {
387                 FilterRepresentation current = mFilters.elementAt(i);
388                 if (current.getFilterType() == FilterRepresentation.TYPE_FX) {
389                     mFilters.remove(i);
390                     replaced = true;
391                     if (!isNoneFxFilter(representation)) {
392                         mFilters.add(i, representation);
393                     }
394                     break;
395                 }
396             }
397             if (!replaced && !isNoneFxFilter(representation)) {
398                 mFilters.add(0, representation);
399             }
400         } else {
401             mFilters.add(representation);
402         }
403         // Enforces Filter type ordering for borders
404         FilterRepresentation border = null;
405         for (int i = 0; i < mFilters.size();) {
406             FilterRepresentation rep = mFilters.elementAt(i);
407             if (rep.getFilterType() == FilterRepresentation.TYPE_BORDER) {
408                 border = rep;
409                 mFilters.remove(i);
410                 continue;
411             }
412             i++;
413         }
414         if (border != null) {
415             mFilters.add(border);
416         }
417     }
418 
isNoneBorderFilter(FilterRepresentation representation)419     private boolean isNoneBorderFilter(FilterRepresentation representation) {
420         return representation instanceof FilterImageBorderRepresentation &&
421                 ((FilterImageBorderRepresentation) representation).getDrawableResource() == 0;
422     }
423 
isNoneFxFilter(FilterRepresentation representation)424     private boolean isNoneFxFilter(FilterRepresentation representation) {
425         return representation instanceof FilterFxRepresentation &&
426                 ((FilterFxRepresentation) representation).getNameResource() == R.string.none;
427     }
428 
getRepresentation(FilterRepresentation filterRepresentation)429     public FilterRepresentation getRepresentation(FilterRepresentation filterRepresentation) {
430         for (int i = 0; i < mFilters.size(); i++) {
431             FilterRepresentation representation = mFilters.elementAt(i);
432             if (sameSerializationName(representation, filterRepresentation)) {
433                 return representation;
434             }
435         }
436         return null;
437     }
438 
apply(Bitmap original, FilterEnvironment environment)439     public Bitmap apply(Bitmap original, FilterEnvironment environment) {
440         Bitmap bitmap = original;
441         bitmap = applyFilters(bitmap, -1, -1, environment);
442         return applyBorder(bitmap, environment);
443     }
444 
getGeometryFilters()445     public Collection<FilterRepresentation> getGeometryFilters() {
446         ArrayList<FilterRepresentation> geometry = new ArrayList<FilterRepresentation>();
447         for (FilterRepresentation r : mFilters) {
448             if (r.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) {
449                 geometry.add(r);
450             }
451         }
452         return geometry;
453     }
454 
getFilterWithSerializationName(String serializationName)455     public FilterRepresentation getFilterWithSerializationName(String serializationName) {
456         for (FilterRepresentation r : mFilters) {
457             if (r != null) {
458                 if (sameSerializationName(r.getSerializationName(), serializationName)) {
459                     return r.copy();
460                 }
461             }
462         }
463         return null;
464     }
465 
finalGeometryRect(int width, int height)466     public Rect finalGeometryRect(int width, int height) {
467         return GeometryMathUtils.finalGeometryRect(width, height, getGeometryFilters());
468     }
469 
applyGeometry(Bitmap bitmap, FilterEnvironment environment)470     public Bitmap applyGeometry(Bitmap bitmap, FilterEnvironment environment) {
471         // Apply any transform -- 90 rotate, flip, straighten, crop
472         // Returns a new bitmap.
473         if (mDoApplyGeometry) {
474             Bitmap bmp = GeometryMathUtils.applyGeometryRepresentations(
475                     getGeometryFilters(), bitmap);
476             if (bmp != bitmap) {
477                 environment.cache(bitmap);
478             }
479             return bmp;
480         }
481         return bitmap;
482     }
483 
applyBorder(Bitmap bitmap, FilterEnvironment environment)484     public Bitmap applyBorder(Bitmap bitmap, FilterEnvironment environment) {
485         // get the border from the list of filters.
486         FilterRepresentation border = getFilterRepresentationForType(
487                 FilterRepresentation.TYPE_BORDER);
488         if (border != null && mDoApplyGeometry) {
489             bitmap = environment.applyRepresentation(border, bitmap);
490             if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) {
491             }
492         }
493         return bitmap;
494     }
495 
nbFilters()496     public int nbFilters() {
497         return mFilters.size();
498     }
499 
applyFilters(Bitmap bitmap, int from, int to, FilterEnvironment environment)500     public Bitmap applyFilters(Bitmap bitmap, int from, int to, FilterEnvironment environment) {
501         if (mDoApplyFilters) {
502             if (from < 0) {
503                 from = 0;
504             }
505             if (to == -1) {
506                 to = mFilters.size();
507             }
508             for (int i = from; i < to; i++) {
509                 FilterRepresentation representation = mFilters.elementAt(i);
510                 if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) {
511                     // skip the geometry as it's already applied.
512                     continue;
513                 }
514                 if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
515                     // for now, let's skip the border as it will be applied in
516                     // applyBorder()
517                     // TODO: might be worth getting rid of applyBorder.
518                     continue;
519                 }
520                 Bitmap tmp = bitmap;
521                 bitmap = environment.applyRepresentation(representation, bitmap);
522                 if (tmp != bitmap) {
523                     environment.cache(tmp);
524                 }
525                 if (environment.needsStop()) {
526                     return bitmap;
527                 }
528             }
529         }
530 
531         return bitmap;
532     }
533 
applyBorder(Allocation in, Allocation out, boolean copyOut, FilterEnvironment environment)534     public void applyBorder(Allocation in, Allocation out,
535             boolean copyOut, FilterEnvironment environment) {
536         FilterRepresentation border = getFilterRepresentationForType(
537                 FilterRepresentation.TYPE_BORDER);
538         if (border != null && mDoApplyGeometry) {
539             // TODO: should keep the bitmap around
540             Allocation bitmapIn = in;
541             if (copyOut) {
542                 bitmapIn = Allocation.createTyped(
543                         CachingPipeline.getRenderScriptContext(), in.getType());
544                 bitmapIn.copyFrom(out);
545             }
546             environment.applyRepresentation(border, bitmapIn, out);
547         }
548     }
549 
applyFilters(int from, int to, Allocation in, Allocation out, FilterEnvironment environment)550     public void applyFilters(int from, int to, Allocation in, Allocation out,
551             FilterEnvironment environment) {
552         if (mDoApplyFilters) {
553             if (from < 0) {
554                 from = 0;
555             }
556             if (to == -1) {
557                 to = mFilters.size();
558             }
559             for (int i = from; i < to; i++) {
560                 FilterRepresentation representation = mFilters.elementAt(i);
561                 if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY
562                         || representation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
563                     continue;
564                 }
565                 if (i > from) {
566                     in.copyFrom(out);
567                 }
568                 environment.applyRepresentation(representation, in, out);
569             }
570         }
571     }
572 
canDoPartialRendering()573     public boolean canDoPartialRendering() {
574         if (MasterImage.getImage().getZoomOrientation() != ImageLoader.ORI_NORMAL) {
575             return false;
576         }
577         for (int i = 0; i < mFilters.size(); i++) {
578             FilterRepresentation representation = mFilters.elementAt(i);
579             if (!representation.supportsPartialRendering()) {
580                 return false;
581             }
582         }
583         return true;
584     }
585 
fillImageStateAdapter(StateAdapter imageStateAdapter)586     public void fillImageStateAdapter(StateAdapter imageStateAdapter) {
587         if (imageStateAdapter == null) {
588             return;
589         }
590         Vector<State> states = new Vector<State>();
591         for (FilterRepresentation filter : mFilters) {
592             if (filter instanceof FilterUserPresetRepresentation) {
593                 // do not show the user preset itself in the state panel
594                 continue;
595             }
596             State state = new State(filter.getName());
597             state.setFilterRepresentation(filter);
598             states.add(state);
599         }
600         imageStateAdapter.fill(states);
601     }
602 
setPartialRendering(boolean partialRendering, Rect bounds)603     public void setPartialRendering(boolean partialRendering, Rect bounds) {
604         mPartialRendering = partialRendering;
605         mPartialRenderingBounds = bounds;
606     }
607 
isPartialRendering()608     public boolean isPartialRendering() {
609         return mPartialRendering;
610     }
611 
getPartialRenderingBounds()612     public Rect getPartialRenderingBounds() {
613         return mPartialRenderingBounds;
614     }
615 
getUsedFilters(BaseFiltersManager filtersManager)616     public Vector<ImageFilter> getUsedFilters(BaseFiltersManager filtersManager) {
617         Vector<ImageFilter> usedFilters = new Vector<ImageFilter>();
618         for (int i = 0; i < mFilters.size(); i++) {
619             FilterRepresentation representation = mFilters.elementAt(i);
620             ImageFilter filter = filtersManager.getFilterForRepresentation(representation);
621             usedFilters.add(filter);
622         }
623         return usedFilters;
624     }
625 
getJsonString(String name)626     public String getJsonString(String name) {
627         StringWriter swriter = new StringWriter();
628         try {
629             JsonWriter writer = new JsonWriter(swriter);
630             writeJson(writer, name);
631             writer.close();
632         } catch (IOException e) {
633             return null;
634         }
635         return swriter.toString();
636     }
637 
writeJson(JsonWriter writer, String name)638     public void writeJson(JsonWriter writer, String name) {
639         int numFilters = mFilters.size();
640         try {
641             writer.beginObject();
642             for (int i = 0; i < numFilters; i++) {
643                 FilterRepresentation filter = mFilters.get(i);
644                 if (filter instanceof FilterUserPresetRepresentation) {
645                     continue;
646                 }
647                 String sname = filter.getSerializationName();
648                 if (DEBUG) {
649                     Log.v(LOGTAG, "Serialization: " + sname);
650                     if (sname == null) {
651                         Log.v(LOGTAG, "Serialization name null for filter: " + filter);
652                     }
653                 }
654                 writer.name(sname);
655                 filter.serializeRepresentation(writer);
656             }
657             writer.endObject();
658 
659         } catch (IOException e) {
660            Log.e(LOGTAG,"Error encoding JASON",e);
661         }
662     }
663 
664     /**
665      * populates preset from JSON string
666      *
667      * @param filterString a JSON string
668      * @return true on success if false ImagePreset is undefined
669      */
readJsonFromString(String filterString)670     public boolean readJsonFromString(String filterString) {
671         if (DEBUG) {
672             Log.v(LOGTAG, "reading preset: \"" + filterString + "\"");
673         }
674         StringReader sreader = new StringReader(filterString);
675         try {
676             JsonReader reader = new JsonReader(sreader);
677             boolean ok = readJson(reader);
678             if (!ok) {
679                 reader.close();
680                 return false;
681             }
682             reader.close();
683         } catch (Exception e) {
684             Log.e(LOGTAG, "\""+filterString+"\"");
685             Log.e(LOGTAG, "parsing the filter parameters:", e);
686             return false;
687         }
688         return true;
689     }
690 
691     /**
692      * populates preset from JSON stream
693      *
694      * @param sreader a JSON string
695      * @return true on success if false ImagePreset is undefined
696      */
readJson(JsonReader sreader)697     public boolean readJson(JsonReader sreader) throws IOException {
698         sreader.beginObject();
699 
700         while (sreader.hasNext()) {
701             String name = sreader.nextName();
702             FilterRepresentation filter = creatFilterFromName(name);
703             if (filter == null) {
704                 Log.w(LOGTAG, "UNKNOWN FILTER! " + name);
705                 return false;
706             }
707             filter.deSerializeRepresentation(sreader);
708             addFilter(filter);
709         }
710         sreader.endObject();
711         return true;
712     }
713 
creatFilterFromName(String name)714     FilterRepresentation creatFilterFromName(String name) {
715         if (FilterRotateRepresentation.SERIALIZATION_NAME.equals(name)) {
716             return new FilterRotateRepresentation();
717         } else if (FilterMirrorRepresentation.SERIALIZATION_NAME.equals(name)) {
718             return new FilterMirrorRepresentation();
719         } else if (FilterStraightenRepresentation.SERIALIZATION_NAME.equals(name)) {
720             return new FilterStraightenRepresentation();
721         } else if (FilterCropRepresentation.SERIALIZATION_NAME.equals(name)) {
722             return new FilterCropRepresentation();
723         }
724         FiltersManager filtersManager = FiltersManager.getManager();
725         return filtersManager.createFilterFromName(name);
726     }
727 
updateWith(ImagePreset preset)728     public void updateWith(ImagePreset preset) {
729         if (preset.mFilters.size() != mFilters.size()) {
730             Log.e(LOGTAG, "Updating a preset with an incompatible one");
731             return;
732         }
733         for (int i = 0; i < mFilters.size(); i++) {
734             FilterRepresentation destRepresentation = mFilters.elementAt(i);
735             FilterRepresentation sourceRepresentation = preset.mFilters.elementAt(i);
736             destRepresentation.useParametersFrom(sourceRepresentation);
737         }
738     }
739 }
740