diff options
author | John Hoford <hoford@google.com> | 2013-08-29 18:34:00 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-08-29 18:34:00 +0000 |
commit | 834efce0da12e6a4664c3f3c63bfd2e77b6e750a (patch) | |
tree | 536e9a1f7b97234e5fc83c0c520cf2ca4b20083e /src/com/android | |
parent | 960e83bd57b6236f4eb7fff98aeb7082a48f6b97 (diff) | |
parent | 37f8e432f4eb94d0ab483bfdc2a1fa024508e85f (diff) | |
download | android_packages_apps_Gallery2-834efce0da12e6a4664c3f3c63bfd2e77b6e750a.tar.gz android_packages_apps_Gallery2-834efce0da12e6a4664c3f3c63bfd2e77b6e750a.tar.bz2 android_packages_apps_Gallery2-834efce0da12e6a4664c3f3c63bfd2e77b6e750a.zip |
Merge "vignette fix & enhance to remove center focus" into gb-ub-photos-carlsbad
Diffstat (limited to 'src/com/android')
6 files changed, 693 insertions, 124 deletions
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorVignette.java b/src/com/android/gallery3d/filtershow/editors/EditorVignette.java index 7127b2188..3a94dce6c 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 @@ public class EditorVignette extends ParametricEditor { 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 @@ public class EditorVignette extends ParametricEditor { @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); + } + 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 && getLocalRepresentation() instanceof FilterVignetteRepresentation) { - FilterVignetteRepresentation drawRep = (FilterVignetteRepresentation) rep; - mImageVignette.setRepresentation(drawRep); + 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 8429d3b5e..2e362f8b5 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 @@ public class FilterVignetteRepresentation extends FilterBasicRepresentation impl 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 @@ public class FilterVignetteRepresentation extends FilterBasicRepresentation impl @Override public boolean isNil() { - return getValue() == 0; + return false; } @Override @@ -126,6 +166,10 @@ public class FilterVignetteRepresentation extends FilterBasicRepresentation impl } 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 @@ public class FilterVignetteRepresentation extends FilterBasicRepresentation impl 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); + private static final String ELLIPSE = "ellipse"; + private static final String ARGS = "adjust"; + @Override + 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(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 7e0a452bf..0ab5016cd 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java @@ -19,14 +19,26 @@ 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; +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 @@ public class ImageFilterVignette extends SimpleImageFilter { 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 @@ public class ImageFilterVignette extends SimpleImageFilter { } @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 @@ public class ImageFilterVignette extends SimpleImageFilter { 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 000000000..709b220e4 --- /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 068464c44..4c0c24d8c 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.RadialGradient; 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 @@ public class EclipseControl { 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 @@ public class EclipseControl { } 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 @@ public class EclipseControl { 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 @@ public class EclipseControl { 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 @@ public class EclipseControl { 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 @@ public class EclipseControl { 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 @@ public class EclipseControl { 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 @@ public class EclipseControl { 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 039aea939..389fe3f41 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java +++ b/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java @@ -48,6 +48,8 @@ public class ImageVignette extends ImageShow { @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 @@ public class ImageVignette extends ImageShow { 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 @@ public class ImageVignette extends ImageShow { 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 @@ public class ImageVignette extends ImageShow { 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 @@ public class ImageVignette extends ImageShow { 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); } |