OSDN Git Service

Support for save state in images
authorJohn Hoford <hoford@google.com>
Tue, 16 Apr 2013 05:10:43 +0000 (22:10 -0700)
committerJohn Hoford <hoford@google.com>
Wed, 17 Apr 2013 16:39:13 +0000 (09:39 -0700)
bug:8626775

Change-Id: I2a34a6027b23dab9c1802f672bfbf399cac0c4f7

33 files changed:
res/values/filtershow_strings.xml
src/com/android/gallery3d/filtershow/FilterShowActivity.java
src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java
src/com/android/gallery3d/filtershow/controller/BasicSlider.java
src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java
src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java
src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java
src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java
src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java
src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java
src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java
src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java
src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java
src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
src/com/android/gallery3d/filtershow/presets/ImagePreset.java
src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java
src/com/android/gallery3d/filtershow/tools/XmpPresets.java [new file with mode: 0644]

index 11f27cf..6a1ec89 100644 (file)
@@ -30,6 +30,8 @@
 
     <!--  Text for original image [CHAR LIMIT=20] -->
     <string name="original">Original</string>
+    <!--  Text for original image [CHAR LIMIT=20] -->
+    <string name="saved">Saved</string>
     <!--  Text for filters that apply a border to a picture [CHAR LIMIT=20] -->
     <string name="borders" msgid="4461692156695893616">Borders</string>
 
index da466f4..d3be827 100644 (file)
@@ -80,6 +80,8 @@ import com.android.gallery3d.filtershow.state.StateAdapter;
 import com.android.gallery3d.filtershow.state.StatePanel;
 import com.android.gallery3d.filtershow.tools.BitmapTask;
 import com.android.gallery3d.filtershow.tools.SaveCopyTask;
+import com.android.gallery3d.filtershow.tools.XmpPresets;
+import com.android.gallery3d.filtershow.tools.XmpPresets.XMresults;
 import com.android.gallery3d.filtershow.ui.FilterIconButton;
 import com.android.gallery3d.filtershow.ui.FramedTextButton;
 import com.android.gallery3d.filtershow.ui.Spline;
@@ -138,7 +140,8 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
     private FilterIconButton mNullFxFilter;
     private FilterIconButton mNullBorderFilter;
     private int mIconSeedSize = 140;
-
+    private Uri mOriginalImageUri = null;
+    private ImagePreset mOriginalPreset = null;
     private View mImageCategoryPanel = null;
 
     @Override
@@ -168,6 +171,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
 
         setDefaultPreset();
 
+        extractXMPData();
         processIntent();
     }
 
@@ -294,9 +298,12 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
         }
 
         mAction = intent.getAction();
-
-        if (intent.getData() != null) {
-            startLoadBitmap(intent.getData());
+        Uri srcUri = intent.getData();
+        if (mOriginalImageUri != null) {
+            srcUri = mOriginalImageUri;
+        }
+        if (srcUri != null) {
+            startLoadBitmap(srcUri);
         } else {
             pickImage();
         }
@@ -432,9 +439,9 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
                 mImageBorderSize));
         for (int i = 0; i < borders.size(); i++) {
             FilterRepresentation filter = borders.elementAt(i);
-            filter.setName(getString(R.string.borders));
+            filter.setScrName(getString(R.string.borders));
             if (i == 0) {
-                filter.setName(getString(R.string.none));
+                filter.setScrName(getString(R.string.none));
             }
             FilterIconButton b = setupFilterRepresentationButton(filter, list, borderButton);
             if (i == 0) {
@@ -511,7 +518,10 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
             MasterImage.getImage().setOriginalGeometry(largeBitmap);
             MasterImage.getImage().getHistory().setOriginalBitmap(mImageLoader.getOriginalBitmapSmall());
             mLoadBitmapTask = null;
-
+            if (mOriginalPreset != null) {
+                MasterImage.getImage().setPreset(mOriginalPreset, true);
+                mOriginalPreset = null;
+            }
             if (mAction == CROP_ACTION) {
                 mPanelController.showComponent(findViewById(EditorCrop.ID));
             } else if (mAction == TINY_PLANET_ACTION) {
@@ -751,7 +761,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
         FilterIconButton icon = (FilterIconButton) inflater.inflate(R.layout.filtericonbutton,
                 panel, false);
         if (representation.getTextId() != 0) {
-            representation.setName(getString(representation.getTextId()));
+            representation.setScrName(getString(representation.getTextId()));
         }
         String text = representation.getName();
         icon.setup(text, mPanelController, panel);
@@ -792,9 +802,11 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
                 R.string.ffx_washout_color,
                 R.string.ffx_x_process
         };
+        FiltersManager filtersManager = FiltersManager.getManager();
 
         for (int i = 0; i < drawid.length; i++) {
             FilterFxRepresentation fx = new FilterFxRepresentation(getString(fxNameid[i]), drawid[i], fxNameid[i]);
+            filtersManager.addRepresentation(fx);
             fxArray[p++] = fx;
         }
 
@@ -1172,4 +1184,13 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
         System.loadLibrary("jni_filtershow_filters");
     }
 
+    private void extractXMPData() {
+        XMresults res = XmpPresets.extractXMPData(
+                getBaseContext(), mMasterImage, getIntent().getData());
+        if (res == null)
+            return;
+
+        mOriginalImageUri = res.originalimage;
+        mOriginalPreset = res.preset;
+    }
 }
index 633e41f..25169c2 100644 (file)
@@ -92,8 +92,6 @@ public class BasicParameterStyle implements ParameterStyles {
 
     @Override
     public void getIcon(int index, RenderingRequestCaller caller) {
-        Log.v(LOGTAG, "############ " + ID + " getIcon " + index);
-
         mEditor.computeIcon(index, caller);
     }
 
@@ -111,5 +109,4 @@ public class BasicParameterStyle implements ParameterStyles {
     public void setFilterView(FilterView editor) {
         mEditor = editor;
     }
-
 }
index df5b6ae..9d8278d 100644 (file)
@@ -84,5 +84,4 @@ public class BasicSlider implements Control {
         mSeekBar.setMax(mParameter.getMaximum() - mParameter.getMinimum());
         mSeekBar.setProgress(mParameter.getValue() - mParameter.getMinimum());
     }
-
 }
index 66ad106..1a2150a 100644 (file)
@@ -16,6 +16,8 @@
 package com.android.gallery3d.filtershow.filters;
 
 import android.content.res.Resources;
+import android.util.Log;
+
 import com.android.gallery3d.filtershow.presets.ImagePreset;
 
 import java.util.HashMap;
@@ -23,9 +25,12 @@ import java.util.Vector;
 
 public abstract class BaseFiltersManager {
     protected HashMap<Class, ImageFilter> mFilters = null;
+    protected HashMap<String, FilterRepresentation> mRepresentationLookup = null;
+    private static final String LOGTAG = "BaseFiltersManager";
 
     protected void init() {
         mFilters = new HashMap<Class, ImageFilter>();
+        mRepresentationLookup = new HashMap<String, FilterRepresentation>();
         Vector<Class> filters = new Vector<Class>();
         addFilterClasses(filters);
         for (Class filterClass : filters) {
@@ -33,6 +38,12 @@ public abstract class BaseFiltersManager {
                 Object filterInstance = filterClass.newInstance();
                 if (filterInstance instanceof ImageFilter) {
                     mFilters.put(filterClass, (ImageFilter) filterInstance);
+
+                    FilterRepresentation rep = 
+                               ((ImageFilter) filterInstance).getDefaultRepresentation();
+                    if (rep != null) {
+                        addRepresentation(rep);
+                    }
                 }
             } catch (InstantiationException e) {
                 e.printStackTrace();
@@ -42,6 +53,20 @@ public abstract class BaseFiltersManager {
         }
     }
 
+    public void addRepresentation(FilterRepresentation rep) {
+        mRepresentationLookup.put(rep.getSerializationName(), rep);
+    }
+
+    public FilterRepresentation createFilterFromName(String name) {
+        try {
+            return mRepresentationLookup.get(name).clone();
+        } catch (Exception e) {
+            Log.v(LOGTAG, "unable to generate a filter representation for \"" + name + "\"");
+            e.printStackTrace();
+        }
+        return null;
+    }
+
     public ImageFilter getFilter(Class c) {
         return mFilters.get(c);
     }
@@ -50,10 +75,6 @@ public abstract class BaseFiltersManager {
         return mFilters.get(representation.getFilterClass());
     }
 
-    public void addFilter(Class filterClass, ImageFilter filter) {
-        mFilters.put(filterClass, filter);
-    }
-
     public FilterRepresentation getRepresentation(Class c) {
         ImageFilter filter = mFilters.get(c);
         if (filter != null) {
index 3ef1e09..e0525e3 100644 (file)
@@ -29,6 +29,8 @@ public class FilterBasicRepresentation extends FilterRepresentation implements P
     private int mMaximum;
     private int mDefaultValue;
     private int mPreviewValue;
+    public static final String SERIAL_NAME = "Name";
+    public static final String SERIAL_VALUE = "Value";
 
     public FilterBasicRepresentation(String name, int minimum, int value, int maximum) {
         super(name);
@@ -165,4 +167,23 @@ public class FilterBasicRepresentation extends FilterRepresentation implements P
     public void copyFrom(Parameter src) {
         useParametersFrom((FilterBasicRepresentation) src);
     }
+
+    @Override
+    public String[][] serializeRepresentation() {
+        String[][] ret = {
+                {SERIAL_NAME  , getName() },
+                {SERIAL_VALUE , Integer.toString(mValue)}};
+        return ret;
+    }
+
+    @Override
+    public void deSerializeRepresentation(String[][] rep) {
+        super.deSerializeRepresentation(rep);
+        for (int i = 0; i < rep.length; i++) {
+            if (SERIAL_VALUE.equals(rep[i][0])) {
+                mValue = Integer.parseInt(rep[i][1]);
+                break;
+            }
+        }
+    }
 }
index 3511c67..56d7517 100644 (file)
@@ -11,6 +11,7 @@ public class FilterCurvesRepresentation extends FilterRepresentation {
 
     public FilterCurvesRepresentation() {
         super("Curves");
+        setSerializationName("CURVES");
         setFilterClass(ImageFilterCurves.class);
         setTextId(R.string.curvesRGB);
         setButtonId(R.id.curvesButtonRGB);
index dc59b0c..9b144b9 100644 (file)
@@ -49,6 +49,7 @@ public class FilterDrawRepresentation extends FilterRepresentation {
 
     public FilterDrawRepresentation() {
         super("Draw");
+        setSerializationName("DRAW");
         setFilterClass(ImageFilterDraw.class);
         setPriority(FilterRepresentation.TYPE_VIGNETTE);
         setTextId(R.string.imageDraw);
index 6e2e7ea..1ceffb4 100644 (file)
@@ -21,7 +21,8 @@ import com.android.gallery3d.app.Log;
 import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 
 public class FilterFxRepresentation extends FilterRepresentation {
-    private static final String LOGTAG = "FilterFxRepresentation";
+   private static final String SERIALIZATION_NAME = "LUT3D";
+   private static final String LOGTAG = "FilterFxRepresentation";
     // TODO: When implementing serialization, we should find a unique way of
     // specifying bitmaps / names (the resource IDs being random)
     private int mBitmapResource = 0;
@@ -29,6 +30,8 @@ public class FilterFxRepresentation extends FilterRepresentation {
 
     public FilterFxRepresentation(String name, int bitmapResource, int nameResource) {
         super(name);
+        setSerializationName(SERIALIZATION_NAME);
+
         mBitmapResource = bitmapResource;
         mNameResource = nameResource;
         setFilterClass(ImageFilterFx.class);
index 3f823ea..8a87841 100644 (file)
@@ -28,6 +28,7 @@ public class FilterRedEyeRepresentation extends FilterPointRepresentation {
 
     public FilterRedEyeRepresentation() {
         super("RedEye",R.string.redeye,EditorRedEye.ID);
+        setSerializationName("REDEYE");
         setFilterClass(ImageFilterRedEye.class);
         setOverlayId(R.drawable.photoeditor_effect_redeye);
         setOverlayOnly(true);
index 5bb0e57..f760e84 100644 (file)
@@ -34,7 +34,7 @@ public class FilterRepresentation implements Cloneable {
     private boolean mShowEditingControls = true;
     private boolean mShowParameterValue = true;
     private boolean mShowUtilityPanel = true;
-
+    private String mSerializationName;
     public static final byte TYPE_BORDER = 1;
     public static final byte TYPE_FX = 2;
     public static final byte TYPE_WBALANCE = 3;
@@ -63,6 +63,8 @@ public class FilterRepresentation implements Cloneable {
         representation.setShowEditingControls(showEditingControls());
         representation.setShowParameterValue(showParameterValue());
         representation.setShowUtilityPanel(showUtilityPanel());
+        representation.mSerializationName = mSerializationName;
+
         representation.mTempRepresentation =
                 mTempRepresentation != null ? mTempRepresentation.clone() : null;
         if (DEBUG) {
@@ -96,7 +98,11 @@ public class FilterRepresentation implements Cloneable {
         return mName;
     }
 
-    public void setName(String name) {
+    public void setScrName(String name) {
+        mName = name;
+    }
+
+    protected void setName(String name) {
         mName = name;
     }
 
@@ -104,6 +110,14 @@ public class FilterRepresentation implements Cloneable {
         return mName;
     }
 
+    public void setSerializationName(String sname) {
+        mSerializationName = sname;
+    }
+
+    public String getSerializationName() {
+        return mSerializationName;
+    }
+
     public void setPriority(int priority) {
         mPriority = priority;
     }
@@ -241,4 +255,17 @@ public class FilterRepresentation implements Cloneable {
         return "";
     }
 
+    public String[][] serializeRepresentation() {
+        String[][] ret = { { "Name" , getName() }};
+        return ret;
+    }
+
+    public void deSerializeRepresentation(String[][] rep) {
+        for (int i = 0; i < rep.length; i++) {
+            if ("Name".equals(rep[i][0])) {
+                mName = rep[i][0];
+                break;
+            }
+        }
+    }
 }
index 7b69ce9..c570a75 100644 (file)
@@ -20,11 +20,14 @@ import com.android.gallery3d.R;
 import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
 
 public class FilterTinyPlanetRepresentation extends FilterBasicRepresentation {
+    private static final String SERIALIZATION_NAME = "TINYPLANET";
     private static final String LOGTAG = "FilterTinyPlanetRepresentation";
+    private static final String SERIAL_ANGLE = "Angle";
     private float mAngle = 0;
 
     public FilterTinyPlanetRepresentation() {
         super("TinyPlanet", 0, 50, 100);
+        setSerializationName(SERIALIZATION_NAME);
         setShowParameterValue(true);
         setFilterClass(ImageFilterTinyPlanet.class);
         setPriority(FilterRepresentation.TYPE_TINYPLANET);
@@ -62,4 +65,25 @@ public class FilterTinyPlanetRepresentation extends FilterBasicRepresentation {
         // TinyPlanet always has an effect
         return false;
     }
+
+    @Override
+    public String[][] serializeRepresentation() {
+        String[][] ret = {
+                {SERIAL_NAME  , getName() },
+                {SERIAL_VALUE , Integer.toString(getValue())},
+                {SERIAL_ANGLE , Float.toString(mAngle)}};
+        return ret;
+    }
+
+    @Override
+    public void deSerializeRepresentation(String[][] rep) {
+        super.deSerializeRepresentation(rep);
+        for (int i = 0; i < rep.length; i++) {
+            if (SERIAL_VALUE.equals(rep[i][0])) {
+                setValue(Integer.parseInt(rep[i][1]));
+            } else if (SERIAL_ANGLE.equals(rep[i][0])) {
+                setAngle(Float.parseFloat(rep[i][1]));
+            }
+        }
+    }
 }
index eef54ef..9827088 100644 (file)
@@ -29,6 +29,7 @@ public class FilterVignetteRepresentation extends FilterBasicRepresentation impl
 
     public FilterVignetteRepresentation() {
         super("Vignette", -100, 50, 100);
+        setSerializationName("VIGNETTE");
         setShowParameterValue(true);
         setPriority(FilterRepresentation.TYPE_VIGNETTE);
         setTextId(R.string.vignette);
@@ -111,4 +112,44 @@ public class FilterVignetteRepresentation extends FilterBasicRepresentation impl
     public boolean isNil() {
         return getValue() == 0;
     }
+
+    private static final String[] sParams = {
+            "Name", "value", "mCenterX", "mCenterY", "mRadiusX",
+            "mRadiusY"
+    };
+
+    @Override
+    public String[][] serializeRepresentation() {
+        String[][] ret = {
+                { sParams[0], getName() },
+                { sParams[1], Integer.toString(getValue()) },
+                { sParams[2], Float.toString(mCenterX) },
+                { sParams[3], Float.toString(mCenterY) },
+                { sParams[4], Float.toString(mRadiusX) },
+                { sParams[5], Float.toString(mRadiusY) }
+        };
+        return ret;
+    }
+
+    @Override
+    public void deSerializeRepresentation(String[][] rep) {
+        super.deSerializeRepresentation(rep);
+        for (int i = 0; i < rep.length; i++) {
+            String key = rep[i][0];
+            String value = rep[i][1];
+            if (sParams[0].equals(key)) {
+                setName(value);
+            } else if (sParams[1].equals(key)) {
+               setValue(Integer.parseInt(value));
+            } else if (sParams[2].equals(key)) {
+                mCenterX = Float.parseFloat(value);
+            } else if (sParams[3].equals(key)) {
+                mCenterY = Float.parseFloat(value);
+            } else if (sParams[4].equals(key)) {
+                mRadiusX = Float.parseFloat(value);
+            } else if (sParams[5].equals(key)) {
+                mRadiusY = Float.parseFloat(value);
+            }
+        }
+    }
 }
index a4626cd..64c48df 100644 (file)
@@ -23,6 +23,7 @@ import android.graphics.Color;
 
 
 public class ImageFilterBwFilter extends SimpleImageFilter {
+    private static final String SERIALIZATION_NAME = "BWFILTER";
 
     public ImageFilterBwFilter() {
         mName = "BW Filter";
@@ -31,6 +32,8 @@ public class ImageFilterBwFilter extends SimpleImageFilter {
     public FilterRepresentation getDefaultRepresentation() {
         FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
         representation.setName("BW Filter");
+        representation.setSerializationName(SERIALIZATION_NAME);
+
         representation.setFilterClass(ImageFilterBwFilter.class);
         representation.setMaximum(180);
         representation.setMinimum(-180);
index 2097f0d..c8b41c2 100644 (file)
@@ -21,6 +21,7 @@ import com.android.gallery3d.R;
 import android.graphics.Bitmap;
 
 public class ImageFilterContrast extends SimpleImageFilter {
+    private static final String SERIALIZATION_NAME = "CONTRAST";
 
     public ImageFilterContrast() {
         mName = "Contrast";
@@ -30,6 +31,8 @@ public class ImageFilterContrast extends SimpleImageFilter {
         FilterBasicRepresentation representation =
                 (FilterBasicRepresentation) super.getDefaultRepresentation();
         representation.setName("Contrast");
+        representation.setSerializationName(SERIALIZATION_NAME);
+
         representation.setFilterClass(ImageFilterContrast.class);
         representation.setTextId(R.string.contrast);
         representation.setButtonId(R.id.contrastButton);
index 0b02fc4..ea2ff35 100644 (file)
@@ -24,6 +24,7 @@ import com.android.gallery3d.R;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
 
 public class ImageFilterDownsample extends SimpleImageFilter {
+    private static final String SERIALIZATION_NAME = "DOWNSAMPLE";
     private static final int ICON_DOWNSAMPLE_FRACTION = 8;
     private ImageLoader mImageLoader;
 
@@ -35,6 +36,8 @@ public class ImageFilterDownsample extends SimpleImageFilter {
     public FilterRepresentation getDefaultRepresentation() {
         FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
         representation.setName("Downsample");
+        representation.setSerializationName(SERIALIZATION_NAME);
+
         representation.setFilterClass(ImageFilterDownsample.class);
         representation.setMaximum(100);
         representation.setMinimum(1);
index 46a9a29..82de2b7 100644 (file)
@@ -21,7 +21,7 @@ import android.graphics.Bitmap;
 import com.android.gallery3d.R;
 
 public class ImageFilterEdge extends SimpleImageFilter {
-
+    private static final String SERIALIZATION_NAME = "EDGE";
     public ImageFilterEdge() {
         mName = "Edge";
     }
@@ -29,6 +29,7 @@ public class ImageFilterEdge extends SimpleImageFilter {
     public FilterRepresentation getDefaultRepresentation() {
         FilterRepresentation representation = super.getDefaultRepresentation();
         representation.setName("Edge");
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setFilterClass(ImageFilterEdge.class);
         representation.setTextId(R.string.edge);
         representation.setButtonId(R.id.edgeButton);
index b0b0b2d..6fdcd24 100644 (file)
@@ -21,7 +21,7 @@ import com.android.gallery3d.R;
 import android.graphics.Bitmap;
 
 public class ImageFilterExposure extends SimpleImageFilter {
-
+    private static final String SERIALIZATION_NAME = "EXPOSURE";
     public ImageFilterExposure() {
         mName = "Exposure";
     }
@@ -30,6 +30,7 @@ public class ImageFilterExposure extends SimpleImageFilter {
         FilterBasicRepresentation representation =
                 (FilterBasicRepresentation) super.getDefaultRepresentation();
         representation.setName("Exposure");
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setFilterClass(ImageFilterExposure.class);
         representation.setTextId(R.string.exposure);
         representation.setButtonId(R.id.exposureButton);
index 68e8a7c..51c6612 100644 (file)
@@ -37,6 +37,11 @@ public class ImageFilterFx extends ImageFilter {
         mFxBitmap = null;
     }
 
+    @Override
+    public FilterRepresentation getDefaultRepresentation() {
+        return null;
+    }
+
     public void useRepresentation(FilterRepresentation representation) {
         FilterFxRepresentation parameters = (FilterFxRepresentation) representation;
         mParameters = parameters;
@@ -87,4 +92,5 @@ public class ImageFilterFx extends ImageFilter {
     public void setResources(Resources resources) {
         mResources = resources;
     }
+
 }
index 0022a9e..0725dd1 100644 (file)
@@ -21,6 +21,7 @@ import android.graphics.Bitmap;
 import com.android.gallery3d.R;
 
 public class ImageFilterHighlights extends SimpleImageFilter {
+    private static final String SERIALIZATION_NAME = "HIGHLIGHTS";
     private static final String LOGTAG = "ImageFilterVignette";
 
     public ImageFilterHighlights() {
@@ -33,7 +34,8 @@ public class ImageFilterHighlights extends SimpleImageFilter {
     public FilterRepresentation getDefaultRepresentation() {
         FilterBasicRepresentation representation =
                 (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("Shadows");
+        representation.setName("Highlights");
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setFilterClass(ImageFilterHighlights.class);
         representation.setTextId(R.string.highlight_recovery);
         representation.setButtonId(R.id.highlightRecoveryButton);
index b1f9f73..7e6f685 100644 (file)
@@ -22,6 +22,7 @@ import com.android.gallery3d.filtershow.editors.BasicEditor;
 import android.graphics.Bitmap;
 
 public class ImageFilterHue extends SimpleImageFilter {
+    private static final String SERIALIZATION_NAME = "HUE";
     private ColorSpaceMatrix cmatrix = null;
 
     public ImageFilterHue() {
@@ -33,6 +34,7 @@ public class ImageFilterHue extends SimpleImageFilter {
         FilterBasicRepresentation representation =
                 (FilterBasicRepresentation) super.getDefaultRepresentation();
         representation.setName("Hue");
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setFilterClass(ImageFilterHue.class);
         representation.setMinimum(-180);
         representation.setMaximum(180);
index 29e6d16..9381381 100644 (file)
@@ -22,6 +22,7 @@ import android.text.format.Time;
 import com.android.gallery3d.R;
 
 public class ImageFilterKMeans extends SimpleImageFilter {
+    private static final String SERIALIZATION_NAME = "KMEANS";
     private int mSeed = 0;
 
     public ImageFilterKMeans() {
@@ -36,6 +37,7 @@ public class ImageFilterKMeans extends SimpleImageFilter {
     public FilterRepresentation getDefaultRepresentation() {
         FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
         representation.setName("KMeans");
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setFilterClass(ImageFilterKMeans.class);
         representation.setMaximum(20);
         representation.setMinimum(2);
index c256686..0747190 100644 (file)
@@ -6,13 +6,14 @@ import com.android.gallery3d.R;
 import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 
 public class ImageFilterNegative extends ImageFilter {
-
+    private static final String SERIALIZATION_NAME = "NEGATIVE";
     public ImageFilterNegative() {
         mName = "Negative";
     }
 
     public FilterRepresentation getDefaultRepresentation() {
         FilterRepresentation representation = new FilterDirectRepresentation("Negative");
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setFilterClass(ImageFilterNegative.class);
         representation.setTextId(R.string.negative);
         representation.setButtonId(R.id.negativeButton);
index 0febe49..adc74c5 100644 (file)
@@ -21,7 +21,7 @@ import com.android.gallery3d.R;
 import android.graphics.Bitmap;
 
 public class ImageFilterSaturated extends SimpleImageFilter {
-
+    private static final String SERIALIZATION_NAME = "SATURATED";
     public ImageFilterSaturated() {
         mName = "Saturated";
     }
@@ -31,6 +31,7 @@ public class ImageFilterSaturated extends SimpleImageFilter {
         FilterBasicRepresentation representation =
                 (FilterBasicRepresentation) super.getDefaultRepresentation();
         representation.setName("Saturated");
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setFilterClass(ImageFilterSaturated.class);
         representation.setTextId(R.string.saturation);
         representation.setButtonId(R.id.saturationButton);
index fd67ee8..845290b 100644 (file)
@@ -21,7 +21,7 @@ import com.android.gallery3d.R;
 import android.graphics.Bitmap;
 
 public class ImageFilterShadows extends SimpleImageFilter {
-
+    private static final String SERIALIZATION_NAME = "SHADOWS";
     public ImageFilterShadows() {
         mName = "Shadows";
 
@@ -31,6 +31,7 @@ public class ImageFilterShadows extends SimpleImageFilter {
         FilterBasicRepresentation representation =
                 (FilterBasicRepresentation) super.getDefaultRepresentation();
         representation.setName("Shadows");
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setFilterClass(ImageFilterShadows.class);
         representation.setTextId(R.string.shadow_recovery);
         representation.setButtonId(R.id.shadowRecoveryButton);
index 76ae475..057c980 100644 (file)
@@ -19,7 +19,7 @@ package com.android.gallery3d.filtershow.filters;
 import com.android.gallery3d.R;
 
 public class ImageFilterSharpen extends ImageFilterRS {
-
+    private static final String SERIALIZATION_NAME = "SHARPEN";
     private static final String LOGTAG = "ImageFilterSharpen";
     private ScriptC_convolve3x3 mScript;
 
@@ -31,6 +31,7 @@ public class ImageFilterSharpen extends ImageFilterRS {
 
     public FilterRepresentation getDefaultRepresentation() {
         FilterRepresentation representation = new FilterBasicRepresentation("Sharpen", 0, 0, 100);
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setShowParameterValue(true);
         representation.setFilterClass(ImageFilterSharpen.class);
         representation.setTextId(R.string.sharpness);
index ea315d3..900fd90 100644 (file)
@@ -21,7 +21,7 @@ import com.android.gallery3d.R;
 import android.graphics.Bitmap;
 
 public class ImageFilterVibrance extends SimpleImageFilter {
-
+    private static final String SERIALIZATION_NAME = "VIBRANCE";
     public ImageFilterVibrance() {
         mName = "Vibrance";
     }
@@ -30,6 +30,7 @@ public class ImageFilterVibrance extends SimpleImageFilter {
         FilterBasicRepresentation representation =
                 (FilterBasicRepresentation) super.getDefaultRepresentation();
         representation.setName("Vibrance");
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setFilterClass(ImageFilterVibrance.class);
         representation.setTextId(R.string.vibrance);
         representation.setButtonId(R.id.vibranceButton);
index c4c293a..84a14c9 100644 (file)
@@ -22,6 +22,7 @@ import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 import android.graphics.Bitmap;
 
 public class ImageFilterWBalance extends ImageFilter {
+    private static final String SERIALIZATION_NAME = "WBALANCE";
     private static final String TAG = "ImageFilterWBalance";
 
     public ImageFilterWBalance() {
@@ -30,6 +31,7 @@ public class ImageFilterWBalance extends ImageFilter {
 
     public FilterRepresentation getDefaultRepresentation() {
         FilterRepresentation representation = new FilterDirectRepresentation("WBalance");
+        representation.setSerializationName(SERIALIZATION_NAME);
         representation.setFilterClass(ImageFilterWBalance.class);
         representation.setPriority(FilterRepresentation.TYPE_WBALANCE);
         representation.setTextId(R.string.wbalance);
index 898fdf0..b0b4c4f 100644 (file)
@@ -20,6 +20,7 @@ import android.graphics.Bitmap;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.util.Log;
 
 import com.android.gallery3d.filtershow.cache.ImageLoader;
 import com.android.gallery3d.filtershow.crop.CropExtras;
@@ -30,7 +31,14 @@ import com.android.gallery3d.filtershow.editors.EditorStraighten;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.ImageFilterGeometry;
 
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+
 public class GeometryMetadata extends FilterRepresentation {
+    private static final String SERIALIZATION_NAME = "GEOM";
     private static final String LOGTAG = "GeometryMetadata";
     private float mScaleFactor = 1.0f;
     private float mRotation = 0;
@@ -40,7 +48,26 @@ public class GeometryMetadata extends FilterRepresentation {
     private FLIP mFlip = FLIP.NONE;
 
     public enum FLIP {
-        NONE, VERTICAL, HORIZONTAL, BOTH
+        NONE("N"), VERTICAL("V"), HORIZONTAL("H"), BOTH("B");
+        String mValue;
+
+        FLIP(String name) {
+            mValue = name;
+        }
+
+        public static FLIP parse(String name){
+            switch (name.charAt(0)) {
+                case 'N':
+                    return NONE;
+                case 'V':
+                    return VERTICAL;
+                case 'H':
+                    return HORIZONTAL;
+                case 'B':
+                    return BOTH;
+            };
+            return NONE;
+        }
     }
 
     // Output format data from intent extras
@@ -64,6 +91,7 @@ public class GeometryMetadata extends FilterRepresentation {
 
     public GeometryMetadata() {
         super("GeometryMetadata");
+        setSerializationName(SERIALIZATION_NAME);
         setFilterClass(ImageFilterGeometry.class);
         setEditorId(EditorCrop.ID);
         setTextId(0);
@@ -468,4 +496,87 @@ public class GeometryMetadata extends FilterRepresentation {
         representation.useParametersFrom(this);
         return representation;
     }
-}
+
+    private static final String[] sParams = {
+            "Name", "ScaleFactor", "Rotation", "StraightenRotation", "CropBoundsLeft",
+            "CropBoundsTop", "CropBoundsRight", "CropBoundsBottom", "PhotoBoundsLeft",
+            "PhotoBoundsTop", "PhotoBoundsRight", "PhotoBoundsBottom", "Flip"
+    };
+
+    @Override
+    public String[][] serializeRepresentation() {
+        String[][] ret = {
+                { "Name", getName() },
+                { "ScaleFactor", Float.toString(mScaleFactor) },
+                { "Rotation", Float.toString(mRotation) },
+                { "StraightenRotation", Float.toString(mStraightenRotation) },
+                { "CropBoundsLeft", Float.toString(mCropBounds.left) },
+                { "CropBoundsTop", Float.toString(mCropBounds.top) },
+                { "CropBoundsRight", Float.toString(mCropBounds.right) },
+                { "CropBoundsBottom", Float.toString(mCropBounds.bottom) },
+                { "PhotoBoundsLeft", Float.toString(mPhotoBounds.left) },
+                { "PhotoBoundsTop", Float.toString(mPhotoBounds.top) },
+                { "PhotoBoundsRight", Float.toString(mPhotoBounds.right) },
+                { "PhotoBoundsBottom", Float.toString(mPhotoBounds.bottom) },
+                { "Flip", mFlip.mValue } };
+        return ret;
+    }
+
+    @Override
+    public void deSerializeRepresentation(String[][] rep) {
+        HashMap<String, Integer> map = new HashMap<String, Integer>();
+        for (int i = 0; i < sParams.length; i++) {
+            map.put(sParams[i], i);
+        }
+        for (int i = 0; i < rep.length; i++) {
+            String key = rep[i][0];
+            String value = rep[i][1];
+
+            switch (map.get(key)) {
+                case -1: // Unknown
+                    break;
+                case 0:
+                    if (!getName().equals(value)) {
+                        throw new IllegalArgumentException("Not a "+getName());
+                    }
+                    break;
+                case 1: // "ScaleFactor", Float
+                    mScaleFactor = Float.parseFloat(value);
+                    break;
+                case 2: // "Rotation", Float
+                    mRotation = Float.parseFloat(value);
+                    break;
+                case 3: // "StraightenRotation", Float
+                    mStraightenRotation = Float.parseFloat(value);
+                    break;
+                case 4: // "mCropBoundsLeft", Float
+                    mCropBounds.left = Float.parseFloat(value);
+                    break;
+                case 5: // "mCropBoundsTop", Float
+                    mCropBounds.top = Float.parseFloat(value);
+                    break;
+                case 6: // "mCropBoundsRight", Float
+                    mCropBounds.right = Float.parseFloat(value);
+                    break;
+                case 7: // "mCropBoundsBottom", Float
+                    mCropBounds.bottom = Float.parseFloat(value);
+                    break;
+                case 8: // "mPhotoBoundsLeft", Float
+                    mPhotoBounds.left = Float.parseFloat(value);
+                    break;
+                case 9: // "mPhotoBoundsTop", Float
+                    mPhotoBounds.top = Float.parseFloat(value);
+                    break;
+                case 10: // "mPhotoBoundsRight", Float
+                    mPhotoBounds.right = Float.parseFloat(value);
+                    break;
+                case 11: // "mPhotoBoundsBottom", Float
+                    mPhotoBounds.bottom = Float.parseFloat(value);
+                    break;
+                case 12: // "Flip", enum
+                    mFlip = FLIP.parse(value);
+                    break;
+            }
+        }
+    }
+}
\ No newline at end of file
index c36befc..2c83d8b 100644 (file)
@@ -20,6 +20,7 @@ import android.graphics.*;
 import android.os.Handler;
 import android.os.Message;
 
+import android.util.Log;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.HistoryAdapter;
 import com.android.gallery3d.filtershow.cache.*;
@@ -132,6 +133,7 @@ public class MasterImage implements RenderingRequestCaller {
     }
 
     public synchronized void setPreset(ImagePreset preset, boolean addToHistory) {
+        preset.showFilters();
         mPreset = preset;
         mPreset.setImageLoader(mLoader);
         setGeometry();
index bd2f494..c18fb05 100644 (file)
@@ -18,18 +18,30 @@ package com.android.gallery3d.filtershow.presets;
 
 import android.graphics.Bitmap;
 import android.graphics.Rect;
+import android.net.Uri;
 import android.support.v8.renderscript.Allocation;
+import android.util.JsonReader;
+import android.util.JsonWriter;
 import android.util.Log;
 
+import com.adobe.xmp.XMPException;
+import com.adobe.xmp.XMPMeta;
+import com.adobe.xmp.options.PropertyOptions;
+import com.android.gallery3d.filtershow.ImageStateAdapter;
 import com.android.gallery3d.filtershow.cache.CachingPipeline;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
 import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.ImageFilter;
 import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.state.StateAdapter;
 
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
 import java.util.Vector;
 
 public class ImagePreset {
@@ -41,6 +53,7 @@ public class ImagePreset {
     public static final int QUALITY_PREVIEW = 1;
     public static final int QUALITY_FINAL = 2;
     public static final int STYLE_ICON = 3;
+    public static final String PRESET_NAME = "PresetName";
 
     private ImageLoader mImageLoader = null;
 
@@ -208,11 +221,11 @@ public class ImagePreset {
         }
         for (FilterRepresentation representation : mFilters) {
             if (representation.getPriority() == FilterRepresentation.TYPE_VIGNETTE
-                && !representation.isNil()) {
+                    && !representation.isNil()) {
                 return false;
             }
             if (representation.getPriority() == FilterRepresentation.TYPE_TINYPLANET
-                && !representation.isNil()) {
+                    && !representation.isNil()) {
                 return false;
             }
         }
@@ -570,4 +583,109 @@ public class ImagePreset {
         return usedFilters;
     }
 
+    public String getJsonString(String name) {
+        StringWriter swriter = new StringWriter();
+        try {
+            JsonWriter writer = new JsonWriter(swriter);
+            writeJson(writer, name);
+            writer.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return swriter.toString();
+    }
+
+    public void writeJson(JsonWriter writer, String name) {
+        int numFilters =  mFilters.size();
+        try {
+            writer.beginObject();
+            writer.name(PRESET_NAME).value(name);
+            writer.name(mGeoData.getSerializationName());
+            writer.beginObject();
+            {
+                String[][] rep = mGeoData.serializeRepresentation();
+                for (int i = 0; i < rep.length; i++) {
+                    writer.name(rep[i][0]);
+                    writer.value(rep[i][1]);
+                }
+            }
+            writer.endObject();
+
+            for (int i = 0; i < numFilters; i++) {
+                FilterRepresentation filter = mFilters.get(i);
+                String sname = filter.getSerializationName();
+                writer.name(sname);
+                writer.beginObject();
+                {
+                    String[][] rep = filter.serializeRepresentation();
+                    for (int k = 0; k < rep.length; k++) {
+                        writer.name(rep[k][0]);
+                        writer.value(rep[k][1]);
+                    }
+                }
+                writer.endObject();
+            }
+            writer.endObject();
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public boolean readJsonFromString(String filterString) {
+        StringReader sreader = new StringReader(filterString);
+        try {
+            JsonReader reader = new JsonReader(sreader);
+            boolean ok = readJson(reader);
+            if (!ok) {
+                return false;
+            }
+            reader.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return true;
+    }
+
+    public boolean readJson(JsonReader sreader) throws IOException {
+        sreader.beginObject();
+        sreader.nextName();
+        mName = sreader.nextString();
+
+        while (sreader.hasNext()) {
+            String name = sreader.nextName();
+
+            if (mGeoData.getSerializationName().equals(name)) {
+                mGeoData.deSerializeRepresentation(read(sreader));
+            } else {
+                FilterRepresentation filter = creatFilterFromName(name);
+                if (filter == null)
+                    return false;
+                filter.deSerializeRepresentation(read(sreader));
+                addFilter(filter);
+            }
+        }
+        sreader.endObject();
+        return true;
+    }
+
+    FilterRepresentation creatFilterFromName(String name) {
+        FiltersManager filtersManager = FiltersManager.getManager();
+        return filtersManager.createFilterFromName(name);
+    }
+
+    String[][] read(JsonReader reader) throws IOException {
+        ArrayList <String[]> al = new ArrayList<String[]>();
+
+        reader.beginObject();
+
+        while (reader.hasNext()) {
+            String[]kv = { reader.nextName(),reader.nextString()};
+            al.add(kv);
+
+        }
+        reader.endObject();
+        return al.toArray(new String[al.size()][]);
+    }
 }
index 35c1553..19cfb58 100644 (file)
@@ -203,6 +203,8 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> {
                     uri = insertContent(context, sourceUri, this.destinationFile, saveFileName,
                             time);
                 }
+                XmpPresets.writeFilterXMP(context, sourceUri, this.destinationFile, preset);
+
                 noBitmap = false;
             } catch (java.lang.OutOfMemoryError e) {
                 // Try 5 times before failing for good.
@@ -216,6 +218,7 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> {
         return uri;
     }
 
+
     @Override
     protected void onPostExecute(Uri result) {
         if (callback != null) {
diff --git a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java b/src/com/android/gallery3d/filtershow/tools/XmpPresets.java
new file mode 100644 (file)
index 0000000..be75f02
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.filtershow.tools;
+
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import com.adobe.xmp.XMPException;
+import com.adobe.xmp.XMPMeta;
+import com.adobe.xmp.XMPMetaFactory;
+import com.android.gallery3d.R;
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.presets.ImagePreset;
+import com.android.gallery3d.util.XmpUtilHelper;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+public class XmpPresets {
+    public static final String
+            XMP_GOOGLE_FILTER_NAMESPACE = "http://ns.google.com/photos/1.0/filter/";
+    public static final String XMP_GOOGLE_FILTER_PREFIX = "AFltr";
+    public static final String XMP_SRC_FILE_URI = "SourceFileUri";
+    public static final String XMP_FILTERSTACK = "filterstack";
+    private static final String LOGTAG = "XmpPresets";
+
+    public static class XMresults {
+        public String presetString;
+        public ImagePreset preset;
+        public Uri originalimage;
+    }
+
+    static {
+        try {
+            XMPMetaFactory.getSchemaRegistry().registerNamespace(
+                    XMP_GOOGLE_FILTER_NAMESPACE, XMP_GOOGLE_FILTER_PREFIX);
+        } catch (XMPException e) {
+            Log.e(LOGTAG, "Register XMP name space failed", e);
+        }
+    }
+
+    public static void writeFilterXMP(
+            Context context, Uri srcUri, File dstFile, ImagePreset preset) {
+        InputStream is = null;
+        XMPMeta xmpMeta = null;
+        try {
+            is = context.getContentResolver().openInputStream(srcUri);
+            xmpMeta = XmpUtilHelper.extractXMPMeta(is);
+        } catch (FileNotFoundException e) {
+
+        } finally {
+            Utils.closeSilently(is);
+        }
+
+        if (xmpMeta == null) {
+            xmpMeta = XMPMetaFactory.create();
+        }
+        try {
+            xmpMeta.setProperty(XMP_GOOGLE_FILTER_NAMESPACE,
+                    XMP_SRC_FILE_URI, srcUri.toString());
+            xmpMeta.setProperty(XMP_GOOGLE_FILTER_NAMESPACE,
+                    XMP_FILTERSTACK, preset.getJsonString(context.getString(R.string.saved)));
+        } catch (XMPException e) {
+            Log.v(LOGTAG, "Write XMP meta to file failed:" + dstFile.getAbsolutePath());
+            return;
+        }
+
+        if (!XmpUtilHelper.writeXMPMeta(dstFile.getAbsolutePath(), xmpMeta)) {
+            Log.v(LOGTAG, "Write XMP meta to file failed:" + dstFile.getAbsolutePath());
+        }
+    }
+
+    public static XMresults extractXMPData(
+            Context context, MasterImage mMasterImage, Uri uriToEdit) {
+        XMresults ret = new XMresults();
+
+        InputStream is = null;
+        XMPMeta xmpMeta = null;
+        try {
+            is = context.getContentResolver().openInputStream(uriToEdit);
+            xmpMeta = XmpUtilHelper.extractXMPMeta(is);
+        } catch (FileNotFoundException e) {
+        } finally {
+            Utils.closeSilently(is);
+        }
+
+        if (xmpMeta == null) {
+            return null;
+        }
+
+        try {
+            String strSrcUri = xmpMeta.getPropertyString(XMP_GOOGLE_FILTER_NAMESPACE,
+                    XMP_SRC_FILE_URI);
+
+            if (strSrcUri != null) {
+                String filterString = xmpMeta.getPropertyString(XMP_GOOGLE_FILTER_NAMESPACE,
+                        XMP_FILTERSTACK);
+
+                Uri srcUri = Uri.parse(strSrcUri);
+                ret.originalimage = srcUri;
+
+                ret.preset = new ImagePreset(mMasterImage.getPreset());
+                ret.presetString = filterString;
+                boolean ok = ret.preset.readJsonFromString(filterString);
+                if (!ok) {
+                    return null;
+                }
+                return ret;
+            }
+        } catch (XMPException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+}