Home | History | Annotate | Download | only in pipeline
      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.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 
     66     public ImagePreset() {
     67     }
     68 
     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 
     76     public Vector<FilterRepresentation> getFilters() {
     77         return mFilters;
     78     }
     79 
     80     public FilterRepresentation getFilterRepresentation(int position) {
     81         FilterRepresentation representation = null;
     82 
     83         representation = mFilters.elementAt(position).copy();
     84 
     85         return representation;
     86     }
     87 
     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 
     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 
    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 
    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 
    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 
    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 
    147     public void updateFilterRepresentations(Collection<FilterRepresentation> reps) {
    148         for (FilterRepresentation r : reps) {
    149             updateOrAddFilterRepresentation(r);
    150         }
    151     }
    152 
    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 
    162     public void setDoApplyGeometry(boolean value) {
    163         mDoApplyGeometry = value;
    164     }
    165 
    166     public void setDoApplyFilters(boolean value) {
    167         mDoApplyFilters = value;
    168     }
    169 
    170     public boolean getDoApplyFilters() {
    171         return mDoApplyFilters;
    172     }
    173 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    320     public FilterRepresentation getLastRepresentation() {
    321         if (mFilters.size() > 0) {
    322             return mFilters.lastElement();
    323         }
    324         return null;
    325     }
    326 
    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.
    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 
    419     private boolean isNoneBorderFilter(FilterRepresentation representation) {
    420         return representation instanceof FilterImageBorderRepresentation &&
    421                 ((FilterImageBorderRepresentation) representation).getDrawableResource() == 0;
    422     }
    423 
    424     private boolean isNoneFxFilter(FilterRepresentation representation) {
    425         return representation instanceof FilterFxRepresentation &&
    426                 ((FilterFxRepresentation) representation).getNameResource() == R.string.none;
    427     }
    428 
    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 
    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 
    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 
    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 
    466     public Rect finalGeometryRect(int width, int height) {
    467         return GeometryMathUtils.finalGeometryRect(width, height, getGeometryFilters());
    468     }
    469 
    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 
    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 
    496     public int nbFilters() {
    497         return mFilters.size();
    498     }
    499 
    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 
    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 
    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 
    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 
    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 
    603     public void setPartialRendering(boolean partialRendering, Rect bounds) {
    604         mPartialRendering = partialRendering;
    605         mPartialRenderingBounds = bounds;
    606     }
    607 
    608     public boolean isPartialRendering() {
    609         return mPartialRendering;
    610     }
    611 
    612     public Rect getPartialRenderingBounds() {
    613         return mPartialRenderingBounds;
    614     }
    615 
    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 
    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 
    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      */
    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      */
    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 
    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 
    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