diff options
Diffstat (limited to 'src/com/android/gallery3d')
49 files changed, 1022 insertions, 117 deletions
diff --git a/src/com/android/gallery3d/app/CommonControllerOverlay.java b/src/com/android/gallery3d/app/CommonControllerOverlay.java index a4f5807ae..9adb4e7a8 100644 --- a/src/com/android/gallery3d/app/CommonControllerOverlay.java +++ b/src/com/android/gallery3d/app/CommonControllerOverlay.java @@ -66,6 +66,10 @@ public abstract class CommonControllerOverlay extends FrameLayout implements protected boolean mCanReplay = true; + public void setSeekable(boolean canSeek) { + mTimeBar.setSeekable(canSeek); + } + public CommonControllerOverlay(Context context) { super(context); diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java index 00e4cd63b..ce9183483 100644 --- a/src/com/android/gallery3d/app/MoviePlayer.java +++ b/src/com/android/gallery3d/app/MoviePlayer.java @@ -25,7 +25,6 @@ import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.IntentFilter; -import android.graphics.Color; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; @@ -135,6 +134,17 @@ public class MoviePlayer implements return true; } }); + mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer player) { + if (!mVideoView.canSeekForward() || !mVideoView.canSeekBackward()) { + mController.setSeekable(false); + } else { + mController.setSeekable(true); + } + setProgress(); + } + }); // The SurfaceView is transparent before drawing the first frame. // This makes the UI flashing when open a video. (black -> old screen diff --git a/src/com/android/gallery3d/app/TimeBar.java b/src/com/android/gallery3d/app/TimeBar.java index 402dfcfab..246346a56 100644 --- a/src/com/android/gallery3d/app/TimeBar.java +++ b/src/com/android/gallery3d/app/TimeBar.java @@ -259,4 +259,8 @@ public class TimeBar extends View { } } + public void setSeekable(boolean canSeek) { + mShowScrubber = canSeek; + } + } diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java index e5ddbf5da..27b5fb914 100644 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java @@ -69,6 +69,8 @@ import com.android.gallery3d.filtershow.provider.SharedImageProvider; import com.android.gallery3d.filtershow.state.StateAdapter; 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.FramedTextButton; import com.android.gallery3d.filtershow.ui.Spline; import com.android.gallery3d.util.GalleryUtils; @@ -119,6 +121,9 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL private LoadBitmapTask mLoadBitmapTask; private boolean mLoading = true; + private Uri mOriginalImageUri = null; + private ImagePreset mOriginalPreset = null; + private CategoryAdapter mCategoryLooksAdapter = null; private CategoryAdapter mCategoryBordersAdapter = null; private CategoryAdapter mCategoryGeometryAdapter = null; @@ -147,6 +152,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL setDefaultPreset(); + extractXMPData(); processIntent(); } @@ -285,9 +291,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(); } @@ -364,8 +373,9 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL for (int i = 0; i < borders.size(); i++) { FilterRepresentation filter = borders.elementAt(i); + filter.setScrName(getString(R.string.borders)); if (i == 0) { - filter.setName(getString(R.string.none)); + filter.setScrName(getString(R.string.none)); } } @@ -519,6 +529,11 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL mCategoryFiltersAdapter.imageLoaded(); mLoadBitmapTask = null; + if (mOriginalPreset != null) { + MasterImage.getImage().setPreset(mOriginalPreset, true); + mOriginalPreset = null; + } + if (mAction == TINY_PLANET_ACTION) { showRepresentation(mCategoryFiltersAdapter.getTinyPlanet()); } @@ -1053,4 +1068,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; + } } diff --git a/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java b/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java index 8760c4a09..1ea40f202 100644 --- a/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java +++ b/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java @@ -29,8 +29,9 @@ import com.android.gallery3d.filtershow.imageshow.GeometryMetadata; import com.android.gallery3d.filtershow.imageshow.MasterImage; import com.android.gallery3d.filtershow.presets.FilterEnvironment; import com.android.gallery3d.filtershow.presets.ImagePreset; +import com.android.gallery3d.filtershow.presets.PipelineInterface; -public class CachingPipeline { +public class CachingPipeline implements PipelineInterface { private static final String LOGTAG = "CachingPipeline"; private boolean DEBUG = false; @@ -65,22 +66,10 @@ public class CachingPipeline { mName = name; } - public static synchronized Resources getResources() { - return sResources; - } - - public static synchronized void setResources(Resources resources) { - sResources = resources; - } - public static synchronized RenderScript getRenderScriptContext() { return sRS; } - public static synchronized void setRenderScriptContext(RenderScript RS) { - sRS = RS; - } - public static synchronized void createRenderscriptContext(Activity context) { if (sRS != null) { Log.w(LOGTAG, "A prior RS context exists when calling setRenderScriptContext"); @@ -128,6 +117,10 @@ public class CachingPipeline { } } + public Resources getResources() { + return sRS.getApplicationContext().getResources(); + } + private synchronized void destroyPixelAllocations() { if (DEBUG) { Log.v(LOGTAG, "destroyPixelAllocations in " + getName()); @@ -167,14 +160,14 @@ public class CachingPipeline { } private void setupEnvironment(ImagePreset preset, boolean highResPreview) { - mEnvironment.setCachingPipeline(this); + mEnvironment.setPipeline(this); mEnvironment.setFiltersManager(mFiltersManager); if (highResPreview) { mEnvironment.setScaleFactor(mHighResPreviewScaleFactor); } else { mEnvironment.setScaleFactor(mPreviewScaleFactor); } - mEnvironment.setQuality(ImagePreset.QUALITY_PREVIEW); + mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); mEnvironment.setImagePreset(preset); mEnvironment.setStop(false); } @@ -293,11 +286,11 @@ public class CachingPipeline { || request.getType() == RenderingRequest.STYLE_ICON_RENDERING) { if (request.getType() == RenderingRequest.ICON_RENDERING) { - mEnvironment.setQuality(ImagePreset.QUALITY_ICON); + mEnvironment.setQuality(FilterEnvironment.QUALITY_ICON); } else if (request.getType() == RenderingRequest.STYLE_ICON_RENDERING) { mEnvironment.setQuality(ImagePreset.STYLE_ICON); } else { - mEnvironment.setQuality(ImagePreset.QUALITY_PREVIEW); + mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); } Bitmap bmp = preset.apply(bitmap, mEnvironment); @@ -317,8 +310,11 @@ public class CachingPipeline { setupEnvironment(preset, false); mFiltersManager.freeFilterResources(preset); preset.applyFilters(-1, -1, in, out, mEnvironment); - // TODO: we should render the border onto a different bitmap instead - preset.applyBorder(in, out, mEnvironment); + boolean copyOut = false; + if (preset.nbFilters() > 0) { + copyOut = true; + } + preset.applyBorder(in, out, copyOut, mEnvironment); } } @@ -328,7 +324,7 @@ public class CachingPipeline { return bitmap; } setupEnvironment(preset, false); - mEnvironment.setQuality(ImagePreset.QUALITY_FINAL); + mEnvironment.setQuality(FilterEnvironment.QUALITY_FINAL); mEnvironment.setScaleFactor(1.0f); mFiltersManager.freeFilterResources(preset); bitmap = preset.applyGeometry(bitmap, mEnvironment); @@ -345,7 +341,7 @@ public class CachingPipeline { } mGeometry.useRepresentation(preset.getGeometry()); return mGeometry.apply(bitmap, mPreviewScaleFactor, - ImagePreset.QUALITY_PREVIEW); + FilterEnvironment.QUALITY_PREVIEW); } public synchronized void compute(TripleBufferBitmap buffer, ImagePreset preset, int type) { @@ -458,4 +454,7 @@ public class CachingPipeline { return mName; } + public RenderScript getRSContext() { + return CachingPipeline.getRenderScriptContext(); + } } diff --git a/src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java b/src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java index 072edd72a..25169c2d8 100644 --- a/src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java +++ b/src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java @@ -109,5 +109,4 @@ public class BasicParameterStyle implements ParameterStyles { public void setFilterView(FilterView editor) { mEditor = editor; } - } diff --git a/src/com/android/gallery3d/filtershow/controller/BasicSlider.java b/src/com/android/gallery3d/filtershow/controller/BasicSlider.java index df5b6ae73..9d8278d52 100644 --- a/src/com/android/gallery3d/filtershow/controller/BasicSlider.java +++ b/src/com/android/gallery3d/filtershow/controller/BasicSlider.java @@ -84,5 +84,4 @@ public class BasicSlider implements Control { mSeekBar.setMax(mParameter.getMaximum() - mParameter.getMinimum()); mSeekBar.setProgress(mParameter.getValue() - mParameter.getMinimum()); } - } diff --git a/src/com/android/gallery3d/filtershow/crop/CropMath.java b/src/com/android/gallery3d/filtershow/crop/CropMath.java index 849ac60ef..671554f16 100644 --- a/src/com/android/gallery3d/filtershow/crop/CropMath.java +++ b/src/com/android/gallery3d/filtershow/crop/CropMath.java @@ -196,14 +196,13 @@ public class CropMath { float finalH = origH; if (origA < a) { finalH = origW / a; + r.top = r.centerY() - finalH / 2; + r.bottom = r.top + finalH; } else { finalW = origH * a; + r.left = r.centerX() - finalW / 2; + r.right = r.left + finalW; } - float centX = r.centerX(); - float centY = r.centerY(); - float hw = finalW / 2; - float hh = finalH / 2; - r.set(centX - hw, centY - hh, centX + hw, centY + hh); } /** diff --git a/src/com/android/gallery3d/filtershow/data/FilterStackDBHelper.java b/src/com/android/gallery3d/filtershow/data/FilterStackDBHelper.java new file mode 100644 index 000000000..e18d3104f --- /dev/null +++ b/src/com/android/gallery3d/filtershow/data/FilterStackDBHelper.java @@ -0,0 +1,101 @@ +/* + * 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.data; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +public class FilterStackDBHelper extends SQLiteOpenHelper { + + public static final int DATABASE_VERSION = 1; + public static final String DATABASE_NAME = "filterstacks.db"; + private static final String SQL_CREATE_TABLE = "CREATE TABLE "; + + public static interface FilterStack { + /** The row uid */ + public static final String _ID = "_id"; + /** The table name */ + public static final String TABLE = "filterstack"; + /** The stack name */ + public static final String STACK_ID = "stack_id"; + /** A serialized stack of filters. */ + public static final String FILTER_STACK= "stack"; + } + + private static final String[][] CREATE_FILTER_STACK = { + { FilterStack._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" }, + { FilterStack.STACK_ID, "TEXT" }, + { FilterStack.FILTER_STACK, "BLOB" }, + }; + + public FilterStackDBHelper(Context context, String name, int version) { + super(context, name, null, version); + } + + public FilterStackDBHelper(Context context, String name) { + this(context, name, DATABASE_VERSION); + } + + public FilterStackDBHelper(Context context) { + this(context, DATABASE_NAME); + } + + @Override + public void onCreate(SQLiteDatabase db) { + createTable(db, FilterStack.TABLE, CREATE_FILTER_STACK); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + dropTable(db, FilterStack.TABLE); + onCreate(db); + } + + protected static void createTable(SQLiteDatabase db, String table, String[][] columns) { + StringBuilder create = new StringBuilder(SQL_CREATE_TABLE); + create.append(table).append('('); + boolean first = true; + for (String[] column : columns) { + if (!first) { + create.append(','); + } + first = false; + for (String val : column) { + create.append(val).append(' '); + } + } + create.append(')'); + db.beginTransaction(); + try { + db.execSQL(create.toString()); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + + protected static void dropTable(SQLiteDatabase db, String table) { + db.beginTransaction(); + try { + db.execSQL("drop table if exists " + table); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } +} diff --git a/src/com/android/gallery3d/filtershow/data/FilterStackSource.java b/src/com/android/gallery3d/filtershow/data/FilterStackSource.java new file mode 100644 index 000000000..4e343777d --- /dev/null +++ b/src/com/android/gallery3d/filtershow/data/FilterStackSource.java @@ -0,0 +1,143 @@ +/* + * 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.data; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; +import android.util.Log; +import android.util.Pair; + +import com.android.gallery3d.filtershow.data.FilterStackDBHelper.FilterStack; + +import java.util.ArrayList; +import java.util.List; + +public class FilterStackSource { + private static final String LOGTAG = "FilterStackSource"; + + private SQLiteDatabase database = null;; + private final FilterStackDBHelper dbHelper; + + public FilterStackSource(Context context) { + dbHelper = new FilterStackDBHelper(context); + } + + public void open() { + try { + database = dbHelper.getWritableDatabase(); + } catch (SQLiteException e) { + Log.w(LOGTAG, "could not open database", e); + } + } + + public void close() { + database = null; + dbHelper.close(); + } + + public boolean insertStack(String stackName, byte[] stackBlob) { + boolean ret = true; + ContentValues val = new ContentValues(); + val.put(FilterStack.STACK_ID, stackName); + val.put(FilterStack.FILTER_STACK, stackBlob); + database.beginTransaction(); + try { + ret = (-1 != database.insert(FilterStack.TABLE, null, val)); + database.setTransactionSuccessful(); + } finally { + database.endTransaction(); + } + return ret; + } + + public boolean removeStack(String stackName) { + boolean ret = true; + database.beginTransaction(); + try { + ret = (0 != database.delete(FilterStack.TABLE, FilterStack.STACK_ID + " = ?", + new String[] { stackName})); + database.setTransactionSuccessful(); + } finally { + database.endTransaction(); + } + return ret; + } + + public void removeAllStacks() { + database.beginTransaction(); + try { + database.delete(FilterStack.TABLE, null, null); + database.setTransactionSuccessful(); + } finally { + database.endTransaction(); + } + } + + public byte[] getStack(String stackName) { + byte[] ret = null; + Cursor c = null; + database.beginTransaction(); + try { + c = database.query(FilterStack.TABLE, + new String[] { FilterStack.FILTER_STACK }, + FilterStack.STACK_ID + " = ?", + new String[] { stackName }, null, null, null, null); + if (c != null && c.moveToFirst() && !c.isNull(0)) { + ret = c.getBlob(0); + } + database.setTransactionSuccessful(); + } finally { + if (c != null) { + c.close(); + } + database.endTransaction(); + } + return ret; + } + + public List<Pair<String, byte[]>> getAllStacks() { + List<Pair<String, byte[]>> ret = new ArrayList<Pair<String, byte[]>>(); + Cursor c = null; + database.beginTransaction(); + try { + c = database.query(FilterStack.TABLE, + new String[] { FilterStack.STACK_ID, FilterStack.FILTER_STACK }, + null, null, null, null, null, null); + if (c != null) { + boolean loopCheck = c.moveToFirst(); + while (loopCheck) { + String name = (c.isNull(0)) ? null : c.getString(0); + byte[] b = (c.isNull(1)) ? null : c.getBlob(1); + ret.add(new Pair<String, byte[]>(name, b)); + loopCheck = c.moveToNext(); + } + } + database.setTransactionSuccessful(); + } finally { + if (c != null) { + c.close(); + } + database.endTransaction(); + } + if (ret.size() <= 0) { + return null; + } + return ret; + } +} diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java index 9927a0a5e..1c7294c3a 100644 --- a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java +++ b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java @@ -17,6 +17,8 @@ package com.android.gallery3d.filtershow.filters; import android.content.Context; import android.content.res.Resources; +import android.util.Log; + import com.android.gallery3d.R; import com.android.gallery3d.filtershow.presets.ImagePreset; @@ -24,11 +26,14 @@ import com.android.gallery3d.filtershow.presets.ImagePreset; import java.util.HashMap; import java.util.Vector; -public abstract class BaseFiltersManager { +public abstract class BaseFiltersManager implements FiltersManagerInterface { 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) { @@ -36,6 +41,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(); @@ -45,6 +56,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); } @@ -53,10 +78,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) { @@ -89,7 +110,7 @@ public abstract class BaseFiltersManager { protected void addFilterClasses(Vector<Class> filters) { filters.add(ImageFilterTinyPlanet.class); - //filters.add(ImageFilterRedEye.class); + filters.add(ImageFilterRedEye.class); filters.add(ImageFilterWBalance.class); filters.add(ImageFilterExposure.class); filters.add(ImageFilterVignette.class); @@ -99,7 +120,7 @@ public abstract class BaseFiltersManager { filters.add(ImageFilterVibrance.class); filters.add(ImageFilterSharpen.class); filters.add(ImageFilterCurves.class); - // filters.add(ImageFilterDraw.class); + filters.add(ImageFilterDraw.class); filters.add(ImageFilterHue.class); filters.add(ImageFilterSaturated.class); filters.add(ImageFilterBwFilter.class); @@ -168,8 +189,8 @@ public abstract class BaseFiltersManager { } public void addTools(Vector<FilterRepresentation> representations) { - //representations.add(getRepresentation(ImageFilterRedEye.class)); - // representations.add(getRepresentation(ImageFilterDraw.class)); + representations.add(getRepresentation(ImageFilterRedEye.class)); + representations.add(getRepresentation(ImageFilterDraw.class)); } public void setFilterResources(Resources resources) { diff --git a/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java index 4d0651edb..368e5c029 100644 --- a/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java +++ b/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java @@ -31,6 +31,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"; private boolean mLogVerbose = Log.isLoggable(LOGTAG, Log.VERBOSE); public FilterBasicRepresentation(String name, int minimum, int value, int maximum) { @@ -171,4 +173,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; + } + } + } } diff --git a/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java index cbcae4b37..a32068aeb 100644 --- a/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java +++ b/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java @@ -15,6 +15,7 @@ public class FilterCurvesRepresentation extends FilterRepresentation { public FilterCurvesRepresentation() { super("Curves"); + setSerializationName("CURVES"); setFilterClass(ImageFilterCurves.class); setTextId(R.string.curvesRGB); setButtonId(R.id.curvesButtonRGB); diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java index dc59b0cfc..9b144b9e9 100644 --- a/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java +++ b/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java index 6e2e7ea16..1ceffb4a2 100644 --- a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java +++ b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java index 3f823ea1e..8a878415c 100644 --- a/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java +++ b/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java index 82012b992..91bf676f3 100644 --- a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java +++ b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java @@ -16,7 +16,7 @@ package com.android.gallery3d.filtershow.filters; -import com.android.gallery3d.app.Log; +import android.util.Log; import com.android.gallery3d.filtershow.editors.BasicEditor; public class FilterRepresentation implements Cloneable { @@ -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,6 +98,10 @@ public class FilterRepresentation implements Cloneable { return mName; } + public void setScrName(String name) { + mName = name; + } + public 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; + } + } + } } diff --git a/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java index ac5e04601..48c8b380e 100644 --- a/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java +++ b/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java @@ -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); @@ -71,4 +74,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])); + } + } + } } diff --git a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java index eef54ef58..9827088ff 100644 --- a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java +++ b/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java @@ -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); + } + } + } } diff --git a/src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java b/src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java new file mode 100644 index 000000000..710128f99 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java @@ -0,0 +1,21 @@ +/* + * 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.filters; + +public interface FiltersManagerInterface { + ImageFilter getFilterForRepresentation(FilterRepresentation representation); +} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java index 96ab84f9d..b80fc7f15 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java @@ -16,12 +16,12 @@ package com.android.gallery3d.filtershow.filters; +import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Matrix; import android.support.v8.renderscript.Allocation; import android.widget.Toast; -import com.android.gallery3d.filtershow.FilterShowActivity; import com.android.gallery3d.filtershow.imageshow.GeometryMetadata; import com.android.gallery3d.filtershow.presets.FilterEnvironment; import com.android.gallery3d.filtershow.presets.ImagePreset; @@ -35,9 +35,9 @@ public abstract class ImageFilter implements Cloneable { // TODO: Temporary, for dogfood note memory issues with toasts for better // feedback. Remove this when filters actually work in low memory // situations. - private static FilterShowActivity sActivity = null; + private static Activity sActivity = null; - public static void setActivityForMemoryToasts(FilterShowActivity activity) { + public static void setActivityForMemoryToasts(Activity activity) { sActivity = activity; } @@ -76,10 +76,6 @@ public abstract class ImageFilter implements Cloneable { return bitmap; } - public ImagePreset getImagePreset() { - return getEnvironment().getImagePreset(); - } - public abstract void useRepresentation(FilterRepresentation representation); native protected void nativeApplyGradientFilter(Bitmap bitmap, int w, int h, @@ -90,10 +86,11 @@ public abstract class ImageFilter implements Cloneable { } protected Matrix getOriginalToScreenMatrix(int w, int h) { - GeometryMetadata geo = getImagePreset().mGeoData; + ImagePreset preset = getEnvironment().getImagePreset(); + GeometryMetadata geo = getEnvironment().getImagePreset().mGeoData; Matrix originalToScreen = geo.getOriginalToScreen(true, - getImagePreset().getImageLoader().getOriginalBounds().width(), - getImagePreset().getImageLoader().getOriginalBounds().height(), + preset.getImageLoader().getOriginalBounds().width(), + preset.getImageLoader().getOriginalBounds().height(), w, h); return originalToScreen; } diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java index a4626cdb2..64c48dffa 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java index 2097f0d6e..c8b41c248 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java index 0b02fc4f6..ea2ff351d 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java index 1fd9071f7..812ab02f0 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java @@ -31,6 +31,7 @@ import android.graphics.PorterDuffColorFilter; import com.android.gallery3d.R; import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation.StrokeData; import com.android.gallery3d.filtershow.imageshow.MasterImage; +import com.android.gallery3d.filtershow.presets.FilterEnvironment; import com.android.gallery3d.filtershow.presets.ImagePreset; import java.util.Vector; @@ -204,7 +205,7 @@ public class ImageFilterDraw extends ImageFilter { public void drawData(Canvas canvas, Matrix originalRotateToScreen, int quality) { Paint paint = new Paint(); - if (quality == ImagePreset.QUALITY_FINAL) { + if (quality == FilterEnvironment.QUALITY_FINAL) { paint.setAntiAlias(true); } paint.setStyle(Style.STROKE); @@ -214,7 +215,7 @@ public class ImageFilterDraw extends ImageFilter { if (mParameters.getDrawing().isEmpty() && mParameters.getCurrentDrawing() == null) { return; } - if (quality == ImagePreset.QUALITY_FINAL) { + if (quality == FilterEnvironment.QUALITY_FINAL) { for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) { paint(strokeData, canvas, originalRotateToScreen, quality); } @@ -248,17 +249,17 @@ public class ImageFilterDraw extends ImageFilter { int n = v.size(); for (int i = mCachedStrokes; i < n; i++) { - paint(v.get(i), drawCache, originalRotateToScreen, ImagePreset.QUALITY_PREVIEW); + paint(v.get(i), drawCache, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW); } mCachedStrokes = n; } public void draw(Canvas canvas, Matrix originalRotateToScreen) { for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) { - paint(strokeData, canvas, originalRotateToScreen, ImagePreset.QUALITY_PREVIEW); + paint(strokeData, canvas, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW); } mDrawingsTypes[mCurrentStyle].paint( - null, canvas, originalRotateToScreen, ImagePreset.QUALITY_PREVIEW); + null, canvas, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW); } @Override diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java index 46a9a294c..82de2b73a 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java index b0b0b2dd8..6fdcd249b 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java index 68e8a7c9d..51c66127b 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java @@ -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; } + } diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java index 0022a9eae..0725dd1c4 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java index b1f9f7365..7e6f68548 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java index 29e6d162f..93813813f 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java index c256686fb..0747190fa 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java index cfbb560c7..69d18f805 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java @@ -22,13 +22,14 @@ import android.support.v8.renderscript.*; import android.util.Log; import android.content.res.Resources; import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.cache.CachingPipeline; +import com.android.gallery3d.filtershow.presets.PipelineInterface; public abstract class ImageFilterRS extends ImageFilter { private static final String LOGTAG = "ImageFilterRS"; private boolean DEBUG = false; private int mLastInputWidth = 0; private int mLastInputHeight = 0; + private long mLastTimeCalled; public static boolean PERF_LOGGING = false; @@ -51,26 +52,36 @@ public abstract class ImageFilterRS extends ImageFilter { } protected RenderScript getRenderScriptContext() { - return CachingPipeline.getRenderScriptContext(); + PipelineInterface pipeline = getEnvironment().getPipeline(); + return pipeline.getRSContext(); } protected Allocation getInPixelsAllocation() { - CachingPipeline pipeline = getEnvironment().getCachingPipeline(); + PipelineInterface pipeline = getEnvironment().getPipeline(); return pipeline.getInPixelsAllocation(); } protected Allocation getOutPixelsAllocation() { - CachingPipeline pipeline = getEnvironment().getCachingPipeline(); + PipelineInterface pipeline = getEnvironment().getPipeline(); return pipeline.getOutPixelsAllocation(); } @Override public void apply(Allocation in, Allocation out) { long startOverAll = System.nanoTime(); + if (PERF_LOGGING) { + long delay = (startOverAll - mLastTimeCalled) / 1000; + String msg = String.format("%s; image size %dx%d; ", getName(), + in.getType().getX(), in.getType().getY()); + msg += String.format("called after %.2f ms (%.2f FPS); ", + delay / 1000.f, 1000000.f / delay); + Log.i(LOGTAG, msg); + } + mLastTimeCalled = startOverAll; long startFilter = 0; long endFilter = 0; if (!mResourcesLoaded) { - CachingPipeline pipeline = getEnvironment().getCachingPipeline(); + PipelineInterface pipeline = getEnvironment().getPipeline(); createFilter(pipeline.getResources(), getEnvironment().getScaleFactor(), getEnvironment().getQuality(), in); mResourcesLoaded = true; @@ -102,7 +113,7 @@ public abstract class ImageFilterRS extends ImageFilter { return bitmap; } try { - CachingPipeline pipeline = getEnvironment().getCachingPipeline(); + PipelineInterface pipeline = getEnvironment().getPipeline(); if (DEBUG) { Log.v(LOGTAG, "apply filter " + getName() + " in pipeline " + pipeline.getName()); } @@ -137,18 +148,16 @@ public abstract class ImageFilterRS extends ImageFilter { displayLowMemoryToast(); Log.e(LOGTAG, "not enough memory for filter " + getName(), e); } - return bitmap; } - protected static Allocation convertBitmap(Bitmap bitmap) { - return Allocation.createFromBitmap(CachingPipeline.getRenderScriptContext(), bitmap, + protected static Allocation convertBitmap(RenderScript RS, Bitmap bitmap) { + return Allocation.createFromBitmap(RS, bitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_TEXTURE); } - private static Allocation convertRGBAtoA(Bitmap bitmap) { - RenderScript RS = CachingPipeline.getRenderScriptContext(); + private static Allocation convertRGBAtoA(RenderScript RS, Bitmap bitmap) { if (RS != mRScache || mGreyConvert == null) { mGreyConvert = new ScriptC_grey(RS, RS.getApplicationContext().getResources(), R.raw.grey); @@ -157,7 +166,7 @@ public abstract class ImageFilterRS extends ImageFilter { Type.Builder tb_a8 = new Type.Builder(RS, Element.A_8(RS)); - Allocation bitmapTemp = convertBitmap(bitmap); + Allocation bitmapTemp = convertBitmap(RS, bitmap); if (bitmapTemp.getType().getElement().isCompatible(Element.A_8(RS))) { return bitmapTemp; } @@ -173,20 +182,20 @@ public abstract class ImageFilterRS extends ImageFilter { } public Allocation loadScaledResourceAlpha(int resource, int inSampleSize) { - Resources res = CachingPipeline.getResources(); + Resources res = getEnvironment().getPipeline().getResources(); final BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ALPHA_8; options.inSampleSize = inSampleSize; Bitmap bitmap = BitmapFactory.decodeResource( res, resource, options); - Allocation ret = convertRGBAtoA(bitmap); + Allocation ret = convertRGBAtoA(getRenderScriptContext(), bitmap); bitmap.recycle(); return ret; } public Allocation loadScaledResourceAlpha(int resource, int w, int h, int inSampleSize) { - Resources res = CachingPipeline.getResources(); + Resources res = getEnvironment().getPipeline().getResources(); final BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ALPHA_8; options.inSampleSize = inSampleSize; @@ -194,7 +203,7 @@ public abstract class ImageFilterRS extends ImageFilter { res, resource, options); Bitmap resizeBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true); - Allocation ret = convertRGBAtoA(resizeBitmap); + Allocation ret = convertRGBAtoA(getRenderScriptContext(), resizeBitmap); resizeBitmap.recycle(); bitmap.recycle(); return ret; @@ -205,13 +214,13 @@ public abstract class ImageFilterRS extends ImageFilter { } public Allocation loadResource(int resource) { - Resources res = CachingPipeline.getResources(); + Resources res = getEnvironment().getPipeline().getResources(); final BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; Bitmap bitmap = BitmapFactory.decodeResource( res, resource, options); - Allocation ret = convertBitmap(bitmap); + Allocation ret = convertBitmap(getRenderScriptContext(), bitmap); bitmap.recycle(); return ret; } @@ -232,7 +241,7 @@ public abstract class ImageFilterRS extends ImageFilter { /** * RS Script objects (and all other RS objects) should be cleared here */ - abstract protected void resetScripts(); + public abstract void resetScripts(); /** * Scripts values should be bound here @@ -244,6 +253,8 @@ public abstract class ImageFilterRS extends ImageFilter { return; } resetAllocations(); + mLastInputWidth = 0; + mLastInputHeight = 0; setResourcesLoaded(false); } } diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java index 0febe4957..adc74c5ec 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java index fd67ee8fc..845290b80 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java index 76ae475ac..1dc2c0516 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java @@ -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); @@ -52,7 +53,7 @@ public class ImageFilterSharpen extends ImageFilterRS { } @Override - protected void resetScripts() { + public void resetScripts() { if (mScript != null) { mScript.destroy(); mScript = null; diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java index 37d5739a0..f265c4dcc 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java @@ -76,7 +76,7 @@ public class ImageFilterTinyPlanet extends SimpleImageFilter { int w = bitmapIn.getWidth(); int h = bitmapIn.getHeight(); int outputSize = (int) (w / 2f); - ImagePreset preset = getImagePreset(); + ImagePreset preset = getEnvironment().getImagePreset(); Bitmap mBitmapOut = null; if (preset != null) { XMPMeta xmp = preset.getImageLoader().getXmpObject(); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java index ea315d326..900fd906c 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java index e06f54493..cfe135033 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java @@ -22,7 +22,7 @@ import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Rect; import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.presets.ImagePreset; +import com.android.gallery3d.filtershow.presets.FilterEnvironment; public class ImageFilterVignette extends SimpleImageFilter { private static final String LOGTAG = "ImageFilterVignette"; @@ -57,9 +57,9 @@ public class ImageFilterVignette extends SimpleImageFilter { @Override public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (SIMPLE_ICONS && ImagePreset.QUALITY_ICON == quality) { + if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) { if (mOverlayBitmap == null) { - Resources res = getEnvironment().getCachingPipeline().getResources(); + Resources res = getEnvironment().getPipeline().getResources(); mOverlayBitmap = IconUtilities.getFXBitmap(res, R.drawable.filtershow_icon_vignette); } diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java index c4c293a4b..84a14c902 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java @@ -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); diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java index e5820a8f2..77dbd5e7b 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java +++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java @@ -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); @@ -492,4 +520,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; + } + } + } } diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java index a0b59c0f8..ab8567f56 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java +++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java @@ -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.*; @@ -139,6 +140,7 @@ public class MasterImage implements RenderingRequestCaller { } public synchronized void setPreset(ImagePreset preset, boolean addToHistory) { + preset.showFilters(); mPreset = preset; mPreset.setImageLoader(mLoader); setGeometry(); diff --git a/src/com/android/gallery3d/filtershow/presets/FilterEnvironment.java b/src/com/android/gallery3d/filtershow/presets/FilterEnvironment.java index c454c1ab6..47f8dfccb 100644 --- a/src/com/android/gallery3d/filtershow/presets/FilterEnvironment.java +++ b/src/com/android/gallery3d/filtershow/presets/FilterEnvironment.java @@ -18,11 +18,9 @@ package com.android.gallery3d.filtershow.presets; import android.graphics.Bitmap; import android.support.v8.renderscript.Allocation; -import android.util.Log; -import com.android.gallery3d.filtershow.cache.CachingPipeline; import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FiltersManager; +import com.android.gallery3d.filtershow.filters.FiltersManagerInterface; import com.android.gallery3d.filtershow.filters.ImageFilter; import java.lang.ref.WeakReference; @@ -33,10 +31,14 @@ public class FilterEnvironment { private ImagePreset mImagePreset; private float mScaleFactor; private int mQuality; - private FiltersManager mFiltersManager; - private CachingPipeline mCachingPipeline; + private FiltersManagerInterface mFiltersManager; + private PipelineInterface mPipeline; private volatile boolean mStop = false; + public static final int QUALITY_ICON = 0; + public static final int QUALITY_PREVIEW = 1; + public static final int QUALITY_FINAL = 2; + public synchronized boolean needsStop() { return mStop; } @@ -98,11 +100,11 @@ public class FilterEnvironment { return mQuality; } - public void setFiltersManager(FiltersManager filtersManager) { + public void setFiltersManager(FiltersManagerInterface filtersManager) { mFiltersManager = filtersManager; } - public FiltersManager getFiltersManager() { + public FiltersManagerInterface getFiltersManager() { return mFiltersManager; } @@ -126,12 +128,12 @@ public class FilterEnvironment { return ret; } - public CachingPipeline getCachingPipeline() { - return mCachingPipeline; + public PipelineInterface getPipeline() { + return mPipeline; } - public void setCachingPipeline(CachingPipeline cachingPipeline) { - mCachingPipeline = cachingPipeline; + public void setPipeline(PipelineInterface cachingPipeline) { + mPipeline = cachingPipeline; } } diff --git a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java index 2a7e601ee..84766958d 100644 --- a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java +++ b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java @@ -18,12 +18,19 @@ 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.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; @@ -32,6 +39,10 @@ import com.android.gallery3d.filtershow.state.State; import com.android.gallery3d.filtershow.state.StateAdapter; import com.android.gallery3d.util.UsageStatistics; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; import java.util.Vector; public class ImagePreset { @@ -39,10 +50,8 @@ public class ImagePreset { private static final String LOGTAG = "ImagePreset"; private FilterRepresentation mBorder = null; - public static final int QUALITY_ICON = 0; - 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; @@ -210,11 +219,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; } } @@ -460,7 +469,7 @@ public class ImagePreset { if (mBorder != null && mDoApplyGeometry) { mBorder.synchronizeRepresentation(); bitmap = environment.applyRepresentation(mBorder, bitmap); - if (environment.getQuality() == QUALITY_FINAL) { + if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) { UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, "SaveBorder", mBorder.getName(), 1); } @@ -468,6 +477,10 @@ public class ImagePreset { return bitmap; } + public int nbFilters() { + return mFilters.size(); + } + public Bitmap applyFilters(Bitmap bitmap, int from, int to, FilterEnvironment environment) { if (mDoApplyFilters) { if (from < 0) { @@ -483,7 +496,7 @@ public class ImagePreset { representation.synchronizeRepresentation(); } bitmap = environment.applyRepresentation(representation, bitmap); - if (environment.getQuality() == QUALITY_FINAL) { + if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) { UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, "SaveFilter", representation.getName(), 1); } @@ -496,17 +509,23 @@ public class ImagePreset { return bitmap; } - public void applyBorder(Allocation in, Allocation out, FilterEnvironment environment) { + public void applyBorder(Allocation in, Allocation out, + boolean copyOut, FilterEnvironment environment) { if (mBorder != null && mDoApplyGeometry) { mBorder.synchronizeRepresentation(); // TODO: should keep the bitmap around - Allocation bitmapIn = Allocation.createTyped(CachingPipeline.getRenderScriptContext(), in.getType()); - bitmapIn.copyFrom(out); + Allocation bitmapIn = in; + if (copyOut) { + bitmapIn = Allocation.createTyped( + CachingPipeline.getRenderScriptContext(), in.getType()); + bitmapIn.copyFrom(out); + } environment.applyRepresentation(mBorder, bitmapIn, out); } } - public void applyFilters(int from, int to, Allocation in, Allocation out, FilterEnvironment environment) { + public void applyFilters(int from, int to, Allocation in, Allocation out, + FilterEnvironment environment) { if (mDoApplyFilters) { if (from < 0) { from = 0; @@ -605,4 +624,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()][]); + } } diff --git a/src/com/android/gallery3d/filtershow/presets/PipelineInterface.java b/src/com/android/gallery3d/filtershow/presets/PipelineInterface.java new file mode 100644 index 000000000..05f0a1aa8 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/presets/PipelineInterface.java @@ -0,0 +1,31 @@ +/* + * 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.presets; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.support.v8.renderscript.Allocation; +import android.support.v8.renderscript.RenderScript; + +public interface PipelineInterface { + public String getName(); + public Resources getResources(); + public Allocation getInPixelsAllocation(); + public Allocation getOutPixelsAllocation(); + public boolean prepareRenderscriptAllocations(Bitmap bitmap); + public RenderScript getRSContext(); +} diff --git a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java index c5851c476..b5de6929a 100644 --- a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java +++ b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java @@ -206,6 +206,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. @@ -219,6 +221,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 index 000000000..be75f0253 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/tools/XmpPresets.java @@ -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; + } +} diff --git a/src/com/android/gallery3d/ui/MenuExecutor.java b/src/com/android/gallery3d/ui/MenuExecutor.java index 8f4854e10..29def0527 100644 --- a/src/com/android/gallery3d/ui/MenuExecutor.java +++ b/src/com/android/gallery3d/ui/MenuExecutor.java @@ -190,7 +190,7 @@ public class MenuExecutor { setMenuItemVisible(menu, R.id.action_setas, supportSetAs); setMenuItemVisible(menu, R.id.action_show_on_map, supportShowOnMap); setMenuItemVisible(menu, R.id.action_edit, supportEdit); - // setMenuItemVisible(menu, R.id.action_simple_edit, supportEdit); + setMenuItemVisible(menu, R.id.action_simple_edit, supportEdit); setMenuItemVisible(menu, R.id.action_details, supportInfo); } diff --git a/src/com/android/gallery3d/util/SaveVideoFileUtils.java b/src/com/android/gallery3d/util/SaveVideoFileUtils.java index c281dd3e7..e2c5f51b9 100644 --- a/src/com/android/gallery3d/util/SaveVideoFileUtils.java +++ b/src/com/android/gallery3d/util/SaveVideoFileUtils.java @@ -19,6 +19,7 @@ package com.android.gallery3d.util; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; +import android.media.MediaMetadataRetriever; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore.Video; @@ -95,7 +96,7 @@ public class SaveVideoFileUtils { ContentResolver contentResolver, Uri uri ) { long nowInMs = System.currentTimeMillis(); long nowInSec = nowInMs / 1000; - final ContentValues values = new ContentValues(12); + final ContentValues values = new ContentValues(13); values.put(Video.Media.TITLE, mDstFileInfo.mFileName); values.put(Video.Media.DISPLAY_NAME, mDstFileInfo.mFile.getName()); values.put(Video.Media.MIME_TYPE, "video/mp4"); @@ -104,6 +105,8 @@ public class SaveVideoFileUtils { values.put(Video.Media.DATE_ADDED, nowInSec); values.put(Video.Media.DATA, mDstFileInfo.mFile.getAbsolutePath()); values.put(Video.Media.SIZE, mDstFileInfo.mFile.length()); + int durationMs = retriveVideoDurationMs(mDstFileInfo.mFile.getPath()); + values.put(Video.Media.DURATION, durationMs); // Copy the data taken and location info from src. String[] projection = new String[] { VideoColumns.DATE_TAKEN, @@ -138,4 +141,18 @@ public class SaveVideoFileUtils { return contentResolver.insert(Video.Media.EXTERNAL_CONTENT_URI, values); } + public static int retriveVideoDurationMs(String path) { + int durationMs = 0; + // Calculate the duration of the destination file. + MediaMetadataRetriever retriever = new MediaMetadataRetriever(); + retriever.setDataSource(path); + String duration = retriever.extractMetadata( + MediaMetadataRetriever.METADATA_KEY_DURATION); + if (duration != null) { + durationMs = Integer.parseInt(duration); + } + retriever.release(); + return durationMs; + } + } |