summaryrefslogtreecommitdiffstats
path: root/libs/rs/java/ImageProcessing/src
diff options
context:
space:
mode:
Diffstat (limited to 'libs/rs/java/ImageProcessing/src')
-rw-r--r--libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java30
-rw-r--r--libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Horizontal_blur.java30
-rw-r--r--libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Threshold.java197
-rw-r--r--libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Vertical_blur.java30
-rw-r--r--libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs40
-rw-r--r--libs/rs/java/ImageProcessing/src/com/android/rs/image/ip.rsh15
-rw-r--r--libs/rs/java/ImageProcessing/src/com/android/rs/image/levels.rs88
-rw-r--r--libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs105
-rw-r--r--libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs49
9 files changed, 312 insertions, 272 deletions
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 0ed1185..606bfa8 100644
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -44,6 +44,7 @@ public class ImageProcessingActivity extends Activity
private ScriptC_Threshold mScript;
private ScriptC_Vertical_blur mScriptVBlur;
private ScriptC_Horizontal_blur mScriptHBlur;
+ private ScriptC_Levels mScriptLevels;
private int mRadius = 0;
private SeekBar mRadiusSeekBar;
@@ -260,29 +261,29 @@ public class ImageProcessingActivity extends Activity
}
else if(seekBar == mInBlackSeekBar) {
mInBlack = (float)progress;
- mScript.set_inBlack(mInBlack);
+ mScriptLevels.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
}
else if(seekBar == mOutBlackSeekBar) {
mOutBlack = (float)progress;
- mScript.set_outBlack(mOutBlack);
+ mScriptLevels.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
}
else if(seekBar == mInWhiteSeekBar) {
mInWhite = (float)progress + 127.0f;
- mScript.set_inWhite(mInWhite);
+ mScriptLevels.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
}
else if(seekBar == mOutWhiteSeekBar) {
mOutWhite = (float)progress + 127.0f;
- mScript.set_outWhite(mOutWhite);
+ mScriptLevels.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
}
else if(seekBar == mGammaSeekBar) {
mGamma = (float)progress/100.0f;
mGamma = Math.max(mGamma, 0.1f);
mGamma = 1.0f / mGamma;
- mScript.set_gamma(mGamma);
+ mScriptLevels.invoke_setGamma(mGamma);
}
else if(seekBar == mSaturationSeekBar) {
mSaturation = (float)progress / 50.0f;
- mScript.set_saturation(mSaturation);
+ mScriptLevels.invoke_setSaturation(mSaturation);
}
long t = java.lang.System.currentTimeMillis();
@@ -375,20 +376,18 @@ public class ImageProcessingActivity extends Activity
mOutPixelsAllocation = Allocation.createBitmapRef(mRS, mBitmapOut);
mScratchPixelsAllocation = Allocation.createBitmapRef(mRS, mBitmapScratch);
- mScriptVBlur = new ScriptC_Vertical_blur(mRS, getResources(), R.raw.vertical_blur_bc, false);
- mScriptHBlur = new ScriptC_Horizontal_blur(mRS, getResources(), R.raw.horizontal_blur_bc, false);
+ mScriptVBlur = new ScriptC_Vertical_blur(mRS, getResources(), R.raw.vertical_blur, false);
+ mScriptHBlur = new ScriptC_Horizontal_blur(mRS, getResources(), R.raw.horizontal_blur, false);
+ mScriptLevels = new ScriptC_Levels(mRS, getResources(), R.raw.levels, false);
- mScript = new ScriptC_Threshold(mRS, getResources(), R.raw.threshold_bc, false);
+ mScript = new ScriptC_Threshold(mRS, getResources(), R.raw.threshold, false);
mScript.set_width(mBitmapIn.getWidth());
mScript.set_height(mBitmapIn.getHeight());
mScript.set_radius(mRadius);
- mScript.set_inBlack(mInBlack);
- mScript.set_outBlack(mOutBlack);
- mScript.set_inWhite(mInWhite);
- mScript.set_outWhite(mOutWhite);
- mScript.set_gamma(mGamma);
- mScript.set_saturation(mSaturation);
+ mScriptLevels.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
+ mScriptLevels.invoke_setGamma(mGamma);
+ mScriptLevels.invoke_setSaturation(mSaturation);
mScript.bind_InPixel(mInPixelsAllocation);
mScript.bind_OutPixel(mOutPixelsAllocation);
@@ -396,6 +395,7 @@ public class ImageProcessingActivity extends Activity
mScript.set_vBlurScript(mScriptVBlur);
mScript.set_hBlurScript(mScriptHBlur);
+ mScript.set_levelsScript(mScriptLevels);
}
private Bitmap loadBitmap(int resource) {
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Horizontal_blur.java b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Horizontal_blur.java
deleted file mode 100644
index c447b9b..0000000
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Horizontal_blur.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2010 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.rs.image;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-import android.util.Log;
-
-public class ScriptC_Horizontal_blur extends ScriptC {
- // Constructor
- public ScriptC_Horizontal_blur(RenderScript rs, Resources resources, int id, boolean isRoot) {
- super(rs, resources, id, isRoot);
- }
-
-}
-
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Threshold.java b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Threshold.java
deleted file mode 100644
index c23dca1..0000000
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Threshold.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2010 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.rs.image;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-import android.util.Log;
-
-public class ScriptC_Threshold extends ScriptC {
- // Constructor
- public ScriptC_Threshold(RenderScript rs, Resources resources, int id, boolean isRoot) {
- super(rs, resources, id, isRoot);
- }
-
- private final static int mExportVarIdx_height = 0;
- private int mExportVar_height;
- public void set_height(int v) {
- mExportVar_height = v;
- setVar(mExportVarIdx_height, v);
- }
-
- public int get_height() {
- return mExportVar_height;
- }
-
- private final static int mExportVarIdx_width = 1;
- private int mExportVar_width;
- public void set_width(int v) {
- mExportVar_width = v;
- setVar(mExportVarIdx_width, v);
- }
-
- public int get_width() {
- return mExportVar_width;
- }
-
- private final static int mExportVarIdx_radius = 2;
- private int mExportVar_radius;
- public void set_radius(int v) {
- mExportVar_radius = v;
- setVar(mExportVarIdx_radius, v);
- }
-
- public int get_radius() {
- return mExportVar_radius;
- }
-
- private final static int mExportVarIdx_InPixel = 3;
- private Allocation mExportVar_InPixel;
- public void bind_InPixel(Allocation v) {
- mExportVar_InPixel = v;
- if(v == null) bindAllocation(null, mExportVarIdx_InPixel);
- else bindAllocation(v, mExportVarIdx_InPixel);
- }
-
- public Allocation get_InPixel() {
- return mExportVar_InPixel;
- }
-
- private final static int mExportVarIdx_OutPixel = 4;
- private Allocation mExportVar_OutPixel;
- public void bind_OutPixel(Allocation v) {
- mExportVar_OutPixel = v;
- if(v == null) bindAllocation(null, mExportVarIdx_OutPixel);
- else bindAllocation(v, mExportVarIdx_OutPixel);
- }
-
- public Allocation get_OutPixel() {
- return mExportVar_OutPixel;
- }
-
- private final static int mExportVarIdx_ScratchPixel = 5;
- private Allocation mExportVar_ScratchPixel;
- public void bind_ScratchPixel(Allocation v) {
- mExportVar_ScratchPixel = v;
- if(v == null) bindAllocation(null, mExportVarIdx_ScratchPixel);
- else bindAllocation(v, mExportVarIdx_ScratchPixel);
- }
-
- public Allocation get_ScratchPixel() {
- return mExportVar_ScratchPixel;
- }
-
- private final static int mExportVarIdx_inBlack = 6;
- private float mExportVar_inBlack;
- public void set_inBlack(float v) {
- mExportVar_inBlack = v;
- setVar(mExportVarIdx_inBlack, v);
- }
-
- public float get_inBlack() {
- return mExportVar_inBlack;
- }
-
- private final static int mExportVarIdx_outBlack = 7;
- private float mExportVar_outBlack;
- public void set_outBlack(float v) {
- mExportVar_outBlack = v;
- setVar(mExportVarIdx_outBlack, v);
- }
-
- public float get_outBlack() {
- return mExportVar_outBlack;
- }
-
- private final static int mExportVarIdx_inWhite = 8;
- private float mExportVar_inWhite;
- public void set_inWhite(float v) {
- mExportVar_inWhite = v;
- setVar(mExportVarIdx_inWhite, v);
- }
-
- public float get_inWhite() {
- return mExportVar_inWhite;
- }
-
- private final static int mExportVarIdx_outWhite = 9;
- private float mExportVar_outWhite;
- public void set_outWhite(float v) {
- mExportVar_outWhite = v;
- setVar(mExportVarIdx_outWhite, v);
- }
-
- public float get_outWhite() {
- return mExportVar_outWhite;
- }
-
- private final static int mExportVarIdx_gamma = 10;
- private float mExportVar_gamma;
- public void set_gamma(float v) {
- mExportVar_gamma = v;
- setVar(mExportVarIdx_gamma, v);
- }
-
- public float get_gamma() {
- return mExportVar_gamma;
- }
-
- private final static int mExportVarIdx_saturation = 11;
- private float mExportVar_saturation;
- public void set_saturation(float v) {
- mExportVar_saturation = v;
- setVar(mExportVarIdx_saturation, v);
- }
-
- public float get_saturation() {
- return mExportVar_saturation;
- }
-
- private final static int mExportVarIdx_vBlurScript = 12;
- private Script mExportVar_vBlurScript;
- public void set_vBlurScript(Script v) {
- mExportVar_vBlurScript = v;
- setVar(mExportVarIdx_vBlurScript, (v == null) ? 0 : v.getID());
- }
-
- public Script get_vBlurScript() {
- return mExportVar_vBlurScript;
- }
-
- private final static int mExportVarIdx_hBlurScript = 13;
- private Script mExportVar_hBlurScript;
- public void set_hBlurScript(Script v) {
- mExportVar_hBlurScript = v;
- setVar(mExportVarIdx_hBlurScript, (v == null) ? 0 : v.getID());
- }
-
- public Script get_hBlurScript() {
- return mExportVar_hBlurScript;
- }
-
- private final static int mExportFuncIdx_filter = 0;
- public void invoke_filter() {
- invoke(mExportFuncIdx_filter);
- }
-
- private final static int mExportFuncIdx_filterBenchmark = 1;
- public void invoke_filterBenchmark() {
- invoke(mExportFuncIdx_filterBenchmark);
- }
-
-}
-
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Vertical_blur.java b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Vertical_blur.java
deleted file mode 100644
index cee74d9..0000000
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Vertical_blur.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2010 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.rs.image;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-import android.util.Log;
-
-public class ScriptC_Vertical_blur extends ScriptC {
- // Constructor
- public ScriptC_Vertical_blur(RenderScript rs, Resources resources, int id, boolean isRoot) {
- super(rs, resources, id, isRoot);
- }
-
-}
-
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs
new file mode 100644
index 0000000..a81d829
--- /dev/null
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs
@@ -0,0 +1,40 @@
+#pragma version(1)
+
+#include <rs_types.rsh>
+#include <rs_math.rsh>
+
+#include "ip.rsh"
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+ uchar4 *output = (uchar4 *)v_out;
+ const FilterStruct *fs = (const FilterStruct *)usrData;
+ const uchar4 *input = (const uchar4 *)rsGetElementAt(fs->ain, 0, y);
+
+ float4 blurredPixel = 0;
+ float4 currentPixel = 0;
+
+ for(int r = -fs->radius; r <= fs->radius; r ++) {
+ // Stepping left and right away from the pixel
+ int validW = x + r;
+ // Clamp to zero and width max() isn't exposed for ints yet
+ if(validW < 0) {
+ validW = 0;
+ }
+ if(validW > fs->width - 1) {
+ validW = fs->width - 1;
+ }
+ //int validW = rsClamp(w + r, 0, width - 1);
+
+ float weight = fs->gaussian[r + fs->radius];
+ currentPixel.x = (float)(input[validW].x);
+ currentPixel.y = (float)(input[validW].y);
+ currentPixel.z = (float)(input[validW].z);
+ //currentPixel.w = (float)(input->a);
+
+ blurredPixel += currentPixel * weight;
+ }
+
+ output->x = (uint8_t)blurredPixel.x;
+ output->y = (uint8_t)blurredPixel.y;
+ output->z = (uint8_t)blurredPixel.z;
+}
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ip.rsh b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ip.rsh
new file mode 100644
index 0000000..34213f5
--- /dev/null
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ip.rsh
@@ -0,0 +1,15 @@
+#pragma rs java_package_name(com.android.rs.image)
+
+#define MAX_RADIUS 25
+
+typedef struct {
+ rs_allocation ain;
+
+ float *gaussian; //[MAX_RADIUS * 2 + 1];
+ int height;
+ int width;
+ int radius;
+
+} FilterStruct;
+
+
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/levels.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/levels.rs
new file mode 100644
index 0000000..b436014
--- /dev/null
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/levels.rs
@@ -0,0 +1,88 @@
+#pragma version(1)
+
+#include <rs_types.rsh>
+#include <rs_math.rsh>
+
+#include "ip.rsh"
+
+
+static float inBlack;
+static float outBlack;
+static float inWhite;
+static float outWhite;
+static float3 gamma;
+static float saturation;
+
+static float inWMinInB;
+static float outWMinOutB;
+static float overInWMinInB;
+static rs_matrix3x3 colorMat;
+
+//#pragma rs export_var(height, width, radius, InPixel, OutPixel, ScratchPixel, inBlack, outBlack, inWhite, outWhite, gamma, saturation, InPixel, OutPixel, ScratchPixel, vBlurScript, hBlurScript)
+#pragma rs export_func(setLevels, setSaturation, setGamma);
+
+void setLevels(float iBlk, float oBlk, float iWht, float oWht) {
+ inBlack = iBlk;
+ outBlack = oBlk;
+ inWhite = iWht;
+ outWhite = oWht;
+
+ inWMinInB = inWhite - inBlack;
+ outWMinOutB = outWhite - outBlack;
+ overInWMinInB = 1.f / inWMinInB;
+}
+
+void setSaturation(float sat) {
+ saturation = sat;
+
+ // Saturation
+ // Linear weights
+ //float rWeight = 0.3086f;
+ //float gWeight = 0.6094f;
+ //float bWeight = 0.0820f;
+
+ // Gamma 2.2 weights (we haven't converted our image to linear space yet for perf reasons)
+ float rWeight = 0.299f;
+ float gWeight = 0.587f;
+ float bWeight = 0.114f;
+
+ float oneMinusS = 1.0f - saturation;
+ rsMatrixSet(&colorMat, 0, 0, oneMinusS * rWeight + saturation);
+ rsMatrixSet(&colorMat, 0, 1, oneMinusS * rWeight);
+ rsMatrixSet(&colorMat, 0, 2, oneMinusS * rWeight);
+ rsMatrixSet(&colorMat, 1, 0, oneMinusS * gWeight);
+ rsMatrixSet(&colorMat, 1, 1, oneMinusS * gWeight + saturation);
+ rsMatrixSet(&colorMat, 1, 2, oneMinusS * gWeight);
+ rsMatrixSet(&colorMat, 2, 0, oneMinusS * bWeight);
+ rsMatrixSet(&colorMat, 2, 1, oneMinusS * bWeight);
+ rsMatrixSet(&colorMat, 2, 2, oneMinusS * bWeight + saturation);
+}
+
+void setGamma(float g) {
+ gamma = (float3)g;
+}
+
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+ const uchar4 *input = v_in;
+ uchar4 *output = v_out;
+
+ float4 currentPixel = 0;
+
+ //currentPixel.xyz = convert_float3(input.xyz);
+ currentPixel.x = (float)(input->x);
+ currentPixel.y = (float)(input->y);
+ currentPixel.z = (float)(input->z);
+
+ float3 temp = rsMatrixMultiply(&colorMat, currentPixel.xyz);
+ temp = (clamp(temp, 0.f, 255.f) - inBlack) * overInWMinInB;
+ temp = pow(temp, (float3)gamma);
+ currentPixel.xyz = clamp(temp * outWMinOutB + outBlack, 0.f, 255.f);
+
+ //output.xyz = convert_uchar3(currentPixel.xyz);
+ output->x = (uint8_t)currentPixel.x;
+ output->y = (uint8_t)currentPixel.y;
+ output->z = (uint8_t)currentPixel.z;
+ output->w = input->w;
+}
+
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs
new file mode 100644
index 0000000..e957d3f
--- /dev/null
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs
@@ -0,0 +1,105 @@
+#pragma version(1)
+
+#include <rs_types.rsh>
+#include <rs_math.rsh>
+
+#include "ip.rsh"
+
+int height;
+int width;
+int radius;
+
+uchar4 * InPixel;
+uchar4 * OutPixel;
+uchar4 * ScratchPixel;
+
+#pragma rs export_var(height, width, radius, InPixel, OutPixel, ScratchPixel, vBlurScript, hBlurScript, levelsScript)
+#pragma rs export_func(filter, filterBenchmark);
+
+rs_script vBlurScript;
+rs_script hBlurScript;
+rs_script levelsScript;
+
+
+// Store our coefficients here
+static float gaussian[MAX_RADIUS * 2 + 1];
+
+
+static void computeGaussianWeights() {
+ // Compute gaussian weights for the blur
+ // e is the euler's number
+ float e = 2.718281828459045f;
+ float pi = 3.1415926535897932f;
+ // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
+ // x is of the form [-radius .. 0 .. radius]
+ // and sigma varies with radius.
+ // Based on some experimental radius values and sigma's
+ // we approximately fit sigma = f(radius) as
+ // sigma = radius * 0.4 + 0.6
+ // The larger the radius gets, the more our gaussian blur
+ // will resemble a box blur since with large sigma
+ // the gaussian curve begins to lose its shape
+ float sigma = 0.4f * (float)radius + 0.6f;
+
+ // Now compute the coefficints
+ // We will store some redundant values to save some math during
+ // the blur calculations
+ // precompute some values
+ float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
+ float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+
+ float normalizeFactor = 0.0f;
+ float floatR = 0.0f;
+ int r;
+ for(r = -radius; r <= radius; r ++) {
+ floatR = (float)r;
+ gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+ normalizeFactor += gaussian[r + radius];
+ }
+
+ //Now we need to normalize the weights because all our coefficients need to add up to one
+ normalizeFactor = 1.0f / normalizeFactor;
+ for(r = -radius; r <= radius; r ++) {
+ floatR = (float)r;
+ gaussian[r + radius] *= normalizeFactor;
+ }
+}
+
+
+static void blur() {
+ computeGaussianWeights();
+
+ FilterStruct fs;
+ fs.gaussian = gaussian;
+ fs.width = width;
+ fs.height = height;
+ fs.radius = radius;
+
+ fs.ain = rsGetAllocation(InPixel);
+ rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel), &fs);
+
+ fs.ain = rsGetAllocation(ScratchPixel);
+ rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs);
+}
+
+void filter() {
+ //RS_DEBUG(radius);
+
+ if(radius > 0) {
+ blur();
+ rsForEach(levelsScript, rsGetAllocation(OutPixel), rsGetAllocation(OutPixel), 0);
+ } else {
+ rsForEach(levelsScript, rsGetAllocation(InPixel), rsGetAllocation(OutPixel), 0);
+ }
+
+ int count = 0;
+ rsSendToClient(&count, 1, 4, 0);
+}
+
+void filterBenchmark() {
+ blur();
+
+ int count = 0;
+ rsSendToClient(&count, 1, 4, 0);
+}
+
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
new file mode 100644
index 0000000..8930e2f
--- /dev/null
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
@@ -0,0 +1,49 @@
+#pragma version(1)
+
+#include <rs_types.rsh>
+#include <rs_math.rsh>
+
+#include "ip.rsh"
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+ uchar4 *output = (uchar4 *)v_out;
+ const FilterStruct *fs = (const FilterStruct *)usrData;
+ const uchar4 *input = (const uchar4 *)rsGetElementAt(fs->ain, x, 0);
+
+ float4 blurredPixel = 0;
+ float4 currentPixel = 0;
+ for(int r = -fs->radius; r <= fs->radius; r ++) {
+#if 1
+ int validH = y + r;
+ // Clamp to zero and width
+ if(validH < 0) {
+ validH = 0;
+ }
+ if(validH > fs->height - 1) {
+ validH = fs->height - 1;
+ }
+
+ const uchar4 *i = input + validH * fs->width;
+ //const uchar4 *i = (const uchar4 *)rsGetElementAt(fs->ain, x, validH);
+
+ float weight = fs->gaussian[r + fs->radius];
+
+ currentPixel.x = (float)(i->x);
+ currentPixel.y = (float)(i->y);
+ currentPixel.z = (float)(i->z);
+
+ blurredPixel.xyz += currentPixel.xyz * weight;
+#else
+ int validH = rsClamp(y + r, 0, height - 1);
+ validH -= y;
+ uchar4 *i = input + validH * width + x;
+ blurredPixel.xyz += convert_float3(i->xyz) * gaussian[r + fs->radius];
+#endif
+ }
+
+ //output->xyz = convert_uchar3(blurredPixel.xyz);
+ output->x = (uint8_t)blurredPixel.x;
+ output->y = (uint8_t)blurredPixel.y;
+ output->z = (uint8_t)blurredPixel.z;
+}
+