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