vignette fix & enhance to remove center focus

Change-Id: Ide19925c5a9113518815d3aacc2204ef5ab9661d
diff --git a/jni/Android.mk b/jni/Android.mk
index e612486..0b8480e 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -37,7 +37,6 @@
                    filters/vibrance.c \
                    filters/geometry.c \
                    filters/negative.c \
-                   filters/vignette.c \
                    filters/redEyeMath.c \
                    filters/fx.c \
                    filters/wbalance.c \
diff --git a/jni/filters/vignette.c b/jni/filters/vignette.c
deleted file mode 100644
index b9ee3ff..0000000
--- a/jni/filters/vignette.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-#include <math.h>
-
-static int* gVignetteMap = 0;
-static int gVignetteWidth = 0;
-static int gVignetteHeight = 0;
-
-void JNIFUNCF(ImageFilterVignette, nativeApplyFilter, jobject bitmap, jint width, jint height, jint centerx, jint centery, jfloat radiusx, jfloat radiusy, jfloat strength)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    int i;
-    int len = width * height * 4;
-    int vignette = 0;
-    float d = centerx;
-    if (radiusx == 0) radiusx = 10;
-    if (radiusy == 0) radiusy = 10;
-    float scalex = 1/radiusx;
-    float scaley = 1/radiusy;
-
-    for (i = 0; i < len; i += 4)
-    {
-        int p = i/4;
-        float x = ((p%width)-centerx)*scalex;
-        float y = ((p/width)-centery)*scaley;
-        float dist = sqrt(x*x+y*y)-1;
-        vignette = (int) (strength*256*MAX(dist,0));
-        destination[RED] = CLAMP(destination[RED] - vignette);
-        destination[GREEN] = CLAMP(destination[GREEN] - vignette);
-        destination[BLUE] = CLAMP(destination[BLUE] - vignette);
-    }
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
diff --git a/res/layout-land/filtershow_vignette_controls.xml b/res/layout-land/filtershow_vignette_controls.xml
new file mode 100644
index 0000000..9bfb29f
--- /dev/null
+++ b/res/layout-land/filtershow_vignette_controls.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent">
+
+    <ScrollView
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:fadeScrollbars="false">
+
+        <GridLayout
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:alignmentMode="alignBounds"
+                android:useDefaultMargins="true"
+                android:columnOrderPreserved="false"
+                android:columnCount="2">
+
+            <TextView
+                    android:layout_gravity="left|center_vertical"
+                    android:text="@string/vignette_exposure"
+                    android:textStyle="bold"
+                    android:layout_marginLeft="8dp"
+                    android:visibility="gone"/>
+            <TextView
+                    android:layout_gravity="right|center_vertical"
+                    android:id="@+id/exposureValue"
+                    android:layout_marginRight="16dp"
+                    android:visibility="gone"/>
+            <SeekBar
+                    android:id="@+id/exposureSeekBar"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    style="@style/FilterShowSlider"
+                    android:layout_columnSpan="2"
+                    android:visibility="gone"/>
+
+            <TextView
+                    android:layout_gravity="left|center_vertical"
+                    android:text="@string/vignette_saturation"
+                    android:textStyle="bold"
+                    android:layout_marginLeft="8dp"/>
+            <TextView
+                    android:layout_gravity="right|center_vertical"
+                    android:id="@+id/saturationValue"
+                    android:layout_marginRight="16dp"/>
+            <SeekBar
+                    android:id="@+id/saturationSeekBar"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    style="@style/FilterShowSlider"
+                    android:layout_columnSpan="2"/>
+
+            <TextView
+                    android:layout_gravity="left|center_vertical"
+                    android:text="@string/vignette_contrast"
+                    android:textStyle="bold"
+                    android:layout_marginLeft="8dp"/>
+            <TextView
+                    android:layout_gravity="right|center_vertical"
+                    android:id="@+id/contrastValue"
+                    android:layout_marginRight="16dp"/>
+            <SeekBar
+                    android:id="@+id/contrastSeekBar"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    style="@style/FilterShowSlider"
+                    android:layout_columnSpan="2"/>
+
+            <TextView
+                    android:layout_gravity="left|center_vertical"
+                    android:text="@string/vignette_falloff"
+                    android:textStyle="bold"
+                    android:layout_marginLeft="8dp"/>
+            <TextView
+                    android:layout_gravity="right|center_vertical"
+                    android:id="@+id/falloffValue"
+                    android:layout_marginRight="16dp"/>
+            <SeekBar
+                    android:id="@+id/falloffSeekBar"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    style="@style/FilterShowSlider"
+                    android:layout_columnSpan="2"/>
+
+        </GridLayout>
+    </ScrollView>
+
+    <GridLayout
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="128dp"
+            android:alignmentMode="alignBounds"
+            android:useDefaultMargins="true"
+            android:columnOrderPreserved="false"
+            android:layout_weight="1"
+            android:columnCount="2">
+
+        <TextView
+                android:layout_gravity="left|center_vertical"
+                android:text="@string/vignette_main"
+                android:layout_marginLeft="8dp"/>
+        <TextView
+                android:layout_gravity="right|center_vertical"
+                android:id="@+id/mainVignetteValue"
+                android:layout_marginRight="16dp"/>
+        <SeekBar
+                android:id="@+id/mainVignetteSeekbar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                style="@style/FilterShowSlider"
+                android:layout_columnSpan="2"/>
+    </GridLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/menu/filtershow_menu_vignette.xml b/res/menu/filtershow_menu_vignette.xml
new file mode 100644
index 0000000..2b32424
--- /dev/null
+++ b/res/menu/filtershow_menu_vignette.xml
@@ -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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <group android:id="@+id/grunge_popupmenu" >
+        <item
+            android:id="@+id/editor_vignette_main"
+            android:title="@string/vignette_main"/>
+        <item
+            android:id="@+id/editor_vignette_falloff"
+            android:title="@string/vignette_falloff"/>
+        <item
+            android:id="@+id/editor_vignette_contrast"
+            android:title="@string/vignette_contrast"/>
+        <item
+            android:id="@+id/editor_vignette_saturation"
+            android:title="@string/vignette_saturation"/>
+       <item
+            android:id="@+id/editor_vignette_exposure"
+            android:title="@string/vignette_exposure"
+            android:visible= "false"/>
+    </group>
+
+</menu>
\ No newline at end of file
diff --git a/res/values/filtershow_strings.xml b/res/values/filtershow_strings.xml
index 4c8996a..802c8e0 100644
--- a/res/values/filtershow_strings.xml
+++ b/res/values/filtershow_strings.xml
@@ -154,6 +154,17 @@
     <string name="curvesRGB">Curves</string>
     <!--  Label for the image vignette filter (darkens photo around edges) button [CHAR LIMIT=10] -->
     <string name="vignette">Vignette</string>
+    <!--  Label for the image vignette main parameter ui [CHAR LIMIT=15] -->
+    <string name="vignette_main">Vignette</string>
+    <!--  Label for the image vignette exposure parameter ui [CHAR LIMIT=15] -->
+    <string name="vignette_exposure">Exposure</string>
+    <!--  Label for the image vignette saturation parameter ui [CHAR LIMIT=15] -->
+    <string name="vignette_saturation">Saturation</string>
+    <!--  Label for the image vignette contrast fparameter ui [CHAR LIMIT=15] -->
+    <string name="vignette_contrast">Contrast</string>
+    <!--  Label for the image vignette Falloff rate parameter ui [CHAR LIMIT=15] -->
+    <string name="vignette_falloff">Falloff</string>
+
     <!--  Label for the image effect that removes redeye. [CHAR LIMIT=10] -->
     <string name="redeye">Red Eye</string>
     <!--  Label for the that allows drawing on Image [CHAR LIMIT=10] -->
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorVignette.java b/src/com/android/gallery3d/filtershow/editors/EditorVignette.java
index 7127b21..3a94dce 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorVignette.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorVignette.java
@@ -17,11 +17,22 @@
 package com.android.gallery3d.filtershow.editors;
 
 import android.content.Context;
+import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
 import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.PopupMenu;
+import android.widget.SeekBar;
+import android.widget.TextView;
 
 import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.controller.BasicParameterInt;
+import com.android.gallery3d.filtershow.controller.Parameter;
 import com.android.gallery3d.filtershow.filters.FilterVignetteRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.imageshow.ImageVignette;
 
 public class EditorVignette extends ParametricEditor {
@@ -29,6 +40,33 @@
     private static final String LOGTAG = "EditorVignettePlanet";
     ImageVignette mImageVignette;
 
+    private SeekBar mVignetteBar;
+    private SeekBar mExposureBar;
+    private SeekBar mSaturationBar;
+    private SeekBar mContrastBar;
+    private SeekBar mFalloffBar;
+
+
+    private TextView mVignetteValue;
+    private TextView mExposureValue;
+    private TextView mSaturationValue;
+    private TextView mContrastValue;
+    private TextView mFalloffValue;
+
+    private SwapButton mButton;
+    private final Handler mHandler = new Handler();
+
+    int[] mMenuStrings = {
+            R.string.vignette_main,
+            R.string.vignette_exposure,
+            R.string.vignette_saturation,
+            R.string.vignette_contrast,
+            R.string.vignette_falloff,
+    };
+
+    String mCurrentlyEditing = null;
+
+
     public EditorVignette() {
         super(ID, R.layout.filtershow_vignette_editor, R.id.imageVignette);
     }
@@ -42,12 +80,299 @@
 
     @Override
     public void reflectCurrentFilter() {
-        super.reflectCurrentFilter();
+        if (useCompact(mContext)) {
+            super.reflectCurrentFilter();
 
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep != null && getLocalRepresentation() instanceof FilterVignetteRepresentation) {
-            FilterVignetteRepresentation drawRep = (FilterVignetteRepresentation) rep;
-            mImageVignette.setRepresentation(drawRep);
+            FilterRepresentation rep = getLocalRepresentation();
+            if (rep != null && getLocalRepresentation() instanceof FilterVignetteRepresentation) {
+                FilterVignetteRepresentation drawRep = (FilterVignetteRepresentation) rep;
+                mImageVignette.setRepresentation(drawRep);
+            }
+            updateText();
+            return;
         }
+        mLocalRepresentation = null;
+        if (getLocalRepresentation() != null
+                && getLocalRepresentation() instanceof FilterVignetteRepresentation) {
+            FilterVignetteRepresentation rep =
+                    (FilterVignetteRepresentation) getLocalRepresentation();
+            int min;
+            int []mode = {
+                    FilterVignetteRepresentation.MODE_VIGNETTE,
+                    FilterVignetteRepresentation.MODE_EXPOSURE,
+                    FilterVignetteRepresentation.MODE_SATURATION,
+                    FilterVignetteRepresentation.MODE_CONTRAST,
+                    FilterVignetteRepresentation.MODE_FALLOFF
+            };
+            SeekBar []sliders = {
+                    mVignetteBar,
+                    mExposureBar,
+                    mSaturationBar,
+                    mContrastBar,
+                    mFalloffBar
+            };
+            TextView []label = {
+                    mVignetteValue,
+                    mExposureValue,
+                    mSaturationValue,
+                    mContrastValue,
+                    mFalloffValue
+            };
+            for (int i = 0; i < mode.length; i++) {
+                BasicParameterInt p = (BasicParameterInt) rep.getFilterParameter(mode[i]);
+                int value = p.getValue();
+                sliders[i].setMax(p.getMaximum() - p.getMinimum());
+                sliders[i].setProgress(value - p.getMinimum());
+                label[i].setText("" + value);
+            }
+
+            mImageVignette.setRepresentation(rep);
+            String text = mContext.getString(rep.getTextId()).toUpperCase();
+            mFilterTitle.setText(text);
+            updateText();
+        }
+    }
+
+
+
+    @Override
+    public String calculateUserMessage(Context context, String effectName, Object parameterValue) {
+        FilterRepresentation rep = getLocalRepresentation();
+        if (rep == null || !(rep instanceof FilterVignetteRepresentation)) {
+            return "";
+        }
+        FilterVignetteRepresentation csrep = (FilterVignetteRepresentation) rep;
+        int mode = csrep.getParameterMode();
+        String paramString;
+
+        paramString = mContext.getString(mMenuStrings[mode]);
+
+        int val = csrep.getCurrentParameter();
+        return paramString + ((val > 0) ? " +" : " ") + val;
+    }
+
+    @Override
+    public void openUtilityPanel(final LinearLayout accessoryViewList) {
+        mButton = (SwapButton) accessoryViewList.findViewById(R.id.applyEffect);
+        mButton.setText(mContext.getString(R.string.vignette_main));
+
+        if (useCompact(mContext)) {
+            final PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), mButton);
+
+            popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_vignette,
+                    popupMenu.getMenu());
+
+            popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+                @Override
+                public boolean onMenuItemClick(MenuItem item) {
+                    selectMenuItem(item);
+                    return true;
+                }
+            });
+            mButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View arg0) {
+                    popupMenu.show();
+                }
+            });
+            mButton.setListener(this);
+
+            FilterVignetteRepresentation csrep = getVignetteRep();
+            String menuString = mContext.getString(mMenuStrings[0]);
+            switchToMode(csrep, FilterVignetteRepresentation.MODE_VIGNETTE, menuString);
+        } else {
+            mButton.setText(mContext.getString(R.string.vignette_main));
+        }
+    }
+
+    @Override
+    public void setUtilityPanelUI(View actionButton, View editControl) {
+        if (useCompact(mContext)) {
+            super.setUtilityPanelUI(actionButton, editControl);
+            return;
+        }
+        mActionButton = actionButton;
+        mEditControl = editControl;
+        mEditTitle.setCompoundDrawables(null, null, null, null);
+        LinearLayout group = (LinearLayout) editControl;
+        LayoutInflater inflater =
+                (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        LinearLayout controls = (LinearLayout) inflater.inflate(
+                R.layout.filtershow_vignette_controls, group, false);
+        ViewGroup.LayoutParams lp = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+        controls.setLayoutParams(lp);
+        group.removeAllViews();
+        group.addView(controls);
+
+        mVignetteBar = (SeekBar) controls.findViewById(R.id.mainVignetteSeekbar);
+        mVignetteBar.setMax(200);
+        mVignetteBar.setOnSeekBarChangeListener(this);
+        mVignetteValue = (TextView) controls.findViewById(R.id.mainVignetteValue);
+        mExposureBar = (SeekBar) controls.findViewById(R.id.exposureSeekBar);
+        mExposureBar.setMax(200);
+        mExposureBar.setOnSeekBarChangeListener(this);
+        mExposureValue = (TextView) controls.findViewById(R.id.exposureValue);
+        mSaturationBar = (SeekBar) controls.findViewById(R.id.saturationSeekBar);
+        mSaturationBar.setMax(200);
+        mSaturationBar.setOnSeekBarChangeListener(this);
+        mSaturationValue = (TextView) controls.findViewById(R.id.saturationValue);
+        mContrastBar = (SeekBar) controls.findViewById(R.id.contrastSeekBar);
+        mContrastBar.setMax(200);
+        mContrastBar.setOnSeekBarChangeListener(this);
+        mContrastValue = (TextView) controls.findViewById(R.id.contrastValue);
+        mFalloffBar = (SeekBar) controls.findViewById(R.id.falloffSeekBar);
+        mFalloffBar.setMax(200);
+        mFalloffBar.setOnSeekBarChangeListener(this);
+        mFalloffValue = (TextView) controls.findViewById(R.id.falloffValue);
+    }
+
+    public int getParameterIndex(int id) {
+        switch (id) {
+            case R.id.editor_vignette_main:
+                return FilterVignetteRepresentation.MODE_VIGNETTE;
+            case R.id.editor_vignette_saturation:
+                return FilterVignetteRepresentation.MODE_SATURATION;
+            case R.id.editor_vignette_contrast:
+                return FilterVignetteRepresentation.MODE_CONTRAST;
+            case R.id.editor_vignette_exposure:
+                return FilterVignetteRepresentation.MODE_EXPOSURE;
+            case R.id.editor_vignette_falloff:
+                return FilterVignetteRepresentation.MODE_FALLOFF;
+        }
+        return -1;
+    }
+
+    @Override
+    public void detach() {
+        if (mButton == null) {
+            return;
+        }
+        mButton.setListener(null);
+        mButton.setOnClickListener(null);
+    }
+
+    private void updateSeekBar(FilterVignetteRepresentation rep) {
+        mControl.updateUI();
+    }
+
+    @Override
+    protected Parameter getParameterToEdit(FilterRepresentation rep) {
+        if (rep instanceof FilterVignetteRepresentation) {
+            FilterVignetteRepresentation csrep = (FilterVignetteRepresentation) rep;
+            Parameter param = csrep.getFilterParameter(csrep.getParameterMode());
+
+            return param;
+        }
+        return null;
+    }
+
+    private FilterVignetteRepresentation getVignetteRep() {
+        FilterRepresentation rep = getLocalRepresentation();
+        if (rep != null
+                && rep instanceof FilterVignetteRepresentation) {
+            FilterVignetteRepresentation csrep = (FilterVignetteRepresentation) rep;
+            return csrep;
+        }
+        return null;
+    }
+
+    protected void selectMenuItem(MenuItem item) {
+        if (getLocalRepresentation() != null
+                && getLocalRepresentation() instanceof FilterVignetteRepresentation) {
+            FilterVignetteRepresentation csrep =
+                    (FilterVignetteRepresentation) getLocalRepresentation();
+
+            switchToMode(csrep, getParameterIndex(item.getItemId()), item.getTitle().toString());
+        }
+    }
+
+    protected void switchToMode(FilterVignetteRepresentation csrep, int mode, String title) {
+        if (csrep == null) {
+            return;
+        }
+        csrep.setParameterMode(mode);
+        mCurrentlyEditing = title;
+        mButton.setText(mCurrentlyEditing);
+        {
+            Parameter param = getParameterToEdit(csrep);
+
+            control(param, mEditControl);
+        }
+        updateSeekBar(csrep);
+        mView.invalidate();
+    }
+
+    @Override
+    public void onProgressChanged(SeekBar sbar, int progress, boolean arg2) {
+        FilterVignetteRepresentation rep = getVignetteRep();
+        int value = progress;
+        BasicParameterInt  p;
+        switch (sbar.getId()) {
+            case R.id.mainVignetteSeekbar:
+                rep.setParameterMode(FilterVignetteRepresentation.MODE_VIGNETTE);
+                p = rep.getFilterParameter(rep.getParameterMode());
+                value += p.getMinimum();
+                mVignetteValue.setText("" + value);
+                break;
+            case R.id.exposureSeekBar:
+                rep.setParameterMode(FilterVignetteRepresentation.MODE_EXPOSURE);
+                p = rep.getFilterParameter(rep.getParameterMode());
+                value += p.getMinimum();
+                mExposureValue.setText("" + value);
+                break;
+            case R.id.saturationSeekBar:
+                rep.setParameterMode(FilterVignetteRepresentation.MODE_SATURATION);
+                p = rep.getFilterParameter(rep.getParameterMode());
+                value += p.getMinimum();
+                mSaturationValue.setText("" + value);
+                break;
+            case R.id.contrastSeekBar:
+                rep.setParameterMode(FilterVignetteRepresentation.MODE_CONTRAST);
+                p = rep.getFilterParameter(rep.getParameterMode());
+                value += p.getMinimum();
+                mContrastValue.setText("" + value);
+                break;
+            case R.id.falloffSeekBar:
+                rep.setParameterMode(FilterVignetteRepresentation.MODE_FALLOFF);
+                p = rep.getFilterParameter(rep.getParameterMode());
+                value += p.getMinimum();
+                mFalloffValue.setText("" + value);
+                break;
+        }
+        rep.setCurrentParameter(value);
+        commitLocalRepresentation();
+    }
+
+    @Override
+    public void swapLeft(MenuItem item) {
+        super.swapLeft(item);
+        mButton.setTranslationX(0);
+        mButton.animate().translationX(mButton.getWidth()).setDuration(SwapButton.ANIM_DURATION);
+        Runnable updateButton = new Runnable() {
+            @Override
+            public void run() {
+                mButton.animate().cancel();
+                mButton.setTranslationX(0);
+            }
+        };
+        mHandler.postDelayed(updateButton, SwapButton.ANIM_DURATION);
+        selectMenuItem(item);
+    }
+
+    @Override
+    public void swapRight(MenuItem item) {
+        super.swapRight(item);
+        mButton.setTranslationX(0);
+        mButton.animate().translationX(-mButton.getWidth()).setDuration(SwapButton.ANIM_DURATION);
+        Runnable updateButton = new Runnable() {
+            @Override
+            public void run() {
+                mButton.animate().cancel();
+                mButton.setTranslationX(0);
+            }
+        };
+        mHandler.postDelayed(updateButton, SwapButton.ANIM_DURATION);
+        selectMenuItem(item);
     }
 }
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
index 8429d3b..2e362f8 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
@@ -16,19 +16,48 @@
 
 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.editors.EditorVignette;
 import com.android.gallery3d.filtershow.imageshow.Oval;
 
-public class FilterVignetteRepresentation extends FilterBasicRepresentation implements Oval {
+import java.io.IOException;
+
+public class FilterVignetteRepresentation extends FilterRepresentation implements Oval {
     private static final String LOGTAG = "FilterVignetteRepresentation";
-    private float mCenterX = Float.NaN;
-    private float mCenterY;
-    private float mRadiusX = Float.NaN;
-    private float mRadiusY;
+
+    private float mCenterX = .5f;
+    private float mCenterY = .5f;
+    private float mRadiusX = .5f;
+    private float mRadiusY = .5f;
+    public static final int MODE_VIGNETTE = 0;
+    public static final int MODE_EXPOSURE = 1;
+    public static final int MODE_SATURATION = 2;
+    public static final int MODE_CONTRAST = 3;
+    public static final int MODE_FALLOFF = 4;
+    private static int MIN = -100;
+    private static int MAX = 100;
+    private static int MAXFALLOF = 200;
+
+    private BasicParameterInt mParamVignette = new BasicParameterInt(MODE_VIGNETTE, 0, MIN, MAX);
+    private BasicParameterInt mParamExposure = new BasicParameterInt(MODE_EXPOSURE, 0, MIN, MAX);
+    private BasicParameterInt mParamSaturation = new BasicParameterInt(MODE_SATURATION, 0, MIN, MAX);
+    private BasicParameterInt mParamContrast = new BasicParameterInt(MODE_CONTRAST, 0, MIN, MAX);
+    private BasicParameterInt mParamFalloff = new BasicParameterInt(MODE_FALLOFF, 40, 0, MAXFALLOF);
+    private BasicParameterInt[] mAllParam = {
+            mParamVignette,
+            mParamExposure,
+            mParamSaturation,
+            mParamContrast,
+            mParamFalloff};
+    private int mParameterMode;
 
     public FilterVignetteRepresentation() {
-        super("Vignette", -100, 50, 100);
+        super("Vignette");
         setSerializationName("VIGNETTE");
         setShowParameterValue(true);
         setFilterType(FilterRepresentation.TYPE_VIGNETTE);
@@ -36,18 +65,29 @@
         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;
+        FilterVignetteRepresentation rep = (FilterVignetteRepresentation) a;
+        mCenterX = rep.mCenterX;
+        mCenterY = rep.mCenterY;
+        mRadiusX = rep.mRadiusX;
+        mRadiusY = rep.mRadiusY;
+        mParamVignette.setValue(rep.mParamVignette.getValue());
+        mParamExposure.setValue(rep.mParamExposure.getValue());
+        mParamSaturation.setValue(rep.mParamSaturation.getValue());
+        mParamContrast.setValue(rep.mParamContrast.getValue());
+        mParamFalloff.setValue(rep.mParamFalloff.getValue());
+    }
+
+    public int getValue(int mode) {
+        return mAllParam[mode].getValue();
+    }
+
+    public void setValue(int mode, int value) {
+        mAllParam[mode].setValue(value);
     }
 
     @Override
@@ -116,7 +156,7 @@
 
     @Override
     public boolean isNil() {
-        return getValue() == 0;
+        return false;
     }
 
     @Override
@@ -126,6 +166,10 @@
         }
         if (representation instanceof FilterVignetteRepresentation) {
             FilterVignetteRepresentation rep = (FilterVignetteRepresentation) representation;
+            for (int i = 0; i < mAllParam.length; i++) {
+                if (mAllParam[i].getValue() != rep.mAllParam[i].getValue())
+                    return false;
+            }
             if (rep.getCenterX() == getCenterX()
                     && rep.getCenterY() == getCenterY()
                     && rep.getRadiusX() == getRadiusX()
@@ -136,43 +180,87 @@
         return false;
     }
 
-    private static final String[] sParams = {
-            "Name", "value", "mCenterX", "mCenterY", "mRadiusX",
-            "mRadiusY"
-    };
-
+    private static final String ELLIPSE = "ellipse";
+    private static final String ARGS = "adjust";
     @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;
+    public void serializeRepresentation(JsonWriter writer) throws IOException {
+        writer.beginObject();
+        writer.name(ELLIPSE);
+        writer.beginArray();
+        writer.value(mCenterX);
+        writer.value(mCenterY);
+        writer.value(mRadiusX);
+        writer.value(mRadiusY);
+        writer.endArray();
+
+        writer.name(ARGS);
+        writer.beginArray();
+        writer.value(mParamVignette.getValue());
+        writer.value(mParamExposure.getValue());
+        writer.value(mParamSaturation.getValue());
+        writer.value(mParamContrast.getValue());
+        writer.value(mParamFalloff.getValue());
+        writer.endArray();
+        writer.endObject();
     }
 
+
     @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);
+    public void deSerializeRepresentation(JsonReader sreader) throws IOException {
+        sreader.beginObject();
+
+        while (sreader.hasNext()) {
+            String name = sreader.nextName();
+            if (name.startsWith(ELLIPSE)) {
+                sreader.beginArray();
+                sreader.hasNext();
+                mCenterX = (float) sreader.nextDouble();
+                sreader.hasNext();
+                mCenterY = (float) sreader.nextDouble();
+                sreader.hasNext();
+                mRadiusX = (float) sreader.nextDouble();
+                sreader.hasNext();
+                mRadiusY = (float) sreader.nextDouble();
+                sreader.hasNext();
+                sreader.endArray();
+            } else if (name.startsWith(ARGS)) {
+                sreader.beginArray();
+                sreader.hasNext();
+                mParamVignette.setValue(sreader.nextInt());
+                sreader.hasNext();
+                mParamExposure.setValue(sreader.nextInt());
+                sreader.hasNext();
+                mParamSaturation.setValue(sreader.nextInt());
+                sreader.hasNext();
+                mParamContrast.setValue(sreader.nextInt());
+                sreader.hasNext();
+                mParamFalloff.setValue(sreader.nextInt());
+                sreader.hasNext();
+                sreader.endArray();
+            } else  {
+                sreader.skipValue();
             }
         }
+        sreader.endObject();
     }
+    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);
+    }
+
+    public BasicParameterInt getFilterParameter(int index) {
+        return mAllParam[index];
+    }
+
 }
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
index 7e0a452..0ab5016 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
@@ -19,14 +19,26 @@
 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;
+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;
 
-public class ImageFilterVignette extends SimpleImageFilter {
+public class ImageFilterVignette extends ImageFilterRS {
     private static final String LOGTAG = "ImageFilterVignette";
     private Bitmap mOverlayBitmap;
+    private ScriptC_vignette mScript;
+    FilterVignetteRepresentation mParameters;
+    public static final int MODE_VIGNETTE = FilterVignetteRepresentation.MODE_VIGNETTE;
+    public static final int MODE_EXPOSURE = FilterVignetteRepresentation.MODE_EXPOSURE;
+    public static final int MODE_SATURATION = FilterVignetteRepresentation.MODE_SATURATION;
+    public static final int MODE_CONTRAST = FilterVignetteRepresentation.MODE_CONTRAST;
+    public static final int MODE_FALLOFF = FilterVignetteRepresentation.MODE_FALLOFF;
 
     public ImageFilterVignette() {
         mName = "Vignette";
@@ -38,8 +50,14 @@
         return representation;
     }
 
+    @Override
+    public void useRepresentation(FilterRepresentation representation) {
+        mParameters = (FilterVignetteRepresentation) representation;
+    }
+
     native protected void nativeApplyFilter(
-            Bitmap bitmap, int w, int h, int cx, int cy, float radx, float rady, float strength);
+            Bitmap bitmap, int w, int h, int cx, int cy, float radx, float rady,
+            float strength, float finalValue);
 
     private float calcRadius(float cx, float cy, int w, int h) {
         float d = cx;
@@ -56,6 +74,51 @@
     }
 
     @Override
+    protected void createFilter(Resources res, float scaleFactor, int quality) {
+        RenderScript rsCtx = getRenderScriptContext();
+
+        mScript = new ScriptC_vignette(rsCtx, res, R.raw.vignette);
+    }
+
+    @Override
+    protected void runFilter() {
+
+        int w = getInPixelsAllocation().getType().getX();
+        int h = getInPixelsAllocation().getType().getY();
+
+        float cx = w / 2;
+        float cy = h / 2;
+        float r = calcRadius(cx, cy, w, h);
+        float rx = r;
+        float ry = r;
+        if (mParameters.isCenterSet()) {
+
+            cx = mParameters.getCenterX() * w;
+            cy = mParameters.getCenterY() * h;
+
+            rx = mParameters.getRadiusX() * w;
+            ry = mParameters.getRadiusY() * h;
+        }
+
+
+        mScript.set_inputWidth(w);
+        mScript.set_inputHeight(h);
+        int v = mParameters.getValue(MODE_VIGNETTE);
+        mScript.set_finalSubtract((v < 0) ? v : 0);
+        mScript.set_finalBright((v > 0) ? -v : 0);
+        mScript.set_finalSaturation(mParameters.getValue(MODE_SATURATION));
+        mScript.set_finalContrast(mParameters.getValue(MODE_CONTRAST));
+        mScript.set_centerx(cx);
+        mScript.set_centery(cy);
+        mScript.set_radiusx(rx);
+        mScript.set_radiusy(ry);
+        mScript.set_strength(mParameters.getValue(MODE_FALLOFF)/10.f);
+        mScript.invoke_setupVignetteParams();
+        mScript.forEach_vignette(getInPixelsAllocation(), getOutPixelsAllocation());
+
+    }
+
+    @Override
     public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
         if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) {
             if (mOverlayBitmap == null) {
@@ -63,36 +126,33 @@
                 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);
+        Bitmap ret = super.apply(bitmap, scaleFactor, quality);
         return bitmap;
     }
+
+
+    @Override
+    protected void resetAllocations() {
+
+    }
+
+    @Override
+    public void resetScripts() {
+
+    }
+
+    @Override
+    protected void bindScriptValues() {
+        int width = getInPixelsAllocation().getType().getX();
+        int height = getInPixelsAllocation().getType().getY();
+        mScript.set_inputWidth(width);
+        mScript.set_inputHeight(height);
+    }
 }
diff --git a/src/com/android/gallery3d/filtershow/filters/vignette.rs b/src/com/android/gallery3d/filtershow/filters/vignette.rs
new file mode 100644
index 0000000..709b220
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/vignette.rs
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013 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)
+
+uint32_t inputWidth;
+uint32_t inputHeight;
+float centerx;
+float centery;
+float radiusx;
+float radiusy;
+float strength;
+float finalBright;
+float finalSaturation;
+float finalContrast;
+float finalSubtract;
+rs_matrix3x3 colorMatrix;
+float scalex;
+float scaley;
+float offset;
+static const float Rf = 0.2999f;
+static const float Gf = 0.587f;
+static const float Bf = 0.114f;
+
+
+void setupVignetteParams() {
+    int k = 0;
+
+    scalex = 1.f / radiusx;
+    scaley = 1.f / radiusy;
+
+    float S = 1 + finalSaturation / 100.f;
+    float MS = 1 - S;
+    float Rt = Rf * MS;
+    float Gt = Gf * MS;
+    float Bt = Bf * MS;
+
+    float b = 1 + finalBright / 100.f;
+    float c = 1 + finalContrast / 100.f;
+    b *= c;
+    offset = .5f - c / 2.f - finalSubtract / 100.f;
+    rsMatrixSet(&colorMatrix, 0, 0, b * (Rt + S));
+    rsMatrixSet(&colorMatrix, 1, 0, b * Gt);
+    rsMatrixSet(&colorMatrix, 2, 0, b * Bt);
+    rsMatrixSet(&colorMatrix, 0, 1, b * Rt);
+    rsMatrixSet(&colorMatrix, 1, 1, b * (Gt + S));
+    rsMatrixSet(&colorMatrix, 2, 1, b * Bt);
+    rsMatrixSet(&colorMatrix, 0, 2, b * Rt);
+    rsMatrixSet(&colorMatrix, 1, 2, b * Gt);
+    rsMatrixSet(&colorMatrix, 2, 2, b * (Bt + S));
+}
+
+uchar4 __attribute__((kernel)) vignette(const uchar4 in, uint32_t x,  uint32_t y) {
+    float4 pixel = rsUnpackColor8888(in);
+    float radx = (x - centerx) * scalex;
+    float rady = (y - centery) * scaley;
+    float dist = strength * (sqrt(radx * radx + rady * rady) - 1.f);
+    float t  =  (1.f + dist / sqrt(1.f + dist* dist)) * .5f;
+    float4 wsum = pixel;
+    wsum.xyz = wsum.xyz * (1 - t) + t * (rsMatrixMultiply(&colorMatrix, wsum.xyz) + offset);
+    wsum.a = 1.0f;
+    uchar4 out = rsPackColorTo8888(clamp(wsum, 0.f, 1.0f));
+    return out;
+}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java b/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
index 068464c..4c0c24d 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
@@ -25,6 +25,7 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Shader;
+import android.util.Log;
 
 import com.android.gallery3d.R;
 
@@ -34,7 +35,7 @@
     private float mRadiusX = 200;
     private float mRadiusY = 300;
     private static int MIN_TOUCH_DIST = 80;// should be a resource & in dips
-
+    private static String LOGTAG = "EclipseControl";
     private float[] handlex = new float[9];
     private float[] handley = new float[9];
     private int mSliderColor;
@@ -104,28 +105,39 @@
     }
 
     private boolean centerIsOutside(float x1, float y1) {
-        return (!mImageBounds.contains((int) x1, (int)  y1));
+        return (!mImageBounds.contains((int) x1, (int) y1));
     }
 
-    public void actionDown(float x, float y, Oval oval) {
-        float[] point = new float[] {
-                x, y };
+    public void actionDown2(float x, float y, int iw, int ih, Oval oval) {
+        float[] point = new float[]{
+                x, y};
         mScrToImg.mapPoints(point);
         mDownX = point[0];
         mDownY = point[1];
-        mDownCenterX = oval.getCenterX();
-        mDownCenterY = oval.getCenterY();
-        mDownRadiusX = oval.getRadiusX();
-        mDownRadiusY = oval.getRadiusY();
+        mDownCenterX = oval.getCenterX() * iw;
+        mDownCenterY = oval.getCenterY() * ih;
+        mDownRadiusX = oval.getRadiusX() * iw;
+        mDownRadiusY = oval.getRadiusY() * ih;
+    }
+
+    public void actionDown(float x, float y, Oval oval) {
+        actionDown2(x, y, 1, 1, oval);
     }
 
     public void actionMove(int handle, float x, float y, Oval oval) {
-        float[] point = new float[] {
-                x, y };
+        actionMove2(handle, x, y, 1, 1, oval);
+    }
+
+    public void actionMove2(int handle, float x, float y, int w, int h, Oval oval) {
+        float[] point = new float[]{
+                x, y};
         mScrToImg.mapPoints(point);
         x = point[0];
         y = point[1];
-
+        if (w == 0) {
+            w = 1;
+            h = 1;
+        }
         // Test if the matrix is swapping x and y
         point[0] = 0;
         point[1] = 1;
@@ -140,7 +152,7 @@
                 if (centerIsOutside(x - ctrdx, y - ctrdy)) {
                     break;
                 }
-                oval.setCenter(x - ctrdx, y - ctrdy);
+                oval.setCenter((x - ctrdx) / w, (y - ctrdy) / h);
                 // setRepresentation(mVignetteRep);
                 break;
             case HAN_NORTH:
@@ -148,10 +160,10 @@
             case HAN_SOUTH:
                 if (swapxy) {
                     float raddx = mDownRadiusY - Math.abs(mDownX - mDownCenterY);
-                    oval.setRadiusY(Math.abs(x - oval.getCenterY() + sign * raddx));
+                    oval.setRadiusY(Math.abs(x - oval.getCenterY() * h + sign * raddx)/h);
                 } else {
                     float raddy = mDownRadiusY - Math.abs(mDownY - mDownCenterY);
-                    oval.setRadiusY(Math.abs(y - oval.getCenterY() + sign * raddy));
+                    oval.setRadiusY(Math.abs(y - oval.getCenterY() * h + sign * raddy)/h);
                 }
                 break;
             case HAN_EAST:
@@ -159,10 +171,10 @@
             case HAN_WEST:
                 if (swapxy) {
                     float raddy = mDownRadiusX - Math.abs(mDownY - mDownCenterX);
-                    oval.setRadiusX(Math.abs(y - oval.getCenterX() + sign * raddy));
+                    oval.setRadiusX(Math.abs(y - oval.getCenterX() * w + sign * raddy)/w);
                 } else {
                     float raddx = mDownRadiusX - Math.abs(mDownX - mDownCenterX);
-                    oval.setRadiusX(Math.abs(x - oval.getCenterX() - sign * raddx));
+                    oval.setRadiusX(Math.abs(x - oval.getCenterX() * w - sign * raddx)/w);
                 }
                 break;
             case HAN_SE:
@@ -174,13 +186,13 @@
                 float ctr_dx = mDownX - mDownCenterX;
                 float ctr_dy = mDownY - mDownCenterY;
                 float downRad = Math.abs(ctr_dx) + Math.abs(ctr_dy) - dr;
-                float rx = oval.getRadiusX();
-                float ry = oval.getRadiusY();
+                float rx = oval.getRadiusX() * w;
+                float ry = oval.getRadiusY() * h;
                 float r = (Math.abs(rx) + Math.abs(ry)) * sin45;
-                float dx = x - oval.getCenterX();
-                float dy = y - oval.getCenterY();
+                float dx = x - oval.getCenterX() * w;
+                float dy = y - oval.getCenterY() * h;
                 float nr = Math.abs(Math.abs(dx) + Math.abs(dy) - downRad);
-                oval.setRadius(rx * nr / r, ry * nr / r);
+                oval.setRadius((rx * nr / r) / w, (ry * nr / r) / h);
 
                 break;
         }
@@ -195,10 +207,10 @@
 
         paint.setStyle(Paint.Style.FILL);
         paint.setColor(Color.BLUE);
-        int[] colors3 = new int[] {
-                Color.GRAY, Color.LTGRAY, 0x66000000, 0 };
-        RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[] {
-                0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
+        int[] colors3 = new int[]{
+                Color.GRAY, Color.LTGRAY, 0x66000000, 0};
+        RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[]{
+                0, .3f, .31f, 1}, Shader.TileMode.CLAMP);
         paint.setShader(g);
         canvas.drawCircle(x, y, mCenterDotSize, paint);
     }
@@ -212,10 +224,10 @@
 
         paint.setStyle(Paint.Style.FILL);
         paint.setColor(Color.BLUE);
-        int[] colors3 = new int[] {
-                mSliderColor, mSliderColor, 0x66000000, 0 };
-        RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[] {
-                0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
+        int[] colors3 = new int[]{
+                mSliderColor, mSliderColor, 0x66000000, 0};
+        RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[]{
+                0, .3f, .31f, 1}, Shader.TileMode.CLAMP);
         paint.setShader(g);
         canvas.drawCircle(x, y, mCenterDotSize, paint);
     }
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java b/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java
index 039aea9..389fe3f 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java
@@ -48,6 +48,8 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
+        int w = MasterImage.getImage().getOriginalBounds().width();
+        int h = MasterImage.getImage().getOriginalBounds().height();
         int mask = event.getActionMasked();
         if (mActiveHandle == -1) {
             if (MotionEvent.ACTION_DOWN != mask) {
@@ -77,11 +79,11 @@
         boolean didComputeEllipses = false;
         switch (mask) {
             case (MotionEvent.ACTION_DOWN):
-                mElipse.actionDown(x, y, mVignetteRep);
+                mElipse.actionDown2(x, y, w, h, mVignetteRep);
                 break;
             case (MotionEvent.ACTION_UP):
             case (MotionEvent.ACTION_MOVE):
-                mElipse.actionMove(mActiveHandle, x, y, mVignetteRep);
+                mElipse.actionMove2(mActiveHandle, x, y, w, h, mVignetteRep);
                 setRepresentation(mVignetteRep);
                 didComputeEllipses = true;
                 break;
@@ -102,19 +104,21 @@
         if (mVignetteRep == null) {
             return;
         }
+        float w = MasterImage.getImage().getOriginalBounds().width();
+        float h = MasterImage.getImage().getOriginalBounds().height();
         Matrix toImg = getScreenToImageMatrix(false);
         Matrix toScr = new Matrix();
         toImg.invert(toScr);
 
         float[] c = new float[] {
-                mVignetteRep.getCenterX(), mVignetteRep.getCenterY() };
+                mVignetteRep.getCenterX() * w, mVignetteRep.getCenterY() * h};
         if (Float.isNaN(c[0])) {
-            float cx = MasterImage.getImage().getOriginalBounds().width() / 2;
-            float cy = MasterImage.getImage().getOriginalBounds().height() / 2;
+            float cx = w / 2;
+            float cy = h / 2;
             float rx = Math.min(cx, cy) * .8f;
             float ry = rx;
-            mVignetteRep.setCenter(cx, cy);
-            mVignetteRep.setRadius(rx, ry);
+            mVignetteRep.setCenter(cx / w, cy / h);
+            mVignetteRep.setRadius(rx / w, ry / h);
 
             c[0] = cx;
             c[1] = cy;
@@ -128,8 +132,8 @@
             toScr.mapPoints(c);
 
             mElipse.setCenter(c[0], c[1]);
-            mElipse.setRadius(toScr.mapRadius(mVignetteRep.getRadiusX()),
-                    toScr.mapRadius(mVignetteRep.getRadiusY()));
+            mElipse.setRadius(toScr.mapRadius(mVignetteRep.getRadiusX() * w),
+                    toScr.mapRadius(mVignetteRep.getRadiusY() * h));
         }
         mEditorVignette.commitLocalRepresentation();
     }
@@ -150,15 +154,17 @@
         if (mVignetteRep == null) {
             return;
         }
+        float w = MasterImage.getImage().getOriginalBounds().width();
+        float h = MasterImage.getImage().getOriginalBounds().height();
         Matrix toImg = getScreenToImageMatrix(false);
         Matrix toScr = new Matrix();
         toImg.invert(toScr);
         float[] c = new float[] {
-                mVignetteRep.getCenterX(), mVignetteRep.getCenterY() };
+                mVignetteRep.getCenterX() * w, mVignetteRep.getCenterY() * h };
         toScr.mapPoints(c);
         mElipse.setCenter(c[0], c[1]);
-        mElipse.setRadius(toScr.mapRadius(mVignetteRep.getRadiusX()),
-                toScr.mapRadius(mVignetteRep.getRadiusY()));
+        mElipse.setRadius(toScr.mapRadius(mVignetteRep.getRadiusX() * w),
+                toScr.mapRadius(mVignetteRep.getRadiusY() * h));
 
         mElipse.draw(canvas);
     }