summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/filtershow/filters
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/filtershow/filters')
-rw-r--r--src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java296
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java225
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java196
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java211
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java113
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java179
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java170
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java38
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java171
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java112
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java497
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java91
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java190
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterPoint.java21
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java88
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java67
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java262
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java190
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java154
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java101
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterUserPresetRepresentation.java53
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java173
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java21
-rw-r--r--src/com/android/gallery3d/filtershow/filters/IconUtilities.java75
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilter.java109
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java92
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java64
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java161
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java58
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java112
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java83
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java278
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java53
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java56
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java111
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java190
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java74
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java64
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java95
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java39
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java69
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java260
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java79
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java58
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java58
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java107
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java158
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java57
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java98
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java59
-rw-r--r--src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java50
-rw-r--r--src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java37
-rw-r--r--src/com/android/gallery3d/filtershow/filters/SplineMath.java166
-rw-r--r--src/com/android/gallery3d/filtershow/filters/convolve3x3.rs67
-rw-r--r--src/com/android/gallery3d/filtershow/filters/grad.rs121
-rw-r--r--src/com/android/gallery3d/filtershow/filters/grey.rs22
-rw-r--r--src/com/android/gallery3d/filtershow/filters/saturation.rs161
57 files changed, 6960 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
new file mode 100644
index 000000000..3fa91916d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
@@ -0,0 +1,296 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorCrop;
+import com.android.gallery3d.filtershow.editors.EditorMirror;
+import com.android.gallery3d.filtershow.editors.EditorRotate;
+import com.android.gallery3d.filtershow.editors.EditorStraighten;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Vector;
+
+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 ArrayList<FilterRepresentation> mLooks = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mBorders = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mTools = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mEffects = new ArrayList<FilterRepresentation>();
+
+ 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) {
+ try {
+ 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();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void addRepresentation(FilterRepresentation rep) {
+ mRepresentationLookup.put(rep.getSerializationName(), rep);
+ }
+
+ public FilterRepresentation createFilterFromName(String name) {
+ try {
+ return mRepresentationLookup.get(name).copy();
+ } 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);
+ }
+
+ @Override
+ public ImageFilter getFilterForRepresentation(FilterRepresentation representation) {
+ return mFilters.get(representation.getFilterClass());
+ }
+
+ public FilterRepresentation getRepresentation(Class c) {
+ ImageFilter filter = mFilters.get(c);
+ if (filter != null) {
+ return filter.getDefaultRepresentation();
+ }
+ return null;
+ }
+
+ public void freeFilterResources(ImagePreset preset) {
+ if (preset == null) {
+ return;
+ }
+ Vector<ImageFilter> usedFilters = preset.getUsedFilters(this);
+ for (Class c : mFilters.keySet()) {
+ ImageFilter filter = mFilters.get(c);
+ if (!usedFilters.contains(filter)) {
+ filter.freeResources();
+ }
+ }
+ }
+
+ public void freeRSFilterScripts() {
+ for (Class c : mFilters.keySet()) {
+ ImageFilter filter = mFilters.get(c);
+ if (filter != null && filter instanceof ImageFilterRS) {
+ ((ImageFilterRS) filter).resetScripts();
+ }
+ }
+ }
+
+ protected void addFilterClasses(Vector<Class> filters) {
+ filters.add(ImageFilterTinyPlanet.class);
+ filters.add(ImageFilterRedEye.class);
+ filters.add(ImageFilterWBalance.class);
+ filters.add(ImageFilterExposure.class);
+ filters.add(ImageFilterVignette.class);
+ filters.add(ImageFilterGrad.class);
+ filters.add(ImageFilterContrast.class);
+ filters.add(ImageFilterShadows.class);
+ filters.add(ImageFilterHighlights.class);
+ filters.add(ImageFilterVibrance.class);
+ filters.add(ImageFilterSharpen.class);
+ filters.add(ImageFilterCurves.class);
+ filters.add(ImageFilterDraw.class);
+ filters.add(ImageFilterHue.class);
+ filters.add(ImageFilterChanSat.class);
+ filters.add(ImageFilterSaturated.class);
+ filters.add(ImageFilterBwFilter.class);
+ filters.add(ImageFilterNegative.class);
+ filters.add(ImageFilterEdge.class);
+ filters.add(ImageFilterKMeans.class);
+ filters.add(ImageFilterFx.class);
+ filters.add(ImageFilterBorder.class);
+ filters.add(ImageFilterParametricBorder.class);
+ }
+
+ public ArrayList<FilterRepresentation> getLooks() {
+ return mLooks;
+ }
+
+ public ArrayList<FilterRepresentation> getBorders() {
+ return mBorders;
+ }
+
+ public ArrayList<FilterRepresentation> getTools() {
+ return mTools;
+ }
+
+ public ArrayList<FilterRepresentation> getEffects() {
+ return mEffects;
+ }
+
+ public void addBorders(Context context) {
+
+ }
+
+ public void addLooks(Context context) {
+ int[] drawid = {
+ R.drawable.filtershow_fx_0005_punch,
+ R.drawable.filtershow_fx_0000_vintage,
+ R.drawable.filtershow_fx_0004_bw_contrast,
+ R.drawable.filtershow_fx_0002_bleach,
+ R.drawable.filtershow_fx_0001_instant,
+ R.drawable.filtershow_fx_0007_washout,
+ R.drawable.filtershow_fx_0003_blue_crush,
+ R.drawable.filtershow_fx_0008_washout_color,
+ R.drawable.filtershow_fx_0006_x_process
+ };
+
+ int[] fxNameid = {
+ R.string.ffx_punch,
+ R.string.ffx_vintage,
+ R.string.ffx_bw_contrast,
+ R.string.ffx_bleach,
+ R.string.ffx_instant,
+ R.string.ffx_washout,
+ R.string.ffx_blue_crush,
+ R.string.ffx_washout_color,
+ R.string.ffx_x_process
+ };
+
+ // Do not localize.
+ String[] serializationNames = {
+ "LUT3D_PUNCH",
+ "LUT3D_VINTAGE",
+ "LUT3D_BW",
+ "LUT3D_BLEACH",
+ "LUT3D_INSTANT",
+ "LUT3D_WASHOUT",
+ "LUT3D_BLUECRUSH",
+ "LUT3D_WASHOUT",
+ "LUT3D_XPROCESS"
+ };
+
+ FilterFxRepresentation nullFx =
+ new FilterFxRepresentation(context.getString(R.string.none),
+ 0, R.string.none);
+ mLooks.add(nullFx);
+
+ for (int i = 0; i < drawid.length; i++) {
+ FilterFxRepresentation fx = new FilterFxRepresentation(
+ context.getString(fxNameid[i]), drawid[i], fxNameid[i]);
+ fx.setSerializationName(serializationNames[i]);
+ ImagePreset preset = new ImagePreset();
+ preset.addFilter(fx);
+ FilterUserPresetRepresentation rep = new FilterUserPresetRepresentation(
+ context.getString(fxNameid[i]), preset, -1);
+ mLooks.add(rep);
+ addRepresentation(fx);
+ }
+ }
+
+ public void addEffects() {
+ mEffects.add(getRepresentation(ImageFilterTinyPlanet.class));
+ mEffects.add(getRepresentation(ImageFilterWBalance.class));
+ mEffects.add(getRepresentation(ImageFilterExposure.class));
+ mEffects.add(getRepresentation(ImageFilterVignette.class));
+ mEffects.add(getRepresentation(ImageFilterGrad.class));
+ mEffects.add(getRepresentation(ImageFilterContrast.class));
+ mEffects.add(getRepresentation(ImageFilterShadows.class));
+ mEffects.add(getRepresentation(ImageFilterHighlights.class));
+ mEffects.add(getRepresentation(ImageFilterVibrance.class));
+ mEffects.add(getRepresentation(ImageFilterSharpen.class));
+ mEffects.add(getRepresentation(ImageFilterCurves.class));
+ mEffects.add(getRepresentation(ImageFilterHue.class));
+ mEffects.add(getRepresentation(ImageFilterChanSat.class));
+ mEffects.add(getRepresentation(ImageFilterBwFilter.class));
+ mEffects.add(getRepresentation(ImageFilterNegative.class));
+ mEffects.add(getRepresentation(ImageFilterEdge.class));
+ mEffects.add(getRepresentation(ImageFilterKMeans.class));
+ }
+
+ public void addTools(Context context) {
+
+ int[] editorsId = {
+ EditorCrop.ID,
+ EditorStraighten.ID,
+ EditorRotate.ID,
+ EditorMirror.ID
+ };
+
+ int[] textId = {
+ R.string.crop,
+ R.string.straighten,
+ R.string.rotate,
+ R.string.mirror
+ };
+
+ int[] overlayId = {
+ R.drawable.filtershow_button_geometry_crop,
+ R.drawable.filtershow_button_geometry_straighten,
+ R.drawable.filtershow_button_geometry_rotate,
+ R.drawable.filtershow_button_geometry_flip
+ };
+
+ FilterRepresentation[] geometryFilters = {
+ new FilterCropRepresentation(),
+ new FilterStraightenRepresentation(),
+ new FilterRotateRepresentation(),
+ new FilterMirrorRepresentation()
+ };
+
+ for (int i = 0; i < editorsId.length; i++) {
+ int editorId = editorsId[i];
+ FilterRepresentation geometry = geometryFilters[i];
+ geometry.setEditorId(editorId);
+ geometry.setTextId(textId[i]);
+ geometry.setOverlayId(overlayId[i]);
+ geometry.setOverlayOnly(true);
+ if (geometry.getTextId() != 0) {
+ geometry.setName(context.getString(geometry.getTextId()));
+ }
+ mTools.add(geometry);
+ }
+
+ mTools.add(getRepresentation(ImageFilterRedEye.class));
+ mTools.add(getRepresentation(ImageFilterDraw.class));
+ }
+
+ public void setFilterResources(Resources resources) {
+ ImageFilterBorder filterBorder = (ImageFilterBorder) getFilter(ImageFilterBorder.class);
+ filterBorder.setResources(resources);
+ ImageFilterFx filterFx = (ImageFilterFx) getFilter(ImageFilterFx.class);
+ filterFx.setResources(resources);
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java b/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java
new file mode 100644
index 000000000..7c307a9e7
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2012 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;
+
+import java.util.Arrays;
+
+public class ColorSpaceMatrix {
+ private final float[] mMatrix = new float[16];
+ private static final float RLUM = 0.3086f;
+ private static final float GLUM = 0.6094f;
+ private static final float BLUM = 0.0820f;
+
+ public ColorSpaceMatrix() {
+ identity();
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param matrix
+ */
+ public ColorSpaceMatrix(ColorSpaceMatrix matrix) {
+ System.arraycopy(matrix.mMatrix, 0, mMatrix, 0, matrix.mMatrix.length);
+ }
+
+ /**
+ * get the matrix
+ *
+ * @return the internal matrix
+ */
+ public float[] getMatrix() {
+ return mMatrix;
+ }
+
+ /**
+ * set matrix to identity
+ */
+ public void identity() {
+ Arrays.fill(mMatrix, 0);
+ mMatrix[0] = mMatrix[5] = mMatrix[10] = mMatrix[15] = 1;
+ }
+
+ public void convertToLuminance() {
+ mMatrix[0] = mMatrix[1] = mMatrix[2] = 0.3086f;
+ mMatrix[4] = mMatrix[5] = mMatrix[6] = 0.6094f;
+ mMatrix[8] = mMatrix[9] = mMatrix[10] = 0.0820f;
+ }
+
+ private void multiply(float[] a)
+ {
+ int x, y;
+ float[] temp = new float[16];
+
+ for (y = 0; y < 4; y++) {
+ int y4 = y * 4;
+ for (x = 0; x < 4; x++) {
+ temp[y4 + x] = mMatrix[y4 + 0] * a[x]
+ + mMatrix[y4 + 1] * a[4 + x]
+ + mMatrix[y4 + 2] * a[8 + x]
+ + mMatrix[y4 + 3] * a[12 + x];
+ }
+ }
+ for (int i = 0; i < 16; i++)
+ mMatrix[i] = temp[i];
+ }
+
+ private void xRotateMatrix(float rs, float rc)
+ {
+ ColorSpaceMatrix c = new ColorSpaceMatrix();
+ float[] tmp = c.mMatrix;
+
+ tmp[5] = rc;
+ tmp[6] = rs;
+ tmp[9] = -rs;
+ tmp[10] = rc;
+
+ multiply(tmp);
+ }
+
+ private void yRotateMatrix(float rs, float rc)
+ {
+ ColorSpaceMatrix c = new ColorSpaceMatrix();
+ float[] tmp = c.mMatrix;
+
+ tmp[0] = rc;
+ tmp[2] = -rs;
+ tmp[8] = rs;
+ tmp[10] = rc;
+
+ multiply(tmp);
+ }
+
+ private void zRotateMatrix(float rs, float rc)
+ {
+ ColorSpaceMatrix c = new ColorSpaceMatrix();
+ float[] tmp = c.mMatrix;
+
+ tmp[0] = rc;
+ tmp[1] = rs;
+ tmp[4] = -rs;
+ tmp[5] = rc;
+ multiply(tmp);
+ }
+
+ private void zShearMatrix(float dx, float dy)
+ {
+ ColorSpaceMatrix c = new ColorSpaceMatrix();
+ float[] tmp = c.mMatrix;
+
+ tmp[2] = dx;
+ tmp[6] = dy;
+ multiply(tmp);
+ }
+
+ /**
+ * sets the transform to a shift in Hue
+ *
+ * @param rot rotation in degrees
+ */
+ public void setHue(float rot)
+ {
+ float mag = (float) Math.sqrt(2.0);
+ float xrs = 1 / mag;
+ float xrc = 1 / mag;
+ xRotateMatrix(xrs, xrc);
+ mag = (float) Math.sqrt(3.0);
+ float yrs = -1 / mag;
+ float yrc = (float) Math.sqrt(2.0) / mag;
+ yRotateMatrix(yrs, yrc);
+
+ float lx = getRedf(RLUM, GLUM, BLUM);
+ float ly = getGreenf(RLUM, GLUM, BLUM);
+ float lz = getBluef(RLUM, GLUM, BLUM);
+ float zsx = lx / lz;
+ float zsy = ly / lz;
+ zShearMatrix(zsx, zsy);
+
+ float zrs = (float) Math.sin(rot * Math.PI / 180.0);
+ float zrc = (float) Math.cos(rot * Math.PI / 180.0);
+ zRotateMatrix(zrs, zrc);
+ zShearMatrix(-zsx, -zsy);
+ yRotateMatrix(-yrs, yrc);
+ xRotateMatrix(-xrs, xrc);
+ }
+
+ /**
+ * set it to a saturation matrix
+ *
+ * @param s
+ */
+ public void changeSaturation(float s) {
+ mMatrix[0] = (1 - s) * RLUM + s;
+ mMatrix[1] = (1 - s) * RLUM;
+ mMatrix[2] = (1 - s) * RLUM;
+ mMatrix[4] = (1 - s) * GLUM;
+ mMatrix[5] = (1 - s) * GLUM + s;
+ mMatrix[6] = (1 - s) * GLUM;
+ mMatrix[8] = (1 - s) * BLUM;
+ mMatrix[9] = (1 - s) * BLUM;
+ mMatrix[10] = (1 - s) * BLUM + s;
+ }
+
+ /**
+ * Transform RGB value
+ *
+ * @param r red pixel value
+ * @param g green pixel value
+ * @param b blue pixel value
+ * @return computed red pixel value
+ */
+ public float getRed(int r, int g, int b) {
+ return r * mMatrix[0] + g * mMatrix[4] + b * mMatrix[8] + mMatrix[12];
+ }
+
+ /**
+ * Transform RGB value
+ *
+ * @param r red pixel value
+ * @param g green pixel value
+ * @param b blue pixel value
+ * @return computed green pixel value
+ */
+ public float getGreen(int r, int g, int b) {
+ return r * mMatrix[1] + g * mMatrix[5] + b * mMatrix[9] + mMatrix[13];
+ }
+
+ /**
+ * Transform RGB value
+ *
+ * @param r red pixel value
+ * @param g green pixel value
+ * @param b blue pixel value
+ * @return computed blue pixel value
+ */
+ public float getBlue(int r, int g, int b) {
+ return r * mMatrix[2] + g * mMatrix[6] + b * mMatrix[10] + mMatrix[14];
+ }
+
+ private float getRedf(float r, float g, float b) {
+ return r * mMatrix[0] + g * mMatrix[4] + b * mMatrix[8] + mMatrix[12];
+ }
+
+ private float getGreenf(float r, float g, float b) {
+ return r * mMatrix[1] + g * mMatrix[5] + b * mMatrix[9] + mMatrix[13];
+ }
+
+ private float getBluef(float r, float g, float b) {
+ return r * mMatrix[2] + g * mMatrix[6] + b * mMatrix[10] + mMatrix[14];
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java
new file mode 100644
index 000000000..1eebdb571
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java
@@ -0,0 +1,196 @@
+/*
+ * 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;
+
+
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.controller.Control;
+import com.android.gallery3d.filtershow.controller.FilterView;
+import com.android.gallery3d.filtershow.controller.Parameter;
+import com.android.gallery3d.filtershow.controller.ParameterInteger;
+
+public class FilterBasicRepresentation extends FilterRepresentation implements ParameterInteger {
+ private static final String LOGTAG = "FilterBasicRep";
+ private int mMinimum;
+ private int mValue;
+ 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) {
+ super(name);
+ mMinimum = minimum;
+ mMaximum = maximum;
+ setValue(value);
+ }
+
+ @Override
+ public String toString() {
+ return getName() + " : " + mMinimum + " < " + mValue + " < " + mMaximum;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterBasicRepresentation representation = new FilterBasicRepresentation(getName(),0,0,0);
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterBasicRepresentation) {
+ FilterBasicRepresentation representation = (FilterBasicRepresentation) a;
+ setMinimum(representation.getMinimum());
+ setMaximum(representation.getMaximum());
+ setValue(representation.getValue());
+ setDefaultValue(representation.getDefaultValue());
+ setPreviewValue(representation.getPreviewValue());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterBasicRepresentation) {
+ FilterBasicRepresentation basic = (FilterBasicRepresentation) representation;
+ if (basic.mMinimum == mMinimum
+ && basic.mMaximum == mMaximum
+ && basic.mValue == mValue
+ && basic.mDefaultValue == mDefaultValue
+ && basic.mPreviewValue == mPreviewValue) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getMinimum() {
+ return mMinimum;
+ }
+
+ public void setMinimum(int minimum) {
+ mMinimum = minimum;
+ }
+
+ @Override
+ public int getValue() {
+ return mValue;
+ }
+
+ @Override
+ public void setValue(int value) {
+ mValue = value;
+ if (mValue < mMinimum) {
+ mValue = mMinimum;
+ }
+ if (mValue > mMaximum) {
+ mValue = mMaximum;
+ }
+ }
+
+ @Override
+ public int getMaximum() {
+ return mMaximum;
+ }
+
+ public void setMaximum(int maximum) {
+ mMaximum = maximum;
+ }
+
+ public void setDefaultValue(int defaultValue) {
+ mDefaultValue = defaultValue;
+ }
+
+ @Override
+ public int getDefaultValue() {
+ return mDefaultValue;
+ }
+
+ public int getPreviewValue() {
+ return mPreviewValue;
+ }
+
+ public void setPreviewValue(int previewValue) {
+ mPreviewValue = previewValue;
+ }
+
+ @Override
+ public String getStateRepresentation() {
+ int val = getValue();
+ return ((val > 0) ? "+" : "") + val;
+ }
+
+ @Override
+ public String getParameterType(){
+ return sParameterType;
+ }
+
+ @Override
+ public void setController(Control control) {
+ }
+
+ @Override
+ public String getValueString() {
+ return getStateRepresentation();
+ }
+
+ @Override
+ public String getParameterName() {
+ return getName();
+ }
+
+ @Override
+ public void setFilterView(FilterView editor) {
+ }
+
+ @Override
+ 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/FilterChanSatRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java
new file mode 100644
index 000000000..7ce67dd96
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java
@@ -0,0 +1,211 @@
+/*
+ * 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;
+
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.controller.BasicParameterInt;
+import com.android.gallery3d.filtershow.controller.Parameter;
+import com.android.gallery3d.filtershow.controller.ParameterSet;
+import com.android.gallery3d.filtershow.editors.EditorChanSat;
+import com.android.gallery3d.filtershow.imageshow.ControlPoint;
+import com.android.gallery3d.filtershow.imageshow.Spline;
+
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * Representation for a filter that has per channel & Master saturation
+ */
+public class FilterChanSatRepresentation extends FilterRepresentation implements ParameterSet {
+ private static final String LOGTAG = "FilterChanSatRepresentation";
+ private static final String ARGS = "ARGS";
+ private static final String SERIALIZATION_NAME = "channelsaturation";
+
+ public static final int MODE_MASTER = 0;
+ public static final int MODE_RED = 1;
+ public static final int MODE_YELLOW = 2;
+ public static final int MODE_GREEN = 3;
+ public static final int MODE_CYAN = 4;
+ public static final int MODE_BLUE = 5;
+ public static final int MODE_MAGENTA = 6;
+ private int mParameterMode = MODE_MASTER;
+
+ private static int MINSAT = -100;
+ private static int MAXSAT = 100;
+ private BasicParameterInt mParamMaster = new BasicParameterInt(MODE_MASTER, 0, MINSAT, MAXSAT);
+ private BasicParameterInt mParamRed = new BasicParameterInt(MODE_RED, 0, MINSAT, MAXSAT);
+ private BasicParameterInt mParamYellow = new BasicParameterInt(MODE_YELLOW, 0, MINSAT, MAXSAT);
+ private BasicParameterInt mParamGreen = new BasicParameterInt(MODE_GREEN, 0, MINSAT, MAXSAT);
+ private BasicParameterInt mParamCyan = new BasicParameterInt(MODE_CYAN, 0, MINSAT, MAXSAT);
+ private BasicParameterInt mParamBlue = new BasicParameterInt(MODE_BLUE, 0, MINSAT, MAXSAT);
+ private BasicParameterInt mParamMagenta = new BasicParameterInt(MODE_MAGENTA, 0, MINSAT, MAXSAT);
+
+ private BasicParameterInt[] mAllParam = {
+ mParamMaster,
+ mParamRed,
+ mParamYellow,
+ mParamGreen,
+ mParamCyan,
+ mParamBlue,
+ mParamMagenta};
+
+ public FilterChanSatRepresentation() {
+ super("ChannelSaturation");
+ setTextId(R.string.saturation);
+ setFilterType(FilterRepresentation.TYPE_NORMAL);
+ setSerializationName(SERIALIZATION_NAME);
+ setFilterClass(ImageFilterChanSat.class);
+ setEditorId(EditorChanSat.ID);
+ }
+
+ public String toString() {
+ return getName() + " : " + mParamRed + ", " + mParamCyan + ", " + mParamRed
+ + ", " + mParamGreen + ", " + mParamMaster + ", " + mParamYellow;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterChanSatRepresentation representation = new FilterChanSatRepresentation();
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterChanSatRepresentation) {
+ FilterChanSatRepresentation representation = (FilterChanSatRepresentation) a;
+
+ for (int i = 0; i < mAllParam.length; i++) {
+ mAllParam[i].copyFrom(representation.mAllParam[i]);
+ }
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterChanSatRepresentation) {
+ FilterChanSatRepresentation rep = (FilterChanSatRepresentation) representation;
+ for (int i = 0; i < mAllParam.length; i++) {
+ if (rep.getValue(i) != getValue(i))
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public int getValue(int mode) {
+ return mAllParam[mode].getValue();
+ }
+
+ public void setValue(int mode, int value) {
+ mAllParam[mode].setValue(value);
+ }
+
+ public int getMinimum() {
+ return mParamMaster.getMinimum();
+ }
+
+ public int getMaximum() {
+ return mParamMaster.getMaximum();
+ }
+
+ public int getParameterMode() {
+ return mParameterMode;
+ }
+
+ public void setParameterMode(int parameterMode) {
+ mParameterMode = parameterMode;
+ }
+
+ public int getCurrentParameter() {
+ return getValue(mParameterMode);
+ }
+
+ public void setCurrentParameter(int value) {
+ setValue(mParameterMode, value);
+ }
+
+ @Override
+ public int getNumberOfParameters() {
+ return 6;
+ }
+
+ @Override
+ public Parameter getFilterParameter(int index) {
+ return mAllParam[index];
+ }
+
+ @Override
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+
+ writer.name(ARGS);
+ writer.beginArray();
+ writer.value(getValue(MODE_MASTER));
+ writer.value(getValue(MODE_RED));
+ writer.value(getValue(MODE_YELLOW));
+ writer.value(getValue(MODE_GREEN));
+ writer.value(getValue(MODE_CYAN));
+ writer.value(getValue(MODE_BLUE));
+ writer.value(getValue(MODE_MAGENTA));
+ writer.endArray();
+ writer.endObject();
+ }
+
+ @Override
+ public void deSerializeRepresentation(JsonReader sreader) throws IOException {
+ sreader.beginObject();
+
+ while (sreader.hasNext()) {
+ String name = sreader.nextName();
+ if (name.startsWith(ARGS)) {
+ sreader.beginArray();
+ sreader.hasNext();
+ setValue(MODE_MASTER, sreader.nextInt());
+ sreader.hasNext();
+ setValue(MODE_RED, sreader.nextInt());
+ sreader.hasNext();
+ setValue(MODE_YELLOW, sreader.nextInt());
+ sreader.hasNext();
+ setValue(MODE_GREEN, sreader.nextInt());
+ sreader.hasNext();
+ setValue(MODE_CYAN, sreader.nextInt());
+ sreader.hasNext();
+ setValue(MODE_BLUE, sreader.nextInt());
+ sreader.hasNext();
+ setValue(MODE_MAGENTA, sreader.nextInt());
+ sreader.hasNext();
+ sreader.endArray();
+ } else {
+ sreader.skipValue();
+ }
+ }
+ sreader.endObject();
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
new file mode 100644
index 000000000..94eb20631
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
@@ -0,0 +1,113 @@
+/*
+ * 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;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+
+public class FilterColorBorderRepresentation extends FilterRepresentation {
+ private int mColor;
+ private int mBorderSize;
+ private int mBorderRadius;
+
+ public FilterColorBorderRepresentation(int color, int size, int radius) {
+ super("ColorBorder");
+ mColor = color;
+ mBorderSize = size;
+ mBorderRadius = radius;
+ setFilterType(FilterRepresentation.TYPE_BORDER);
+ setTextId(R.string.borders);
+ setEditorId(ImageOnlyEditor.ID);
+ setShowParameterValue(false);
+ }
+
+ public String toString() {
+ return "FilterBorder: " + getName();
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterColorBorderRepresentation representation = new FilterColorBorderRepresentation(0,0,0);
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterColorBorderRepresentation) {
+ FilterColorBorderRepresentation representation = (FilterColorBorderRepresentation) a;
+ setName(representation.getName());
+ setColor(representation.getColor());
+ setBorderSize(representation.getBorderSize());
+ setBorderRadius(representation.getBorderRadius());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterColorBorderRepresentation) {
+ FilterColorBorderRepresentation border = (FilterColorBorderRepresentation) representation;
+ if (border.mColor == mColor
+ && border.mBorderSize == mBorderSize
+ && border.mBorderRadius == mBorderRadius) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean allowsSingleInstanceOnly() {
+ return true;
+ }
+
+ @Override
+ public int getTextId() {
+ return R.string.borders;
+ }
+
+ public int getColor() {
+ return mColor;
+ }
+
+ public void setColor(int color) {
+ mColor = color;
+ }
+
+ public int getBorderSize() {
+ return mBorderSize;
+ }
+
+ public void setBorderSize(int borderSize) {
+ mBorderSize = borderSize;
+ }
+
+ public int getBorderRadius() {
+ return mBorderRadius;
+ }
+
+ public void setBorderRadius(int borderRadius) {
+ mBorderRadius = borderRadius;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java
new file mode 100644
index 000000000..c1bd7b3bb
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java
@@ -0,0 +1,179 @@
+/*
+ * 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;
+
+import android.graphics.RectF;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorCrop;
+
+import java.io.IOException;
+
+public class FilterCropRepresentation extends FilterRepresentation {
+ public static final String SERIALIZATION_NAME = "CROP";
+ public static final String[] BOUNDS = {
+ "C0", "C1", "C2", "C3"
+ };
+ private static final String TAG = FilterCropRepresentation.class.getSimpleName();
+
+ RectF mCrop = getNil();
+
+ public FilterCropRepresentation(RectF crop) {
+ super(FilterCropRepresentation.class.getSimpleName());
+ setSerializationName(SERIALIZATION_NAME);
+ setShowParameterValue(true);
+ setFilterClass(FilterCropRepresentation.class);
+ setFilterType(FilterRepresentation.TYPE_GEOMETRY);
+ setTextId(R.string.crop);
+ setEditorId(EditorCrop.ID);
+ setCrop(crop);
+ }
+
+ public FilterCropRepresentation(FilterCropRepresentation m) {
+ this(m.mCrop);
+ }
+
+ public FilterCropRepresentation() {
+ this(sNilRect);
+ }
+
+ public void set(FilterCropRepresentation r) {
+ mCrop.set(r.mCrop);
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation rep) {
+ if (!(rep instanceof FilterCropRepresentation)) {
+ return false;
+ }
+ FilterCropRepresentation crop = (FilterCropRepresentation) rep;
+ if (mCrop.bottom != crop.mCrop.bottom
+ || mCrop.left != crop.mCrop.left
+ || mCrop.right != crop.mCrop.right
+ || mCrop.top != crop.mCrop.top) {
+ return false;
+ }
+ return true;
+ }
+
+ public RectF getCrop() {
+ return new RectF(mCrop);
+ }
+
+ public void getCrop(RectF r) {
+ r.set(mCrop);
+ }
+
+ public void setCrop(RectF crop) {
+ if (crop == null) {
+ throw new IllegalArgumentException("Argument to setCrop is null");
+ }
+ mCrop.set(crop);
+ }
+
+ /**
+ * Takes a crop rect contained by [0, 0, 1, 1] and scales it by the height
+ * and width of the image rect.
+ */
+ public static void findScaledCrop(RectF crop, int bitmapWidth, int bitmapHeight) {
+ crop.left *= bitmapWidth;
+ crop.top *= bitmapHeight;
+ crop.right *= bitmapWidth;
+ crop.bottom *= bitmapHeight;
+ }
+
+ /**
+ * Takes crop rect and normalizes it by scaling down by the height and width
+ * of the image rect.
+ */
+ public static void findNormalizedCrop(RectF crop, int bitmapWidth, int bitmapHeight) {
+ crop.left /= bitmapWidth;
+ crop.top /= bitmapHeight;
+ crop.right /= bitmapWidth;
+ crop.bottom /= bitmapHeight;
+ }
+
+ @Override
+ public boolean allowsSingleInstanceOnly() {
+ return true;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ return new FilterCropRepresentation(this);
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ if (!(representation instanceof FilterCropRepresentation)) {
+ throw new IllegalArgumentException("calling copyAllParameters with incompatible types!");
+ }
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ if (!(a instanceof FilterCropRepresentation)) {
+ throw new IllegalArgumentException("calling useParametersFrom with incompatible types!");
+ }
+ setCrop(((FilterCropRepresentation) a).mCrop);
+ }
+
+ private static final RectF sNilRect = new RectF(0, 0, 1, 1);
+
+ @Override
+ public boolean isNil() {
+ return mCrop.equals(sNilRect);
+ }
+
+ public static RectF getNil() {
+ return new RectF(sNilRect);
+ }
+
+ @Override
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+ writer.name(BOUNDS[0]).value(mCrop.left);
+ writer.name(BOUNDS[1]).value(mCrop.top);
+ writer.name(BOUNDS[2]).value(mCrop.right);
+ writer.name(BOUNDS[3]).value(mCrop.bottom);
+ writer.endObject();
+ }
+
+ @Override
+ public void deSerializeRepresentation(JsonReader reader) throws IOException {
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ if (BOUNDS[0].equals(name)) {
+ mCrop.left = (float) reader.nextDouble();
+ } else if (BOUNDS[1].equals(name)) {
+ mCrop.top = (float) reader.nextDouble();
+ } else if (BOUNDS[2].equals(name)) {
+ mCrop.right = (float) reader.nextDouble();
+ } else if (BOUNDS[3].equals(name)) {
+ mCrop.bottom = (float) reader.nextDouble();
+ } else {
+ reader.skipValue();
+ }
+ }
+ reader.endObject();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java
new file mode 100644
index 000000000..edab2a08d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java
@@ -0,0 +1,170 @@
+package com.android.gallery3d.filtershow.filters;
+
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.imageshow.ControlPoint;
+import com.android.gallery3d.filtershow.imageshow.Spline;
+
+import java.io.IOException;
+
+/**
+ * TODO: Insert description here. (generated by hoford)
+ */
+public class FilterCurvesRepresentation extends FilterRepresentation {
+ private static final String LOGTAG = "FilterCurvesRepresentation";
+ public static final String SERIALIZATION_NAME = "Curve";
+ private static final int MAX_SPLINE_NUMBER = 4;
+
+ private Spline[] mSplines = new Spline[MAX_SPLINE_NUMBER];
+
+ public FilterCurvesRepresentation() {
+ super("Curves");
+ setSerializationName("CURVES");
+ setFilterClass(ImageFilterCurves.class);
+ setTextId(R.string.curvesRGB);
+ setOverlayId(R.drawable.filtershow_button_colors_curve);
+ setEditorId(R.id.imageCurves);
+ setShowParameterValue(false);
+ setSupportsPartialRendering(true);
+ reset();
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterCurvesRepresentation representation = new FilterCurvesRepresentation();
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ if (!(a instanceof FilterCurvesRepresentation)) {
+ Log.v(LOGTAG, "cannot use parameters from " + a);
+ return;
+ }
+ FilterCurvesRepresentation representation = (FilterCurvesRepresentation) a;
+ Spline[] spline = new Spline[MAX_SPLINE_NUMBER];
+ for (int i = 0; i < spline.length; i++) {
+ Spline sp = representation.mSplines[i];
+ if (sp != null) {
+ spline[i] = new Spline(sp);
+ } else {
+ spline[i] = new Spline();
+ }
+ }
+ mSplines = spline;
+ }
+
+ @Override
+ public boolean isNil() {
+ for (int i = 0; i < MAX_SPLINE_NUMBER; i++) {
+ if (getSpline(i) != null && !getSpline(i).isOriginal()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+
+ if (!(representation instanceof FilterCurvesRepresentation)) {
+ return false;
+ } else {
+ FilterCurvesRepresentation curve =
+ (FilterCurvesRepresentation) representation;
+ for (int i = 0; i < MAX_SPLINE_NUMBER; i++) {
+ if (!getSpline(i).sameValues(curve.getSpline(i))) {
+ return false;
+ }
+ }
+ }
+ // Every spline matches, therefore they are the same.
+ return true;
+ }
+
+ public void reset() {
+ Spline spline = new Spline();
+
+ spline.addPoint(0.0f, 1.0f);
+ spline.addPoint(1.0f, 0.0f);
+
+ for (int i = 0; i < MAX_SPLINE_NUMBER; i++) {
+ mSplines[i] = new Spline(spline);
+ }
+ }
+
+ public void setSpline(int splineIndex, Spline s) {
+ mSplines[splineIndex] = s;
+ }
+
+ public Spline getSpline(int splineIndex) {
+ return mSplines[splineIndex];
+ }
+
+ @Override
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+ {
+ writer.name(NAME_TAG);
+ writer.value(getName());
+ for (int i = 0; i < mSplines.length; i++) {
+ writer.name(SERIALIZATION_NAME + i);
+ writer.beginArray();
+ int nop = mSplines[i].getNbPoints();
+ for (int j = 0; j < nop; j++) {
+ ControlPoint p = mSplines[i].getPoint(j);
+ writer.beginArray();
+ writer.value(p.x);
+ writer.value(p.y);
+ writer.endArray();
+ }
+ writer.endArray();
+ }
+
+ }
+ writer.endObject();
+ }
+
+ @Override
+ public void deSerializeRepresentation(JsonReader sreader) throws IOException {
+ sreader.beginObject();
+ Spline[] spline = new Spline[MAX_SPLINE_NUMBER];
+ while (sreader.hasNext()) {
+ String name = sreader.nextName();
+ if (NAME_TAG.equals(name)) {
+ setName(sreader.nextString());
+ } else if (name.startsWith(SERIALIZATION_NAME)) {
+ int curveNo = Integer.parseInt(name.substring(SERIALIZATION_NAME.length()));
+ spline[curveNo] = new Spline();
+ sreader.beginArray();
+ while (sreader.hasNext()) {
+ sreader.beginArray();
+ sreader.hasNext();
+ float x = (float) sreader.nextDouble();
+ sreader.hasNext();
+ float y = (float) sreader.nextDouble();
+ sreader.endArray();
+ spline[curveNo].addPoint(x, y);
+ }
+ sreader.endArray();
+
+ }
+ }
+ mSplines = spline;
+ sreader.endObject();
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java
new file mode 100644
index 000000000..ac0cb7492
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java
@@ -0,0 +1,38 @@
+/*
+ * 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 class FilterDirectRepresentation extends FilterRepresentation {
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterDirectRepresentation representation = new FilterDirectRepresentation(getName());
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ public FilterDirectRepresentation(String name) {
+ super(name);
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java
new file mode 100644
index 000000000..977dbeac5
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java
@@ -0,0 +1,171 @@
+/*
+ * 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;
+
+import android.graphics.Path;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorDraw;
+
+import java.util.Vector;
+
+public class FilterDrawRepresentation extends FilterRepresentation {
+ private static final String LOGTAG = "FilterDrawRepresentation";
+
+ public static class StrokeData implements Cloneable {
+ public byte mType;
+ public Path mPath;
+ public float mRadius;
+ public int mColor;
+ public int noPoints = 0;
+ @Override
+ public String toString() {
+ return "stroke(" + mType + ", path(" + (mPath) + "), " + mRadius + " , "
+ + Integer.toHexString(mColor) + ")";
+ }
+ @Override
+ public StrokeData clone() throws CloneNotSupportedException {
+ return (StrokeData) super.clone();
+ }
+ }
+
+ private Vector<StrokeData> mDrawing = new Vector<StrokeData>();
+ private StrokeData mCurrent; // used in the currently drawing style
+
+ public FilterDrawRepresentation() {
+ super("Draw");
+ setFilterClass(ImageFilterDraw.class);
+ setSerializationName("DRAW");
+ setFilterType(FilterRepresentation.TYPE_VIGNETTE);
+ setTextId(R.string.imageDraw);
+ setEditorId(EditorDraw.ID);
+ setOverlayId(R.drawable.filtershow_drawing);
+ setOverlayOnly(true);
+ }
+
+ @Override
+ public String toString() {
+ return getName() + " : strokes=" + mDrawing.size()
+ + ((mCurrent == null) ? " no current "
+ : ("draw=" + mCurrent.mType + " " + mCurrent.noPoints));
+ }
+
+ public Vector<StrokeData> getDrawing() {
+ return mDrawing;
+ }
+
+ public StrokeData getCurrentDrawing() {
+ return mCurrent;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterDrawRepresentation representation = new FilterDrawRepresentation();
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public boolean isNil() {
+ return getDrawing().isEmpty();
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterDrawRepresentation) {
+ FilterDrawRepresentation representation = (FilterDrawRepresentation) a;
+ try {
+ if (representation.mCurrent != null) {
+ mCurrent = (StrokeData) representation.mCurrent.clone();
+ } else {
+ mCurrent = null;
+ }
+ if (representation.mDrawing != null) {
+ mDrawing = (Vector<StrokeData>) representation.mDrawing.clone();
+ } else {
+ mDrawing = null;
+ }
+
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ } else {
+ Log.v(LOGTAG, "cannot use parameters from " + a);
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterDrawRepresentation) {
+ FilterDrawRepresentation fdRep = (FilterDrawRepresentation) representation;
+ if (fdRep.mDrawing.size() != mDrawing.size())
+ return false;
+ if (fdRep.mCurrent == null && mCurrent.mPath == null) {
+ return true;
+ }
+ if (fdRep.mCurrent != null && mCurrent.mPath != null) {
+ if (fdRep.mCurrent.noPoints == mCurrent.noPoints) {
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
+ }
+
+ public void startNewSection(byte type, int color, float size, float x, float y) {
+ mCurrent = new StrokeData();
+ mCurrent.mColor = color;
+ mCurrent.mRadius = size;
+ mCurrent.mType = type;
+ mCurrent.mPath = new Path();
+ mCurrent.mPath.moveTo(x, y);
+ mCurrent.noPoints = 0;
+ }
+
+ public void addPoint(float x, float y) {
+ mCurrent.noPoints++;
+ mCurrent.mPath.lineTo(x, y);
+ }
+
+ public void endSection(float x, float y) {
+ mCurrent.mPath.lineTo(x, y);
+ mCurrent.noPoints++;
+ mDrawing.add(mCurrent);
+ mCurrent = null;
+ }
+
+ public void clearCurrentSection() {
+ mCurrent = null;
+ }
+
+ public void clear() {
+ mCurrent = null;
+ mDrawing.clear();
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java
new file mode 100644
index 000000000..e5a6fdd23
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java
@@ -0,0 +1,112 @@
+/*
+ * 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;
+
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+
+public class FilterFxRepresentation extends FilterRepresentation {
+ 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;
+ private int mNameResource = 0;
+
+ public FilterFxRepresentation(String name, int bitmapResource, int nameResource) {
+ super(name);
+ setFilterClass(ImageFilterFx.class);
+ mBitmapResource = bitmapResource;
+ mNameResource = nameResource;
+ setFilterType(FilterRepresentation.TYPE_FX);
+ setTextId(nameResource);
+ setEditorId(ImageOnlyEditor.ID);
+ setShowParameterValue(false);
+ setSupportsPartialRendering(true);
+ }
+
+ @Override
+ public String toString() {
+ return "FilterFx: " + hashCode() + " : " + getName() + " bitmap rsc: " + mBitmapResource;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterFxRepresentation representation = new FilterFxRepresentation(getName(),0,0);
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public synchronized void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterFxRepresentation) {
+ FilterFxRepresentation representation = (FilterFxRepresentation) a;
+ setName(representation.getName());
+ setSerializationName(representation.getSerializationName());
+ setBitmapResource(representation.getBitmapResource());
+ setNameResource(representation.getNameResource());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterFxRepresentation) {
+ FilterFxRepresentation fx = (FilterFxRepresentation) representation;
+ if (fx.mNameResource == mNameResource
+ && fx.mBitmapResource == mBitmapResource) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean same(FilterRepresentation representation) {
+ if (!super.same(representation)) {
+ return false;
+ }
+ return equals(representation);
+ }
+
+ @Override
+ public boolean allowsSingleInstanceOnly() {
+ return true;
+ }
+
+ public int getNameResource() {
+ return mNameResource;
+ }
+
+ public void setNameResource(int nameResource) {
+ mNameResource = nameResource;
+ }
+
+ public int getBitmapResource() {
+ return mBitmapResource;
+ }
+
+ public void setBitmapResource(int bitmapResource) {
+ mBitmapResource = bitmapResource;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java
new file mode 100644
index 000000000..0c272d48a
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java
@@ -0,0 +1,497 @@
+/*
+ * 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;
+
+import android.graphics.Rect;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorGrad;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.imageshow.Line;
+
+import java.io.IOException;
+import java.util.Vector;
+
+public class FilterGradRepresentation extends FilterRepresentation
+ implements Line {
+ private static final String LOGTAG = "FilterGradRepresentation";
+ public static final int MAX_POINTS = 16;
+ public static final int PARAM_BRIGHTNESS = 0;
+ public static final int PARAM_SATURATION = 1;
+ public static final int PARAM_CONTRAST = 2;
+ private static final double ADD_MIN_DIST = .05;
+ private static String LINE_NAME = "Point";
+ private static final String SERIALIZATION_NAME = "grad";
+
+ public FilterGradRepresentation() {
+ super("Grad");
+ setSerializationName(SERIALIZATION_NAME);
+ creatExample();
+ setOverlayId(R.drawable.filtershow_button_grad);
+ setFilterClass(ImageFilterGrad.class);
+ setTextId(R.string.grad);
+ setEditorId(EditorGrad.ID);
+ }
+
+ public void trimVector(){
+ int n = mBands.size();
+ for (int i = n; i < MAX_POINTS; i++) {
+ mBands.add(new Band());
+ }
+ for (int i = MAX_POINTS; i < n; i++) {
+ mBands.remove(i);
+ }
+ }
+
+ Vector<Band> mBands = new Vector<Band>();
+ Band mCurrentBand;
+
+ static class Band {
+ private boolean mask = true;
+
+ private int xPos1 = -1;
+ private int yPos1 = 100;
+ private int xPos2 = -1;
+ private int yPos2 = 100;
+ private int brightness = 40;
+ private int contrast = 0;
+ private int saturation = 0;
+
+
+ public Band() {
+ }
+
+ public Band(int x, int y) {
+ xPos1 = x;
+ yPos1 = y+30;
+ xPos2 = x;
+ yPos2 = y-30;
+ }
+
+ public Band(Band copy) {
+ mask = copy.mask;
+ xPos1 = copy.xPos1;
+ yPos1 = copy.yPos1;
+ xPos2 = copy.xPos2;
+ yPos2 = copy.yPos2;
+ brightness = copy.brightness;
+ contrast = copy.contrast;
+ saturation = copy.saturation;
+ }
+
+ }
+
+ @Override
+ public String toString() {
+ int count = 0;
+ for (Band point : mBands) {
+ if (!point.mask) {
+ count++;
+ }
+ }
+ return "c=" + mBands.indexOf(mBands) + "[" + mBands.size() + "]" + count;
+ }
+
+ private void creatExample() {
+ Band p = new Band();
+ p.mask = false;
+ p.xPos1 = -1;
+ p.yPos1 = 100;
+ p.xPos2 = -1;
+ p.yPos2 = 100;
+ p.brightness = 40;
+ p.contrast = 0;
+ p.saturation = 0;
+ mBands.add(0, p);
+ mCurrentBand = p;
+ trimVector();
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ FilterGradRepresentation rep = (FilterGradRepresentation) a;
+ Vector<Band> tmpBands = new Vector<Band>();
+ int n = (rep.mCurrentBand == null) ? 0 : rep.mBands.indexOf(rep.mCurrentBand);
+ for (Band band : rep.mBands) {
+ tmpBands.add(new Band(band));
+ }
+ mCurrentBand = null;
+ mBands = tmpBands;
+ mCurrentBand = mBands.elementAt(n);
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterGradRepresentation representation = new FilterGradRepresentation();
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (representation instanceof FilterGradRepresentation) {
+ FilterGradRepresentation rep = (FilterGradRepresentation) representation;
+ int n = getNumberOfBands();
+ if (rep.getNumberOfBands() != n) {
+ return false;
+ }
+ for (int i = 0; i < mBands.size(); i++) {
+ Band b1 = mBands.get(i);
+ Band b2 = rep.mBands.get(i);
+ if (b1.mask != b2.mask
+ || b1.brightness != b2.brightness
+ || b1.contrast != b2.contrast
+ || b1.saturation != b2.saturation
+ || b1.xPos1 != b2.xPos1
+ || b1.xPos2 != b2.xPos2
+ || b1.yPos1 != b2.yPos1
+ || b1.yPos2 != b2.yPos2) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public int getNumberOfBands() {
+ int count = 0;
+ for (Band point : mBands) {
+ if (!point.mask) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ public int addBand(Rect rect) {
+ mBands.add(0, mCurrentBand = new Band(rect.centerX(), rect.centerY()));
+ mCurrentBand.mask = false;
+ int x = (mCurrentBand.xPos1 + mCurrentBand.xPos2)/2;
+ int y = (mCurrentBand.yPos1 + mCurrentBand.yPos2)/2;
+ double addDelta = ADD_MIN_DIST * Math.max(rect.width(), rect.height());
+ boolean moved = true;
+ int count = 0;
+ int toMove = mBands.indexOf(mCurrentBand);
+
+ while (moved) {
+ moved = false;
+ count++;
+ if (count > 14) {
+ break;
+ }
+
+ for (Band point : mBands) {
+ if (point.mask) {
+ break;
+ }
+ }
+
+ for (Band point : mBands) {
+ if (point.mask) {
+ break;
+ }
+ int index = mBands.indexOf(point);
+
+ if (toMove != index) {
+ double dist = Math.hypot(point.xPos1 - x, point.yPos1 - y);
+ if (dist < addDelta) {
+ moved = true;
+ mCurrentBand.xPos1 += addDelta;
+ mCurrentBand.yPos1 += addDelta;
+ mCurrentBand.xPos2 += addDelta;
+ mCurrentBand.yPos2 += addDelta;
+ x = (mCurrentBand.xPos1 + mCurrentBand.xPos2)/2;
+ y = (mCurrentBand.yPos1 + mCurrentBand.yPos2)/2;
+
+ if (mCurrentBand.yPos1 > rect.bottom) {
+ mCurrentBand.yPos1 = (int) (rect.top + addDelta);
+ }
+ if (mCurrentBand.xPos1 > rect.right) {
+ mCurrentBand.xPos1 = (int) (rect.left + addDelta);
+ }
+ }
+ }
+ }
+ }
+ trimVector();
+ return 0;
+ }
+
+ public void deleteCurrentBand() {
+ int index = mBands.indexOf(mCurrentBand);
+ mBands.remove(mCurrentBand);
+ trimVector();
+ if (getNumberOfBands() == 0) {
+ addBand(MasterImage.getImage().getOriginalBounds());
+ }
+ mCurrentBand = mBands.get(0);
+ }
+
+ public void nextPoint(){
+ int index = mBands.indexOf(mCurrentBand);
+ int tmp = index;
+ Band point;
+ int k = 0;
+ do {
+ index = (index+1)% mBands.size();
+ point = mBands.get(index);
+ if (k++ >= mBands.size()) {
+ break;
+ }
+ }
+ while (point.mask == true);
+ mCurrentBand = mBands.get(index);
+ }
+
+ public void setSelectedPoint(int pos) {
+ mCurrentBand = mBands.get(pos);
+ }
+
+ public int getSelectedPoint() {
+ return mBands.indexOf(mCurrentBand);
+ }
+
+ public boolean[] getMask() {
+ boolean[] ret = new boolean[mBands.size()];
+ int i = 0;
+ for (Band point : mBands) {
+ ret[i++] = !point.mask;
+ }
+ return ret;
+ }
+
+ public int[] getXPos1() {
+ int[] ret = new int[mBands.size()];
+ int i = 0;
+ for (Band point : mBands) {
+ ret[i++] = point.xPos1;
+ }
+ return ret;
+ }
+
+ public int[] getYPos1() {
+ int[] ret = new int[mBands.size()];
+ int i = 0;
+ for (Band point : mBands) {
+ ret[i++] = point.yPos1;
+ }
+ return ret;
+ }
+
+ public int[] getXPos2() {
+ int[] ret = new int[mBands.size()];
+ int i = 0;
+ for (Band point : mBands) {
+ ret[i++] = point.xPos2;
+ }
+ return ret;
+ }
+
+ public int[] getYPos2() {
+ int[] ret = new int[mBands.size()];
+ int i = 0;
+ for (Band point : mBands) {
+ ret[i++] = point.yPos2;
+ }
+ return ret;
+ }
+
+ public int[] getBrightness() {
+ int[] ret = new int[mBands.size()];
+ int i = 0;
+ for (Band point : mBands) {
+ ret[i++] = point.brightness;
+ }
+ return ret;
+ }
+
+ public int[] getContrast() {
+ int[] ret = new int[mBands.size()];
+ int i = 0;
+ for (Band point : mBands) {
+ ret[i++] = point.contrast;
+ }
+ return ret;
+ }
+
+ public int[] getSaturation() {
+ int[] ret = new int[mBands.size()];
+ int i = 0;
+ for (Band point : mBands) {
+ ret[i++] = point.saturation;
+ }
+ return ret;
+ }
+
+ public int getParameter(int type) {
+ switch (type){
+ case PARAM_BRIGHTNESS:
+ return mCurrentBand.brightness;
+ case PARAM_SATURATION:
+ return mCurrentBand.saturation;
+ case PARAM_CONTRAST:
+ return mCurrentBand.contrast;
+ }
+ throw new IllegalArgumentException("no such type " + type);
+ }
+
+ public int getParameterMax(int type) {
+ switch (type) {
+ case PARAM_BRIGHTNESS:
+ return 100;
+ case PARAM_SATURATION:
+ return 100;
+ case PARAM_CONTRAST:
+ return 100;
+ }
+ throw new IllegalArgumentException("no such type " + type);
+ }
+
+ public int getParameterMin(int type) {
+ switch (type) {
+ case PARAM_BRIGHTNESS:
+ return -100;
+ case PARAM_SATURATION:
+ return -100;
+ case PARAM_CONTRAST:
+ return -100;
+ }
+ throw new IllegalArgumentException("no such type " + type);
+ }
+
+ public void setParameter(int type, int value) {
+ mCurrentBand.mask = false;
+ switch (type) {
+ case PARAM_BRIGHTNESS:
+ mCurrentBand.brightness = value;
+ break;
+ case PARAM_SATURATION:
+ mCurrentBand.saturation = value;
+ break;
+ case PARAM_CONTRAST:
+ mCurrentBand.contrast = value;
+ break;
+ default:
+ throw new IllegalArgumentException("no such type " + type);
+ }
+ }
+
+ @Override
+ public void setPoint1(float x, float y) {
+ mCurrentBand.xPos1 = (int)x;
+ mCurrentBand.yPos1 = (int)y;
+ }
+
+ @Override
+ public void setPoint2(float x, float y) {
+ mCurrentBand.xPos2 = (int)x;
+ mCurrentBand.yPos2 = (int)y;
+ }
+
+ @Override
+ public float getPoint1X() {
+ return mCurrentBand.xPos1;
+ }
+
+ @Override
+ public float getPoint1Y() {
+ return mCurrentBand.yPos1;
+ }
+ @Override
+ public float getPoint2X() {
+ return mCurrentBand.xPos2;
+ }
+
+ @Override
+ public float getPoint2Y() {
+ return mCurrentBand.yPos2;
+ }
+
+ @Override
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+ int len = mBands.size();
+ int count = 0;
+
+ for (int i = 0; i < len; i++) {
+ Band point = mBands.get(i);
+ if (point.mask) {
+ continue;
+ }
+ writer.name(LINE_NAME + count);
+ count++;
+ writer.beginArray();
+ writer.value(point.xPos1);
+ writer.value(point.yPos1);
+ writer.value(point.xPos2);
+ writer.value(point.yPos2);
+ writer.value(point.brightness);
+ writer.value(point.contrast);
+ writer.value(point.saturation);
+ writer.endArray();
+ }
+ writer.endObject();
+ }
+
+ @Override
+ public void deSerializeRepresentation(JsonReader sreader) throws IOException {
+ sreader.beginObject();
+ Vector<Band> points = new Vector<Band>();
+
+ while (sreader.hasNext()) {
+ String name = sreader.nextName();
+ if (name.startsWith(LINE_NAME)) {
+ int pointNo = Integer.parseInt(name.substring(LINE_NAME.length()));
+ sreader.beginArray();
+ Band p = new Band();
+ p.mask = false;
+ sreader.hasNext();
+ p.xPos1 = sreader.nextInt();
+ sreader.hasNext();
+ p.yPos1 = sreader.nextInt();
+ sreader.hasNext();
+ p.xPos2 = sreader.nextInt();
+ sreader.hasNext();
+ p.yPos2 = sreader.nextInt();
+ sreader.hasNext();
+ p.brightness = sreader.nextInt();
+ sreader.hasNext();
+ p.contrast = sreader.nextInt();
+ sreader.hasNext();
+ p.saturation = sreader.nextInt();
+ sreader.hasNext();
+ sreader.endArray();
+ points.add(p);
+
+ } else {
+ sreader.skipValue();
+ }
+ }
+ mBands = points;
+ trimVector();
+ mCurrentBand = mBands.get(0);
+ sreader.endObject();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
new file mode 100644
index 000000000..f310a2be1
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
@@ -0,0 +1,91 @@
+/*
+ * 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;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+
+public class FilterImageBorderRepresentation extends FilterRepresentation {
+ private int mDrawableResource = 0;
+
+ public FilterImageBorderRepresentation(int drawableResource) {
+ super("ImageBorder");
+ setFilterClass(ImageFilterBorder.class);
+ mDrawableResource = drawableResource;
+ setFilterType(FilterRepresentation.TYPE_BORDER);
+ setTextId(R.string.borders);
+ setEditorId(ImageOnlyEditor.ID);
+ setShowParameterValue(false);
+ }
+
+ public String toString() {
+ return "FilterBorder: " + getName();
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterImageBorderRepresentation representation =
+ new FilterImageBorderRepresentation(mDrawableResource);
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterImageBorderRepresentation) {
+ FilterImageBorderRepresentation representation = (FilterImageBorderRepresentation) a;
+ setName(representation.getName());
+ setDrawableResource(representation.getDrawableResource());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterImageBorderRepresentation) {
+ FilterImageBorderRepresentation border = (FilterImageBorderRepresentation) representation;
+ if (border.mDrawableResource == mDrawableResource) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getTextId() {
+ return R.string.none;
+ }
+
+ public boolean allowsSingleInstanceOnly() {
+ return true;
+ }
+
+ public int getDrawableResource() {
+ return mDrawableResource;
+ }
+
+ public void setDrawableResource(int drawableResource) {
+ mDrawableResource = drawableResource;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java
new file mode 100644
index 000000000..8dcff0d16
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java
@@ -0,0 +1,190 @@
+/*
+ * 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;
+
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorMirror;
+
+import java.io.IOException;
+
+public class FilterMirrorRepresentation extends FilterRepresentation {
+ public static final String SERIALIZATION_NAME = "MIRROR";
+ private static final String SERIALIZATION_MIRROR_VALUE = "value";
+ private static final String TAG = FilterMirrorRepresentation.class.getSimpleName();
+
+ Mirror mMirror;
+
+ public enum Mirror {
+ NONE('N'), VERTICAL('V'), HORIZONTAL('H'), BOTH('B');
+ char mValue;
+
+ private Mirror(char value) {
+ mValue = value;
+ }
+
+ public char value() {
+ return mValue;
+ }
+
+ public static Mirror fromValue(char value) {
+ switch (value) {
+ case 'N':
+ return NONE;
+ case 'V':
+ return VERTICAL;
+ case 'H':
+ return HORIZONTAL;
+ case 'B':
+ return BOTH;
+ default:
+ return null;
+ }
+ }
+ }
+
+ public FilterMirrorRepresentation(Mirror mirror) {
+ super(FilterMirrorRepresentation.class.getSimpleName());
+ setSerializationName(SERIALIZATION_NAME);
+ setShowParameterValue(true);
+ setFilterClass(FilterMirrorRepresentation.class);
+ setFilterType(FilterRepresentation.TYPE_GEOMETRY);
+ setTextId(R.string.mirror);
+ setEditorId(EditorMirror.ID);
+ setMirror(mirror);
+ }
+
+ public FilterMirrorRepresentation(FilterMirrorRepresentation m) {
+ this(m.getMirror());
+ }
+
+ public FilterMirrorRepresentation() {
+ this(getNil());
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation rep) {
+ if (!(rep instanceof FilterMirrorRepresentation)) {
+ return false;
+ }
+ FilterMirrorRepresentation mirror = (FilterMirrorRepresentation) rep;
+ if (mMirror != mirror.mMirror) {
+ return false;
+ }
+ return true;
+ }
+
+ public Mirror getMirror() {
+ return mMirror;
+ }
+
+ public void set(FilterMirrorRepresentation r) {
+ mMirror = r.mMirror;
+ }
+
+ public void setMirror(Mirror mirror) {
+ if (mirror == null) {
+ throw new IllegalArgumentException("Argument to setMirror is null");
+ }
+ mMirror = mirror;
+ }
+
+ public void cycle() {
+ switch (mMirror) {
+ case NONE:
+ mMirror = Mirror.HORIZONTAL;
+ break;
+ case HORIZONTAL:
+ mMirror = Mirror.VERTICAL;
+ break;
+ case VERTICAL:
+ mMirror = Mirror.BOTH;
+ break;
+ case BOTH:
+ mMirror = Mirror.NONE;
+ break;
+ }
+ }
+
+ @Override
+ public boolean allowsSingleInstanceOnly() {
+ return true;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ return new FilterMirrorRepresentation(this);
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ if (!(representation instanceof FilterMirrorRepresentation)) {
+ throw new IllegalArgumentException("calling copyAllParameters with incompatible types!");
+ }
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ if (!(a instanceof FilterMirrorRepresentation)) {
+ throw new IllegalArgumentException("calling useParametersFrom with incompatible types!");
+ }
+ setMirror(((FilterMirrorRepresentation) a).getMirror());
+ }
+
+ @Override
+ public boolean isNil() {
+ return mMirror == getNil();
+ }
+
+ public static Mirror getNil() {
+ return Mirror.NONE;
+ }
+
+ @Override
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+ writer.name(SERIALIZATION_MIRROR_VALUE).value(mMirror.value());
+ writer.endObject();
+ }
+
+ @Override
+ public void deSerializeRepresentation(JsonReader reader) throws IOException {
+ boolean unset = true;
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ if (SERIALIZATION_MIRROR_VALUE.equals(name)) {
+ Mirror r = Mirror.fromValue((char) reader.nextInt());
+ if (r != null) {
+ setMirror(r);
+ unset = false;
+ }
+ } else {
+ reader.skipValue();
+ }
+ }
+ if (unset) {
+ Log.w(TAG, "WARNING: bad value when deserializing " + SERIALIZATION_NAME);
+ }
+ reader.endObject();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterPoint.java b/src/com/android/gallery3d/filtershow/filters/FilterPoint.java
new file mode 100644
index 000000000..4520717a1
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterPoint.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 FilterPoint {
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java
new file mode 100644
index 000000000..9bd1699d9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java
@@ -0,0 +1,88 @@
+/*
+ * 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;
+
+import java.util.Vector;
+
+public abstract class FilterPointRepresentation extends FilterRepresentation {
+ private static final String LOGTAG = "FilterPointRepresentation";
+ private Vector<FilterPoint> mCandidates = new Vector<FilterPoint>();
+
+ public FilterPointRepresentation(String type, int textid, int editorID) {
+ super(type);
+ setFilterClass(ImageFilterRedEye.class);
+ setFilterType(FilterRepresentation.TYPE_NORMAL);
+ setTextId(textid);
+ setEditorId(editorID);
+ }
+
+ @Override
+ public abstract FilterRepresentation copy();
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ public boolean hasCandidates() {
+ return mCandidates != null;
+ }
+
+ public Vector<FilterPoint> getCandidates() {
+ return mCandidates;
+ }
+
+ @Override
+ public boolean isNil() {
+ if (getCandidates() != null && getCandidates().size() > 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public Object getCandidate(int index) {
+ return this.mCandidates.get(index);
+ }
+
+ public void addCandidate(FilterPoint c) {
+ this.mCandidates.add(c);
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterPointRepresentation) {
+ FilterPointRepresentation representation = (FilterPointRepresentation) a;
+ mCandidates.clear();
+ for (FilterPoint redEyeCandidate : representation.mCandidates) {
+ mCandidates.add(redEyeCandidate);
+ }
+ }
+ }
+
+ public void removeCandidate(RedEyeCandidate c) {
+ this.mCandidates.remove(c);
+ }
+
+ public void clearCandidates() {
+ this.mCandidates.clear();
+ }
+
+ public int getNumberOfCandidates() {
+ return mCandidates.size();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java
new file mode 100644
index 000000000..dd06a9760
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+import android.graphics.RectF;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorRedEye;
+
+import java.util.Vector;
+
+public class FilterRedEyeRepresentation extends FilterPointRepresentation {
+ private static final String LOGTAG = "FilterRedEyeRepresentation";
+
+ public FilterRedEyeRepresentation() {
+ super("RedEye",R.string.redeye,EditorRedEye.ID);
+ setSerializationName("REDEYE");
+ setFilterClass(ImageFilterRedEye.class);
+ setOverlayId(R.drawable.photoeditor_effect_redeye);
+ setOverlayOnly(true);
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterRedEyeRepresentation representation = new FilterRedEyeRepresentation();
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ public void addRect(RectF rect, RectF bounds) {
+ Vector<RedEyeCandidate> intersects = new Vector<RedEyeCandidate>();
+ for (int i = 0; i < getCandidates().size(); i++) {
+ RedEyeCandidate r = (RedEyeCandidate) getCandidate(i);
+ if (r.intersect(rect)) {
+ intersects.add(r);
+ }
+ }
+ for (int i = 0; i < intersects.size(); i++) {
+ RedEyeCandidate r = intersects.elementAt(i);
+ rect.union(r.mRect);
+ bounds.union(r.mBounds);
+ removeCandidate(r);
+ }
+ addCandidate(new RedEyeCandidate(rect, bounds));
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
new file mode 100644
index 000000000..5b33ffba5
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
@@ -0,0 +1,262 @@
+/*
+ * 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;
+
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.editors.BasicEditor;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class FilterRepresentation {
+ private static final String LOGTAG = "FilterRepresentation";
+ private static final boolean DEBUG = false;
+ private String mName;
+ private int mPriority = TYPE_NORMAL;
+ private Class<?> mFilterClass;
+ private boolean mSupportsPartialRendering = false;
+ private int mTextId = 0;
+ private int mEditorId = BasicEditor.ID;
+ private int mButtonId = 0;
+ private int mOverlayId = 0;
+ private boolean mOverlayOnly = false;
+ private boolean mShowParameterValue = 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;
+ public static final byte TYPE_VIGNETTE = 4;
+ public static final byte TYPE_NORMAL = 5;
+ public static final byte TYPE_TINYPLANET = 6;
+ public static final byte TYPE_GEOMETRY = 7;
+ protected static final String NAME_TAG = "Name";
+
+ public FilterRepresentation(String name) {
+ mName = name;
+ }
+
+ public FilterRepresentation copy(){
+ FilterRepresentation representation = new FilterRepresentation(mName);
+ representation.useParametersFrom(this);
+ return representation;
+ }
+
+ protected void copyAllParameters(FilterRepresentation representation) {
+ representation.setName(getName());
+ representation.setFilterClass(getFilterClass());
+ representation.setFilterType(getFilterType());
+ representation.setSupportsPartialRendering(supportsPartialRendering());
+ representation.setTextId(getTextId());
+ representation.setEditorId(getEditorId());
+ representation.setOverlayId(getOverlayId());
+ representation.setOverlayOnly(getOverlayOnly());
+ representation.setShowParameterValue(showParameterValue());
+ representation.mSerializationName = mSerializationName;
+
+ }
+
+ public boolean equals(FilterRepresentation representation) {
+ if (representation == null) {
+ return false;
+ }
+ if (representation.mFilterClass == mFilterClass
+ && representation.mName.equalsIgnoreCase(mName)
+ && representation.mPriority == mPriority
+ // TODO: After we enable partial rendering, we can switch back
+ // to use member variable here.
+ && representation.supportsPartialRendering() == supportsPartialRendering()
+ && representation.mTextId == mTextId
+ && representation.mEditorId == mEditorId
+ && representation.mButtonId == mButtonId
+ && representation.mOverlayId == mOverlayId
+ && representation.mOverlayOnly == mOverlayOnly
+ && representation.mShowParameterValue == mShowParameterValue) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return mName;
+ }
+
+ public void setName(String name) {
+ mName = name;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public void setSerializationName(String sname) {
+ mSerializationName = sname;
+ }
+
+ public String getSerializationName() {
+ return mSerializationName;
+ }
+
+ public void setFilterType(int priority) {
+ mPriority = priority;
+ }
+
+ public int getFilterType() {
+ return mPriority;
+ }
+
+ public boolean isNil() {
+ return false;
+ }
+
+ public boolean supportsPartialRendering() {
+ return false && mSupportsPartialRendering; // disable for now
+ }
+
+ public void setSupportsPartialRendering(boolean value) {
+ mSupportsPartialRendering = value;
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ }
+
+ public boolean allowsSingleInstanceOnly() {
+ return false;
+ }
+
+ public Class<?> getFilterClass() {
+ return mFilterClass;
+ }
+
+ public void setFilterClass(Class<?> filterClass) {
+ mFilterClass = filterClass;
+ }
+
+ // This same() function is different from equals(), basically it checks
+ // whether 2 FilterRepresentations are the same type. It doesn't care about
+ // the values.
+ public boolean same(FilterRepresentation b) {
+ if (b == null) {
+ return false;
+ }
+ return getFilterClass() == b.getFilterClass();
+ }
+
+ public int getTextId() {
+ return mTextId;
+ }
+
+ public void setTextId(int textId) {
+ mTextId = textId;
+ }
+
+ public int getOverlayId() {
+ return mOverlayId;
+ }
+
+ public void setOverlayId(int overlayId) {
+ mOverlayId = overlayId;
+ }
+
+ public boolean getOverlayOnly() {
+ return mOverlayOnly;
+ }
+
+ public void setOverlayOnly(boolean value) {
+ mOverlayOnly = value;
+ }
+
+ final public int getEditorId() {
+ return mEditorId;
+ }
+
+ public int[] getEditorIds() {
+ return new int[] {
+ mEditorId };
+ }
+
+ public void setEditorId(int editorId) {
+ mEditorId = editorId;
+ }
+
+ public boolean showParameterValue() {
+ return mShowParameterValue;
+ }
+
+ public void setShowParameterValue(boolean showParameterValue) {
+ mShowParameterValue = showParameterValue;
+ }
+
+ public String getStateRepresentation() {
+ return "";
+ }
+
+ /**
+ * Method must "beginObject()" add its info and "endObject()"
+ * @param writer
+ * @throws IOException
+ */
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+ {
+ String[][] rep = serializeRepresentation();
+ for (int k = 0; k < rep.length; k++) {
+ writer.name(rep[k][0]);
+ writer.value(rep[k][1]);
+ }
+ }
+ writer.endObject();
+ }
+
+ // this is the old way of doing this and will be removed soon
+ public String[][] serializeRepresentation() {
+ String[][] ret = {{NAME_TAG, getName()}};
+ return ret;
+ }
+
+ public void deSerializeRepresentation(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();
+ String[][] oldFormat = al.toArray(new String[al.size()][]);
+
+ deSerializeRepresentation(oldFormat);
+ }
+
+ // this is the old way of doing this and will be removed soon
+ public void deSerializeRepresentation(String[][] rep) {
+ for (int i = 0; i < rep.length; i++) {
+ if (NAME_TAG.equals(rep[i][0])) {
+ mName = rep[i][1];
+ break;
+ }
+ }
+ }
+
+ // Override this in subclasses
+ public int getStyle() {
+ return -1;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java
new file mode 100644
index 000000000..eb89de036
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java
@@ -0,0 +1,190 @@
+/*
+ * 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;
+
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorRotate;
+
+import java.io.IOException;
+
+public class FilterRotateRepresentation extends FilterRepresentation {
+ public static final String SERIALIZATION_NAME = "ROTATION";
+ public static final String SERIALIZATION_ROTATE_VALUE = "value";
+ private static final String TAG = FilterRotateRepresentation.class.getSimpleName();
+
+ Rotation mRotation;
+
+ public enum Rotation {
+ ZERO(0), NINETY(90), ONE_EIGHTY(180), TWO_SEVENTY(270);
+ private final int mValue;
+
+ private Rotation(int value) {
+ mValue = value;
+ }
+
+ public int value() {
+ return mValue;
+ }
+
+ public static Rotation fromValue(int value) {
+ switch (value) {
+ case 0:
+ return ZERO;
+ case 90:
+ return NINETY;
+ case 180:
+ return ONE_EIGHTY;
+ case 270:
+ return TWO_SEVENTY;
+ default:
+ return null;
+ }
+ }
+ }
+
+ public FilterRotateRepresentation(Rotation rotation) {
+ super(FilterRotateRepresentation.class.getSimpleName());
+ setSerializationName(SERIALIZATION_NAME);
+ setShowParameterValue(true);
+ setFilterClass(FilterRotateRepresentation.class);
+ setFilterType(FilterRepresentation.TYPE_GEOMETRY);
+ setTextId(R.string.rotate);
+ setEditorId(EditorRotate.ID);
+ setRotation(rotation);
+ }
+
+ public FilterRotateRepresentation(FilterRotateRepresentation r) {
+ this(r.getRotation());
+ }
+
+ public FilterRotateRepresentation() {
+ this(getNil());
+ }
+
+ public Rotation getRotation() {
+ return mRotation;
+ }
+
+ public void rotateCW() {
+ switch(mRotation) {
+ case ZERO:
+ mRotation = Rotation.NINETY;
+ break;
+ case NINETY:
+ mRotation = Rotation.ONE_EIGHTY;
+ break;
+ case ONE_EIGHTY:
+ mRotation = Rotation.TWO_SEVENTY;
+ break;
+ case TWO_SEVENTY:
+ mRotation = Rotation.ZERO;
+ break;
+ }
+ }
+
+ public void set(FilterRotateRepresentation r) {
+ mRotation = r.mRotation;
+ }
+
+ public void setRotation(Rotation rotation) {
+ if (rotation == null) {
+ throw new IllegalArgumentException("Argument to setRotation is null");
+ }
+ mRotation = rotation;
+ }
+
+ @Override
+ public boolean allowsSingleInstanceOnly() {
+ return true;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ return new FilterRotateRepresentation(this);
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ if (!(representation instanceof FilterRotateRepresentation)) {
+ throw new IllegalArgumentException("calling copyAllParameters with incompatible types!");
+ }
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ if (!(a instanceof FilterRotateRepresentation)) {
+ throw new IllegalArgumentException("calling useParametersFrom with incompatible types!");
+ }
+ setRotation(((FilterRotateRepresentation) a).getRotation());
+ }
+
+ @Override
+ public boolean isNil() {
+ return mRotation == getNil();
+ }
+
+ public static Rotation getNil() {
+ return Rotation.ZERO;
+ }
+
+ @Override
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+ writer.name(SERIALIZATION_ROTATE_VALUE).value(mRotation.value());
+ writer.endObject();
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation rep) {
+ if (!(rep instanceof FilterRotateRepresentation)) {
+ return false;
+ }
+ FilterRotateRepresentation rotate = (FilterRotateRepresentation) rep;
+ if (rotate.mRotation.value() != mRotation.value()) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void deSerializeRepresentation(JsonReader reader) throws IOException {
+ boolean unset = true;
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ if (SERIALIZATION_ROTATE_VALUE.equals(name)) {
+ Rotation r = Rotation.fromValue(reader.nextInt());
+ if (r != null) {
+ setRotation(r);
+ unset = false;
+ }
+ } else {
+ reader.skipValue();
+ }
+ }
+ if (unset) {
+ Log.w(TAG, "WARNING: bad value when deserializing " + SERIALIZATION_NAME);
+ }
+ reader.endObject();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java
new file mode 100644
index 000000000..94c9497fc
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java
@@ -0,0 +1,154 @@
+/*
+ * 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;
+
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorStraighten;
+
+import java.io.IOException;
+
+public class FilterStraightenRepresentation extends FilterRepresentation {
+ public static final String SERIALIZATION_NAME = "STRAIGHTEN";
+ public static final String SERIALIZATION_STRAIGHTEN_VALUE = "value";
+ private static final String TAG = FilterStraightenRepresentation.class.getSimpleName();
+ public static final int MAX_STRAIGHTEN_ANGLE = 45;
+ public static final int MIN_STRAIGHTEN_ANGLE = -45;
+
+ float mStraighten;
+
+ public FilterStraightenRepresentation(float straighten) {
+ super(FilterStraightenRepresentation.class.getSimpleName());
+ setSerializationName(SERIALIZATION_NAME);
+ setShowParameterValue(true);
+ setFilterClass(FilterStraightenRepresentation.class);
+ setFilterType(FilterRepresentation.TYPE_GEOMETRY);
+ setTextId(R.string.straighten);
+ setEditorId(EditorStraighten.ID);
+ setStraighten(straighten);
+ }
+
+ public FilterStraightenRepresentation(FilterStraightenRepresentation s) {
+ this(s.getStraighten());
+ }
+
+ public FilterStraightenRepresentation() {
+ this(getNil());
+ }
+
+ public void set(FilterStraightenRepresentation r) {
+ mStraighten = r.mStraighten;
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation rep) {
+ if (!(rep instanceof FilterStraightenRepresentation)) {
+ return false;
+ }
+ FilterStraightenRepresentation straighten = (FilterStraightenRepresentation) rep;
+ if (straighten.mStraighten != mStraighten) {
+ return false;
+ }
+ return true;
+ }
+
+ public float getStraighten() {
+ return mStraighten;
+ }
+
+ public void setStraighten(float straighten) {
+ if (!rangeCheck(straighten)) {
+ straighten = Math.min(Math.max(straighten, MIN_STRAIGHTEN_ANGLE), MAX_STRAIGHTEN_ANGLE);
+ }
+ mStraighten = straighten;
+ }
+
+ @Override
+ public boolean allowsSingleInstanceOnly() {
+ return true;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ return new FilterStraightenRepresentation(this);
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ if (!(representation instanceof FilterStraightenRepresentation)) {
+ throw new IllegalArgumentException("calling copyAllParameters with incompatible types!");
+ }
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ if (!(a instanceof FilterStraightenRepresentation)) {
+ throw new IllegalArgumentException("calling useParametersFrom with incompatible types!");
+ }
+ setStraighten(((FilterStraightenRepresentation) a).getStraighten());
+ }
+
+ @Override
+ public boolean isNil() {
+ return mStraighten == getNil();
+ }
+
+ public static float getNil() {
+ return 0;
+ }
+
+ @Override
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+ writer.name(SERIALIZATION_STRAIGHTEN_VALUE).value(mStraighten);
+ writer.endObject();
+ }
+
+ @Override
+ public void deSerializeRepresentation(JsonReader reader) throws IOException {
+ boolean unset = true;
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ if (SERIALIZATION_STRAIGHTEN_VALUE.equals(name)) {
+ float s = (float) reader.nextDouble();
+ if (rangeCheck(s)) {
+ setStraighten(s);
+ unset = false;
+ }
+ } else {
+ reader.skipValue();
+ }
+ }
+ if (unset) {
+ Log.w(TAG, "WARNING: bad value when deserializing " + SERIALIZATION_NAME);
+ }
+ reader.endObject();
+ }
+
+ private boolean rangeCheck(double s) {
+ if (s < -45 || s > 45) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java
new file mode 100644
index 000000000..be1812957
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 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;
+
+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);
+ setFilterType(FilterRepresentation.TYPE_TINYPLANET);
+ setTextId(R.string.tinyplanet);
+ setEditorId(EditorTinyPlanet.ID);
+ setMinimum(1);
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterTinyPlanetRepresentation representation = new FilterTinyPlanetRepresentation();
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ FilterTinyPlanetRepresentation representation = (FilterTinyPlanetRepresentation) a;
+ super.useParametersFrom(a);
+ mAngle = representation.mAngle;
+ setZoom(representation.getZoom());
+ }
+
+ public void setAngle(float angle) {
+ mAngle = angle;
+ }
+
+ public float getAngle() {
+ return mAngle;
+ }
+
+ public int getZoom() {
+ return getValue();
+ }
+
+ public void setZoom(int zoom) {
+ setValue(zoom);
+ }
+
+ public boolean isNil() {
+ // 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/FilterUserPresetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterUserPresetRepresentation.java
new file mode 100644
index 000000000..dfdb6fcf0
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterUserPresetRepresentation.java
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+
+public class FilterUserPresetRepresentation extends FilterRepresentation {
+
+ private ImagePreset mPreset;
+ private int mId;
+
+ public FilterUserPresetRepresentation(String name, ImagePreset preset, int id) {
+ super(name);
+ setEditorId(ImageOnlyEditor.ID);
+ setFilterType(FilterRepresentation.TYPE_FX);
+ mPreset = preset;
+ mId = id;
+ }
+
+ public ImagePreset getImagePreset() {
+ return mPreset;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public FilterRepresentation copy(){
+ FilterRepresentation representation = new FilterUserPresetRepresentation(getName(),
+ new ImagePreset(mPreset), mId);
+ return representation;
+ }
+
+ @Override
+ public boolean allowsSingleInstanceOnly() {
+ return true;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
new file mode 100644
index 000000000..42a7406bc
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2012 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;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorVignette;
+import com.android.gallery3d.filtershow.imageshow.Oval;
+
+public class FilterVignetteRepresentation extends FilterBasicRepresentation implements Oval {
+ private static final String LOGTAG = "FilterVignetteRepresentation";
+ private float mCenterX = Float.NaN;
+ private float mCenterY;
+ private float mRadiusX = Float.NaN;
+ private float mRadiusY;
+
+ public FilterVignetteRepresentation() {
+ super("Vignette", -100, 50, 100);
+ setSerializationName("VIGNETTE");
+ setShowParameterValue(true);
+ setFilterType(FilterRepresentation.TYPE_VIGNETTE);
+ setTextId(R.string.vignette);
+ setEditorId(EditorVignette.ID);
+ setName("Vignette");
+ setFilterClass(ImageFilterVignette.class);
+ setMinimum(-100);
+ setMaximum(100);
+ setDefaultValue(0);
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ super.useParametersFrom(a);
+ mCenterX = ((FilterVignetteRepresentation) a).mCenterX;
+ mCenterY = ((FilterVignetteRepresentation) a).mCenterY;
+ mRadiusX = ((FilterVignetteRepresentation) a).mRadiusX;
+ mRadiusY = ((FilterVignetteRepresentation) a).mRadiusY;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterVignetteRepresentation representation = new FilterVignetteRepresentation();
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public void setCenter(float centerX, float centerY) {
+ mCenterX = centerX;
+ mCenterY = centerY;
+ }
+
+ @Override
+ public float getCenterX() {
+ return mCenterX;
+ }
+
+ @Override
+ public float getCenterY() {
+ return mCenterY;
+ }
+
+ @Override
+ public void setRadius(float radiusX, float radiusY) {
+ mRadiusX = radiusX;
+ mRadiusY = radiusY;
+ }
+
+ @Override
+ public void setRadiusX(float radiusX) {
+ mRadiusX = radiusX;
+ }
+
+ @Override
+ public void setRadiusY(float radiusY) {
+ mRadiusY = radiusY;
+ }
+
+ @Override
+ public float getRadiusX() {
+ return mRadiusX;
+ }
+
+ @Override
+ public float getRadiusY() {
+ return mRadiusY;
+ }
+
+ public boolean isCenterSet() {
+ return mCenterX != Float.NaN;
+ }
+
+ @Override
+ public boolean isNil() {
+ return getValue() == 0;
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterVignetteRepresentation) {
+ FilterVignetteRepresentation rep = (FilterVignetteRepresentation) representation;
+ if (rep.getCenterX() == getCenterX()
+ && rep.getCenterY() == getCenterY()
+ && rep.getRadiusX() == getRadiusX()
+ && rep.getRadiusY() == getRadiusY()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ 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/IconUtilities.java b/src/com/android/gallery3d/filtershow/filters/IconUtilities.java
new file mode 100644
index 000000000..e2a01472d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/IconUtilities.java
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import com.android.gallery3d.R;
+
+public class IconUtilities {
+ public static final int PUNCH = R.drawable.filtershow_fx_0005_punch;
+ public static final int VINTAGE = R.drawable.filtershow_fx_0000_vintage;
+ public static final int BW_CONTRAST = R.drawable.filtershow_fx_0004_bw_contrast;
+ public static final int BLEACH = R.drawable.filtershow_fx_0002_bleach;
+ public static final int INSTANT = R.drawable.filtershow_fx_0001_instant;
+ public static final int WASHOUT = R.drawable.filtershow_fx_0007_washout;
+ public static final int BLUECRUSH = R.drawable.filtershow_fx_0003_blue_crush;
+ public static final int WASHOUT_COLOR = R.drawable.filtershow_fx_0008_washout_color;
+ public static final int X_PROCESS = R.drawable.filtershow_fx_0006_x_process;
+
+ public static Bitmap getFXBitmap(Resources res, int id) {
+ Bitmap ret;
+ BitmapFactory.Options o = new BitmapFactory.Options();
+ o.inScaled = false;
+
+ if (id != 0) {
+ return BitmapFactory.decodeResource(res, id, o);
+ }
+ return null;
+ }
+
+ public static Bitmap loadBitmap(Resources res, int resource) {
+
+ final BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ Bitmap bitmap = BitmapFactory.decodeResource(
+ res,
+ resource, options);
+
+ return bitmap;
+ }
+
+ public static Bitmap applyFX(Bitmap bitmap, final Bitmap fxBitmap) {
+ ImageFilterFx fx = new ImageFilterFx() {
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ int fxw = fxBitmap.getWidth();
+ int fxh = fxBitmap.getHeight();
+ int start = 0;
+ int end = w * h * 4;
+ nativeApplyFilter(bitmap, w, h, fxBitmap, fxw, fxh, start, end);
+ return bitmap;
+ }
+ };
+ return fx.apply(bitmap, 0, 0);
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
new file mode 100644
index 000000000..437137416
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2012 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;
+
+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.imageshow.GeometryMathUtils;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+
+public abstract class ImageFilter implements Cloneable {
+ private FilterEnvironment mEnvironment = null;
+
+ protected String mName = "Original";
+ private final String LOGTAG = "ImageFilter";
+ protected static final boolean SIMPLE_ICONS = true;
+ // TODO: Temporary, for dogfood note memory issues with toasts for better
+ // feedback. Remove this when filters actually work in low memory
+ // situations.
+ private static Activity sActivity = null;
+
+ public static void setActivityForMemoryToasts(Activity activity) {
+ sActivity = activity;
+ }
+
+ public static void resetStatics() {
+ sActivity = null;
+ }
+
+ public void freeResources() {}
+
+ public void displayLowMemoryToast() {
+ if (sActivity != null) {
+ sActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ Toast.makeText(sActivity, "Memory too low for filter " + getName() +
+ ", please file a bug report", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }
+
+ public void setName(String name) {
+ mName = name;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public boolean supportsAllocationInput() { return false; }
+
+ public void apply(Allocation in, Allocation out) {
+ setGeneralParameters();
+ }
+
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ // do nothing here, subclasses will implement filtering here
+ setGeneralParameters();
+ return bitmap;
+ }
+
+ public abstract void useRepresentation(FilterRepresentation representation);
+
+ native protected void nativeApplyGradientFilter(Bitmap bitmap, int w, int h,
+ int[] redGradient, int[] greenGradient, int[] blueGradient);
+
+ public FilterRepresentation getDefaultRepresentation() {
+ return null;
+ }
+
+ protected Matrix getOriginalToScreenMatrix(int w, int h) {
+ return GeometryMathUtils.getImageToScreenMatrix(getEnvironment().getImagePreset()
+ .getGeometryFilters(), true, MasterImage.getImage().getOriginalBounds(), w, h);
+ }
+
+ public void setEnvironment(FilterEnvironment environment) {
+ mEnvironment = environment;
+ }
+
+ public FilterEnvironment getEnvironment() {
+ return mEnvironment;
+ }
+
+ public void setGeneralParameters() {
+ // should implement in subclass which like to transport
+ // some information to other filters. (like the style setting from RetroLux
+ // and Film to FixedFrame)
+ mEnvironment.clearGeneralParameters();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
new file mode 100644
index 000000000..a7286f0fa
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+
+import java.util.HashMap;
+
+public class ImageFilterBorder extends ImageFilter {
+ private static final float NINEPATCH_ICON_SCALING = 10;
+ private static final float BITMAP_ICON_SCALING = 1 / 3.0f;
+ private FilterImageBorderRepresentation mParameters = null;
+ private Resources mResources = null;
+
+ private HashMap<Integer, Drawable> mDrawables = new HashMap<Integer, Drawable>();
+
+ public ImageFilterBorder() {
+ mName = "Border";
+ }
+
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterImageBorderRepresentation parameters = (FilterImageBorderRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public FilterImageBorderRepresentation getParameters() {
+ return mParameters;
+ }
+
+ public void freeResources() {
+ mDrawables.clear();
+ }
+
+ public Bitmap applyHelper(Bitmap bitmap, float scale1, float scale2 ) {
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ Rect bounds = new Rect(0, 0, (int) (w * scale1), (int) (h * scale1));
+ Canvas canvas = new Canvas(bitmap);
+ canvas.scale(scale2, scale2);
+ Drawable drawable = getDrawable(getParameters().getDrawableResource());
+ drawable.setBounds(bounds);
+ drawable.draw(canvas);
+ return bitmap;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null || getParameters().getDrawableResource() == 0) {
+ return bitmap;
+ }
+ float scale2 = scaleFactor * 2.0f;
+ float scale1 = 1 / scale2;
+ return applyHelper(bitmap, scale1, scale2);
+ }
+
+ public void setResources(Resources resources) {
+ if (mResources != resources) {
+ mResources = resources;
+ mDrawables.clear();
+ }
+ }
+
+ public Drawable getDrawable(int rsc) {
+ Drawable drawable = mDrawables.get(rsc);
+ if (drawable == null && mResources != null && rsc != 0) {
+ drawable = new BitmapDrawable(mResources, BitmapFactory.decodeResource(mResources, rsc));
+ mDrawables.put(rsc, drawable);
+ }
+ return drawable;
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
new file mode 100644
index 000000000..50837ca2f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 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;
+
+import com.android.gallery3d.R;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+
+
+public class ImageFilterBwFilter extends SimpleImageFilter {
+ private static final String SERIALIZATION_NAME = "BWFILTER";
+
+ public ImageFilterBwFilter() {
+ mName = "BW Filter";
+ }
+
+ 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);
+ representation.setTextId(R.string.bwfilter);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, int r, int g, int b);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ float[] hsv = new float[] {
+ 180 + getParameters().getValue(), 1, 1
+ };
+ int rgb = Color.HSVToColor(hsv);
+ int r = 0xFF & (rgb >> 16);
+ int g = 0xFF & (rgb >> 8);
+ int b = 0xFF & (rgb >> 0);
+ nativeApplyFilter(bitmap, w, h, r, g, b);
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java
new file mode 100644
index 000000000..1ea8edfb8
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java
@@ -0,0 +1,161 @@
+/*
+ * 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;
+
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.support.v8.renderscript.Allocation;
+import android.support.v8.renderscript.Element;
+import android.support.v8.renderscript.RenderScript;
+import android.support.v8.renderscript.Script.LaunchOptions;
+import android.support.v8.renderscript.Type;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+
+public class ImageFilterChanSat extends ImageFilterRS {
+ private static final String LOGTAG = "ImageFilterChanSat";
+ private ScriptC_saturation mScript;
+ private Bitmap mSourceBitmap;
+
+ private static final int STRIP_SIZE = 64;
+
+ FilterChanSatRepresentation mParameters = new FilterChanSatRepresentation();
+ private Bitmap mOverlayBitmap;
+
+ public ImageFilterChanSat() {
+ mName = "ChannelSat";
+ }
+
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterChanSatRepresentation();
+ }
+
+ @Override
+ public void useRepresentation(FilterRepresentation representation) {
+ mParameters = (FilterChanSatRepresentation) representation;
+ }
+
+ @Override
+ protected void resetAllocations() {
+
+ }
+
+ @Override
+ public void resetScripts() {
+ if (mScript != null) {
+ mScript.destroy();
+ mScript = null;
+ }
+ }
+ @Override
+ protected void createFilter(android.content.res.Resources res, float scaleFactor,
+ int quality) {
+ createFilter(res, scaleFactor, quality, getInPixelsAllocation());
+ }
+
+ @Override
+ protected void createFilter(android.content.res.Resources res, float scaleFactor,
+ int quality, Allocation in) {
+ RenderScript rsCtx = getRenderScriptContext();
+
+ Type.Builder tb_float = new Type.Builder(rsCtx, Element.F32_4(rsCtx));
+ tb_float.setX(in.getType().getX());
+ tb_float.setY(in.getType().getY());
+ mScript = new ScriptC_saturation(rsCtx, res, R.raw.saturation);
+ }
+
+
+ private Bitmap getSourceBitmap() {
+ assert (mSourceBitmap != null);
+ return mSourceBitmap;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) {
+ return bitmap;
+ }
+
+ mSourceBitmap = bitmap;
+ Bitmap ret = super.apply(bitmap, scaleFactor, quality);
+ mSourceBitmap = null;
+
+ return ret;
+ }
+
+ @Override
+ protected void bindScriptValues() {
+ int width = getInPixelsAllocation().getType().getX();
+ int height = getInPixelsAllocation().getType().getY();
+ }
+
+
+
+ @Override
+ protected void runFilter() {
+ int []sat = new int[7];
+ for(int i = 0;i<sat.length ;i ++){
+ sat[i] = mParameters.getValue(i);
+ }
+
+
+ int width = getInPixelsAllocation().getType().getX();
+ int height = getInPixelsAllocation().getType().getY();
+ Matrix m = getOriginalToScreenMatrix(width, height);
+
+
+ mScript.set_saturation(sat);
+
+ mScript.invoke_setupGradParams();
+ runSelectiveAdjust(
+ getInPixelsAllocation(), getOutPixelsAllocation());
+
+ }
+
+ private void runSelectiveAdjust(Allocation in, Allocation out) {
+ int width = in.getType().getX();
+ int height = in.getType().getY();
+
+ LaunchOptions options = new LaunchOptions();
+ int ty;
+ options.setX(0, width);
+
+ for (ty = 0; ty < height; ty += STRIP_SIZE) {
+ int endy = ty + STRIP_SIZE;
+ if (endy > height) {
+ endy = height;
+ }
+ options.setY(ty, endy);
+ mScript.forEach_selectiveAdjust(in, out, options);
+ if (checkStop()) {
+ return;
+ }
+ }
+ }
+
+ private boolean checkStop() {
+ RenderScript rsCtx = getRenderScriptContext();
+ rsCtx.finish();
+ if (getEnvironment().needsStop()) {
+ return true;
+ }
+ return false;
+ }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
new file mode 100644
index 000000000..27c0e0877
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 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;
+
+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";
+ }
+
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Contrast");
+ representation.setSerializationName(SERIALIZATION_NAME);
+
+ representation.setFilterClass(ImageFilterContrast.class);
+ representation.setTextId(R.string.contrast);
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float strength);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ float value = getParameters().getValue();
+ nativeApplyFilter(bitmap, w, h, value);
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java
new file mode 100644
index 000000000..61b60d2e3
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.graphics.Bitmap;
+
+import com.android.gallery3d.filtershow.imageshow.Spline;
+
+public class ImageFilterCurves extends ImageFilter {
+
+ private static final String LOGTAG = "ImageFilterCurves";
+ FilterCurvesRepresentation mParameters = new FilterCurvesRepresentation();
+
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterCurvesRepresentation();
+ }
+
+ @Override
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterCurvesRepresentation parameters = (FilterCurvesRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public ImageFilterCurves() {
+ mName = "Curves";
+ reset();
+ }
+
+ public void populateArray(int[] array, int curveIndex) {
+ Spline spline = mParameters.getSpline(curveIndex);
+ if (spline == null) {
+ return;
+ }
+ float[] curve = spline.getAppliedCurve();
+ for (int i = 0; i < 256; i++) {
+ array[i] = (int) (curve[i] * 255);
+ }
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (!mParameters.getSpline(Spline.RGB).isOriginal()) {
+ int[] rgbGradient = new int[256];
+ populateArray(rgbGradient, Spline.RGB);
+ nativeApplyGradientFilter(bitmap, bitmap.getWidth(), bitmap.getHeight(),
+ rgbGradient, rgbGradient, rgbGradient);
+ }
+
+ int[] redGradient = null;
+ if (!mParameters.getSpline(Spline.RED).isOriginal()) {
+ redGradient = new int[256];
+ populateArray(redGradient, Spline.RED);
+ }
+ int[] greenGradient = null;
+ if (!mParameters.getSpline(Spline.GREEN).isOriginal()) {
+ greenGradient = new int[256];
+ populateArray(greenGradient, Spline.GREEN);
+ }
+ int[] blueGradient = null;
+ if (!mParameters.getSpline(Spline.BLUE).isOriginal()) {
+ blueGradient = new int[256];
+ populateArray(blueGradient, Spline.BLUE);
+ }
+
+ nativeApplyGradientFilter(bitmap, bitmap.getWidth(), bitmap.getHeight(),
+ redGradient, greenGradient, blueGradient);
+ return bitmap;
+ }
+
+ public void setSpline(Spline spline, int splineIndex) {
+ mParameters.setSpline(splineIndex, new Spline(spline));
+ }
+
+ public Spline getSpline(int splineIndex) {
+ return mParameters.getSpline(splineIndex);
+ }
+
+ public void reset() {
+ Spline spline = new Spline();
+
+ spline.addPoint(0.0f, 1.0f);
+ spline.addPoint(1.0f, 0.0f);
+
+ for (int i = 0; i < 4; i++) {
+ mParameters.setSpline(i, new Spline(spline));
+ }
+ }
+
+ public void useFilter(ImageFilter a) {
+ ImageFilterCurves c = (ImageFilterCurves) a;
+ for (int i = 0; i < 4; i++) {
+ if (c.mParameters.getSpline(i) != null) {
+ setSpline(c.mParameters.getSpline(i), i);
+ }
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
new file mode 100644
index 000000000..efb9cde71
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+
+public class ImageFilterDownsample extends SimpleImageFilter {
+ private static final String SERIALIZATION_NAME = "DOWNSAMPLE";
+ private static final int ICON_DOWNSAMPLE_FRACTION = 8;
+ private ImageLoader mImageLoader;
+
+ public ImageFilterDownsample(ImageLoader loader) {
+ mName = "Downsample";
+ mImageLoader = loader;
+ }
+
+ 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);
+ representation.setValue(50);
+ representation.setDefaultValue(50);
+ representation.setPreviewValue(3);
+ representation.setTextId(R.string.downsample);
+ return representation;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ int p = getParameters().getValue();
+
+ // size of original precached image
+ Rect size = MasterImage.getImage().getOriginalBounds();
+ int orig_w = size.width();
+ int orig_h = size.height();
+
+ if (p > 0 && p < 100) {
+ // scale preview to same size as the resulting bitmap from a "save"
+ int newWidth = orig_w * p / 100;
+ int newHeight = orig_h * p / 100;
+
+ // only scale preview if preview isn't already scaled enough
+ if (newWidth <= 0 || newHeight <= 0 || newWidth >= w || newHeight >= h) {
+ return bitmap;
+ }
+ Bitmap ret = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
+ if (ret != bitmap) {
+ bitmap.recycle();
+ }
+ return ret;
+ }
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
new file mode 100644
index 000000000..7df5ffb64
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation.StrokeData;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+
+import java.util.Vector;
+
+public class ImageFilterDraw extends ImageFilter {
+ private static final String LOGTAG = "ImageFilterDraw";
+ public final static byte SIMPLE_STYLE = 0;
+ public final static byte BRUSH_STYLE_SPATTER = 1;
+ public final static byte BRUSH_STYLE_MARKER = 2;
+ public final static int NUMBER_OF_STYLES = 3;
+ Bitmap mOverlayBitmap; // this accelerates interaction
+ int mCachedStrokes = -1;
+ int mCurrentStyle = 0;
+
+ FilterDrawRepresentation mParameters = new FilterDrawRepresentation();
+
+ public ImageFilterDraw() {
+ mName = "Image Draw";
+ }
+
+ DrawStyle[] mDrawingsTypes = new DrawStyle[] {
+ new SimpleDraw(),
+ new Brush(R.drawable.brush_marker),
+ new Brush(R.drawable.brush_spatter)
+ };
+ {
+ for (int i = 0; i < mDrawingsTypes.length; i++) {
+ mDrawingsTypes[i].setType((byte) i);
+ }
+
+ }
+
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterDrawRepresentation();
+ }
+
+ @Override
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterDrawRepresentation parameters = (FilterDrawRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public void setStyle(byte style) {
+ mCurrentStyle = style % mDrawingsTypes.length;
+ }
+
+ public int getStyle() {
+ return mCurrentStyle;
+ }
+
+ public static interface DrawStyle {
+ public void setType(byte type);
+ public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
+ int quality);
+ }
+
+ class SimpleDraw implements DrawStyle {
+ byte mType;
+
+ @Override
+ public void setType(byte type) {
+ mType = type;
+ }
+
+ @Override
+ public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
+ int quality) {
+ if (sd == null) {
+ return;
+ }
+ if (sd.mPath == null) {
+ return;
+ }
+ Paint paint = new Paint();
+
+ paint.setStyle(Style.STROKE);
+ paint.setColor(sd.mColor);
+ paint.setStrokeWidth(toScrMatrix.mapRadius(sd.mRadius));
+
+ // done this way because of a bug in path.transform(matrix)
+ Path mCacheTransPath = new Path();
+ mCacheTransPath.addPath(sd.mPath, toScrMatrix);
+
+ canvas.drawPath(mCacheTransPath, paint);
+ }
+ }
+
+ class Brush implements DrawStyle {
+ int mBrushID;
+ Bitmap mBrush;
+ byte mType;
+
+ public Brush(int brushID) {
+ mBrushID = brushID;
+ }
+
+ public Bitmap getBrush() {
+ if (mBrush == null) {
+ BitmapFactory.Options opt = new BitmapFactory.Options();
+ opt.inPreferredConfig = Bitmap.Config.ALPHA_8;
+ mBrush = BitmapFactory.decodeResource(MasterImage.getImage().getActivity()
+ .getResources(), mBrushID, opt);
+ mBrush = mBrush.extractAlpha();
+ }
+ return mBrush;
+ }
+
+ @Override
+ public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas,
+ Matrix toScrMatrix,
+ int quality) {
+ if (sd == null || sd.mPath == null) {
+ return;
+ }
+ Paint paint = new Paint();
+ paint.setStyle(Style.STROKE);
+ paint.setAntiAlias(true);
+ Path mCacheTransPath = new Path();
+ mCacheTransPath.addPath(sd.mPath, toScrMatrix);
+ draw(canvas, paint, sd.mColor, toScrMatrix.mapRadius(sd.mRadius) * 2,
+ mCacheTransPath);
+ }
+
+ public Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
+ {
+ Matrix m = new Matrix();
+ m.setScale(dstWidth / (float) src.getWidth(), dstHeight / (float) src.getHeight());
+ Bitmap result = Bitmap.createBitmap(dstWidth, dstHeight, src.getConfig());
+ Canvas canvas = new Canvas(result);
+
+ Paint paint = new Paint();
+ paint.setFilterBitmap(filter);
+ canvas.drawBitmap(src, m, paint);
+
+ return result;
+
+ }
+ void draw(Canvas canvas, Paint paint, int color, float size, Path path) {
+ PathMeasure mPathMeasure = new PathMeasure();
+ float[] mPosition = new float[2];
+ float[] mTan = new float[2];
+
+ mPathMeasure.setPath(path, false);
+
+ paint.setAntiAlias(true);
+ paint.setColor(color);
+
+ paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
+ Bitmap brush;
+ // done this way because of a bug in
+ // Bitmap.createScaledBitmap(getBrush(),(int) size,(int) size,true);
+ brush = createScaledBitmap(getBrush(), (int) size, (int) size, true);
+ float len = mPathMeasure.getLength();
+ float s2 = size / 2;
+ float step = s2 / 8;
+ for (float i = 0; i < len; i += step) {
+ mPathMeasure.getPosTan(i, mPosition, mTan);
+ // canvas.drawCircle(pos[0], pos[1], size, paint);
+ canvas.drawBitmap(brush, mPosition[0] - s2, mPosition[1] - s2, paint);
+ }
+ }
+
+ @Override
+ public void setType(byte type) {
+ mType = type;
+ }
+ }
+
+ void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
+ int quality) {
+ mDrawingsTypes[sd.mType].paint(sd, canvas, toScrMatrix, quality);
+ }
+
+ public void drawData(Canvas canvas, Matrix originalRotateToScreen, int quality) {
+ Paint paint = new Paint();
+ if (quality == FilterEnvironment.QUALITY_FINAL) {
+ paint.setAntiAlias(true);
+ }
+ paint.setStyle(Style.STROKE);
+ paint.setColor(Color.RED);
+ paint.setStrokeWidth(40);
+
+ if (mParameters.getDrawing().isEmpty() && mParameters.getCurrentDrawing() == null) {
+ return;
+ }
+ if (quality == FilterEnvironment.QUALITY_FINAL) {
+ for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) {
+ paint(strokeData, canvas, originalRotateToScreen, quality);
+ }
+ return;
+ }
+
+ if (mOverlayBitmap == null ||
+ mOverlayBitmap.getWidth() != canvas.getWidth() ||
+ mOverlayBitmap.getHeight() != canvas.getHeight() ||
+ mParameters.getDrawing().size() < mCachedStrokes) {
+
+ mOverlayBitmap = Bitmap.createBitmap(
+ canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
+ mCachedStrokes = 0;
+ }
+
+ if (mCachedStrokes < mParameters.getDrawing().size()) {
+ fillBuffer(originalRotateToScreen);
+ }
+ canvas.drawBitmap(mOverlayBitmap, 0, 0, paint);
+
+ StrokeData stroke = mParameters.getCurrentDrawing();
+ if (stroke != null) {
+ paint(stroke, canvas, originalRotateToScreen, quality);
+ }
+ }
+
+ public void fillBuffer(Matrix originalRotateToScreen) {
+ Canvas drawCache = new Canvas(mOverlayBitmap);
+ Vector<FilterDrawRepresentation.StrokeData> v = mParameters.getDrawing();
+ int n = v.size();
+
+ for (int i = mCachedStrokes; i < n; i++) {
+ 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, FilterEnvironment.QUALITY_PREVIEW);
+ }
+ mDrawingsTypes[mCurrentStyle].paint(
+ null, canvas, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW);
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+
+ Matrix m = getOriginalToScreenMatrix(w, h);
+ drawData(new Canvas(bitmap), m, quality);
+ return bitmap;
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
new file mode 100644
index 000000000..2d0d7653d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 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;
+
+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";
+ }
+
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterRepresentation representation = super.getDefaultRepresentation();
+ representation.setName("Edge");
+ representation.setSerializationName(SERIALIZATION_NAME);
+ representation.setFilterClass(ImageFilterEdge.class);
+ representation.setTextId(R.string.edge);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float p);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ float p = getParameters().getValue() + 101;
+ p = (float) p / 100;
+ nativeApplyFilter(bitmap, w, h, p);
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
new file mode 100644
index 000000000..69eab7330
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 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;
+
+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";
+ }
+
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Exposure");
+ representation.setSerializationName(SERIALIZATION_NAME);
+ representation.setFilterClass(ImageFilterExposure.class);
+ representation.setTextId(R.string.exposure);
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float bright);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ float value = getParameters().getValue();
+ nativeApplyFilter(bitmap, w, h, value);
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java
new file mode 100644
index 000000000..19bea593b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import com.android.gallery3d.app.Log;
+
+public class ImageFilterFx extends ImageFilter {
+ private static final String LOGTAG = "ImageFilterFx";
+ private FilterFxRepresentation mParameters = null;
+ private Bitmap mFxBitmap = null;
+ private Resources mResources = null;
+ private int mFxBitmapId = 0;
+
+ public ImageFilterFx() {
+ }
+
+ @Override
+ public void freeResources() {
+ if (mFxBitmap != null) mFxBitmap.recycle();
+ mFxBitmap = null;
+ }
+
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ return null;
+ }
+
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterFxRepresentation parameters = (FilterFxRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public FilterFxRepresentation getParameters() {
+ return mParameters;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h,
+ Bitmap fxBitmap, int fxw, int fxh,
+ int start, int end);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null || mResources == null) {
+ return bitmap;
+ }
+
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+
+ int bitmapResourceId = getParameters().getBitmapResource();
+ if (bitmapResourceId == 0) { // null filter fx
+ return bitmap;
+ }
+
+ if (mFxBitmap == null || mFxBitmapId != bitmapResourceId) {
+ BitmapFactory.Options o = new BitmapFactory.Options();
+ o.inScaled = false;
+ mFxBitmapId = bitmapResourceId;
+ if (mFxBitmapId != 0) {
+ mFxBitmap = BitmapFactory.decodeResource(mResources, mFxBitmapId, o);
+ } else {
+ Log.w(LOGTAG, "bad resource for filter: " + mName);
+ }
+ }
+
+ if (mFxBitmap == null) {
+ return bitmap;
+ }
+
+ int fxw = mFxBitmap.getWidth();
+ int fxh = mFxBitmap.getHeight();
+
+ int stride = w * 4;
+ int max = stride * h;
+ int increment = stride * 256; // 256 lines
+ for (int i = 0; i < max; i += increment) {
+ int start = i;
+ int end = i + increment;
+ if (end > max) {
+ end = max;
+ }
+ if (!getEnvironment().needsStop()) {
+ nativeApplyFilter(bitmap, w, h, mFxBitmap, fxw, fxh, start, end);
+ }
+ }
+
+ return bitmap;
+ }
+
+ public void setResources(Resources resources) {
+ mResources = resources;
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java
new file mode 100644
index 000000000..cbdfaa623
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java
@@ -0,0 +1,190 @@
+/*
+ * 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;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Matrix;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.support.v8.renderscript.Allocation;
+import android.support.v8.renderscript.Element;
+import android.support.v8.renderscript.RenderScript;
+import android.support.v8.renderscript.Script.LaunchOptions;
+import android.support.v8.renderscript.Type;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+
+public class ImageFilterGrad extends ImageFilterRS {
+ private static final String LOGTAG = "ImageFilterGrad";
+ private ScriptC_grad mScript;
+ private Bitmap mSourceBitmap;
+ private static final int RADIUS_SCALE_FACTOR = 160;
+
+ private static final int STRIP_SIZE = 64;
+
+ FilterGradRepresentation mParameters = new FilterGradRepresentation();
+ private Bitmap mOverlayBitmap;
+
+ public ImageFilterGrad() {
+ mName = "grad";
+ }
+
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterGradRepresentation();
+ }
+
+ @Override
+ public void useRepresentation(FilterRepresentation representation) {
+ mParameters = (FilterGradRepresentation) representation;
+ }
+
+ @Override
+ protected void resetAllocations() {
+
+ }
+
+ @Override
+ public void resetScripts() {
+ if (mScript != null) {
+ mScript.destroy();
+ mScript = null;
+ }
+ }
+ @Override
+ protected void createFilter(android.content.res.Resources res, float scaleFactor,
+ int quality) {
+ createFilter(res, scaleFactor, quality, getInPixelsAllocation());
+ }
+
+ @Override
+ protected void createFilter(android.content.res.Resources res, float scaleFactor,
+ int quality, Allocation in) {
+ RenderScript rsCtx = getRenderScriptContext();
+
+ Type.Builder tb_float = new Type.Builder(rsCtx, Element.F32_4(rsCtx));
+ tb_float.setX(in.getType().getX());
+ tb_float.setY(in.getType().getY());
+ mScript = new ScriptC_grad(rsCtx, res, R.raw.grad);
+ }
+
+
+ private Bitmap getSourceBitmap() {
+ assert (mSourceBitmap != null);
+ return mSourceBitmap;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) {
+ return bitmap;
+ }
+
+ mSourceBitmap = bitmap;
+ Bitmap ret = super.apply(bitmap, scaleFactor, quality);
+ mSourceBitmap = null;
+
+ return ret;
+ }
+
+ @Override
+ protected void bindScriptValues() {
+ int width = getInPixelsAllocation().getType().getX();
+ int height = getInPixelsAllocation().getType().getY();
+ mScript.set_inputWidth(width);
+ mScript.set_inputHeight(height);
+ }
+
+ @Override
+ protected void runFilter() {
+ int[] x1 = mParameters.getXPos1();
+ int[] y1 = mParameters.getYPos1();
+ int[] x2 = mParameters.getXPos2();
+ int[] y2 = mParameters.getYPos2();
+
+ int width = getInPixelsAllocation().getType().getX();
+ int height = getInPixelsAllocation().getType().getY();
+ Matrix m = getOriginalToScreenMatrix(width, height);
+ float[] coord = new float[2];
+ for (int i = 0; i < x1.length; i++) {
+ coord[0] = x1[i];
+ coord[1] = y1[i];
+ m.mapPoints(coord);
+ x1[i] = (int) coord[0];
+ y1[i] = (int) coord[1];
+ coord[0] = x2[i];
+ coord[1] = y2[i];
+ m.mapPoints(coord);
+ x2[i] = (int) coord[0];
+ y2[i] = (int) coord[1];
+ }
+
+ mScript.set_mask(mParameters.getMask());
+ mScript.set_xPos1(x1);
+ mScript.set_yPos1(y1);
+ mScript.set_xPos2(x2);
+ mScript.set_yPos2(y2);
+
+ mScript.set_brightness(mParameters.getBrightness());
+ mScript.set_contrast(mParameters.getContrast());
+ mScript.set_saturation(mParameters.getSaturation());
+
+ mScript.invoke_setupGradParams();
+ runSelectiveAdjust(
+ getInPixelsAllocation(), getOutPixelsAllocation());
+
+ }
+
+ private void runSelectiveAdjust(Allocation in, Allocation out) {
+ int width = in.getType().getX();
+ int height = in.getType().getY();
+
+ LaunchOptions options = new LaunchOptions();
+ int ty;
+ options.setX(0, width);
+
+ for (ty = 0; ty < height; ty += STRIP_SIZE) {
+ int endy = ty + STRIP_SIZE;
+ if (endy > height) {
+ endy = height;
+ }
+ options.setY(ty, endy);
+ mScript.forEach_selectiveAdjust(in, out, options);
+ if (checkStop()) {
+ return;
+ }
+ }
+ }
+
+ private boolean checkStop() {
+ RenderScript rsCtx = getRenderScriptContext();
+ rsCtx.finish();
+ if (getEnvironment().needsStop()) {
+ return true;
+ }
+ return false;
+ }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java
new file mode 100644
index 000000000..4c837e0bf
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+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() {
+ mName = "Highlights";
+ }
+
+ SplineMath mSpline = new SplineMath(5);
+ double[] mHighlightCurve = { 0.0, 0.32, 0.418, 0.476, 0.642 };
+
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Highlights");
+ representation.setSerializationName(SERIALIZATION_NAME);
+ representation.setFilterClass(ImageFilterHighlights.class);
+ representation.setTextId(R.string.highlight_recovery);
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float[] luminanceMap);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ float p = getParameters().getValue();
+ double t = p/100.;
+ for (int i = 0; i < 5; i++) {
+ double x = i / 4.;
+ double y = mHighlightCurve[i] *t+x*(1-t);
+ mSpline.setPoint(i, x, y);
+ }
+
+ float[][] curve = mSpline.calculatetCurve(256);
+ float[] luminanceMap = new float[curve.length];
+ for (int i = 0; i < luminanceMap.length; i++) {
+ luminanceMap[i] = curve[i][1];
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+
+ nativeApplyFilter(bitmap, w, h, luminanceMap);
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
new file mode 100644
index 000000000..b87c25490
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 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;
+
+import com.android.gallery3d.R;
+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() {
+ mName = "Hue";
+ cmatrix = new ColorSpaceMatrix();
+ }
+
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Hue");
+ representation.setSerializationName(SERIALIZATION_NAME);
+ representation.setFilterClass(ImageFilterHue.class);
+ representation.setMinimum(-180);
+ representation.setMaximum(180);
+ representation.setTextId(R.string.hue);
+ representation.setEditorId(BasicEditor.ID);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float []matrix);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ float value = getParameters().getValue();
+ cmatrix.identity();
+ cmatrix.setHue(value);
+
+ nativeApplyFilter(bitmap, w, h, cmatrix.getMatrix());
+
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
new file mode 100644
index 000000000..77cdf47b3
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.graphics.Bitmap;
+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() {
+ mName = "KMeans";
+
+ // set random seed for session
+ Time t = new Time();
+ t.setToNow();
+ mSeed = (int) t.toMillis(false);
+ }
+
+ 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);
+ representation.setValue(4);
+ representation.setDefaultValue(4);
+ representation.setPreviewValue(4);
+ representation.setTextId(R.string.kmeans);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int width, int height,
+ Bitmap large_ds_bm, int lwidth, int lheight, Bitmap small_ds_bm,
+ int swidth, int sheight, int p, int seed);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+
+ Bitmap large_bm_ds = bitmap;
+ Bitmap small_bm_ds = bitmap;
+
+ // find width/height for larger downsampled bitmap
+ int lw = w;
+ int lh = h;
+ while (lw > 256 && lh > 256) {
+ lw /= 2;
+ lh /= 2;
+ }
+ if (lw != w) {
+ large_bm_ds = Bitmap.createScaledBitmap(bitmap, lw, lh, true);
+ }
+
+ // find width/height for smaller downsampled bitmap
+ int sw = lw;
+ int sh = lh;
+ while (sw > 64 && sh > 64) {
+ sw /= 2;
+ sh /= 2;
+ }
+ if (sw != lw) {
+ small_bm_ds = Bitmap.createScaledBitmap(large_bm_ds, sw, sh, true);
+ }
+
+ if (getParameters() != null) {
+ int p = Math.max(getParameters().getValue(), getParameters().getMinimum()) % (getParameters().getMaximum() + 1);
+ nativeApplyFilter(bitmap, w, h, large_bm_ds, lw, lh, small_bm_ds, sw, sh, p, mSeed);
+ }
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
new file mode 100644
index 000000000..98497596b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
@@ -0,0 +1,39 @@
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+
+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.setShowParameterValue(false);
+ representation.setEditorId(ImageOnlyEditor.ID);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h);
+
+ @Override
+ public void useRepresentation(FilterRepresentation representation) {
+
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ nativeApplyFilter(bitmap, w, h);
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java
new file mode 100644
index 000000000..25e5d1476
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+
+public class ImageFilterParametricBorder extends ImageFilter {
+ private FilterColorBorderRepresentation mParameters = null;
+
+ public ImageFilterParametricBorder() {
+ mName = "Border";
+ }
+
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterColorBorderRepresentation parameters = (FilterColorBorderRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public FilterColorBorderRepresentation getParameters() {
+ return mParameters;
+ }
+
+ private void applyHelper(Canvas canvas, int w, int h) {
+ if (getParameters() == null) {
+ return;
+ }
+ Path border = new Path();
+ border.moveTo(0, 0);
+ float bs = getParameters().getBorderSize() / 100.0f * w;
+ float r = getParameters().getBorderRadius() / 100.0f * w;
+ border.lineTo(0, h);
+ border.lineTo(w, h);
+ border.lineTo(w, 0);
+ border.lineTo(0, 0);
+ border.addRoundRect(new RectF(bs, bs, w - bs, h - bs),
+ r, r, Path.Direction.CW);
+
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setColor(getParameters().getColor());
+ canvas.drawPath(border, paint);
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ Canvas canvas = new Canvas(bitmap);
+ applyHelper(canvas, bitmap.getWidth(), bitmap.getHeight());
+ return bitmap;
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
new file mode 100644
index 000000000..5695ef53e
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.content.res.Resources;
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.pipeline.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;
+
+ private static ScriptC_grey mGreyConvert = null;
+ private static RenderScript mRScache = null;
+
+ private volatile boolean mResourcesLoaded = false;
+
+ protected abstract void createFilter(android.content.res.Resources res,
+ float scaleFactor, int quality);
+
+ protected void createFilter(android.content.res.Resources res,
+ float scaleFactor, int quality, Allocation in) {}
+ protected void bindScriptValues(Allocation in) {}
+
+ protected abstract void runFilter();
+
+ protected void update(Bitmap bitmap) {
+ getOutPixelsAllocation().copyTo(bitmap);
+ }
+
+ protected RenderScript getRenderScriptContext() {
+ PipelineInterface pipeline = getEnvironment().getPipeline();
+ return pipeline.getRSContext();
+ }
+
+ protected Allocation getInPixelsAllocation() {
+ PipelineInterface pipeline = getEnvironment().getPipeline();
+ return pipeline.getInPixelsAllocation();
+ }
+
+ protected Allocation getOutPixelsAllocation() {
+ 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) {
+ PipelineInterface pipeline = getEnvironment().getPipeline();
+ createFilter(pipeline.getResources(), getEnvironment().getScaleFactor(),
+ getEnvironment().getQuality(), in);
+ mResourcesLoaded = true;
+ }
+ startFilter = System.nanoTime();
+ bindScriptValues(in);
+ run(in, out);
+ if (PERF_LOGGING) {
+ getRenderScriptContext().finish();
+ endFilter = System.nanoTime();
+ long endOverAll = System.nanoTime();
+ String msg = String.format("%s; image size %dx%d; ", getName(),
+ in.getType().getX(), in.getType().getY());
+ long timeOverAll = (endOverAll - startOverAll) / 1000;
+ long timeFilter = (endFilter - startFilter) / 1000;
+ msg += String.format("over all %.2f ms (%.2f FPS); ",
+ timeOverAll / 1000.f, 1000000.f / timeOverAll);
+ msg += String.format("run filter %.2f ms (%.2f FPS)",
+ timeFilter / 1000.f, 1000000.f / timeFilter);
+ Log.i(LOGTAG, msg);
+ }
+ }
+
+ protected void run(Allocation in, Allocation out) {}
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (bitmap == null || bitmap.getWidth() == 0 || bitmap.getHeight() == 0) {
+ return bitmap;
+ }
+ try {
+ PipelineInterface pipeline = getEnvironment().getPipeline();
+ if (DEBUG) {
+ Log.v(LOGTAG, "apply filter " + getName() + " in pipeline " + pipeline.getName());
+ }
+ Resources rsc = pipeline.getResources();
+ boolean sizeChanged = false;
+ if (getInPixelsAllocation() != null
+ && ((getInPixelsAllocation().getType().getX() != mLastInputWidth)
+ || (getInPixelsAllocation().getType().getY() != mLastInputHeight))) {
+ sizeChanged = true;
+ }
+ if (pipeline.prepareRenderscriptAllocations(bitmap)
+ || !isResourcesLoaded() || sizeChanged) {
+ freeResources();
+ createFilter(rsc, scaleFactor, quality);
+ setResourcesLoaded(true);
+ mLastInputWidth = getInPixelsAllocation().getType().getX();
+ mLastInputHeight = getInPixelsAllocation().getType().getY();
+ }
+ bindScriptValues();
+ runFilter();
+ update(bitmap);
+ if (DEBUG) {
+ Log.v(LOGTAG, "DONE apply filter " + getName() + " in pipeline " + pipeline.getName());
+ }
+ } catch (android.renderscript.RSIllegalArgumentException e) {
+ Log.e(LOGTAG, "Illegal argument? " + e);
+ } catch (android.renderscript.RSRuntimeException e) {
+ Log.e(LOGTAG, "RS runtime exception ? " + e);
+ } catch (java.lang.OutOfMemoryError e) {
+ // Many of the renderscript filters allocated large (>16Mb resources) in order to apply.
+ System.gc();
+ displayLowMemoryToast();
+ Log.e(LOGTAG, "not enough memory for filter " + getName(), e);
+ }
+ return 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(RenderScript RS, Bitmap bitmap) {
+ if (RS != mRScache || mGreyConvert == null) {
+ mGreyConvert = new ScriptC_grey(RS, RS.getApplicationContext().getResources(),
+ R.raw.grey);
+ mRScache = RS;
+ }
+
+ Type.Builder tb_a8 = new Type.Builder(RS, Element.A_8(RS));
+
+ Allocation bitmapTemp = convertBitmap(RS, bitmap);
+ if (bitmapTemp.getType().getElement().isCompatible(Element.A_8(RS))) {
+ return bitmapTemp;
+ }
+
+ tb_a8.setX(bitmapTemp.getType().getX());
+ tb_a8.setY(bitmapTemp.getType().getY());
+ Allocation bitmapAlloc = Allocation.createTyped(RS, tb_a8.create(),
+ Allocation.MipmapControl.MIPMAP_NONE,
+ Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_TEXTURE);
+ mGreyConvert.forEach_RGBAtoA(bitmapTemp, bitmapAlloc);
+ bitmapTemp.destroy();
+ return bitmapAlloc;
+ }
+
+ public Allocation loadScaledResourceAlpha(int resource, int inSampleSize) {
+ 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(getRenderScriptContext(), bitmap);
+ bitmap.recycle();
+ return ret;
+ }
+
+ public Allocation loadScaledResourceAlpha(int resource, int w, int h, int inSampleSize) {
+ 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);
+ Bitmap resizeBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
+ Allocation ret = convertRGBAtoA(getRenderScriptContext(), resizeBitmap);
+ resizeBitmap.recycle();
+ bitmap.recycle();
+ return ret;
+ }
+
+ public Allocation loadResourceAlpha(int resource) {
+ return loadScaledResourceAlpha(resource, 1);
+ }
+
+ public Allocation loadResource(int resource) {
+ 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(getRenderScriptContext(), bitmap);
+ bitmap.recycle();
+ return ret;
+ }
+
+ private boolean isResourcesLoaded() {
+ return mResourcesLoaded;
+ }
+
+ private void setResourcesLoaded(boolean resourcesLoaded) {
+ mResourcesLoaded = resourcesLoaded;
+ }
+
+ /**
+ * Bitmaps and RS Allocations should be cleared here
+ */
+ abstract protected void resetAllocations();
+
+ /**
+ * RS Script objects (and all other RS objects) should be cleared here
+ */
+ public abstract void resetScripts();
+
+ /**
+ * Scripts values should be bound here
+ */
+ abstract protected void bindScriptValues();
+
+ public void freeResources() {
+ if (!isResourcesLoaded()) {
+ return;
+ }
+ resetAllocations();
+ mLastInputWidth = 0;
+ mLastInputHeight = 0;
+ setResourcesLoaded(false);
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java
new file mode 100644
index 000000000..511f9e90f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java
@@ -0,0 +1,79 @@
+/*
+ * 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;
+
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.graphics.RectF;
+
+import java.util.Vector;
+
+public class ImageFilterRedEye extends ImageFilter {
+ private static final String LOGTAG = "ImageFilterRedEye";
+ FilterRedEyeRepresentation mParameters = new FilterRedEyeRepresentation();
+
+ public ImageFilterRedEye() {
+ mName = "Red Eye";
+ }
+
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterRedEyeRepresentation();
+ }
+
+ public boolean isNil() {
+ return mParameters.isNil();
+ }
+
+ public Vector<FilterPoint> getCandidates() {
+ return mParameters.getCandidates();
+ }
+
+ public void clear() {
+ mParameters.clearCandidates();
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, short[] matrix);
+
+ @Override
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterRedEyeRepresentation parameters = (FilterRedEyeRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ short[] rect = new short[4];
+
+ int size = mParameters.getNumberOfCandidates();
+ Matrix originalToScreen = getOriginalToScreenMatrix(w, h);
+ for (int i = 0; i < size; i++) {
+ RectF r = new RectF(((RedEyeCandidate) (mParameters.getCandidate(i))).mRect);
+ originalToScreen.mapRect(r);
+ if (r.intersect(0, 0, w, h)) {
+ rect[0] = (short) r.left;
+ rect[1] = (short) r.top;
+ rect[2] = (short) r.width();
+ rect[3] = (short) r.height();
+ nativeApplyFilter(bitmap, w, h, rect);
+ }
+ }
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
new file mode 100644
index 000000000..c3124ff77
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 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;
+
+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";
+ }
+
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Saturated");
+ representation.setSerializationName(SERIALIZATION_NAME);
+ representation.setFilterClass(ImageFilterSaturated.class);
+ representation.setTextId(R.string.saturation);
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float saturation);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ int p = getParameters().getValue();
+ float value = 1 + p / 100.0f;
+ nativeApplyFilter(bitmap, w, h, value);
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
new file mode 100644
index 000000000..bd119bbc9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 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;
+
+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";
+
+ }
+
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Shadows");
+ representation.setSerializationName(SERIALIZATION_NAME);
+ representation.setFilterClass(ImageFilterShadows.class);
+ representation.setTextId(R.string.shadow_recovery);
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float factor);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ float p = getParameters().getValue();
+
+ nativeApplyFilter(bitmap, w, h, p);
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
new file mode 100644
index 000000000..3bd794464
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 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;
+
+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;
+
+ private FilterBasicRepresentation mParameters;
+
+ public ImageFilterSharpen() {
+ mName = "Sharpen";
+ }
+
+ 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);
+ representation.setOverlayId(R.drawable.filtershow_button_colors_sharpen);
+ representation.setEditorId(R.id.imageShow);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterBasicRepresentation parameters = (FilterBasicRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ @Override
+ protected void resetAllocations() {
+ // nothing to do
+ }
+
+ @Override
+ public void resetScripts() {
+ if (mScript != null) {
+ mScript.destroy();
+ mScript = null;
+ }
+ }
+
+ @Override
+ protected void createFilter(android.content.res.Resources res, float scaleFactor,
+ int quality) {
+ if (mScript == null) {
+ mScript = new ScriptC_convolve3x3(getRenderScriptContext(), res, R.raw.convolve3x3);
+ }
+ }
+
+ private void computeKernel() {
+ float scaleFactor = getEnvironment().getScaleFactor();
+ float p1 = mParameters.getValue() * scaleFactor;
+ float value = p1 / 100.0f;
+ float f[] = new float[9];
+ float p = value;
+ f[0] = -p;
+ f[1] = -p;
+ f[2] = -p;
+ f[3] = -p;
+ f[4] = 8 * p + 1;
+ f[5] = -p;
+ f[6] = -p;
+ f[7] = -p;
+ f[8] = -p;
+ mScript.set_gCoeffs(f);
+ }
+
+ @Override
+ protected void bindScriptValues() {
+ int w = getInPixelsAllocation().getType().getX();
+ int h = getInPixelsAllocation().getType().getY();
+ mScript.set_gWidth(w);
+ mScript.set_gHeight(h);
+ }
+
+ @Override
+ protected void runFilter() {
+ if (mParameters == null) {
+ return;
+ }
+ computeKernel();
+ mScript.set_gIn(getInPixelsAllocation());
+ mScript.bind_gPixels(getInPixelsAllocation());
+ mScript.forEach_root(getInPixelsAllocation(), getOutPixelsAllocation());
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java
new file mode 100644
index 000000000..77250bd7a
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.RectF;
+
+import com.adobe.xmp.XMPException;
+import com.adobe.xmp.XMPMeta;
+import com.android.gallery3d.app.Log;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+
+/**
+ * An image filter which creates a tiny planet projection.
+ */
+public class ImageFilterTinyPlanet extends SimpleImageFilter {
+
+
+ private static final String LOGTAG = ImageFilterTinyPlanet.class.getSimpleName();
+ public static final String GOOGLE_PANO_NAMESPACE = "http://ns.google.com/photos/1.0/panorama/";
+ FilterTinyPlanetRepresentation mParameters = new FilterTinyPlanetRepresentation();
+
+ public static final String CROPPED_AREA_IMAGE_WIDTH_PIXELS =
+ "CroppedAreaImageWidthPixels";
+ public static final String CROPPED_AREA_IMAGE_HEIGHT_PIXELS =
+ "CroppedAreaImageHeightPixels";
+ public static final String CROPPED_AREA_FULL_PANO_WIDTH_PIXELS =
+ "FullPanoWidthPixels";
+ public static final String CROPPED_AREA_FULL_PANO_HEIGHT_PIXELS =
+ "FullPanoHeightPixels";
+ public static final String CROPPED_AREA_LEFT =
+ "CroppedAreaLeftPixels";
+ public static final String CROPPED_AREA_TOP =
+ "CroppedAreaTopPixels";
+
+ public ImageFilterTinyPlanet() {
+ mName = "TinyPlanet";
+ }
+
+ @Override
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterTinyPlanetRepresentation parameters = (FilterTinyPlanetRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterTinyPlanetRepresentation();
+ }
+
+
+ native protected void nativeApplyFilter(
+ Bitmap bitmapIn, int width, int height, Bitmap bitmapOut, int outSize, float scale,
+ float angle);
+
+
+ @Override
+ public Bitmap apply(Bitmap bitmapIn, float scaleFactor, int quality) {
+ int w = bitmapIn.getWidth();
+ int h = bitmapIn.getHeight();
+ int outputSize = (int) (w / 2f);
+ ImagePreset preset = getEnvironment().getImagePreset();
+ Bitmap mBitmapOut = null;
+ if (preset != null) {
+ XMPMeta xmp = ImageLoader.getXmpObject(MasterImage.getImage().getActivity());
+ // Do nothing, just use bitmapIn as is if we don't have XMP.
+ if(xmp != null) {
+ bitmapIn = applyXmp(bitmapIn, xmp, w);
+ }
+ }
+ if (mBitmapOut != null) {
+ if (outputSize != mBitmapOut.getHeight()) {
+ mBitmapOut = null;
+ }
+ }
+ while (mBitmapOut == null) {
+ try {
+ mBitmapOut = getEnvironment().getBitmap(outputSize, outputSize);
+ } catch (java.lang.OutOfMemoryError e) {
+ System.gc();
+ outputSize /= 2;
+ Log.v(LOGTAG, "No memory to create Full Tiny Planet create half");
+ }
+ }
+ nativeApplyFilter(bitmapIn, bitmapIn.getWidth(), bitmapIn.getHeight(), mBitmapOut,
+ outputSize, mParameters.getZoom() / 100f, mParameters.getAngle());
+
+ return mBitmapOut;
+ }
+
+ private Bitmap applyXmp(Bitmap bitmapIn, XMPMeta xmp, int intermediateWidth) {
+ try {
+ int croppedAreaWidth =
+ getInt(xmp, CROPPED_AREA_IMAGE_WIDTH_PIXELS);
+ int croppedAreaHeight =
+ getInt(xmp, CROPPED_AREA_IMAGE_HEIGHT_PIXELS);
+ int fullPanoWidth =
+ getInt(xmp, CROPPED_AREA_FULL_PANO_WIDTH_PIXELS);
+ int fullPanoHeight =
+ getInt(xmp, CROPPED_AREA_FULL_PANO_HEIGHT_PIXELS);
+ int left = getInt(xmp, CROPPED_AREA_LEFT);
+ int top = getInt(xmp, CROPPED_AREA_TOP);
+
+ if (fullPanoWidth == 0 || fullPanoHeight == 0) {
+ return bitmapIn;
+ }
+ // Make sure the intermediate image has the similar size to the
+ // input.
+ Bitmap paddedBitmap = null;
+ float scale = intermediateWidth / (float) fullPanoWidth;
+ while (paddedBitmap == null) {
+ try {
+ paddedBitmap = Bitmap.createBitmap(
+ (int) (fullPanoWidth * scale), (int) (fullPanoHeight * scale),
+ Bitmap.Config.ARGB_8888);
+ } catch (java.lang.OutOfMemoryError e) {
+ System.gc();
+ scale /= 2;
+ }
+ }
+ Canvas paddedCanvas = new Canvas(paddedBitmap);
+
+ int right = left + croppedAreaWidth;
+ int bottom = top + croppedAreaHeight;
+ RectF destRect = new RectF(left * scale, top * scale, right * scale, bottom * scale);
+ paddedCanvas.drawBitmap(bitmapIn, null, destRect, null);
+ bitmapIn = paddedBitmap;
+ } catch (XMPException ex) {
+ // Do nothing, just use bitmapIn as is.
+ }
+ return bitmapIn;
+ }
+
+ private static int getInt(XMPMeta xmp, String key) throws XMPException {
+ if (xmp.doesPropertyExist(GOOGLE_PANO_NAMESPACE, key)) {
+ return xmp.getPropertyInteger(GOOGLE_PANO_NAMESPACE, key);
+ } else {
+ return 0;
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
new file mode 100644
index 000000000..86be9a155
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 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;
+
+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";
+ }
+
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Vibrance");
+ representation.setSerializationName(SERIALIZATION_NAME);
+ representation.setFilterClass(ImageFilterVibrance.class);
+ representation.setTextId(R.string.vibrance);
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float bright);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ float value = getParameters().getValue();
+ nativeApplyFilter(bitmap, w, h, value);
+
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
new file mode 100644
index 000000000..7e0a452bf
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+
+public class ImageFilterVignette extends SimpleImageFilter {
+ private static final String LOGTAG = "ImageFilterVignette";
+ private Bitmap mOverlayBitmap;
+
+ public ImageFilterVignette() {
+ mName = "Vignette";
+ }
+
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterVignetteRepresentation representation = new FilterVignetteRepresentation();
+ return representation;
+ }
+
+ native protected void nativeApplyFilter(
+ Bitmap bitmap, int w, int h, int cx, int cy, float radx, float rady, float strength);
+
+ private float calcRadius(float cx, float cy, int w, int h) {
+ float d = cx;
+ if (d < (w - cx)) {
+ d = w - cx;
+ }
+ if (d < cy) {
+ d = cy;
+ }
+ if (d < (h - cy)) {
+ d = h - cy;
+ }
+ return d * d * 2.0f;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) {
+ if (mOverlayBitmap == null) {
+ Resources res = getEnvironment().getPipeline().getResources();
+ mOverlayBitmap = IconUtilities.getFXBitmap(res,
+ R.drawable.filtershow_icon_vignette);
+ }
+ Canvas c = new Canvas(bitmap);
+ int dim = Math.max(bitmap.getWidth(), bitmap.getHeight());
+ Rect r = new Rect(0, 0, dim, dim);
+ c.drawBitmap(mOverlayBitmap, null, r, null);
+ return bitmap;
+ }
+ FilterVignetteRepresentation rep = (FilterVignetteRepresentation) getParameters();
+ if (rep == null) {
+ return bitmap;
+ }
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ float value = rep.getValue() / 100.0f;
+ float cx = w / 2;
+ float cy = h / 2;
+ float r = calcRadius(cx, cy, w, h);
+ float rx = r;
+ float ry = r;
+ if (rep.isCenterSet()) {
+ Matrix m = getOriginalToScreenMatrix(w, h);
+ cx = rep.getCenterX();
+ cy = rep.getCenterY();
+ float[] center = new float[] { cx, cy };
+ m.mapPoints(center);
+ cx = center[0];
+ cy = center[1];
+ rx = m.mapRadius(rep.getRadiusX());
+ ry = m.mapRadius(rep.getRadiusY());
+ }
+ nativeApplyFilter(bitmap, w, h, (int) cx, (int) cy, rx, ry, value);
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
new file mode 100644
index 000000000..6bb88ec21
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 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;
+
+import com.android.gallery3d.R;
+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() {
+ mName = "WBalance";
+ }
+
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterRepresentation representation = new FilterDirectRepresentation("WBalance");
+ representation.setSerializationName(SERIALIZATION_NAME);
+ representation.setFilterClass(ImageFilterWBalance.class);
+ representation.setFilterType(FilterRepresentation.TYPE_WBALANCE);
+ representation.setTextId(R.string.wbalance);
+ representation.setShowParameterValue(false);
+ representation.setEditorId(ImageOnlyEditor.ID);
+ representation.setSupportsPartialRendering(true);
+ return representation;
+ }
+
+ @Override
+ public void useRepresentation(FilterRepresentation representation) {
+
+ }
+
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, int locX, int locY);
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ nativeApplyFilter(bitmap, w, h, -1, -1);
+ return bitmap;
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java b/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java
new file mode 100644
index 000000000..a40d4fa3b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java
@@ -0,0 +1,50 @@
+/*
+ * 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;
+
+import android.graphics.RectF;
+
+public class RedEyeCandidate implements FilterPoint {
+ RectF mRect = new RectF();
+ RectF mBounds = new RectF();
+
+ public RedEyeCandidate(RedEyeCandidate candidate) {
+ mRect.set(candidate.mRect);
+ mBounds.set(candidate.mBounds);
+ }
+
+ public RedEyeCandidate(RectF rect, RectF bounds) {
+ mRect.set(rect);
+ mBounds.set(bounds);
+ }
+
+ public boolean equals(RedEyeCandidate candidate) {
+ if (candidate.mRect.equals(mRect)
+ && candidate.mBounds.equals(mBounds)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean intersect(RectF rect) {
+ return mRect.intersect(rect);
+ }
+
+ public RectF getRect() {
+ return mRect;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java b/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java
new file mode 100644
index 000000000..c891d20f3
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java
@@ -0,0 +1,37 @@
+/*
+ * 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 class SimpleImageFilter extends ImageFilter {
+
+ private FilterBasicRepresentation mParameters;
+
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterRepresentation representation = new FilterBasicRepresentation("Default", 0, 50, 100);
+ representation.setShowParameterValue(true);
+ return representation;
+ }
+
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterBasicRepresentation parameters = (FilterBasicRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public FilterBasicRepresentation getParameters() {
+ return mParameters;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/SplineMath.java b/src/com/android/gallery3d/filtershow/filters/SplineMath.java
new file mode 100644
index 000000000..5b12d0a61
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/SplineMath.java
@@ -0,0 +1,166 @@
+package com.android.gallery3d.filtershow.filters;
+
+
+public class SplineMath {
+ double[][] mPoints = new double[6][2];
+ double[] mDerivatives;
+ SplineMath(int n) {
+ mPoints = new double[n][2];
+ }
+
+ public void setPoint(int index, double x, double y) {
+ mPoints[index][0] = x;
+ mPoints[index][1] = y;
+ mDerivatives = null;
+ }
+
+ public float[][] calculatetCurve(int n) {
+ float[][] curve = new float[n][2];
+ double[][] points = new double[mPoints.length][2];
+ for (int i = 0; i < mPoints.length; i++) {
+
+ points[i][0] = mPoints[i][0];
+ points[i][1] = mPoints[i][1];
+
+ }
+ double[] derivatives = solveSystem(points);
+ float start = (float) points[0][0];
+ float end = (float) (points[points.length - 1][0]);
+
+ curve[0][0] = (float) (points[0][0]);
+ curve[0][1] = (float) (points[0][1]);
+ int last = curve.length - 1;
+ curve[last][0] = (float) (points[points.length - 1][0]);
+ curve[last][1] = (float) (points[points.length - 1][1]);
+
+ for (int i = 0; i < curve.length; i++) {
+
+ double[] cur = null;
+ double[] next = null;
+ double x = start + i * (end - start) / (curve.length - 1);
+ int pivot = 0;
+ for (int j = 0; j < points.length - 1; j++) {
+ if (x >= points[j][0] && x <= points[j + 1][0]) {
+ pivot = j;
+ }
+ }
+ cur = points[pivot];
+ next = points[pivot + 1];
+ if (x <= next[0]) {
+ double x1 = cur[0];
+ double x2 = next[0];
+ double y1 = cur[1];
+ double y2 = next[1];
+
+ // Use the second derivatives to apply the cubic spline
+ // equation:
+ double delta = (x2 - x1);
+ double delta2 = delta * delta;
+ double b = (x - x1) / delta;
+ double a = 1 - b;
+ double ta = a * y1;
+ double tb = b * y2;
+ double tc = (a * a * a - a) * derivatives[pivot];
+ double td = (b * b * b - b) * derivatives[pivot + 1];
+ double y = ta + tb + (delta2 / 6) * (tc + td);
+
+ curve[i][0] = (float) (x);
+ curve[i][1] = (float) (y);
+ } else {
+ curve[i][0] = (float) (next[0]);
+ curve[i][1] = (float) (next[1]);
+ }
+ }
+ return curve;
+ }
+
+ public double getValue(double x) {
+ double[] cur = null;
+ double[] next = null;
+ if (mDerivatives == null)
+ mDerivatives = solveSystem(mPoints);
+ int pivot = 0;
+ for (int j = 0; j < mPoints.length - 1; j++) {
+ pivot = j;
+ if (x <= mPoints[j][0]) {
+ break;
+ }
+ }
+ cur = mPoints[pivot];
+ next = mPoints[pivot + 1];
+ double x1 = cur[0];
+ double x2 = next[0];
+ double y1 = cur[1];
+ double y2 = next[1];
+
+ // Use the second derivatives to apply the cubic spline
+ // equation:
+ double delta = (x2 - x1);
+ double delta2 = delta * delta;
+ double b = (x - x1) / delta;
+ double a = 1 - b;
+ double ta = a * y1;
+ double tb = b * y2;
+ double tc = (a * a * a - a) * mDerivatives[pivot];
+ double td = (b * b * b - b) * mDerivatives[pivot + 1];
+ double y = ta + tb + (delta2 / 6) * (tc + td);
+
+ return y;
+
+ }
+
+ double[] solveSystem(double[][] points) {
+ int n = points.length;
+ double[][] system = new double[n][3];
+ double[] result = new double[n]; // d
+ double[] solution = new double[n]; // returned coefficients
+ system[0][1] = 1;
+ system[n - 1][1] = 1;
+ double d6 = 1.0 / 6.0;
+ double d3 = 1.0 / 3.0;
+
+ // let's create a tridiagonal matrix representing the
+ // system, and apply the TDMA algorithm to solve it
+ // (see http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm)
+ for (int i = 1; i < n - 1; i++) {
+ double deltaPrevX = points[i][0] - points[i - 1][0];
+ double deltaX = points[i + 1][0] - points[i - 1][0];
+ double deltaNextX = points[i + 1][0] - points[i][0];
+ double deltaNextY = points[i + 1][1] - points[i][1];
+ double deltaPrevY = points[i][1] - points[i - 1][1];
+ system[i][0] = d6 * deltaPrevX; // a_i
+ system[i][1] = d3 * deltaX; // b_i
+ system[i][2] = d6 * deltaNextX; // c_i
+ result[i] = (deltaNextY / deltaNextX) - (deltaPrevY / deltaPrevX); // d_i
+ }
+
+ // Forward sweep
+ for (int i = 1; i < n; i++) {
+ // m = a_i/b_i-1
+ double m = system[i][0] / system[i - 1][1];
+ // b_i = b_i - m(c_i-1)
+ system[i][1] = system[i][1] - m * system[i - 1][2];
+ // d_i = d_i - m(d_i-1)
+ result[i] = result[i] - m * result[i - 1];
+ }
+
+ // Back substitution
+ solution[n - 1] = result[n - 1] / system[n - 1][1];
+ for (int i = n - 2; i >= 0; --i) {
+ solution[i] = (result[i] - system[i][2] * solution[i + 1]) / system[i][1];
+ }
+ return solution;
+ }
+
+ public static void main(String[] args) {
+ SplineMath s = new SplineMath(10);
+ for (int i = 0; i < 10; i++) {
+ s.setPoint(i, i, i);
+ }
+ float[][] curve = s.calculatetCurve(40);
+
+ for (int j = 0; j < curve.length; j++) {
+ System.out.println(curve[j][0] + "," + curve[j][1]);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs b/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs
new file mode 100644
index 000000000..2acffab06
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+const uchar4 *gPixels;
+rs_allocation gIn;
+
+float gCoeffs[9];
+
+void root(const uchar4 *in, uchar4 *out, const void *usrData, uint32_t x, uint32_t y) {
+ uint32_t x1 = min((int32_t)x+1, gWidth-1);
+ uint32_t x2 = max((int32_t)x-1, 0);
+ uint32_t y1 = min((int32_t)y+1, gHeight-1);
+ uint32_t y2 = max((int32_t)y-1, 0);
+
+ float4 p00 = rsUnpackColor8888(gPixels[x1 + gWidth * y1]);
+ float4 p01 = rsUnpackColor8888(gPixels[x + gWidth * y1]);
+ float4 p02 = rsUnpackColor8888(gPixels[x2 + gWidth * y1]);
+ float4 p10 = rsUnpackColor8888(gPixels[x1 + gWidth * y]);
+ float4 p11 = rsUnpackColor8888(gPixels[x + gWidth * y]);
+ float4 p12 = rsUnpackColor8888(gPixels[x2 + gWidth * y]);
+ float4 p20 = rsUnpackColor8888(gPixels[x1 + gWidth * y2]);
+ float4 p21 = rsUnpackColor8888(gPixels[x + gWidth * y2]);
+ float4 p22 = rsUnpackColor8888(gPixels[x2 + gWidth * y2]);
+
+ p00 *= gCoeffs[0];
+ p01 *= gCoeffs[1];
+ p02 *= gCoeffs[2];
+ p10 *= gCoeffs[3];
+ p11 *= gCoeffs[4];
+ p12 *= gCoeffs[5];
+ p20 *= gCoeffs[6];
+ p21 *= gCoeffs[7];
+ p22 *= gCoeffs[8];
+
+ p00 += p01;
+ p02 += p10;
+ p11 += p12;
+ p20 += p21;
+
+ p22 += p00;
+ p02 += p11;
+
+ p20 += p22;
+ p20 += p02;
+
+ p20 = clamp(p20, 0.f, 1.f);
+ *out = rsPackColorTo8888(p20.r, p20.g, p20.b);
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/grad.rs b/src/com/android/gallery3d/filtershow/filters/grad.rs
new file mode 100644
index 000000000..ddbafd349
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/grad.rs
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 Unknown
+ *
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
+
+#define MAX_POINTS 16
+
+uint32_t inputWidth;
+uint32_t inputHeight;
+static const float Rf = 0.2999f;
+static const float Gf = 0.587f;
+static const float Bf = 0.114f;
+//static const float size_scale = 0.01f;
+
+typedef struct {
+ rs_matrix3x3 colorMatrix;
+ float rgbOff;
+ float dx;
+ float dy;
+ float off;
+} UPointData;
+int mNumberOfLines;
+// input data
+bool mask[MAX_POINTS];
+int xPos1[MAX_POINTS];
+int yPos1[MAX_POINTS];
+int xPos2[MAX_POINTS];
+int yPos2[MAX_POINTS];
+int size[MAX_POINTS];
+int brightness[MAX_POINTS];
+int contrast[MAX_POINTS];
+int saturation[MAX_POINTS];
+
+// generated data
+static UPointData grads[MAX_POINTS];
+
+void setupGradParams() {
+ int k = 0;
+ for (int i = 0; i < MAX_POINTS; i++) {
+ if (!mask[i]) {
+ continue;
+ }
+ float x1 = xPos1[i];
+ float y1 = yPos1[i];
+ float x2 = xPos2[i];
+ float y2 = yPos2[i];
+
+ float denom = (y2 * y2 - 2 * y1 * y2 + x2 * x2 - 2 * x1 * x2 + y1 * y1 + x1 * x1);
+ if (denom == 0) {
+ continue;
+ }
+ grads[k].dy = (y1 - y2) / denom;
+ grads[k].dx = (x1 - x2) / denom;
+ grads[k].off = (y2 * y2 + x2 * x2 - x1 * x2 - y1 * y2) / denom;
+
+ float S = 1+saturation[i]/100.f;
+ float MS = 1-S;
+ float Rt = Rf * MS;
+ float Gt = Gf * MS;
+ float Bt = Bf * MS;
+
+ float b = 1+brightness[i]/100.f;
+ float c = 1+contrast[i]/100.f;
+ b *= c;
+ grads[k].rgbOff = .5f - c/2.f;
+ rsMatrixSet(&grads[i].colorMatrix, 0, 0, b * (Rt + S));
+ rsMatrixSet(&grads[i].colorMatrix, 1, 0, b * Gt);
+ rsMatrixSet(&grads[i].colorMatrix, 2, 0, b * Bt);
+ rsMatrixSet(&grads[i].colorMatrix, 0, 1, b * Rt);
+ rsMatrixSet(&grads[i].colorMatrix, 1, 1, b * (Gt + S));
+ rsMatrixSet(&grads[i].colorMatrix, 2, 1, b * Bt);
+ rsMatrixSet(&grads[i].colorMatrix, 0, 2, b * Rt);
+ rsMatrixSet(&grads[i].colorMatrix, 1, 2, b * Gt);
+ rsMatrixSet(&grads[i].colorMatrix, 2, 2, b * (Bt + S));
+
+ k++;
+ }
+ mNumberOfLines = k;
+}
+
+void init() {
+
+}
+
+uchar4 __attribute__((kernel)) selectiveAdjust(const uchar4 in, uint32_t x,
+ uint32_t y) {
+ float4 pixel = rsUnpackColor8888(in);
+
+ float4 wsum = pixel;
+ wsum.a = 0.f;
+ for (int i = 0; i < mNumberOfLines; i++) {
+ UPointData* grad = &grads[i];
+ float t = clamp(x*grad->dx+y*grad->dy+grad->off,0.f,1.0f);
+ wsum.xyz = wsum.xyz*(1-t)+
+ t*(rsMatrixMultiply(&grad->colorMatrix ,wsum.xyz)+grad->rgbOff);
+
+ }
+
+ pixel.rgb = wsum.rgb;
+ pixel.a = 1.0f;
+
+ uchar4 out = rsPackColorTo8888(clamp(pixel, 0.f, 1.0f));
+ return out;
+}
+
+
+
diff --git a/src/com/android/gallery3d/filtershow/filters/grey.rs b/src/com/android/gallery3d/filtershow/filters/grey.rs
new file mode 100644
index 000000000..e01880360
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/grey.rs
@@ -0,0 +1,22 @@
+ /*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
+
+uchar __attribute__((kernel)) RGBAtoA(uchar4 in) {
+ return in.r;
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/saturation.rs b/src/com/android/gallery3d/filtershow/filters/saturation.rs
new file mode 100644
index 000000000..5210e34a3
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/saturation.rs
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2012 Unknown
+ *
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
+
+#define MAX_CHANELS 7
+#define MAX_HUE 4096
+static const int ABITS = 4;
+static const int HSCALE = 256;
+static const int k1=255 << ABITS;
+static const int k2=HSCALE << ABITS;
+
+static const float Rf = 0.2999f;
+static const float Gf = 0.587f;
+static const float Bf = 0.114f;
+
+rs_matrix3x3 colorMatrix_min;
+rs_matrix3x3 colorMatrix_max;
+
+int mNumberOfLines;
+// input data
+int saturation[MAX_CHANELS];
+float sat[MAX_CHANELS];
+
+float satLut[MAX_HUE];
+// generated data
+
+
+void setupGradParams() {
+
+ int master = saturation[0];
+ int max = master+saturation[1];
+ int min = max;
+
+ // calculate the minimum and maximum saturation
+ for (int i = 1; i < MAX_CHANELS; i++) {
+ int v = master+saturation[i];
+ if (max < v) {
+ max = v;
+ }
+ else if (min > v) {
+ min = v;
+ }
+ }
+ // generate a lookup table for all hue 0 to 4K which goes from 0 to 1 0=min sat 1 = max sat
+ min = min - 1;
+ for(int i = 0; i < MAX_HUE ; i++) {
+ float p = i * 6 / (float)MAX_HUE;
+ int ip = ((int)(p + .5f)) % 6;
+ int v = master + saturation[ip + 1];
+ satLut[i] = (v - min)/(float)(max - min);
+ }
+
+ float S = 1 + max / 100.f;
+ float MS = 1 - S;
+ float Rt = Rf * MS;
+ float Gt = Gf * MS;
+ float Bt = Bf * MS;
+ float b = 1.f;
+
+ // Generate 2 color matrix one at min sat and one at max
+ rsMatrixSet(&colorMatrix_max, 0, 0, b * (Rt + S));
+ rsMatrixSet(&colorMatrix_max, 1, 0, b * Gt);
+ rsMatrixSet(&colorMatrix_max, 2, 0, b * Bt);
+ rsMatrixSet(&colorMatrix_max, 0, 1, b * Rt);
+ rsMatrixSet(&colorMatrix_max, 1, 1, b * (Gt + S));
+ rsMatrixSet(&colorMatrix_max, 2, 1, b * Bt);
+ rsMatrixSet(&colorMatrix_max, 0, 2, b * Rt);
+ rsMatrixSet(&colorMatrix_max, 1, 2, b * Gt);
+ rsMatrixSet(&colorMatrix_max, 2, 2, b * (Bt + S));
+
+ S = 1 + min / 100.f;
+ MS = 1-S;
+ Rt = Rf * MS;
+ Gt = Gf * MS;
+ Bt = Bf * MS;
+ b = 1;
+
+ rsMatrixSet(&colorMatrix_min, 0, 0, b * (Rt + S));
+ rsMatrixSet(&colorMatrix_min, 1, 0, b * Gt);
+ rsMatrixSet(&colorMatrix_min, 2, 0, b * Bt);
+ rsMatrixSet(&colorMatrix_min, 0, 1, b * Rt);
+ rsMatrixSet(&colorMatrix_min, 1, 1, b * (Gt + S));
+ rsMatrixSet(&colorMatrix_min, 2, 1, b * Bt);
+ rsMatrixSet(&colorMatrix_min, 0, 2, b * Rt);
+ rsMatrixSet(&colorMatrix_min, 1, 2, b * Gt);
+ rsMatrixSet(&colorMatrix_min, 2, 2, b * (Bt + S));
+}
+
+static ushort rgb2hue( uchar4 rgb)
+{
+ int iMin,iMax,chroma;
+
+ int ri = rgb.r;
+ int gi = rgb.g;
+ int bi = rgb.b;
+ short rv,rs,rh;
+
+ if (ri > gi) {
+ iMax = max (ri, bi);
+ iMin = min (gi, bi);
+ } else {
+ iMax = max (gi, bi);
+ iMin = min (ri, bi);
+ }
+
+ rv = (short) (iMax << ABITS);
+
+ if (rv == 0) {
+ return 0;
+ }
+
+ chroma = iMax - iMin;
+ rs = (short) ((k1 * chroma) / iMax);
+ if (rs == 0) {
+ return 0;
+ }
+
+ if ( ri == iMax ) {
+ rh = (short) ((k2 * (6 * chroma + gi - bi))/(6 * chroma));
+ if (rh >= k2) {
+ rh -= k2;
+ }
+ return rh;
+ }
+
+ if (gi == iMax) {
+ return(short) ((k2 * (2 * chroma + bi - ri)) / (6 * chroma));
+ }
+
+ return (short) ((k2 * (4 * chroma + ri - gi)) / (6 * chroma));
+}
+
+uchar4 __attribute__((kernel)) selectiveAdjust(const uchar4 in, uint32_t x,
+ uint32_t y) {
+ float4 pixel = rsUnpackColor8888(in);
+
+ float4 wsum = pixel;
+ int hue = rgb2hue(in);
+
+ float t = satLut[hue];
+ pixel.xyz = rsMatrixMultiply(&colorMatrix_min ,pixel.xyz) * (1 - t) +
+ t * (rsMatrixMultiply(&colorMatrix_max ,pixel.xyz));
+
+ pixel.a = 1.0f;
+ return rsPackColorTo8888(clamp(pixel, 0.f, 1.0f));
+} \ No newline at end of file