diff options
author | John Hoford <hoford@google.com> | 2013-07-19 17:11:31 -0700 |
---|---|---|
committer | John Hoford <hoford@google.com> | 2013-07-29 17:21:34 -0700 |
commit | 52e9277b6774bc938a9e55694640c20e4ba90365 (patch) | |
tree | da8abe57ccc4c2040b9989739b926ccf0544c8c9 /src/com/android/gallery3d/filtershow/filters | |
parent | a5c138bdac37dddf53acd37807a364aac753acb6 (diff) | |
download | android_packages_apps_Snap-52e9277b6774bc938a9e55694640c20e4ba90365.tar.gz android_packages_apps_Snap-52e9277b6774bc938a9e55694640c20e4ba90365.tar.bz2 android_packages_apps_Snap-52e9277b6774bc938a9e55694640c20e4ba90365.zip |
add Grad filter
Change-Id: I30fc0810c54f3daa31726188a4c3762df33953a7
Diffstat (limited to 'src/com/android/gallery3d/filtershow/filters')
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; +} + + + |