OSDN Git Service

add Per Channel Saturation
authorJohn Hoford <hoford@google.com>
Tue, 30 Jul 2013 21:40:18 +0000 (14:40 -0700)
committerJohn Hoford <hoford@google.com>
Thu, 1 Aug 2013 23:13:52 +0000 (16:13 -0700)
Change-Id: Icfd24c817674b81ac9caecc2d73348dc7734f037

13 files changed:
res/menu/filtershow_menu_chan_sat.xml [new file with mode: 0644]
res/values/filtershow_ids.xml
res/values/filtershow_strings.xml
src/com/android/gallery3d/filtershow/FilterShowActivity.java
src/com/android/gallery3d/filtershow/controller/BasicParameterInt.java
src/com/android/gallery3d/filtershow/editors/EditorChanSat.java [new file with mode: 0644]
src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java [new file with mode: 0644]
src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java
src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java [new file with mode: 0644]
src/com/android/gallery3d/filtershow/filters/saturation.rs [new file with mode: 0644]
src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java

diff --git a/res/menu/filtershow_menu_chan_sat.xml b/res/menu/filtershow_menu_chan_sat.xml
new file mode 100644 (file)
index 0000000..eae559d
--- /dev/null
@@ -0,0 +1,43 @@
+<!--
+     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_chan_sat_main"
+            android:title="@string/editor_chan_sat_main"/>
+        <item
+            android:id="@+id/editor_chan_sat_red"
+            android:title="@string/editor_chan_sat_red"/>
+        <item
+            android:id="@+id/editor_chan_sat_yellow"
+            android:title="@string/editor_chan_sat_yellow"/>
+        <item
+            android:id="@+id/editor_chan_sat_green"
+            android:title="@string/editor_chan_sat_green"/>
+       <item
+            android:id="@+id/editor_chan_sat_cyan"
+            android:title="@string/editor_chan_sat_cyan"/>
+        <item
+            android:id="@+id/editor_chan_sat_blue"
+            android:title="@string/editor_chan_sat_blue"/>
+        <item
+            android:id="@+id/editor_chan_sat_magenta"
+            android:title="@string/editor_chan_sat_magenta"/>
+    </group>
+
+</menu>
\ No newline at end of file
index e57a0d5..b315d12 100644 (file)
@@ -48,4 +48,5 @@
     <item type="id" name="editorStraighten" />
     <item type="id" name="editorParametric" />
     <item type="id" name="editorGrad" />
+    <item type="id" name="editorChanSat" />
 </resources>
index a820871..68eca34 100644 (file)
     <string name="editor_grad_contrast">Contrast</string>
     <!--  Label for the saturation effect  [CHAR LIMIT=20] -->
     <string name="editor_grad_saturation">Saturation</string>
-
+    <!--  Label for the Main or Master control for per channel saturation effect [CHAR LIMIT=20] -->
+    <string name="editor_chan_sat_main">Main</string>
+    <!--  Label for the red control for per channel saturation effect [CHAR LIMIT=20] -->
+    <string name="editor_chan_sat_red">Red</string>
+    <!--  Label for the yellow control for per channel saturation effect [CHAR LIMIT=20] -->
+    <string name="editor_chan_sat_yellow">Yellow</string>
+    <!--  Label for the green control for per channel saturation effect [CHAR LIMIT=20] -->
+    <string name="editor_chan_sat_green">Green</string>
+    <!--  Label for the cyan control for per channel saturation effect [CHAR LIMIT=20] -->
+    <string name="editor_chan_sat_cyan">Cyan</string>
+    <!--  Label for the blue control for per channel saturation effect [CHAR LIMIT=20] -->
+    <string name="editor_chan_sat_blue">Blue</string>
+    <!--  Label for the Magenta control for per channel saturation effect [CHAR LIMIT=20] -->
+    <string name="editor_chan_sat_magenta">Magenta</string>
     <!--  Label for the image graduated filter effect  [CHAR LIMIT=20] -->
     <string name="editor_grad_style">Style</string>
     <!--  Label for the image new grad layer  [CHAR LIMIT=20] -->
index f0b1aa8..ab508b6 100644 (file)
@@ -59,6 +59,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.EditorChanSat;
 import com.android.gallery3d.filtershow.editors.EditorGrad;
 import com.android.gallery3d.filtershow.data.FilterStackSource;
 import com.android.gallery3d.filtershow.data.UserPresetsManager;
@@ -386,6 +387,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
     }
 
     private void fillEditors() {
+        mEditorPlaceHolder.addEditor(new EditorChanSat());
         mEditorPlaceHolder.addEditor(new EditorGrad());
         mEditorPlaceHolder.addEditor(new EditorDraw());
         mEditorPlaceHolder.addEditor(new BasicEditor());
index 777bc43..92145e9 100644 (file)
@@ -45,6 +45,14 @@ public class BasicParameterInt implements ParameterInteger {
         ID = id;
         mValue = value;
     }
+
+    public BasicParameterInt(int id, int value, int min, int max) {
+        ID = id;
+        mValue = value;
+        mMinimum = min;
+        mMaximum = max;
+    }
+
     @Override
     public String getParameterName() {
         return mParameterName;
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java b/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java
new file mode 100644 (file)
index 0000000..7e31f09
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * 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.graphics.Bitmap;
+import android.os.Handler;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.LinearLayout;
+import android.widget.PopupMenu;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.controller.BasicParameterStyle;
+import com.android.gallery3d.filtershow.controller.FilterView;
+import com.android.gallery3d.filtershow.controller.Parameter;
+import com.android.gallery3d.filtershow.filters.FilterChanSatRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+import com.android.gallery3d.filtershow.pipeline.RenderingRequest;
+import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
+
+public class EditorChanSat extends ParametricEditor implements OnSeekBarChangeListener, FilterView {
+    public static final int ID = R.id.editorChanSat;
+    private final String LOGTAG = "EditorGrunge";
+    private SwapButton mButton;
+    private final Handler mHandler = new Handler();
+
+    int[] mMenuStrings = {
+            R.string.editor_chan_sat_main,
+            R.string.editor_chan_sat_red,
+            R.string.editor_chan_sat_yellow,
+            R.string.editor_chan_sat_green,
+            R.string.editor_chan_sat_cyan,
+            R.string.editor_chan_sat_blue,
+            R.string.editor_chan_sat_magenta
+    };
+
+    String mCurrentlyEditing = null;
+
+    public EditorChanSat() {
+        super(ID, R.layout.filtershow_default_editor, R.id.basicEditor);
+    }
+
+    @Override
+    public String calculateUserMessage(Context context, String effectName, Object parameterValue) {
+        FilterRepresentation rep = getLocalRepresentation();
+        if (rep == null || !(rep instanceof FilterChanSatRepresentation)) {
+            return "";
+        }
+        FilterChanSatRepresentation csrep = (FilterChanSatRepresentation) 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.editor_chan_sat_main));
+
+        final PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), mButton);
+
+        popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_chan_sat, popupMenu.getMenu());
+
+        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+            @Override
+            public boolean onMenuItemClick(MenuItem item) {
+                selectMenuItem(item);
+                return true;
+            }
+        });
+        mButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View arg0) {
+                popupMenu.show();
+            }
+        });
+        mButton.setListener(this);
+
+        FilterChanSatRepresentation csrep = getChanSatRep();
+        String menuString = mContext.getString(mMenuStrings[0]);
+        switchToMode(csrep, FilterChanSatRepresentation.MODE_MASTER, menuString);
+
+    }
+
+    public int getParameterIndex(int id) {
+        switch (id) {
+            case R.id.editor_chan_sat_main:
+                return FilterChanSatRepresentation.MODE_MASTER;
+            case R.id.editor_chan_sat_red:
+                return FilterChanSatRepresentation.MODE_RED;
+            case R.id.editor_chan_sat_yellow:
+                return FilterChanSatRepresentation.MODE_YELLOW;
+            case R.id.editor_chan_sat_green:
+                return FilterChanSatRepresentation.MODE_GREEN;
+            case R.id.editor_chan_sat_cyan:
+                return FilterChanSatRepresentation.MODE_CYAN;
+            case R.id.editor_chan_sat_blue:
+                return FilterChanSatRepresentation.MODE_BLUE;
+            case R.id.editor_chan_sat_magenta:
+                return FilterChanSatRepresentation.MODE_MAGENTA;
+        }
+        return -1;
+    }
+
+    @Override
+    public void detach() {
+        mButton.setListener(null);
+        mButton.setOnClickListener(null);
+    }
+
+    private void updateSeekBar(FilterChanSatRepresentation rep) {
+        mControl.updateUI();
+    }
+
+    @Override
+    protected Parameter getParameterToEdit(FilterRepresentation rep) {
+        if (rep instanceof FilterChanSatRepresentation) {
+            FilterChanSatRepresentation csrep = (FilterChanSatRepresentation) rep;
+            Parameter param = csrep.getFilterParameter(csrep.getParameterMode());
+            if (param instanceof BasicParameterStyle) {
+                param.setFilterView(EditorChanSat.this);
+            }
+            return param;
+        }
+        return null;
+    }
+
+    private FilterChanSatRepresentation getChanSatRep() {
+        FilterRepresentation rep = getLocalRepresentation();
+        if (rep != null
+                && rep instanceof FilterChanSatRepresentation) {
+            FilterChanSatRepresentation csrep = (FilterChanSatRepresentation) rep;
+            return csrep;
+        }
+        return null;
+    }
+
+    @Override
+    public void computeIcon(int n, RenderingRequestCaller caller) {
+        FilterChanSatRepresentation rep = getChanSatRep();
+        if (rep == null) return;
+        rep = (FilterChanSatRepresentation) rep.copy();
+        ImagePreset preset = new ImagePreset();
+        preset.addFilter(rep);
+        Bitmap src = MasterImage.getImage().getThumbnailBitmap();
+        RenderingRequest.post(null, src, preset, RenderingRequest.STYLE_ICON_RENDERING,
+                caller);
+    }
+
+    protected void selectMenuItem(MenuItem item) {
+        if (getLocalRepresentation() != null
+                && getLocalRepresentation() instanceof FilterChanSatRepresentation) {
+            FilterChanSatRepresentation csrep =
+                    (FilterChanSatRepresentation) getLocalRepresentation();
+
+            switchToMode(csrep, getParameterIndex(item.getItemId()), item.getTitle().toString());
+
+        }
+    }
+
+    protected void switchToMode(FilterChanSatRepresentation csrep, int mode, String title) {
+        csrep.setParameterMode(mode);
+        mCurrentlyEditing = title;
+        mButton.setText(mCurrentlyEditing);
+        {
+            Parameter param = getParameterToEdit(csrep);
+
+            control(param, mEditControl);
+        }
+        updateSeekBar(csrep);
+        mView.invalidate();
+    }
+
+    @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);
+    }
+}
index 4708abb..3fa9191 100644 (file)
@@ -133,6 +133,7 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
         filters.add(ImageFilterCurves.class);
         filters.add(ImageFilterDraw.class);
         filters.add(ImageFilterHue.class);
+        filters.add(ImageFilterChanSat.class);
         filters.add(ImageFilterSaturated.class);
         filters.add(ImageFilterBwFilter.class);
         filters.add(ImageFilterNegative.class);
@@ -232,7 +233,7 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
         mEffects.add(getRepresentation(ImageFilterSharpen.class));
         mEffects.add(getRepresentation(ImageFilterCurves.class));
         mEffects.add(getRepresentation(ImageFilterHue.class));
-        mEffects.add(getRepresentation(ImageFilterSaturated.class));
+        mEffects.add(getRepresentation(ImageFilterChanSat.class));
         mEffects.add(getRepresentation(ImageFilterBwFilter.class));
         mEffects.add(getRepresentation(ImageFilterNegative.class));
         mEffects.add(getRepresentation(ImageFilterEdge.class));
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java
new file mode 100644 (file)
index 0000000..7ce67dd
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.controller.BasicParameterInt;
+import com.android.gallery3d.filtershow.controller.Parameter;
+import com.android.gallery3d.filtershow.controller.ParameterSet;
+import com.android.gallery3d.filtershow.editors.EditorChanSat;
+import com.android.gallery3d.filtershow.imageshow.ControlPoint;
+import com.android.gallery3d.filtershow.imageshow.Spline;
+
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * Representation for a filter that has per channel & Master saturation
+ */
+public class FilterChanSatRepresentation extends FilterRepresentation implements ParameterSet {
+    private static final String LOGTAG = "FilterChanSatRepresentation";
+    private static final String ARGS = "ARGS";
+    private static final String SERIALIZATION_NAME = "channelsaturation";
+
+    public static final int MODE_MASTER = 0;
+    public static final int MODE_RED = 1;
+    public static final int MODE_YELLOW = 2;
+    public static final int MODE_GREEN = 3;
+    public static final int MODE_CYAN = 4;
+    public static final int MODE_BLUE = 5;
+    public static final int MODE_MAGENTA = 6;
+    private int mParameterMode = MODE_MASTER;
+
+    private static int MINSAT = -100;
+    private static int MAXSAT = 100;
+    private BasicParameterInt mParamMaster = new BasicParameterInt(MODE_MASTER, 0, MINSAT, MAXSAT);
+    private BasicParameterInt mParamRed = new BasicParameterInt(MODE_RED, 0, MINSAT, MAXSAT);
+    private BasicParameterInt mParamYellow = new BasicParameterInt(MODE_YELLOW, 0, MINSAT, MAXSAT);
+    private BasicParameterInt mParamGreen = new BasicParameterInt(MODE_GREEN, 0, MINSAT, MAXSAT);
+    private BasicParameterInt mParamCyan = new BasicParameterInt(MODE_CYAN, 0, MINSAT, MAXSAT);
+    private BasicParameterInt mParamBlue = new BasicParameterInt(MODE_BLUE, 0, MINSAT, MAXSAT);
+    private BasicParameterInt mParamMagenta = new BasicParameterInt(MODE_MAGENTA, 0, MINSAT, MAXSAT);
+
+    private BasicParameterInt[] mAllParam = {
+            mParamMaster,
+            mParamRed,
+            mParamYellow,
+            mParamGreen,
+            mParamCyan,
+            mParamBlue,
+            mParamMagenta};
+
+    public FilterChanSatRepresentation() {
+        super("ChannelSaturation");
+        setTextId(R.string.saturation);
+        setFilterType(FilterRepresentation.TYPE_NORMAL);
+        setSerializationName(SERIALIZATION_NAME);
+        setFilterClass(ImageFilterChanSat.class);
+        setEditorId(EditorChanSat.ID);
+    }
+
+    public String toString() {
+        return getName() + " : " + mParamRed + ", " + mParamCyan + ", " + mParamRed
+                + ", " + mParamGreen + ", " + mParamMaster + ", " + mParamYellow;
+    }
+
+    @Override
+    public FilterRepresentation copy() {
+        FilterChanSatRepresentation representation = new FilterChanSatRepresentation();
+        copyAllParameters(representation);
+        return representation;
+    }
+
+    @Override
+    protected void copyAllParameters(FilterRepresentation representation) {
+        super.copyAllParameters(representation);
+        representation.useParametersFrom(this);
+    }
+
+    public void useParametersFrom(FilterRepresentation a) {
+        if (a instanceof FilterChanSatRepresentation) {
+            FilterChanSatRepresentation representation = (FilterChanSatRepresentation) a;
+
+            for (int i = 0; i < mAllParam.length; i++) {
+                mAllParam[i].copyFrom(representation.mAllParam[i]);
+            }
+        }
+    }
+
+    @Override
+    public boolean equals(FilterRepresentation representation) {
+        if (!super.equals(representation)) {
+            return false;
+        }
+        if (representation instanceof FilterChanSatRepresentation) {
+            FilterChanSatRepresentation rep = (FilterChanSatRepresentation) representation;
+            for (int i = 0; i < mAllParam.length; i++) {
+                if (rep.getValue(i) != getValue(i))
+                    return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public int getValue(int mode) {
+        return mAllParam[mode].getValue();
+    }
+
+    public void setValue(int mode, int value) {
+        mAllParam[mode].setValue(value);
+    }
+
+    public int getMinimum() {
+        return mParamMaster.getMinimum();
+    }
+
+    public int getMaximum() {
+        return mParamMaster.getMaximum();
+    }
+
+    public int getParameterMode() {
+        return mParameterMode;
+    }
+
+    public void setParameterMode(int parameterMode) {
+        mParameterMode = parameterMode;
+    }
+
+    public int getCurrentParameter() {
+        return getValue(mParameterMode);
+    }
+
+    public void setCurrentParameter(int value) {
+        setValue(mParameterMode, value);
+    }
+
+    @Override
+    public int getNumberOfParameters() {
+        return 6;
+    }
+
+    @Override
+    public Parameter getFilterParameter(int index) {
+        return mAllParam[index];
+    }
+
+    @Override
+    public void serializeRepresentation(JsonWriter writer) throws IOException {
+        writer.beginObject();
+
+        writer.name(ARGS);
+        writer.beginArray();
+        writer.value(getValue(MODE_MASTER));
+        writer.value(getValue(MODE_RED));
+        writer.value(getValue(MODE_YELLOW));
+        writer.value(getValue(MODE_GREEN));
+        writer.value(getValue(MODE_CYAN));
+        writer.value(getValue(MODE_BLUE));
+        writer.value(getValue(MODE_MAGENTA));
+        writer.endArray();
+        writer.endObject();
+    }
+
+    @Override
+    public void deSerializeRepresentation(JsonReader sreader) throws IOException {
+        sreader.beginObject();
+
+        while (sreader.hasNext()) {
+            String name = sreader.nextName();
+            if (name.startsWith(ARGS)) {
+                sreader.beginArray();
+                sreader.hasNext();
+                setValue(MODE_MASTER, sreader.nextInt());
+                sreader.hasNext();
+                setValue(MODE_RED, sreader.nextInt());
+                sreader.hasNext();
+                setValue(MODE_YELLOW, sreader.nextInt());
+                sreader.hasNext();
+                setValue(MODE_GREEN, sreader.nextInt());
+                sreader.hasNext();
+                setValue(MODE_CYAN, sreader.nextInt());
+                sreader.hasNext();
+                setValue(MODE_BLUE, sreader.nextInt());
+                sreader.hasNext();
+                setValue(MODE_MAGENTA, sreader.nextInt());
+                sreader.hasNext();
+                sreader.endArray();
+            } else {
+                sreader.skipValue();
+            }
+        }
+        sreader.endObject();
+    }
+}
\ No newline at end of file
index 64e7fb0..0c272d4 100644 (file)
@@ -419,7 +419,6 @@ public class FilterGradRepresentation extends FilterRepresentation
     public float getPoint1Y() {
         return mCurrentBand.yPos1;
     }
-
     @Override
     public float getPoint2X() {
         return mCurrentBand.xPos2;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java
new file mode 100644 (file)
index 0000000..1ea8edf
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.support.v8.renderscript.Allocation;
+import android.support.v8.renderscript.Element;
+import android.support.v8.renderscript.RenderScript;
+import android.support.v8.renderscript.Script.LaunchOptions;
+import android.support.v8.renderscript.Type;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+
+public class ImageFilterChanSat extends ImageFilterRS {
+    private static final String LOGTAG = "ImageFilterChanSat";
+    private ScriptC_saturation mScript;
+    private Bitmap mSourceBitmap;
+
+    private static final int STRIP_SIZE = 64;
+
+    FilterChanSatRepresentation mParameters = new FilterChanSatRepresentation();
+    private Bitmap mOverlayBitmap;
+
+    public ImageFilterChanSat() {
+        mName = "ChannelSat";
+    }
+
+    @Override
+    public FilterRepresentation getDefaultRepresentation() {
+        return new FilterChanSatRepresentation();
+    }
+
+    @Override
+    public void useRepresentation(FilterRepresentation representation) {
+        mParameters = (FilterChanSatRepresentation) representation;
+    }
+
+    @Override
+    protected void resetAllocations() {
+
+    }
+
+    @Override
+    public void resetScripts() {
+        if (mScript != null) {
+            mScript.destroy();
+            mScript = null;
+        }
+    }
+    @Override
+    protected void createFilter(android.content.res.Resources res, float scaleFactor,
+                                int quality) {
+        createFilter(res, scaleFactor, quality, getInPixelsAllocation());
+    }
+
+    @Override
+    protected void createFilter(android.content.res.Resources res, float scaleFactor,
+                                int quality, Allocation in) {
+        RenderScript rsCtx = getRenderScriptContext();
+
+        Type.Builder tb_float = new Type.Builder(rsCtx, Element.F32_4(rsCtx));
+        tb_float.setX(in.getType().getX());
+        tb_float.setY(in.getType().getY());
+        mScript = new ScriptC_saturation(rsCtx, res, R.raw.saturation);
+    }
+
+
+    private Bitmap getSourceBitmap() {
+        assert (mSourceBitmap != null);
+        return mSourceBitmap;
+    }
+
+    @Override
+    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+        if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) {
+            return bitmap;
+        }
+
+        mSourceBitmap = bitmap;
+        Bitmap ret = super.apply(bitmap, scaleFactor, quality);
+        mSourceBitmap = null;
+
+        return ret;
+    }
+
+    @Override
+    protected void bindScriptValues() {
+        int width = getInPixelsAllocation().getType().getX();
+        int height = getInPixelsAllocation().getType().getY();
+    }
+
+
+
+    @Override
+    protected void runFilter() {
+        int []sat = new int[7];
+        for(int i = 0;i<sat.length ;i ++){
+          sat[i] =   mParameters.getValue(i);
+        }
+
+
+        int width = getInPixelsAllocation().getType().getX();
+        int height = getInPixelsAllocation().getType().getY();
+        Matrix m = getOriginalToScreenMatrix(width, height);
+
+
+        mScript.set_saturation(sat);
+
+        mScript.invoke_setupGradParams();
+        runSelectiveAdjust(
+                getInPixelsAllocation(), getOutPixelsAllocation());
+
+    }
+
+    private void runSelectiveAdjust(Allocation in, Allocation out) {
+        int width = in.getType().getX();
+        int height = in.getType().getY();
+
+        LaunchOptions options = new LaunchOptions();
+        int ty;
+        options.setX(0, width);
+
+        for (ty = 0; ty < height; ty += STRIP_SIZE) {
+            int endy = ty + STRIP_SIZE;
+            if (endy > height) {
+                endy = height;
+            }
+            options.setY(ty, endy);
+            mScript.forEach_selectiveAdjust(in, out, options);
+            if (checkStop()) {
+                return;
+            }
+        }
+    }
+
+    private boolean checkStop() {
+        RenderScript rsCtx = getRenderScriptContext();
+        rsCtx.finish();
+        if (getEnvironment().needsStop()) {
+            return true;
+        }
+        return false;
+    }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/filters/saturation.rs b/src/com/android/gallery3d/filtershow/filters/saturation.rs
new file mode 100644 (file)
index 0000000..5210e34
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2012 Unknown
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
+
+#define MAX_CHANELS 7
+#define MAX_HUE 4096
+static const int ABITS = 4;
+static const int HSCALE = 256;
+static const int k1=255 << ABITS;
+static const int k2=HSCALE << ABITS;
+
+static const float Rf = 0.2999f;
+static const float Gf = 0.587f;
+static const float Bf = 0.114f;
+
+rs_matrix3x3 colorMatrix_min;
+rs_matrix3x3 colorMatrix_max;
+
+int mNumberOfLines;
+// input data
+int saturation[MAX_CHANELS];
+float sat[MAX_CHANELS];
+
+float satLut[MAX_HUE];
+// generated data
+
+
+void setupGradParams() {
+
+    int master = saturation[0];
+    int max = master+saturation[1];
+    int min = max;
+
+    // calculate the minimum and maximum saturation
+    for (int i = 1; i < MAX_CHANELS; i++) {
+       int v = master+saturation[i];
+       if (max < v) {
+         max = v;
+       }
+       else if (min > v) {
+         min = v;
+       }
+    }
+    // generate a lookup table for all hue 0 to 4K  which goes from 0 to 1 0=min sat 1 = max sat
+    min = min - 1;
+    for(int i = 0; i < MAX_HUE ; i++) {
+       float p =  i * 6 / (float)MAX_HUE;
+       int ip = ((int)(p + .5f)) % 6;
+       int v = master + saturation[ip + 1];
+       satLut[i] = (v - min)/(float)(max - min);
+    }
+
+    float S = 1 + max / 100.f;
+    float MS = 1 - S;
+    float Rt = Rf * MS;
+    float Gt = Gf * MS;
+    float Bt = Bf * MS;
+    float b = 1.f;
+
+    // Generate 2 color matrix one at min sat and one at max
+    rsMatrixSet(&colorMatrix_max, 0, 0, b * (Rt + S));
+    rsMatrixSet(&colorMatrix_max, 1, 0, b * Gt);
+    rsMatrixSet(&colorMatrix_max, 2, 0, b * Bt);
+    rsMatrixSet(&colorMatrix_max, 0, 1, b * Rt);
+    rsMatrixSet(&colorMatrix_max, 1, 1, b * (Gt + S));
+    rsMatrixSet(&colorMatrix_max, 2, 1, b * Bt);
+    rsMatrixSet(&colorMatrix_max, 0, 2, b * Rt);
+    rsMatrixSet(&colorMatrix_max, 1, 2, b * Gt);
+    rsMatrixSet(&colorMatrix_max, 2, 2, b * (Bt + S));
+
+    S = 1 + min / 100.f;
+    MS = 1-S;
+    Rt = Rf * MS;
+    Gt = Gf * MS;
+    Bt = Bf * MS;
+    b = 1;
+
+    rsMatrixSet(&colorMatrix_min, 0, 0, b * (Rt + S));
+    rsMatrixSet(&colorMatrix_min, 1, 0, b * Gt);
+    rsMatrixSet(&colorMatrix_min, 2, 0, b * Bt);
+    rsMatrixSet(&colorMatrix_min, 0, 1, b * Rt);
+    rsMatrixSet(&colorMatrix_min, 1, 1, b * (Gt + S));
+    rsMatrixSet(&colorMatrix_min, 2, 1, b * Bt);
+    rsMatrixSet(&colorMatrix_min, 0, 2, b * Rt);
+    rsMatrixSet(&colorMatrix_min, 1, 2, b * Gt);
+    rsMatrixSet(&colorMatrix_min, 2, 2, b * (Bt + S));
+}
+
+static ushort rgb2hue( uchar4 rgb)
+{
+    int iMin,iMax,chroma;
+
+    int ri = rgb.r;
+    int gi = rgb.g;
+    int bi = rgb.b;
+    short rv,rs,rh;
+
+    if (ri > gi) {
+        iMax = max (ri, bi);
+        iMin = min (gi, bi);
+    } else {
+        iMax = max (gi, bi);
+        iMin = min (ri, bi);
+    }
+
+    rv = (short) (iMax << ABITS);
+
+    if (rv == 0) {
+        return 0;
+    }
+
+    chroma = iMax - iMin;
+    rs = (short) ((k1 * chroma) / iMax);
+    if (rs == 0) {
+        return 0;
+    }
+
+    if ( ri == iMax ) {
+        rh  = (short) ((k2 * (6 * chroma + gi - bi))/(6 * chroma));
+        if (rh >= k2) {
+           rh -= k2;
+        }
+        return rh;
+    }
+
+    if (gi  == iMax) {
+        return(short) ((k2 * (2 * chroma + bi - ri)) / (6 * chroma));
+    }
+
+    return (short) ((k2 * (4 * chroma + ri - gi)) / (6 * chroma));
+}
+
+uchar4 __attribute__((kernel)) selectiveAdjust(const uchar4 in, uint32_t x,
+    uint32_t y) {
+    float4 pixel = rsUnpackColor8888(in);
+
+    float4 wsum = pixel;
+    int hue = rgb2hue(in);
+
+    float t = satLut[hue];
+        pixel.xyz = rsMatrixMultiply(&colorMatrix_min ,pixel.xyz) * (1 - t) +
+            t * (rsMatrixMultiply(&colorMatrix_max ,pixel.xyz));
+
+    pixel.a = 1.0f;
+    return rsPackColorTo8888(clamp(pixel, 0.f, 1.0f));
+}
\ No newline at end of file
index 64643e4..d34216a 100644 (file)
@@ -613,7 +613,7 @@ public class ImagePreset {
             writer.endObject();
 
         } catch (IOException e) {
-            e.printStackTrace();
+           Log.e(LOGTAG,"Error encoding JASON",e);
         }
     }
 
index 8ea21ad..3266425 100644 (file)
@@ -25,6 +25,7 @@ public class EditorManager {
 
     public static void addEditors(EditorPlaceHolder editorPlaceHolder) {
         editorPlaceHolder.addEditor(new EditorGrad());
+        editorPlaceHolder.addEditor(new EditorChanSat());
         editorPlaceHolder.addEditor(new EditorZoom());
         editorPlaceHolder.addEditor(new EditorCurves());
         editorPlaceHolder.addEditor(new EditorTinyPlanet());