diff options
Diffstat (limited to 'src/com/android/gallery3d')
9 files changed, 1683 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java index 7929e252d..d822553ce 100644 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java @@ -58,6 +58,7 @@ import android.widget.Toast; import com.android.gallery3d.R; import com.android.gallery3d.app.PhotoPage; import com.android.gallery3d.data.LocalAlbum; +import com.android.gallery3d.filtershow.editors.EditorGrad; import com.android.gallery3d.filtershow.pipeline.CachingPipeline; import com.android.gallery3d.filtershow.cache.ImageLoader; import com.android.gallery3d.filtershow.category.Action; @@ -376,6 +377,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL } private void fillEditors() { + mEditorPlaceHolder.addEditor(new EditorGrad()); mEditorPlaceHolder.addEditor(new EditorDraw()); mEditorPlaceHolder.addEditor(new BasicEditor()); mEditorPlaceHolder.addEditor(new ImageOnlyEditor()); diff --git a/src/com/android/gallery3d/filtershow/editors/EditorGrad.java b/src/com/android/gallery3d/filtershow/editors/EditorGrad.java new file mode 100644 index 000000000..f427ccbd8 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/editors/EditorGrad.java @@ -0,0 +1,315 @@ +/* + * 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.editors; + +import android.content.Context; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.PopupMenu; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.ToggleButton; + +import com.android.gallery3d.R; +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.ParameterActionAndInt; +import com.android.gallery3d.filtershow.filters.FilterGradRepresentation; +import com.android.gallery3d.filtershow.filters.FilterRepresentation; +import com.android.gallery3d.filtershow.imageshow.ImageGrad; +import com.android.gallery3d.filtershow.imageshow.MasterImage; + +public class EditorGrad extends ParametricEditor + implements OnSeekBarChangeListener, ParameterActionAndInt { + private static final String LOGTAG = "EditorGrad"; + public static final int ID = R.id.editorGrad; + PopupMenu mPopupMenu; + ToggleButton mAddModeButton; + String mEffectName = ""; + private static final int MODE_BRIGHTNESS = FilterGradRepresentation.PARAM_BRIGHTNESS; + private static final int MODE_SATURATION = FilterGradRepresentation.PARAM_SATURATION; + private static final int MODE_CONTRAST = FilterGradRepresentation.PARAM_CONTRAST; + private static final int ADD_ICON = R.drawable.ic_grad_add; + private static final int DEL_ICON = R.drawable.ic_grad_del; + private int mSliderMode = MODE_BRIGHTNESS; + ImageGrad mImageGrad; + + public EditorGrad() { + super(ID, R.layout.filtershow_grad_editor, R.id.gradEditor); + } + + @Override + public void createEditor(Context context, FrameLayout frameLayout) { + super.createEditor(context, frameLayout); + mImageGrad = (ImageGrad) mImageShow; + mImageGrad.setEditor(this); + + } + + public void clearAddMode() { + mAddModeButton.setChecked(false); + FilterRepresentation tmpRep = getLocalRepresentation(); + if (tmpRep instanceof FilterGradRepresentation) { + updateMenuItems((FilterGradRepresentation) tmpRep); + } + } + + @Override + public void reflectCurrentFilter() { + super.reflectCurrentFilter(); + FilterRepresentation tmpRep = getLocalRepresentation(); + if (tmpRep instanceof FilterGradRepresentation) { + FilterGradRepresentation rep = (FilterGradRepresentation) tmpRep; + boolean f = rep.showParameterValue(); + + mImageGrad.setRepresentation(rep); + } + } + + public void updateSeekBar(FilterGradRepresentation rep) { + mControl.updateUI(); + } + + @Override + public void onProgressChanged(SeekBar sbar, int progress, boolean arg2) { + FilterRepresentation tmpRep = getLocalRepresentation(); + if (tmpRep instanceof FilterGradRepresentation) { + FilterGradRepresentation rep = (FilterGradRepresentation) tmpRep; + int min = rep.getParameterMin(mSliderMode); + int value = progress + min; + rep.setParameter(mSliderMode, value); + mView.invalidate(); + commitLocalRepresentation(); + } + } + + @Override + public void openUtilityPanel(final LinearLayout accessoryViewList) { + Button view = (Button) accessoryViewList.findViewById(R.id.applyEffect); + view.setText(mContext.getString(R.string.editor_grad_brightness)); + view.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + showPopupMenu(accessoryViewList); + } + }); + + setUpPopupMenu(view); + setEffectName(); + } + + private void updateMenuItems(FilterGradRepresentation rep) { + int n = rep.getNumberOfBands(); + } + + public void setEffectName() { + if (mPopupMenu != null) { + MenuItem item = mPopupMenu.getMenu().findItem(R.id.editor_grad_brightness); + mEffectName = item.getTitle().toString(); + } + } + + private void showPopupMenu(LinearLayout accessoryViewList) { + Button button = (Button) accessoryViewList.findViewById(R.id.applyEffect); + if (button == null) { + return; + } + + if (mPopupMenu == null) { + setUpPopupMenu(button); + } + mPopupMenu.show(); + } + + private void setUpPopupMenu(Button button) { + mPopupMenu = new PopupMenu(mImageShow.getActivity(), button); + mPopupMenu.getMenuInflater() + .inflate(R.menu.filtershow_menu_grad, mPopupMenu.getMenu()); + FilterGradRepresentation rep = (FilterGradRepresentation) getLocalRepresentation(); + if (rep == null) { + return; + } + updateMenuItems(rep); + hackFixStrings(mPopupMenu.getMenu()); + setEffectName(); + updateText(); + + mPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + FilterRepresentation tmpRep = getLocalRepresentation(); + + if (tmpRep instanceof FilterGradRepresentation) { + FilterGradRepresentation rep = (FilterGradRepresentation) tmpRep; + int cmdID = item.getItemId(); + switch (cmdID) { + case R.id.editor_grad_brightness: + mSliderMode = MODE_BRIGHTNESS; + mEffectName = item.getTitle().toString(); + break; + case R.id.editor_grad_contrast: + mSliderMode = MODE_CONTRAST; + mEffectName = item.getTitle().toString(); + break; + case R.id.editor_grad_saturation: + mSliderMode = MODE_SATURATION; + mEffectName = item.getTitle().toString(); + break; + } + updateMenuItems(rep); + updateSeekBar(rep); + + commitLocalRepresentation(); + mView.invalidate(); + } + return true; + } + }); + } + + @Override + public String calculateUserMessage(Context context, String effectName, Object parameterValue) { + FilterGradRepresentation rep = getGradRepresentation(); + if (rep == null) { + return mEffectName; + } + int val = rep.getParameter(mSliderMode); + return mEffectName.toUpperCase() + ((val > 0) ? " +" : " ") + val; + } + + private FilterGradRepresentation getGradRepresentation() { + FilterRepresentation tmpRep = getLocalRepresentation(); + if (tmpRep instanceof FilterGradRepresentation) { + return (FilterGradRepresentation) tmpRep; + } + return null; + } + + @Override + public int getMaximum() { + FilterGradRepresentation rep = getGradRepresentation(); + if (rep == null) { + return 0; + } + return rep.getParameterMax(mSliderMode); + } + + @Override + public int getMinimum() { + FilterGradRepresentation rep = getGradRepresentation(); + if (rep == null) { + return 0; + } + return rep.getParameterMin(mSliderMode); + } + + @Override + public int getDefaultValue() { + return 0; + } + + @Override + public int getValue() { + FilterGradRepresentation rep = getGradRepresentation(); + if (rep == null) { + return 0; + } + return rep.getParameter(mSliderMode); + } + + @Override + public String getValueString() { + return null; + } + + @Override + public void setValue(int value) { + FilterGradRepresentation rep = getGradRepresentation(); + if (rep == null) { + return; + } + rep.setParameter(mSliderMode, value); + } + + @Override + public String getParameterName() { + return mEffectName; + } + + @Override + public String getParameterType() { + return sParameterType; + } + + @Override + public void setController(Control c) { + + } + + @Override + public void fireLeftAction() { + FilterGradRepresentation rep = getGradRepresentation(); + if (rep == null) { + return; + } + rep.addBand(MasterImage.getImage().getOriginalBounds()); + updateMenuItems(rep); + updateSeekBar(rep); + + commitLocalRepresentation(); + mView.invalidate(); + } + + @Override + public int getLeftIcon() { + return ADD_ICON; + } + + @Override + public void fireRightAction() { + FilterGradRepresentation rep = getGradRepresentation(); + if (rep == null) { + return; + } + rep.deleteCurrentBand(); + + updateMenuItems(rep); + updateSeekBar(rep); + commitLocalRepresentation(); + mView.invalidate(); + } + + @Override + public int getRightIcon() { + return DEL_ICON; + } + + @Override + public void setFilterView(FilterView editor) { + + } + + @Override + public void copyFrom(Parameter src) { + + } + +} diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java index d140f0d8d..550b9d7fc 100644 --- a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java +++ b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java @@ -121,6 +121,7 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface { 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); @@ -217,6 +218,7 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface { 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)); 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..1bfce6f05 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java @@ -0,0 +1,514 @@ +/* + * 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_colors_vignette); + 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 boolean active = 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; + private boolean inking; + + 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; + active = copy.active; + xPos1 = copy.xPos1; + yPos1 = copy.yPos1; + xPos2 = copy.xPos2; + yPos2 = copy.yPos2; + brightness = copy.brightness; + contrast = copy.contrast; + saturation = copy.saturation; + inking = copy.inking; + } + + } + + @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.active = true; + p.xPos1 = -1; + p.yPos1 = 100; + p.xPos2 = -1; + p.yPos2 = 100; + p.brightness = 40; + p.contrast = 0; + p.saturation = 0; + p.inking = false; + 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) { + return true; // TODO much more extensive equals needed + } + return false; + } + + public int getNumberOfBands() { + int count = 0; + for (Band point : mBands) { + if (!point.mask) { + count++; + } + } + return count; + } + + public void toggleInking() { + mCurrentBand.inking = !mCurrentBand.inking; + } + + public void setInking(boolean on) { + for (Band point : mBands) { + point.inking = false; + } + mCurrentBand.inking = on; + } + + 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 boolean[] getActive() { + boolean[] ret = new boolean[mBands.size()]; + int i = 0; + String s = ""; + for (Band point : mBands) { + ret[i++] = point.active; + s += (point.active) ? "1" : "0"; + } + 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 boolean[] getInking() { + boolean[] ret = new boolean[mBands.size()]; + int i = 0; + for (Band point : mBands) { + ret[i++] = point.inking; + } + 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/ImageFilterGrad.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java new file mode 100644 index 000000000..e5e9f13f5 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java @@ -0,0 +1,201 @@ +/* + * 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); + } + + private boolean hasInk() { + boolean[] ink = mParameters.getInking(); + for (int i = 0; i < ink.length; i++) { + if (ink[i]) + return true; + } + return false; + } + + @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_active(mParameters.getActive()); + 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.set_inking(mParameters.getInking()); + + 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/grad.rs b/src/com/android/gallery3d/filtershow/filters/grad.rs new file mode 100644 index 000000000..42e1e5faf --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/grad.rs @@ -0,0 +1,131 @@ +/* + * 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 { + bool active; + bool inking; + rs_matrix3x3 colorMatrix; + float rgbOff; + float dx; + float dy; + float off; +} UPointData; +int mNumberOfLines; +// input data +bool mask[MAX_POINTS]; +bool active[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]; +bool inking[MAX_POINTS]; + + +// generated data +static UPointData grads[MAX_POINTS]; + +void setupGradParams() { + int k = 0; + for (int i = 0; i < MAX_POINTS; i++) { + grads[i].active = false; + 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) { + grads[i].active = false; + 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)); + + + grads[k].active = true; + grads[k].inking = inking[i]; + 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/imageshow/GradControl.java b/src/com/android/gallery3d/filtershow/imageshow/GradControl.java new file mode 100644 index 000000000..964da99e9 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/imageshow/GradControl.java @@ -0,0 +1,274 @@ +/* + * 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.imageshow; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.DashPathEffect; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RadialGradient; +import android.graphics.Rect; +import android.graphics.Shader; + +import com.android.gallery3d.R; + +public class GradControl { + private float mPoint1X = Float.NaN; // used to flag parameters have not been set + private float mPoint1Y = 0; + private float mPoint2X = 200; + private float mPoint2Y = 300; + private int mMinTouchDist = 80;// should be a resource & in dips + + private float[] handlex = new float[3]; + private float[] handley = new float[3]; + private int mSliderColor; + private int mCenterDotSize; + private float mDownX; + private float mDownY; + private float mDownPoint1X; + private float mDownPoint1Y; + private float mDownPoint2X; + private float mDownPoint2Y; + Rect mImageBounds; + int mImageHeight; + private Matrix mScrToImg; + Paint mPaint = new Paint(); + DashPathEffect mDash = new DashPathEffect(new float[]{30, 30}, 0); + private boolean mShowReshapeHandles = true; + public final static int HAN_CENTER = 0; + public final static int HAN_NORTH = 2; + public final static int HAN_SOUTH = 1; + private int[] mPointColorPatern; + private int[] mGrayPointColorPatern; + private float[] mPointRadialPos = new float[]{0, .3f, .31f, 1}; + private int mLineColor; + private int mlineShadowColor; + + public GradControl(Context context) { + + Resources res = context.getResources(); + mCenterDotSize = (int) res.getDimension(R.dimen.gradcontrol_dot_size); + mMinTouchDist = (int) res.getDimension(R.dimen.gradcontrol_min_touch_dist); + int grayPointCenterColor = res.getColor(R.color.gradcontrol_graypoint_center); + int grayPointEdgeColor = res.getColor(R.color.gradcontrol_graypoint_edge); + int pointCenterColor = res.getColor(R.color.gradcontrol_point_center); + int pointEdgeColor = res.getColor(R.color.gradcontrol_point_edge); + int pointShadowStartColor = res.getColor(R.color.gradcontrol_point_shadow_start); + int pointShadowEndColor = res.getColor(R.color.gradcontrol_point_shadow_end); + mPointColorPatern = new int[]{ + pointCenterColor, pointEdgeColor, pointShadowStartColor, pointShadowEndColor}; + mGrayPointColorPatern = new int[]{ + grayPointCenterColor, grayPointEdgeColor, pointShadowStartColor, pointShadowEndColor}; + mSliderColor = Color.WHITE; + mLineColor = res.getColor(R.color.gradcontrol_line_color); + mlineShadowColor = res.getColor(R.color.gradcontrol_line_shadow); + } + + public void setPoint2(float x, float y) { + mPoint2X = x; + mPoint2Y = y; + } + + public void setPoint1(float x, float y) { + mPoint1X = x; + mPoint1Y = y; + } + + public int getCloseHandle(float x, float y) { + float min = Float.MAX_VALUE; + int handle = -1; + for (int i = 0; i < handlex.length; i++) { + float dx = handlex[i] - x; + float dy = handley[i] - y; + float dist = dx * dx + dy * dy; + if (dist < min) { + min = dist; + handle = i; + } + } + + if (min < mMinTouchDist * mMinTouchDist) { + return handle; + } + for (int i = 0; i < handlex.length; i++) { + float dx = handlex[i] - x; + float dy = handley[i] - y; + float dist = (float) Math.sqrt(dx * dx + dy * dy); + } + + return -1; + } + + public void setScrImageInfo(Matrix scrToImg, Rect imageBounds) { + mScrToImg = scrToImg; + mImageBounds = new Rect(imageBounds); + } + + private boolean centerIsOutside(float x1, float y1, float x2, float y2) { + return (!mImageBounds.contains((int) ((x1 + x2) / 2), (int) ((y1 + y2) / 2))); + } + + public void actionDown(float x, float y, Line line) { + float[] point = new float[]{ + x, y}; + mScrToImg.mapPoints(point); + mDownX = point[0]; + mDownY = point[1]; + mDownPoint1X = line.getPoint1X(); + mDownPoint1Y = line.getPoint1Y(); + mDownPoint2X = line.getPoint2X(); + mDownPoint2Y = line.getPoint2Y(); + } + + public void actionMove(int handle, float x, float y, Line line) { + float[] point = new float[]{ + x, y}; + mScrToImg.mapPoints(point); + x = point[0]; + y = point[1]; + + // Test if the matrix is swapping x and y + point[0] = 0; + point[1] = 1; + mScrToImg.mapVectors(point); + boolean swapxy = (point[0] > 0.0f); + + int sign = 1; + + float dx = x - mDownX; + float dy = y - mDownY; + switch (handle) { + case HAN_CENTER: + if (centerIsOutside(mDownPoint1X + dx, mDownPoint1Y + dy, + mDownPoint2X + dx, mDownPoint2Y + dy)) { + break; + } + line.setPoint1(mDownPoint1X + dx, mDownPoint1Y + dy); + line.setPoint2(mDownPoint2X + dx, mDownPoint2Y + dy); + break; + case HAN_SOUTH: + if (centerIsOutside(mDownPoint1X + dx, mDownPoint1Y + dy, + mDownPoint2X, mDownPoint2Y)) { + break; + } + line.setPoint1(mDownPoint1X + dx, mDownPoint1Y + dy); + break; + case HAN_NORTH: + if (centerIsOutside(mDownPoint1X, mDownPoint1Y, + mDownPoint2X + dx, mDownPoint2Y + dy)) { + break; + } + line.setPoint2(mDownPoint2X + dx, mDownPoint2Y + dy); + break; + } + } + + public void paintGrayPoint(Canvas canvas, float x, float y) { + if (isUndefined()) { + return; + } + + Paint paint = new Paint(); + paint.setStyle(Paint.Style.FILL); + RadialGradient g = new RadialGradient(x, y, mCenterDotSize, mGrayPointColorPatern, + mPointRadialPos, Shader.TileMode.CLAMP); + paint.setShader(g); + canvas.drawCircle(x, y, mCenterDotSize, paint); + } + + public void paintPoint(Canvas canvas, float x, float y) { + if (isUndefined()) { + return; + } + + Paint paint = new Paint(); + paint.setStyle(Paint.Style.FILL); + RadialGradient g = new RadialGradient(x, y, mCenterDotSize, mPointColorPatern, + mPointRadialPos, Shader.TileMode.CLAMP); + paint.setShader(g); + canvas.drawCircle(x, y, mCenterDotSize, paint); + } + + void paintLines(Canvas canvas, float p1x, float p1y, float p2x, float p2y) { + if (isUndefined()) { + return; + } + + mPaint.setAntiAlias(true); + mPaint.setStyle(Paint.Style.STROKE); + + mPaint.setStrokeWidth(6); + mPaint.setColor(mlineShadowColor); + mPaint.setPathEffect(mDash); + paintOvallines(canvas, mPaint, p1x, p1y, p2x, p2y); + + mPaint.setStrokeWidth(3); + mPaint.setColor(mLineColor); + mPaint.setPathEffect(mDash); + paintOvallines(canvas, mPaint, p1x, p1y, p2x, p2y); + } + + public void paintOvallines( + Canvas canvas, Paint paint, float p1x, float p1y, float p2x, float p2y) { + + + + canvas.drawLine(p1x, p1y, p2x, p2y, paint); + + float cx = (p1x + p2x) / 2; + float cy = (p1y + p2y) / 2; + float dx = p1x - p2x; + float dy = p1y - p2y; + float len = (float) Math.sqrt(dx * dx + dy * dy); + dx *= 2048 / len; + dy *= 2048 / len; + + canvas.drawLine(p1x + dy, p1y - dx, p1x - dy, p1y + dx, paint); + canvas.drawLine(p2x + dy, p2y - dx, p2x - dy, p2y + dx, paint); + } + + public void fillHandles(Canvas canvas, float p1x, float p1y, float p2x, float p2y) { + float cx = (p1x + p2x) / 2; + float cy = (p1y + p2y) / 2; + handlex[0] = cx; + handley[0] = cy; + handlex[1] = p1x; + handley[1] = p1y; + handlex[2] = p2x; + handley[2] = p2y; + + } + + public void draw(Canvas canvas) { + paintLines(canvas, mPoint1X, mPoint1Y, mPoint2X, mPoint2Y); + fillHandles(canvas, mPoint1X, mPoint1Y, mPoint2X, mPoint2Y); + paintPoint(canvas, mPoint2X, mPoint2Y); + paintPoint(canvas, mPoint1X, mPoint1Y); + paintPoint(canvas, (mPoint1X + mPoint2X) / 2, (mPoint1Y + mPoint2Y) / 2); + } + + public boolean isUndefined() { + return Float.isNaN(mPoint1X); + } + + public void setShowReshapeHandles(boolean showReshapeHandles) { + this.mShowReshapeHandles = showReshapeHandles; + } +} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java b/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java new file mode 100644 index 000000000..ef72e8a6e --- /dev/null +++ b/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java @@ -0,0 +1,218 @@ +package com.android.gallery3d.filtershow.imageshow; +/* + * 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. + */ + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import com.android.gallery3d.R; +import com.android.gallery3d.filtershow.editors.EditorGrad; +import com.android.gallery3d.filtershow.filters.FilterGradRepresentation; + +public class ImageGrad extends ImageShow { + private static final String LOGTAG = "ImageGrad"; + private FilterGradRepresentation mGradRep; + private EditorGrad mEditorGrad; + private int mMinTouchDist; + private int mActiveHandle = -1; + private GradControl mEllipse; + + Matrix mToScr = new Matrix(); + float[] mPointsX = new float[FilterGradRepresentation.MAX_POINTS]; + float[] mPointsY = new float[FilterGradRepresentation.MAX_POINTS]; + + public ImageGrad(Context context) { + super(context); + Resources res = context.getResources(); + mMinTouchDist = res.getDimensionPixelSize(R.dimen.gradcontrol_min_touch_dist); + mEllipse = new GradControl(context); + mEllipse.setShowReshapeHandles(false); + } + + public ImageGrad(Context context, AttributeSet attrs) { + super(context, attrs); + mEllipse = new GradControl(context); + mEllipse.setShowReshapeHandles(false); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int mask = event.getActionMasked(); + + if (mask == MotionEvent.ACTION_DOWN || mask == MotionEvent.ACTION_UP) { + mGradRep.setInking(MotionEvent.ACTION_DOWN == mask); + } + + if (mActiveHandle == -1) { + if (MotionEvent.ACTION_DOWN != mask) { + return super.onTouchEvent(event); + } + if (event.getPointerCount() == 1) { + mActiveHandle = mEllipse.getCloseHandle(event.getX(), event.getY()); + if (mActiveHandle == -1) { + float x = event.getX(); + float y = event.getY(); + float min_d = Float.MAX_VALUE; + int pos = -1; + for (int i = 0; i < mPointsX.length; i++) { + if (mPointsX[i] == -1) { + continue; + } + float d = (float) Math.hypot(x - mPointsX[i], y - mPointsY[i]); + if ( min_d > d) { + min_d = d; + pos = i; + } + } + if (min_d > mMinTouchDist){ + pos = -1; + } + + if (pos != -1) { + mGradRep.setSelectedPoint(pos); + mGradRep.setInking(true); + resetImageCaches(this); + mEditorGrad.updateSeekBar(mGradRep); + mEditorGrad.commitLocalRepresentation(); + invalidate(); + } + } + } + if (mActiveHandle == -1) { + return super.onTouchEvent(event); + } + } else { + switch (mask) { + case MotionEvent.ACTION_UP: { + + mActiveHandle = -1; + break; + } + case MotionEvent.ACTION_DOWN: { + break; + } + } + } + float x = event.getX(); + float y = event.getY(); + + mEllipse.setScrImageInfo(getScreenToImageMatrix(true), + MasterImage.getImage().getOriginalBounds()); + + switch (mask) { + case (MotionEvent.ACTION_DOWN): { + mEllipse.actionDown(x, y, mGradRep); + break; + } + case (MotionEvent.ACTION_UP): + case (MotionEvent.ACTION_MOVE): { + mEllipse.actionMove(mActiveHandle, x, y, mGradRep); + setRepresentation(mGradRep); + break; + } + } + invalidate(); + mEditorGrad.commitLocalRepresentation(); + return true; + } + + public void setRepresentation(FilterGradRepresentation pointRep) { + mGradRep = pointRep; + Matrix toImg = getScreenToImageMatrix(false); + + toImg.invert(mToScr); + + float[] c1 = new float[] { mGradRep.getPoint1X(), mGradRep.getPoint1Y() }; + float[] c2 = new float[] { mGradRep.getPoint2X(), mGradRep.getPoint2Y() }; + + if (c1[0] == -1) { + float cx = MasterImage.getImage().getOriginalBounds().width() / 2; + float cy = MasterImage.getImage().getOriginalBounds().height() / 2; + float rx = Math.min(cx, cy) * .4f; + + mGradRep.setPoint1(cx, cy-rx); + mGradRep.setPoint2(cx, cy+rx); + c1[0] = cx; + c1[1] = cy-rx; + mToScr.mapPoints(c1); + if (getWidth() != 0) { + mEllipse.setPoint1(c1[0], c1[1]); + c2[0] = cx; + c2[1] = cy+rx; + mToScr.mapPoints(c2); + mEllipse.setPoint2(c2[0], c2[1]); + } + mEditorGrad.commitLocalRepresentation(); + } else { + mToScr.mapPoints(c1); + mToScr.mapPoints(c2); + mEllipse.setPoint1(c1[0], c1[1]); + mEllipse.setPoint2(c2[0], c2[1]); + } + } + + public void drawOtherPoints(Canvas canvas) { + computCenterLocations(); + for (int i = 0; i < mPointsX.length; i++) { + if (mPointsX[i] != -1) { + mEllipse.paintGrayPoint(canvas, mPointsX[i], mPointsY[i]); + } + } + } + + public void computCenterLocations() { + int x1[] = mGradRep.getXPos1(); + int y1[] = mGradRep.getYPos1(); + int x2[] = mGradRep.getXPos2(); + int y2[] = mGradRep.getYPos2(); + int selected = mGradRep.getSelectedPoint(); + boolean m[] = mGradRep.getMask(); + float[] c = new float[2]; + for (int i = 0; i < m.length; i++) { + if (selected == i || !m[i]) { + mPointsX[i] = -1; + continue; + } + + c[0] = (x1[i]+x2[i])/2; + c[1] = (y1[i]+y2[i])/2; + mToScr.mapPoints(c); + + mPointsX[i] = c[0]; + mPointsY[i] = c[1]; + } + } + + public void setEditor(EditorGrad editorGrad) { + mEditorGrad = editorGrad; + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (mGradRep == null) { + return; + } + setRepresentation(mGradRep); + mEllipse.draw(canvas); + drawOtherPoints(canvas); + } + +} diff --git a/src/com/android/gallery3d/filtershow/imageshow/Line.java b/src/com/android/gallery3d/filtershow/imageshow/Line.java new file mode 100644 index 000000000..a767bd809 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/imageshow/Line.java @@ -0,0 +1,26 @@ +/* + * 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.imageshow; + +public interface Line { + void setPoint1(float x, float y); + void setPoint2(float x, float y); + float getPoint1X(); + float getPoint1Y(); + float getPoint2X(); + float getPoint2Y(); +} |