summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/filtershow/filters
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/filtershow/filters')
-rw-r--r--src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java2
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java514
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java201
-rw-r--r--src/com/android/gallery3d/filtershow/filters/grad.rs131
4 files changed, 848 insertions, 0 deletions
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;
+}
+
+
+